データベースに接続するために、Ubuntu 10.04 Lucid LTS で次のソフトウェア スタックを使用しています。
- python 2.6.5 (ubuntu パッケージ)
- pyodbc git トランク コミット
eb545758079a743b2e809e2e219c8848bc6256b2
- unixodbc 2.2.11 (ubuntu パッケージ)
- freetds 0.82 (ubuntu パッケージ)
- Windows と Microsoft SQL Server 2000 (8.0)
SQL SERVER 関数への引数でネイティブ パラメーター バインドを実行しようとすると、次のエラーが発生します。
Traceback (most recent call last):
File "/home/nosklo/devel/testes/sqlfunc.py", line 32, in <module>
cur.execute("SELECT * FROM fn_FuncTest(?)", ('test',))
pyodbc.ProgrammingError: ('42000', '[42000] [FreeTDS][SQL
Server]SqlDumpExceptionHandler: Process 54 generated fatal exception
c0000005 EXCEPTION_ACCESS_VIOLATION. SQL Server is terminating this
process.\r\n (0) (SQLPrepare)')
再現コードは次のとおりです。
import pyodbc
constring = 'server=myserver;uid=uid;pwd=pwd;database=db;TDS_Version=8.0;driver={FreeTDS}'
con = pyodbc.connect(constring)
print 'VERSION: ', con.getinfo(pyodbc.SQL_DBMS_VER)
cur = con.cursor()
try:
cur.execute('DROP FUNCTION fn_FuncTest')
con.commit()
print "Function dropped"
except pyodbc.Error:
pass
cur.execute('''
CREATE FUNCTION fn_FuncTest (@testparam varchar(4))
RETURNS @retTest TABLE (param varchar(4))
AS
BEGIN
INSERT @retTest
SELECT @testparam
RETURN
END''')
con.commit()
これで関数が作成されました。クエリで値を直接使用して呼び出そうとすると (値のネイティブ バインドはありません)、正常に動作します。
cur.execute("SELECT * FROM fn_FuncTest('test')")
assert cur.fetchone()[0] == 'test'
ただし、ネイティブ バインドを実行しようとすると、上記のエラーが発生します (パラメーター プレースホルダーを使用して値を個別に渡すことにより)。
cur.execute("SELECT * FROM fn_FuncTest(?)", ('test',))
さらなる調査により、私が関連付けたいいくつかの奇妙なことが明らかになりました。
- TDS バージョンを 4.2 に変更すると、すべて正常に動作します (ただし、SQL Server からのバージョン レポートは間違っています。実際のバージョンではなく、
4.2
取得した TDS バージョンを 使用します)。'95.08.0255'
'08.00.0760'
- 他の 2 種類の関数については、すべて正常に動作します。値を返す関数と、単なる SELECT クエリ (ビューなど) の関数の両方が正常に動作します。他の (壊れた) 関数に対するクエリの結果を返す新しい関数を定義することもできます。これにより、パラメータに対してネイティブ バインドを実行する場合でも、すべてが機能します。例えば:
CREATE FUNCTION fn_tempFunc(@testparam varchar(4)) RETURNS TABLE AS RETURN (SELECT * FROM fn_FuncTest(@testparam))
- このエラーの後、接続が非常に不安定になり、回復できなくなります。
- 任意のタイプのデータをバインドしようとすると、エラーが発生します。
どうすればこれをさらに追求できますか?関数パラメーターへのネイティブ バインドを行いたいと思います。