«Комментарии - это ложь»
Комментарии не выполняются и легко игнорируются. Намерение лучше выразить с помощью ясного, переработанного кода, проиллюстрированного модульными тестами. (Конечно, модульные тесты написаны TDD ...)
Мы не пишем комментарии, потому что они многословны и скрывают то, что на самом деле происходит в коде. Если вы чувствуете необходимость комментировать - выясните, что не ясно в коде, и реорганизуйте / напишите более четкие тесты, пока нет необходимости комментировать ...
... кое-что, чему я научился из экстремального программирования (конечно, предполагается, что вы установили командные нормы для очистки кода ...)
Ха, сразу после предложения награды я нашел решение.
Вы должны использовать SET TEXTSIZE 2147483647
в запросе в дополнение к тексту параметр конфигурации размера в /etc/freetds/freetds.conf
.
Я использовал
cur.execute('SET TEXTSIZE 2147483647 SELECT myimage FROM testing WHERE id = 1')
И все работало нормально.
Странно то, что в документации FreeTDS говорится о параметре конфигурации размера текста:
значение по умолчанию
TEXTSIZE
, в байтах. Для типов данныхтекст
иизображение
устанавливает максимальную ширину любого возвращаемого столбца. Ср.установите TEXTSIZE
в документацииT-SQL
для вашего сервера.
В конфигурации также указано, что максимальное значение (и значение по умолчанию) составляет 4 294 967 295. Однако при попытке использовать это значение в запросе я получаю сообщение об ошибке, максимальное число, которое я мог бы использовать в запросе, - 2 147 483 647 (половина).
Исходя из этого объяснения, я подумал, что достаточно установить только этот параметр конфигурации. Оказалось, что я ошибался, установка TEXTSIZE в запросе устранила проблему.
Ниже приведен полный рабочий код:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pyodbc
import urllib2
odbcstring = "SERVER=10.32.42.69;UID=sa;PWD=secret;DATABASE=Common;DRIVER=FreeTDS"
con = pyodbc.connect(odbcstring)
cur = con.cursor()
cur.execute("""
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'testing')
DROP TABLE testing
""")
cur.execute('''
CREATE TABLE testing (
id INTEGER NOT NULL IDENTITY(1,1),
myimage IMAGE NULL,
PRIMARY KEY (id)
)
''')
con.commit()
cur = con.cursor()
url = 'http://www.forestwander.com/wp-content/original/2009_02/west-virginia-mountains.jpg'
data = urllib2.urlopen(url).read()
sql = "INSERT INTO testing (myimage) VALUES (?)"
cur.execute(sql, (pyodbc.Binary(data),))
con.commit()
cur.execute('SELECT DATALENGTH(myimage) FROM testing WHERE id = 1')
data_inside = cur.fetchone()[0]
assert data_inside == len(data)
cur.execute('SET TEXTSIZE 2147483647 SELECT myimage FROM testing WHERE id = 1')
result = cur.fetchone()
returned_data = str(result[0])
print 'Original: %d; Returned; %d' % (len(data), len(returned_data))
assert data == returned_data
Я думаю, вам следует использовать экземпляр pyodbc.Binary
, чтобы обернуть данные:
cur.execute('INSERT INTO testing (myimage) VALUES (?)', (pyodbc.Binary(data),))
Получение должно be
cur.execute('SELECT myimage FROM testing')
print "image bytes: %r" % str(cur.fetchall()[0][0])
ОБНОВЛЕНИЕ: Проблема в прошивке. Измените SQL-код вставки на следующее:
"""DECLARE @txtptr varbinary(16)
INSERT INTO testing (myimage) VALUES ('')
SELECT @txtptr = TEXTPTR(myimage) FROM testing
WRITETEXT testing.myimage @txtptr ?
"""
Я также обновил ошибку, которую допустил при использовании атрибута value в коде поиска.
С этим изменением я могу вставлять и извлекать изображение 320K JPEG в база данных (полученные данные идентичны вставленным данным).
NB Тип данных image
устарел и заменен на varbinary (max)
в более поздних версиях SQL Server. Однако такая же логика для вставки / извлечения должна применяться для столбца нового типа.