-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Migrated issue, originally created by Matthew Booth
OpenStack's oslo.db contains a TimestampMixin, which defines a created_at column:
created_at = Column(DateTime, default=lambda: timeutils.utcnow())
Attempting to insert multiple rows without explicitly specifying this column will fail. e.g.:
DBError: (sqlite3.ProgrammingError) Incorrect number of bindings supplied. The current statement uses 20, and there are 19 supplied. [SQL: u'INSERT INTO fixed_ips (created_at, deleted, address, network_id, virtual_interface_id, instance_uuid, allocated, leased, reserved, host) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'] [parameters: ('2015-01-13 14:04:51.046323', 0, '192.168.1.5', 1, None, 'd4473f3a-dbb9-43ce-a30b-51a4583ead5f', 0, 0, 0, '127.0.0.1', 0, '192.168.1.6', 2, None, 'd4473f3a-dbb9-43ce-a30b-51a4583ead5f', 1, 0, 0, 'localhost')]
In the above case, the caller is not passing a value for created_at:
params = [
{'reserved': False, 'deleted': 0, 'leased': False,
'host': '127.0.0.1', 'address': address_1, 'allocated': False,
'instance_uuid': instance_uuid, 'network_id': network_id_1,
'virtual_interface_id': None},
{'reserved': False, 'deleted': 0, 'leased': False,
'host': 'localhost', 'address': address_2, 'allocated': True,
'instance_uuid': instance_uuid, 'network_id': network_id_2,
'virtual_interface_id': None}
]
... openstack stuff ...
tab = models.FixedIp.__table__
insert = tab.insert().values(ips)
session.execute(insert)
The cause seems to be in _extend_values_for_multiparams:
values.extend(
[
(
c,
(_create_bind_param(
compiler, c, row[c.key],
name="%s_%d" % (c.key, i + 1)
) if elements._is_literal(row[c.key])
else compiler.process(
row[c.key].self_group(), **kw))
if c.key in row else param
)
for (c, param) in values_0
]
for i, row in enumerate(stmt.parameters[1:])
)
Note how the tricky innermost code only calls _create_bind_param() 'if c.key in row'. In the above case, created_at is not in the statement parameters. The first row is handled separately, and correctly adds a bind parameter for created_at, hence the error message complains about having only 19 bind values.