首页 > 解决方案 > SQLite Query in Python returns empty results

问题描述

I have to download a database file and decompress it and query using SQLite query in python. Location of the file:

http://amazonlinux.us-east-2.amazonaws.com/2/core/2.0/x86_64/11be506f86779fba9940dfce8be18d996726d1db2267fd3b13585c19e638db48/repodata/primary.sqlite.gz

For some strange reason the below code returns empty results if the run this code on remote database (primary.sqlite) , unlike if I run the same code to a custom created database with similar values.

The below code returns all the values between two version ranges if the upper limit of the version given is greater the the max value of the version in the table.

Customdb.db :

create table packages(version varchar,name varchar);


insert into packages values('7.61.1',"libcurl");
insert into packages values('7.51.1',"libcurl");
insert into packages values('7.51.1',"libcurl");
insert into packages values('7.51.1',"libcurl");
insert into packages values('7.51.1',"libcurl");
insert into packages values('7.51.1',"libcurl");
insert into packages values('7.61.1',"libcurl");

Query:

import sqlite3
conn = sqlite3.connect('Customdb.db')

c = conn.cursor()

software_name = "libcurl"
v1_start = "0.0.0"
v2_end_inc = "24.12.1"
v2_end_ex = "24.12.1"
only_version = '20.61.1'
print (type(v2_end_inc))

c.execute("""
        select name,version from packages
        where name = ?1 and
        1000000 * replace(version, '.', 'x') +
        1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
        replace(version, '.', '000') % 1000
        between
        (1000000 * replace(?2, '.', 'x') +
        1000 * replace(substr(?2, instr(?2, '.') + 1), '.', 'x') +
        replace(?2, '.', '000') % 1000)
        and
        (1000000 * replace(?3, '.', 'x') +
        1000 * replace(substr(?3, instr(?3, '.') + 1), '.', 'x') +
        replace(?3, '.', '000') % 1000)
        and
        (SELECT 1000000 * replace(?3, '.', 'x') +
        1000 * replace(substr(?3, instr(?3, '.') + 1), '.', 'x') +
        replace(?3, '.', '000') % 1000) >=
        (SELECT MAX(1000000 * replace(version, '.', 'x') +
        1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
        replace(version, '.', '000') % 1000 ) FROM packages)
        ORDER BY
        (1000000 * replace(version, '.', 'x') +
        1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
        replace(version, '.', '000') % 1000)
    """, (software_name, v1_start, v2_end_inc))



Results:

libcurl|7.51.1                                                                                                                          
libcurl|7.51.1                                                                                                                          
libcurl|7.51.1                                                                                                                          
libcurl|7.51.1                                                                                                                          
libcurl|7.51.1                                                                                                                          
libcurl|7.61.1                                                                                                                          
libcurl|7.61.1

If I download the file and decompress it and run the simple code it returns these results so there is nothing wrong with the downloading the remote file and decompressing it.

import sqlite3
conn = sqlite3.connect('primary.sqlite')

c = conn.cursor()

c.execute("SELECT version FROM packages where name = 'libcurl' ")

results = c.fetchall()

package_obj_list = []  
l = len(results)
for package in results:
   package_obj_list.append(package)

print (package_obj_list)

results are:

[ [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  “7.61.1” ], [  “7.61.1” ], [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  “7.61.1” ]]



The below code returns all the values between two version ranges if the upper limit of the version given is greater the the max value of the version in the table.

Customdb.db :

create table packages(version varchar,name varchar);


insert into packages values('7.61.1',"libcurl");
insert into packages values('7.51.1',"libcurl");
insert into packages values('7.51.1',"libcurl");
insert into packages values('7.51.1',"libcurl");
insert into packages values('7.51.1',"libcurl");
insert into packages values('7.51.1',"libcurl");
insert into packages values('7.61.1',"libcurl");

Query:

import sqlite3
conn = sqlite3.connect('Customdb.db')

c = conn.cursor()

software_name = "libcurl"
v1_start = "0.0.0"
v2_end_inc = "24.12.1"
v2_end_ex = "24.12.1"
only_version = '20.61.1'
print (type(v2_end_inc))

c.execute("""
        select name,version from packages
        where name = ?1 and
        1000000 * replace(version, '.', 'x') +
        1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
        replace(version, '.', '000') % 1000
        between
        (1000000 * replace(?2, '.', 'x') +
        1000 * replace(substr(?2, instr(?2, '.') + 1), '.', 'x') +
        replace(?2, '.', '000') % 1000)
        and
        (1000000 * replace(?3, '.', 'x') +
        1000 * replace(substr(?3, instr(?3, '.') + 1), '.', 'x') +
        replace(?3, '.', '000') % 1000)
        and
        (SELECT 1000000 * replace(?3, '.', 'x') +
        1000 * replace(substr(?3, instr(?3, '.') + 1), '.', 'x') +
        replace(?3, '.', '000') % 1000) >=
        (SELECT MAX(1000000 * replace(version, '.', 'x') +
        1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
        replace(version, '.', '000') % 1000 ) FROM packages)
        ORDER BY
        (1000000 * replace(version, '.', 'x') +
        1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
        replace(version, '.', '000') % 1000)
    """, (software_name, v1_start, v2_end_inc))



Results:

libcurl|7.51.1                                                                                                                          
libcurl|7.51.1                                                                                                                          
libcurl|7.51.1                                                                                                                          
libcurl|7.51.1                                                                                                                          
libcurl|7.51.1                                                                                                                          
libcurl|7.61.1                                                                                                                          
libcurl|7.61.1

If I download the file and decompress it and run the simple code it returns these results so there is nothing wrong with the downloading the remote file and decompressing it.

import sqlite3
conn = sqlite3.connect('primary.sqlite')

c = conn.cursor()

c.execute("SELECT version FROM packages where name = 'libcurl' ")

results = c.fetchall()

package_obj_list = []  
l = len(results)
for package in results:
   package_obj_list.append(package)

print (package_obj_list)

results are:

[ [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  “7.61.1” ], [  “7.61.1” ], [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  “7.61.1” ]]



However if I run the same code as that run on "primary.sqlite" file gives empty results.

software_name = "libcurl"
v1_start = "0.0.0"
v2_end_inc = "24.12.1"
v2_end_ex = "24.12.1"
only_version = '20.61.1'
print (type(v2_end_inc))

c.execute("""
        select name,version from packages
        where name = ?1 and
        1000000 * replace(version, '.', 'x') +
        1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
        replace(version, '.', '000') % 1000
        between
        (1000000 * replace(?2, '.', 'x') +
        1000 * replace(substr(?2, instr(?2, '.') + 1), '.', 'x') +
        replace(?2, '.', '000') % 1000)
        and
        (1000000 * replace(?3, '.', 'x') +
        1000 * replace(substr(?3, instr(?3, '.') + 1), '.', 'x') +
        replace(?3, '.', '000') % 1000)
        and
        (SELECT 1000000 * replace(?3, '.', 'x') +
        1000 * replace(substr(?3, instr(?3, '.') + 1), '.', 'x') +
        replace(?3, '.', '000') % 1000) >=
        (SELECT MAX(1000000 * replace(version, '.', 'x') +
        1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
        replace(version, '.', '000') % 1000 ) FROM packages)
        ORDER BY
        (1000000 * replace(version, '.', 'x') +
        1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
        replace(version, '.', '000') % 1000)
    """, (software_name, v1_start, v2_end_inc))

Expected Results:

[ [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  “7.61.1” ], [  “7.61.1” ], [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  "7.55.1" ], [  “7.61.1” ]]

Current Results:

[]

标签: pythonsqlsqlite

解决方案


缺陷在这里:

>=
        (SELECT MAX(1000000 * replace(version, '.', 'x') +
        1000 * replace(substr(version, instr(version, '.') + 1), '.', 'x') +
        replace(version, '.', '000') % 1000 ) FROM packages)

在“customdb”测试中返回预期结果,因为只有特定的名称/版本行。SELECT version FROM packages where name = 'libcurl'在测试中返回预期结果,primary.sqlite因为结果是按名称过滤的。

但是,由于上面引用的子查询没有名称过滤,它正在为所有行选择最大“编号”版本packages


推荐阅读