I am running SQLAlchemy against FirebirdSQL, and when I execute an insert
command in my project, SQLAlchemy is raising an exception on returning from executing against the connection. However, the insert
query is being constructed and executed successfully. Querying the database shows that the items are actually being inserted correctly.
Edit: I'm digging down into the fbcore.py
module now, and checking the value of value
and vartype
indicates that the issue is probably how the SEQUENCE
item used to generate the primary key ID is returning its data is at issue. The vartype
is SQL_LONG
, but the actual value is [<an integer>]
where <an integer>
is the value returned by a sequence generator I created to auto-increment the primary key (e.g. [14]
). This suggests to me that the problem should be resolved by fixing that, though I'm not sure how to do it. The generator appears to be working correctly within the database itself, but causing problems when returned to SQLAlchemy.
See below for my existing implementation and the stack trace for details.
My code:
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_
The traceback:
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()
I'm not yet sufficiently familiar with SQLAlchemy's to see why this is an issue; the style of my statement is pretty much identical to that in the tutorial. This appears to be an issue with how the parameters are being passed – possibly something about using a dict rather than keyword arguments? But there's nothing in the docs on how to handle parameters that suggests I have anything amiss here – it seems right from what I'm seeing there.
I've also tried this with self.table.insert().values(values)
rather than passing the values
term to the execute
method, with the same results (as I would expect).
Edit: I note from reading the docstring on execute
in fbcore.py
that it raises a TypeError when the parameters passed to the method are not given either as a list or a tuple. Is this a change that is not yet reflected in the documentation?
Edit 2: As a comment notes, the stack trace indicates that it's running against the kinterbasdb driver, though I have explicitly configured the engine to run using fdb. This is also confusing to me.