ArcadeData / arcadedb

ArcadeDB Multi-Model Database, one DBMS that supports SQL, Cypher, Gremlin, HTTP/JSON, MongoDB and Redis. ArcadeDB is a conceptual fork of OrientDB, the first Multi-Model DBMS. ArcadeDB supports Vector Embeddings.
https://arcadedb.com
Apache License 2.0
486 stars 60 forks source link

Accessing a result set has unexpected side effects #1652

Closed finduspedersen closed 2 months ago

finduspedersen commented 2 months ago

ArcadeDB Version:

24.5.1

OS and JDK Version:

Official Docker image

Expected behavior

Accessing a variable with a result set should be idempotent.

Actual behavior

The result set is modified as a side effect of accessing the variable.

This is the output:

2024-07-11 00:42:43 2024-07-10 22:42:43.520 INFO  [ConsoleStatement] <ArcadeDB_0> {SIZE=1}
2024-07-11 00:42:43 2024-07-10 22:42:43.521 INFO  [ConsoleStatement] <ArcadeDB_0> {OK=[{"@cat":"v","@type":"Dummy","@rid":"#450:5"}]}
2024-07-11 00:42:43 2024-07-10 22:42:43.521 INFO  [ConsoleStatement] <ArcadeDB_0> {FAILS=[]}
2024-07-11 00:42:43 2024-07-10 22:42:43.521 INFO  [ConsoleStatement] <ArcadeDB_0> {SIZE=1}

Steps to reproduce

LET $schemaTypes = SELECT FROM schema:types WHERE name='Dummy';

IF ($schemaTypes.size() != 1) {
  CREATE VERTEX TYPE Dummy;
}

LET $vertices = CREATE VERTEX Dummy;

CONSOLE.log map('SIZE', $vertices.size());
CONSOLE.log map('OK', $vertices.asJSON());

CONSOLE.log map('FAILS', $vertices.asJSON());
CONSOLE.log map('SIZE', $vertices.size());

CONSOLE.log map('DEBUG', 'END');
gramian commented 2 months ago

Hi,

this is odd. Here is a simpler test case:

CREATE VERTEX TYPE Dummy IF NOT EXISTS;

LET $vertices = CREATE VERTEX Dummy;

SELECT $vertices.asJSON() AS a, $vertices.asJSON() AS b;
finduspedersen commented 2 months ago

Yes, this fails as well.

BTW: "IF NOT EXISTS" is not documented in the manual for CREATE VERTEX :-)

gramian commented 2 months ago

Note CREATE VERTEX TYPE and CREATE VERTEX are very different animals. The former is a DDL statement defining a type, the latter is a DML statement instantiating a type. IF NOT EXISTS is documented under CREATE TYPE, see https://docs.arcadedb.com/#SQL-Create-Type .

finduspedersen commented 2 months ago

Adding a .asList() seems to circumvent the bug:

CREATE VERTEX TYPE Dummy IF NOT EXISTS;

LET $vertices = CREATE VERTEX Dummy;
LET $vertices = $vertices.asList();

SELECT $vertices.asJSON() AS a, $vertices.asJSON() AS b;
lvca commented 2 months ago

This is because the resultset is read and exhausted once you execute asJSON(). It's like in Java when you have an iterator and you browse the iterator to print the result. In the end that iterator is not usable. Some of ArcadeDB resultset have the .reset() method to reuse it, but I'd stick with using asList() as the best way to have something you can use multiple times.

finduspedersen commented 2 months ago

Makes sense. Thank you for the explanation 😊

lvca commented 2 months ago

Improved the documentation detailing this behavior when asJSON() is applied to result sets.