2017-02-21 6 views
2

데이터베이스 (PostgreSQL, pyodbc, Python 3.4.4, Windows 7)의 문자 필드에서 하위 문자열의 발생 횟수를 계산하려고했습니다. 그러나 문자 필드가 511보다 큰 경우 count()는 항상 0을 반환합니다. 반환 된 문자열 (예 : 인덱스 0에서 문자열에 액세스하거나 문자열을보기 위해 print()를 사용하는 등)을 "수행"한 후에 만 ​​count()가 예상 값을 반환하고있었습니다. 길이가 511 이하인 문자열에는 아무런 문제가 없었습니다.pyodbc를 사용하여 511보다 큰 문자 필드에 액세스 할 때 count()가 0을 반환하는 이유는 무엇입니까?

(512 또는 그 이상) 문자열의 크기가 변경되는 것 같습니다 (아래 예제 참조).

이 문제는 pyodbc를 사용할 때 PostgreSQL, SQLite 및 Oracle에서 발생하는 것으로 보입니다. psycopg2를 사용하여 재현 할 수 없었습니다.

그래서, pyodbc의 버그입니까? 아니면 어떤 종류의 최적화입니까? count()에 문제가 있습니까? (다른 함수 (예 : len())와 같은 것이 좋습니다.

다음 Python 스크립트는 PostgreSQL, SQLite-ODBC 또는 Oracle을 사용하여이 문제를 재현합니다. 두 테이블을 만들고 텍스트를 삽입하고 반환 된 데이터에서 count() 함수를 사용하려고합니다.

import pyodbc 
import sys 

#conn = pyodbc.connect('driver={SQLite3 ODBC Driver}; server=localhost; database=D:\\test.db;') 
#conn = pyodbc.connect('DSN=test-oracle;uid=xx;pwd=xx') 
conn = pyodbc.connect('DSN=test-postgresql;uid=xx;pwd=xx') 
cursor = conn.cursor() 
with conn.cursor() as cursor: 

    cursor.execute("create table testtable511 (txt char(511) default ' ' primary key not NULL);") 
    cursor.execute("insert into testtable511 (txt) values ('"+511*"t"+"');") 
    cursor.execute("create table testtable512 (txt char(512) default ' ' primary key not NULL);") 
    cursor.execute("insert into testtable512 (txt) values ('"+512*"t"+"');") 

    cursor.execute('select * from testtable511') 
    data511 = cursor.fetchone() 
    print('511') 
    print(80*'#') 
    # count is 511, size is 560 
    print('counting t before "accessing" string of testtable511:  ', data511[0].count('t')) 
    print('size of string before "accessing" string of testtable511: ', sys.getsizeof(data511[0])) 
    data511[0][0] 
    # count is 511, size is 560 
    print('counting t after "accessing" string of testtable511:  ', data511[0].count('t')) 
    print('size of string after "accessing" string of testtable511: ', sys.getsizeof(data511[0])) 
    print(80*'#') 

    print() 

    cursor.execute('select * from testtable512') 
    data512 = cursor.fetchone() 
    print('512') 
    print(80*'#') 
    # count is 0, size is 1106 
    print('counting t before "accessing" string of testtable512:  ', data512[0].count('t')) 
    print('size of string before "accessing" string of testtable512: ', sys.getsizeof(data512[0])) 
    data512[0][0] 
    # count is 512, size is 593 
    print('counting t after "accessing" string of testtable512:  ', data512[0].count('t')) 
    print('size of string after "accessing" string of testtable512: ', sys.getsizeof(data512[0])) 
    print(80*'#') 

    cursor.execute("drop table testtable511;") 
    cursor.execute("drop table testtable512;") 

conn.close() 

업데이트 : pyodbc 3.0.10에서 문제가 발생했습니다. 버전 4.0.11에서이 문제점을 수정했습니다.

+1

pyodbc 4.0.11을 사용하고 있습니까? –

+0

pyodbc 버전 3.0.10을 사용하고있었습니다. 감사. 그래서 분명히 버그이며 4.0.11이이 문제를 해결하고 있습니다. – segmentationfault

답변

2

이 문제는 pyodbc 4.0.11에서 수정되었습니다.

그래서 이전 pyodbc 버전의 버그였습니다 (3.0.10 사용).