Summary
Setting a property typed DATETIME to the Cypher datetime() value reports the value in the same statement's RETURN projection, but the value is NOT persisted — a subsequent MATCH returns null for
the property. The same data round-trips correctly when (a) the property is typed STRING instead of DATETIME, or (b) the assignment goes through SQL sysdate() rather than Cypher datetime().
Environment
- ArcadeDB 26.5.1-SNAPSHOT (build
1dc68da159f12ef9c8c436e5b5998a7ab483714b)
- HTTP API
/api/v1/command/<db> with language=cypher
- Reproduced fresh (no MERGE, no UNIQUE index, no transaction wrapper) — pure raw HTTP
Reproduction
Schema:
CREATE VERTEX TYPE Foo;
CREATE PROPERTY Foo.id STRING;
CREATE PROPERTY Foo.t DATETIME;
Failing case A — CREATE with inline datetime()
CREATE (n:Foo {id: "a", t: datetime()}) RETURN n.t AS t
Returns [{"t":null}] — the value is null even in the originating statement's RETURN.
Subsequent MATCH (n:Foo {id:"a"}) RETURN n.t → [{"t":null}].
Failing case B — SET after CREATE
CREATE (n:Foo {id: "b"});
MATCH (n:Foo {id: "b"}) SET n.t = datetime() RETURN n.t AS t;
Returns [{"t":"2026-05-07T12:37:33.058190574Z[GMT]"}] in the same statement.
But: MATCH (n:Foo {id:"b"}) RETURN n.t → [{"t":null}] — not persisted.
Failing case C — SET with explicit ISO string
MATCH (n:Foo {id: "c"}) SET n.t = datetime("2026-01-01T00:00:00") RETURN n.t AS t
Same shape: same-statement RETURN gives 2026-01-01T00:00Z, follow-up MATCH gives null.
Working case D — SQL sysdate()
UPDATE Foo SET t = sysdate() WHERE id = 'd'
Subsequent Cypher MATCH (n:Foo {id:"d"}) RETURN n.t AS t → [{"t":"2026-05-07 12:37:33"}]. Persists correctly.
Working case E — STRING property, same Cypher value
CREATE PROPERTY Foo.s STRING;
MATCH (n:Foo {id: "e"}) SET n.s = datetime() RETURN n.s AS s
Both same-statement RETURN and follow-up MATCH → [{"s":"2026-05-07T12:37:33.209202625Z[GMT]"}]. Persists correctly (because the column is STRING, not DATETIME).
Whole-record dump after all 5 cases
[
{"@rid":"#1:0","@type":"Foo","@cat":"v","t":null,"id":"a"},
{"@rid":"#1:1","@type":"Foo","@cat":"v","id":"b"},
{"@rid":"#1:2","@type":"Foo","@cat":"v","id":"c"},
{"@rid":"#1:3","@type":"Foo","@cat":"v","id":"d","t":"2026-05-07 12:37:33"},
{"@rid":"#1:4","@type":"Foo","@cat":"v","id":"e","s":"2026-05-07T12:37:33.209202625Z[GMT]"}
]
Note that records #1:1 and #1:2 (cases B and C) have no t field at all in the persisted record — the SET silently dropped.
Expected behavior
SET n.t = datetime() on a DATETIME-typed property should persist the current timestamp as a DATETIME value, identical to SQL sysdate().
Impact
This is the only reason a Cypher MERGE … ON CREATE SET t = datetime() ON MATCH SET t = datetime() upsert flow can't be used today — it forces a fallback to SQL UPDATE … UPSERT WHERE via the HTTP API.
Also affects any pure-Cypher write path that tracks timestamps on typed columns.
Possibly related to #4089 (no-throw fix landed in 26.5.1, the persistence side appears separate).
Summary
Setting a property typed
DATETIMEto the Cypherdatetime()value reports the value in the same statement'sRETURNprojection, but the value is NOT persisted — a subsequentMATCHreturnsnullforthe property. The same data round-trips correctly when (a) the property is typed
STRINGinstead ofDATETIME, or (b) the assignment goes through SQLsysdate()rather than Cypherdatetime().Environment
1dc68da159f12ef9c8c436e5b5998a7ab483714b)/api/v1/command/<db>withlanguage=cypherReproduction
Schema:
Failing case A —
CREATEwith inlinedatetime()Returns
[{"t":null}]— the value is null even in the originating statement's RETURN.Subsequent
MATCH (n:Foo {id:"a"}) RETURN n.t→[{"t":null}].Failing case B —
SETafterCREATEReturns
[{"t":"2026-05-07T12:37:33.058190574Z[GMT]"}]in the same statement.But:
MATCH (n:Foo {id:"b"}) RETURN n.t→[{"t":null}]— not persisted.Failing case C —
SETwith explicit ISO stringSame shape: same-statement RETURN gives
2026-01-01T00:00Z, follow-up MATCH givesnull.Working case D — SQL
sysdate()Subsequent Cypher
MATCH (n:Foo {id:"d"}) RETURN n.t AS t→[{"t":"2026-05-07 12:37:33"}]. Persists correctly.Working case E — STRING property, same Cypher value
Both same-statement RETURN and follow-up MATCH →
[{"s":"2026-05-07T12:37:33.209202625Z[GMT]"}]. Persists correctly (because the column is STRING, not DATETIME).Whole-record dump after all 5 cases
[ {"@rid":"#1:0","@type":"Foo","@cat":"v","t":null,"id":"a"}, {"@rid":"#1:1","@type":"Foo","@cat":"v","id":"b"}, {"@rid":"#1:2","@type":"Foo","@cat":"v","id":"c"}, {"@rid":"#1:3","@type":"Foo","@cat":"v","id":"d","t":"2026-05-07 12:37:33"}, {"@rid":"#1:4","@type":"Foo","@cat":"v","id":"e","s":"2026-05-07T12:37:33.209202625Z[GMT]"} ]Note that records
#1:1and#1:2(cases B and C) have notfield at all in the persisted record — the SET silently dropped.Expected behavior
SET n.t = datetime()on a DATETIME-typed property should persist the current timestamp as a DATETIME value, identical to SQLsysdate().Impact
This is the only reason a Cypher
MERGE … ON CREATE SET t = datetime() ON MATCH SET t = datetime()upsert flow can't be used today — it forces a fallback to SQLUPDATE … UPSERT WHEREvia the HTTP API.Also affects any pure-Cypher write path that tracks timestamps on typed columns.
Possibly related to #4089 (no-throw fix landed in 26.5.1, the persistence side appears separate).