Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/modules/ROOT/pages/how-to/databases-and-queries.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ db.query("sql", "SELECT FROM V WHERE @rid IN :ids", {"ids": [rid_a, rid_b]})
db.query("sql", "SELECT FROM V WHERE @rid IN ?", [[rid_a, rid_b]])
----

A dict on its own (also `[d]` and `(d,)`) is the named map, so it cannot fill a `?`. The engine binds a `?` that has no key in the map to null and does not fail: `db.command("sql", "INSERT INTO T SET v = ?", {"a": 1})` would store a record with no `v`. The bindings raise `TypeError` before the statement runs when a SQL or SQLScript call passes a lone dict and the statement has a `?` and no `:name` or `$name` outside string literals. To fix the call, pass a list for a `?` (`[value]`), or write `:name` in the statement and pass `{"name": value}`. A dict that you mean as one value goes in a list together with another positional value, or is bound by name. A dict with a digit-string key (`{"0": value}`) binds positional slot 0 by key, as the engine does, and is not refused.
A dict on its own (also `[d]` and `(d,)`) is the named map, so it cannot fill a `?`. Engines before 26.11.1 bind a `?` (or a `:name`) that has no key in the map to null and do not fail: `db.command("sql", "INSERT INTO T SET v = ?", {"a": 1})` would store a record with no `v`. From 26.11.1 the engine refuses such a call and names the missing parameter (ArcadeData/arcadedb#11098: an `ArcadeDBError` caused by the engine's `CommandParameterMissingException`); a key whose value is `None` still binds null. The bindings raise `TypeError` before the statement runs when a SQL or SQLScript call passes a lone dict and the statement has a `?` and no `:name` or `$name` outside string literals. To fix the call, pass a list for a `?` (`[value]`), or write `:name` in the statement and pass `{"name": value}`. A dict that you mean as one value goes in a list together with another positional value, or is bound by name. A dict with a digit-string key (`{"0": value}`) binds positional slot 0 by key, as the engine does, and is not refused.

The exact-count rule below is about positional values (a list, a tuple or separate arguments); it does not cover a dict.

Expand Down
4 changes: 2 additions & 2 deletions tests/test_dict_with_positional.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""A lone dict is the named-parameter map, so a statement with only ``?`` placeholders is refused, not bound to null.

``command("sql", "INSERT INTO T SET v = ?", {"a": 1})`` (and ``[{"a": 1}]``, ``({"a": 1},)``) hands the engine a named map. The
engine binds a positional ``?`` that has no key in the map to null and nothing fails (ArcadeData/arcadedb#11098), so the record is
stored without the value. The bindings refuse that call with a TypeError on both builds before it runs. A dict that has a
engine binds a positional ``?`` that has no key in the map to null and nothing fails before 26.11.1 (ArcadeData/arcadedb#11098, fixed in
26.11.1, where the engine refuses it), so the record is stored without the value. The bindings refuse that call with a TypeError on both builds before it runs. A dict that has a
``:name`` placeholder to bind, or a digit-string key (``{"0": v}`` binds positional slot 0 by key), keeps working.
"""

Expand Down
Loading