4

FirebirdSQL に対して SQLAlchemy をinsert実行しています。プロジェクトでコマンドを実行すると、SQLAlchemy は接続に対する実行から戻るときに例外を発生させます。ただしinsertクエリは正常に作成および実行されています。データベースにクエリを実行すると、アイテムが実際に正しく挿入されていることがわかります。

編集:fbcore.py私は今、モジュールを掘り下げて、値をチェックして、主キー ID を生成するために使用される項目がそのデータを返す方法が問題であることを示していvalueます。はですが、実際の値は です は、主キーを自動インクリメントするために作成したシーケンス ジェネレーターによって返される値です (例: )。これは、それを修正することで問題を解決する必要があることを示唆していますが、その方法はわかりません。ジェネレーターはデータベース内では正しく動作しているように見えますが、SQLAlchemy に戻すと問題が発生します。vartypeSEQUENCEvartypeSQL_LONG[<an integer>]<an integer>[14]

詳細については、既存の実装とスタック トレースについては以下を参照してください。

私のコード:

class Project:
    # (I've snipped project instantiation, where engine connection, table, etc. are configured)
    def save_project(self, id_=None, title=None, file_name=None, file_location=None):

        # Build the dictionary of values to store
        values = {}
        if title is not None:
            values['title'] = title

        if file_name is not None:
            values['file_name'] = file_name

        if file_location is not None:
            values['file_location'] = file_location

        # Simplification: I account for the case that there *is* data---skipping that here

        # Execute the correct kind of statement: insert or settings_update.
        if id_ is None:
            statement = self.table.insert()

        else:
            statement = self.table.update().where(self.table.c.id == id_)

        result = self.connection.execute(statement, values)

        # If we inserted a row, get the new primary key. Otherwise, return
        # the one specified by the user; it does not change on settings_update.
        project_id = result.inserted_primary_key if result.is_insert else id_

トレースバック:

  File "/Users/chris/development/quest/workspace/my_project/data/tables.py", line 350, in save_project
    result = self.connection.execute(statement, values)
  File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/engine/base.py", line 720, in execute
    return meth(self, multiparams, params)
  File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/sql/elements.py", line 317, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/engine/base.py", line 817, in _execute_clauseelement
    compiled_sql, distilled_params
  File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/engine/base.py", line 947, in _execute_context
    context)
  File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/engine/base.py", line 1111, in _handle_dbapi_exception
    util.reraise(*exc_info)
  File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/util/compat.py", line 168, in reraise
    raise value
  File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/engine/base.py", line 940, in _execute_context
    context)
  File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/dialects/firebird/kinterbasdb.py", line 106, in do_execute
    cursor.execute(statement, parameters or [])
  File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/fdb/fbcore.py", line 3323, in execute
    self._ps._execute(parameters)
  File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/fdb/fbcore.py", line 2991, in _execute
    self.__Tuple2XSQLDA(self._in_sqlda, parameters)
  File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/fdb/fbcore.py", line 2782, in __Tuple2XSQLDA
    sqlvar.sqlscale)
  File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/fdb/fbcore.py", line 2266, in _check_integer_range
    if (value < vmin) or (value > vmax):
TypeError: unorderable types: list() < int()

なぜこれが問題なのかを理解するには、SQLAlchemy についてまだ十分に理解していません。私のステートメントのスタイルは、チュートリアルのスタイルとほとんど同じです。これは、パラメータが渡される方法に問題があるようです。おそらく、キーワード引数ではなく dict を使用することに関するものでしょうか? しかし、ここで何か問題があることを示唆するパラメーターの処理方法に関するドキュメントには何もありません。私が見ているものからは正しいようです。

また、用語をメソッドにself.table.insert().values(values)渡すのではなく、これを試してみましたが、同じ結果が得られました(予想どおり)。valuesexecute

編集:メソッドに渡されたパラメーターがリストまたはタプルとして指定されていない場合、TypeError が発生するという点でexecute、docstring を読んだことに注意してください。fbcore.pyこれはドキュメントにまだ反映されていない変更ですか?

編集 2:コメントにあるように、スタック トレースは、 fdb を使用して実行するようにエンジンを明示的に構成しましたが、kinterbasdb ドライバーに対して実行されていることを示します。これも私を混乱させます。

4

2 に答える 2

3

UPDATE私が予想していたように、特に行が期待どおりに挿入されたが、その後すぐに関数で呼び出されたことが問題であることがわかったとき、問題は関連するコードでした。私は結果を次のように返していましたproject_id(上記のコードでわかるように)。まったく関係のない理由 (ブリンカー信号に関係する) で、メソッドが再度呼び出され、返された値は次のproject_idように設定されました。

project_id = result.inserted_primary_key if result.is_insert else id_

この行の正しいバージョンは、わずかに異なるだけです。

project_id = result.inserted_primary_key[0] if result.is_insert else id_

SQLAlchemy docsから(強調鉱山):

挿入した行の主キーを返します。

戻り値は、ターゲット テーブルの主キー列のリストに対応するスカラー値のリストです。

主キーはデータベース内の複数のフィールドの組み合わせになる可能性があるため、ここでの戻り値はリストでなければなりません。(これは私には明らかだったはずです。ここ 1 年以上、本格的なデータベース作業を行っていないことは明らかです。) この場合の主キーは単一の値であるため、その値を選択して返しただけで、問題は次のとおりです。解決しました。

もちろん、今度はそのウインカー信号の問題を突き止めなければなりません — このメソッドは 2 回呼び出されるべきではありません — しかし c'est la vie...

于 2014-04-04T20:39:20.087 に答える