Confusing error message when passing empty list to Insert.values()

Issue #2944 resolved
Former user created an issue

When passing a list of dictionaries to Insert.values(), I happened to pass an empty list, as in the following test case:

#!/usr/bin/python
import sqlalchemy
print sqlalchemy.__version__
from sqlalchemy import Table, Column, Integer, MetaData, insert
m = MetaData()
c1 = Column('c1', Integer)
t1 = Table('t1', m, c1)
s = t1.insert().values([obtained the following exception:


{{{
0.9.0b1
Traceback (most recent call last):
  File "sqlalchemybug.py", line 11, in <module>
    s = t1.insert().values([](])

and)) File "<string>", line 1, in <lambda> File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.9.0b1-py2.7.egg/sqlalchemy/sql/base.py", line 42, in _generative fn(self, args1:, *kw) File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.9.0b1-py2.7.egg/sqlalchemy/sql/dml.py", line 283, in values self._process_colparams(v) File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.9.0b1-py2.7.egg/sqlalchemy/sql/dml.py", line 41, in _process_colparams isinstance(parameters0, (list, tuple, dict)): IndexError: list index out of range }}}

Upon checking the documentation I note that it does say "This mode is indicated by passing a list of ''one or more'' dictionaries/tuples", i.e. behaviour on a list of zero dictionaries/tuples is undefined. I feel this warrants a more explicit error message, rather than letting the {{{IndexError}}} bubble up.

Comments (3)

  1. Mike Bayer repo owner

    an empty list should indicate a single list of parameters for one row, where the row has no values.

    so this patch:

    diff --git a/lib/sqlalchemy/sql/dml.py b/lib/sqlalchemy/sql/dml.py
    index 854b894..658b116 100644
    --- a/lib/sqlalchemy/sql/dml.py
    +++ b/lib/sqlalchemy/sql/dml.py
    @@ -37,7 +37,8 @@ class UpdateBase(DialectKWArgs, HasPrefixes, Executable, ClauseElement):
                     return p
    
             if isinstance(parameters, (list, tuple)) and \
    -              isinstance(parameters[0](0), (list, tuple, dict)):
    +            parameters and \
    +            isinstance(parameters[0](0), (list, tuple, dict)):
    
                 if not self._supports_multi_parameters:
                     raise exc.InvalidRequestError(
    

    gets us this for PG:

    from sqlalchemy.sql import table, column
    from sqlalchemy.dialects import postgresql
    
    s = table('t', column('a'), column('b')).insert().values([])
    print s.compile(dialect=postgresql.dialect())}
    
    INSERT INTO t DEFAULT VALUES
    

    the same as if you called .values() with no argument.

  2. Log in to comment