From f921b18eed8c4fe641ffb074308d96e1c22c61f1 Mon Sep 17 00:00:00 2001 From: Taewoon Kim Date: Mon, 2 Nov 2026 06:15:48 +0900 Subject: [PATCH] docs: a map placeholder with no key is refused from engine 26.11.1 (#188) ArcadeData/arcadedb#11111 (in 26.11.1) fixed #11098: a ? or :name with no key in the parameter map now raises CommandParameterMissingException instead of binding null. The query docs and the test docstring said the engine always binds null; they now say which engines do what. The bindings' TypeError for a lone dict against a ? runs first, so the test itself is unchanged. Co-Authored-By: Claude Opus 5.5 --- docs/modules/ROOT/pages/how-to/databases-and-queries.adoc | 2 +- tests/test_dict_with_positional.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/modules/ROOT/pages/how-to/databases-and-queries.adoc b/docs/modules/ROOT/pages/how-to/databases-and-queries.adoc index 68610d5..543d1c0 100644 --- a/docs/modules/ROOT/pages/how-to/databases-and-queries.adoc +++ b/docs/modules/ROOT/pages/how-to/databases-and-queries.adoc @@ -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. diff --git a/tests/test_dict_with_positional.py b/tests/test_dict_with_positional.py index 6d3008d..3e46cc3 100644 --- a/tests/test_dict_with_positional.py +++ b/tests/test_dict_with_positional.py @@ -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. """