diff --git a/core-concepts/modules/ROOT/examples/driver/python_driver_setup.py b/core-concepts/modules/ROOT/examples/driver/python_driver_setup.py index ee30529c0..f061de4ee 100644 --- a/core-concepts/modules/ROOT/examples/driver/python_driver_setup.py +++ b/core-concepts/modules/ROOT/examples/driver/python_driver_setup.py @@ -14,7 +14,7 @@ credentials = Credentials("admin", "password") #end::constants_credentials[] #tag::constants_options[] -options = DriverOptions(is_tls_enabled=True, tls_root_ca_path=None) +options = DriverOptions(is_tls_enabled=False, tls_root_ca_path=None) #end::constants_options[] #end::constants[] #end::import_and_constants[] diff --git a/core-concepts/modules/ROOT/examples/driver/python_driver_usage.py b/core-concepts/modules/ROOT/examples/driver/python_driver_usage.py index 7cde66bb2..462326a45 100644 --- a/core-concepts/modules/ROOT/examples/driver/python_driver_usage.py +++ b/core-concepts/modules/ROOT/examples/driver/python_driver_usage.py @@ -6,7 +6,7 @@ DB_NAME = "my_database" address = "localhost:1729" credentials = Credentials("admin", "password") -options = DriverOptions(is_tls_enabled=True, tls_root_ca_path=None) +options = DriverOptions(is_tls_enabled=False, tls_root_ca_path=None) #end::import_and_constants[] #tag::driver_create[] diff --git a/core-concepts/modules/ROOT/pages/typedb/crud.adoc b/core-concepts/modules/ROOT/pages/typedb/crud.adoc index 5bb3f354c..6911276bf 100644 --- a/core-concepts/modules/ROOT/pages/typedb/crud.adoc +++ b/core-concepts/modules/ROOT/pages/typedb/crud.adoc @@ -176,7 +176,7 @@ This allows structuring the output of the query to map precisely to the structur [,typeql] ---- -#!test[read, documents] +#!test[read] match $p isa person; fetch { diff --git a/core-concepts/modules/ROOT/pages/typeql/query-clauses.adoc b/core-concepts/modules/ROOT/pages/typeql/query-clauses.adoc index 05e613ac3..0babc802b 100644 --- a/core-concepts/modules/ROOT/pages/typeql/query-clauses.adoc +++ b/core-concepts/modules/ROOT/pages/typeql/query-clauses.adoc @@ -150,7 +150,7 @@ Removes duplicate answers in the stream. [,typeql] ---- -#!test[read, count=3] +#!test[read, count=4] match { $p isa person; } or { $p has name "John"; }; distinct; # Make sure that the person with name John is returned at most once. diff --git a/core-concepts/modules/ROOT/pages/typeql/sql-vs-typeql.adoc b/core-concepts/modules/ROOT/pages/typeql/sql-vs-typeql.adoc new file mode 100644 index 000000000..bf5c5c98c --- /dev/null +++ b/core-concepts/modules/ROOT/pages/typeql/sql-vs-typeql.adoc @@ -0,0 +1,760 @@ += Understanding SQL vs. TypeQL +:test-typeql: linear + +This guide helps SQL users understand TypeQL by mapping familiar SQL constructs to their TypeQL equivalents. + +[NOTE] +==== +TypeQL operates on a data model using entity, relation, and attribute types (and their instances), instead of tables and rows. +This difference means that some SQL concepts map directly, while others require a different approach. +==== + +== Schema setup + +For the examples here, we can use a simple TypeQL schema: + +[,typeql] +---- +#!test[schema] +define + attribute name, value string; + attribute email, value string; + attribute age, value integer; + relation employment, relates employee, relates employer; + entity person, owns name, owns email, owns age, plays employment:employee; + entity company, owns name, plays employment:employer; +---- + +With the following data: +[,typeql] +---- +#!test[write, commit] +insert + $alice isa person, has name "Alice", has email "alice@example.com", has age 30; + $bob isa person, has name "Bob", has email "bob@example.com", has age 25; + $charlie isa person, has name "Charlie", has email "charlie@example.com", has age 35; + $acme isa company, has name "Acme Corp"; + $e1 isa employment, links (employee: $alice, employer: $acme); +---- + +==== + +== Data retrieval + +=== SELECT → match + fetch/select + +In SQL, `SELECT` retrieves data from tables. In TypeQL, `match` finds data by pattern, and `fetch` or `select` projects the results. + +**SQL:** +[sql] +---- +SELECT name, email FROM person; +---- + +**TypeQL:** + +In TypeQL, use `select` to filter out unwanted data. This is a filtering operation, and does not set ordering of result variables. + +[,typeql] +---- +#!test[read, count=3] +match + $p isa person, has name $name, has email $email; +select $name, $email; # eliminates $p +---- + +If you want your data to be returned in JSON, you can format it through a `fetch` clause, which also works as a projection: + +[,typeql] +---- +#!test[read, count=3] +match + $p isa person, has name $name; +fetch { + "name": $name, + "email": $p.email # projection in the fetch clause +}; +---- + +=== WHERE → match + +SQL's `WHERE` clause filters rows. In TypeQL, constraints are part of the `match` pattern. + +**SQL:** +[sql] +---- +SELECT name FROM person WHERE age > 25; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=2] +match + $p isa person, has name $name, has age $age; + $age > 25; +select $name; +---- + +Shorthand: +[,typeql] +---- +#!test[read, count=2] +match + $p isa person, has name $name, has age > 25; +select $name; +---- + + +==== AND/OR conditions in WHERE clauses + +SQL uses `AND` (conjunction) and `OR` (disjunction) in `WHERE` clauses. + +In TypeQL, statements and composite patterns are combined an implicit `and` by default: `;` and `,` both are implicit conjunctions. An `or` pattern is used to explicitly represent a disjunction. + +**SQL with AND:** +[sql] +---- +SELECT name FROM person WHERE age > 25 AND email LIKE '%@example.com'; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=2] +match + $p isa person, has name $name, has age $age, has email $email; + $age > 25; + $email like ".*@example.com"; +select $name; +---- + +**SQL with OR:** +[sql] +---- +SELECT name FROM person WHERE age < 20 OR age > 30; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=1] +match + $p isa person, has name $name, has age $age; + { $age < 20; } or { $age > 30; }; +select $name; +---- + +=== JOIN → relation patterns + +SQL uses `JOIN` to combine data from multiple tables. In TypeQL, relations naturally connect entities through patterns. +The type of JOIN determines which entities are included in the results when relationships don't exist. + +==== INNER JOIN (or JOIN) + +An INNER JOIN returns only rows where there is a match in both tables. In TypeQL, this is the default behavior when matching relations. + +**SQL:** +[sql] +---- +SELECT p.name, e.id +FROM person p +INNER JOIN employment e ON p.id = e.employee_id; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=1] +match + $p isa person, has name $pname; + $e isa employment, links (employee: $p); +select $pname, $e; +---- + +This returns only persons who have an employment relation attached. + +==== LEFT JOIN + +A LEFT JOIN returns all rows from the left table (person), and matching rows from the right table (employment). +If there's no match, NULL values are returned for the right table columns. In TypeQL, use the `try` construct for optional matching. + +**SQL:** +[sql] +---- +SELECT p.name, e.id +FROM person p +LEFT JOIN employment e ON p.id = e.employee_id; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=3] +match + $p isa person, has name $pname; + try { + $e isa employment, links (employee: $p); + }; +select $pname, $e; +---- + +This returns all persons, with their employment if they have one. +Persons without employment will still appear in the results (with `$e` unbound). + +==== RIGHT JOIN + +A RIGHT JOIN returns all rows from the right table (employment), and matching rows from the left table (person). +If there's no match, NULL values are returned for the left table columns. In TypeQL, reverse the pattern to start from the right side. + +**SQL:** +[sql] +---- +SELECT p.name, e.id +FROM person p +RIGHT JOIN employment e ON p.id = e.employee_id; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=1] +match + $e isa employment; + try { + $p isa person, has name $pname; + $e links (employee: $p); + }; +select $pname; +---- + +This returns employments' employee names if they exist. +Employments without matching persons will still appear in the results (with `$pname` unbound, set to `None`). + +==== CROSS JOIN + +A CROSS JOIN returns the Cartesian product of two tables - every row from the first table combined with every row from the second table. +In TypeQL, match entities from both types independently without requiring any relation between them. + +**SQL:** +[sql] +---- +SELECT p.name, e.id +FROM person p +CROSS JOIN employment e; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=3] +match + $p isa person, has name $pname; + $e isa employment; +select $pname, $e; +---- + +This returns every combination of person and employment, regardless of whether they have any relationship. The result set size is the product of the number of persons and employments. + +==== FULL OUTER JOIN + +A FULL OUTER JOIN returns all rows from both tables, with NULL values where there's no match. + +Full outer joins do not translate well to TypeQL. If your application requires an equivalent of a full outer join, please contact us! + +== Data modification + +=== INSERT → insert + +**SQL:** +[sql] +---- +INSERT INTO person (name, email, age) VALUES ('David', 'david@example.com', 28); +---- + +**TypeQL:** +[,typeql] +---- +#!test[write, commit, count=1] +insert + $p isa person, has name "David", has email "david@example.com", has age 28; +---- + +**SQL INSERT with SELECT:** +[sql] +---- +INSERT INTO employment (employee_id, employer_id) +SELECT p.id, c.id +FROM person p, company c +WHERE p.name = 'Alice' AND c.name = 'Acme Corp'; +---- + +**TypeQL:** +[,typeql] +---- +#!test[write, commit, count=1] +match + $p isa person, has name "Alice"; + $c isa company, has name "Acme Corp"; +insert + $e isa employment, links (employee: $p, employer: $c); +---- + +=== UPDATE → update + +**SQL:** +[sql] +---- +UPDATE person SET email = 'newemail@example.com' WHERE name = 'Alice'; +---- + +**TypeQL:** +[,typeql] +---- +#!test[write, count=1] +match + $p isa person, has name "Alice"; +update $p has email "newemail@example.com"; +---- + +[NOTE] +==== +The `update` clause in TypeQL works only for attributes with cardinality `@card(0..1)` or `@card(1)`. +It automatically deletes the old value and inserts the new one. +==== + +=== DELETE → delete + +**SQL:** +[sql] +---- +DELETE FROM person WHERE name = 'Charlie'; +---- + +**TypeQL:** +[,typeql] +---- +#!test[write, rollback, count=1] +match + $p isa person, has name "Charlie"; +delete $p; +---- + +**SQL DELETE with JOIN:** +[sql] +---- +DELETE e FROM employment e +INNER JOIN person p ON e.employee_id = p.id +WHERE p.name = 'Alice'; +---- + +**TypeQL:** +[,typeql] +---- +#!test[write, rollback, count=2] +match + $p isa person, has name "Alice"; + $e isa employment, links (employee: $p); +delete $e; +---- + +== Aggregation and grouping + +=== GROUP BY → reduce with groupby + +**SQL:** +[sql] +---- +SELECT age, COUNT(*) as count +FROM person +GROUP BY age; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=4] +match + $p isa person, has age $age; +reduce $count = count groupby $age; +---- + +=== Aggregate Functions + +**SQL:** +[sql] +---- +SELECT + COUNT(*) as total, + AVG(age) as avg_age, + MAX(age) as max_age, + MIN(age) as min_age, + SUM(age) as sum_age +FROM person; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=1] +match + $p isa person, has age $age; +reduce + $total = count, + $avg_age = mean($age), + $max_age = max($age), + $min_age = min($age), + $sum_age = sum($age); +---- + +=== HAVING → reduce + match + +**SQL:** +[sql] +---- +SELECT age, COUNT(*) as count +FROM person +GROUP BY age +HAVING COUNT(*) > 1; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=0] +match + $p isa person, has age $age; +reduce $count = count groupby $age; +match $count > 1; +---- + +== Sorting and pagination + +=== ORDER BY → sort + +**SQL:** +[sql] +---- +SELECT name, age FROM person ORDER BY age DESC, name ASC; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=4] +match + $p isa person, has name $name, has age $age; +sort $age desc, $name asc; +select $name, $age; +---- + +=== LIMIT and OFFSET + +**SQL:** +[sql] +---- +SELECT name FROM person ORDER BY name LIMIT 10 OFFSET 20; +---- + +**TypeQL:** + +In TypeQL, we call stages like `limit`/`offset` (also, `select`, `sort`) _stream operators_, since they only manipulate the answer stream and don't access the database. Order of stages matter! + +[,typeql] +---- +#!test[read, count=0] +match + $p isa person, has name $name; +sort $name; +offset 20; +limit 10; +select $name; +---- + +Here we take the `match` answers, `sort` them, skip the first 20 with `offset`, the take the first `10`. + +If we did `limit`, then `order`, we would `limit` the sorted answers to the first then, and then try to skip the first 20 with `offset` - resulting in 0 answers every time! + +== Advanced operations + +=== DISTINCT → distinct + +**SQL:** +[sql] +---- +SELECT DISTINCT age FROM person; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=4] +match + $p isa person, has age $age; +select $age; +distinct; +---- + +=== Subqueries → functions + +**SQL:** +[sql] +---- +SELECT name FROM person +WHERE age > (SELECT AVG(age) FROM person); +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=2] +with fun avg_age() -> double: + match $p isa person, has age $age; + return mean($age); +match + $p isa person, has name $name, has age $age; + let $avg = avg_age(); + $age > $avg; +select $avg, $name, $age; +---- + +=== UNION → or patterns + +**SQL:** +[sql] +---- +SELECT name FROM person WHERE age < 25 +UNION +SELECT name FROM person WHERE age >= 35; +---- + +**TypeQL:** + +In TypeQL, you have multiple ways to execute this union using `or`: + +[,typeql] +---- +#!test[read, count=1] +match + $p isa person, has name $name, has age $age; + { $age < 25; } or { $age >= 35; }; +select $name; +---- + +[,typeql] +---- +#!test[read, count=1] +match + { + $p isa person, has name $name, has age < 25; + } or { + $p isa person, has name $name, has age >= 35; + }; +select $name; +---- + +Both are valid! + +=== EXISTS → not { not { ... } } + +**SQL:** +[sql] +---- +SELECT name FROM person p +WHERE EXISTS ( + SELECT 1 FROM employment e + WHERE e.employee_id = p.id OR e.employer_id = p.id +); +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=1] +match + $p isa person, has name $name; + not { not { $e isa employment, links (employee: $p); }; }; +select $name; +---- + +This reads as: we're looking for a person such that it's not true that: there is not an employment involving that person. + +_This will be improved in future versions of TypeQL!_ + +=== IN → multiple value constraints + +**SQL:** +[sql] +---- +SELECT name FROM person WHERE age IN (25, 30, 35); +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=3] +match + $p isa person, has name $name, has age $age; + { $age == 25; } or { $age == 30; } or { $age == 35; }; +select $name; +---- + +TypeQL's roadmap features lists, which would allow writing the following: +[,typeql] +---- +# NOTE: roadmap feature! +match + $p isa person, has name $name, has age $age; + $age in [25, 30, 35]; +select $name; +---- + +=== LIKE → like (regex) + +**SQL:** +[sql] +---- +SELECT name FROM person WHERE email LIKE '%@example.com'; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=4] +match + $p isa person, has name $name, has email $email; + $email like ".*@example.com"; +select $name; +---- + +=== NULL checks → not { ... } + +**SQL:** +[sql] +---- +SELECT name FROM person WHERE email IS NULL; +---- + +**TypeQL:** + +TypeQL doesn't store NULLs. A value is either existing or absent in the database: + +[,typeql] +---- +#!test[read, count=0] +match + $p isa person, has name $name; + not { $p has email $_; }; +select $name; +---- + +**SQL:** +[sql] +---- +SELECT name FROM person WHERE email IS NOT NULL; +---- + +**TypeQL:** +[,typeql] +---- +#!test[read, count=4] +match + $p isa person, has name $name, has email $_; +select $name; +---- + +Note that for optional matches like when using LEFT/RIGHT joins, TypeQL's `try` construct can create `None` values. Unlike `null`s in SQL, a `None` is not a value that can be stored. It's also only possible to generated for optional variables (ie. ones generated in `try` patterns.) + +Fundamentally, in SQL a `null` is an extra value that any column could contain. In TypeQL, a `None` is a marker given to a variable when it is unset, but it is never used _as_ a value in the data. In other words, any typical value in SQL has the range of possible values of: ` + null`. In TypeQL, variables that are optional can hold `Either` instead of the typical `Value`. + +== Key differences and concepts + +=== No explicit FROM clause + +In TypeQL, there's no `FROM` clause. The `match` pattern implicitly defines what data to search through by specifying types and their relationships. + +=== Pattern-based matching + +TypeQL uses pattern matching rather than table joins. Relations are first-class citizens that naturally connect entities, making complex queries more intuitive. + +=== Strong typing + +TypeQL is strongly typed. Variables are bound to specific types (entities, relations, attributes), and the query engine enforces type safety. Optional variables are known at query compilation time and validated throughout. + +=== Pipeline model + +TypeQL queries are pipelines where each clause processes a stream of answers. This allows for powerful composition: + +[,typeql] +---- +#!test[read, count=1] +match + $p isa person, has name $name, has age $age; +reduce $avg_age = mean($age); +match $avg_age > 29; +---- + +=== Relations vs foreign keys + +In SQL, relationships are represented through foreign keys. In TypeQL, relationships are explicit relations that can have their own attributes and connect multiple entities. + +**SQL (with foreign keys):** +[sql] +---- +CREATE TABLE employment ( + id INT PRIMARY KEY, + employee_id INT REFERENCES person(id), + employer_id INT REFERENCES company(id), + start_date DATE +); +---- + +**TypeQL:** +[,typeql] +---- +define + relation employment, relates employee, relates employer, owns start-date; + attribute start-date, value datetime; + person plays employment:employee; + company plays employment:employer; +---- + +== Summary table + +[cols="^1,^1,^1", options="header"] +|=== +| SQL Construct | TypeQL Equivalent | Notes + +| `SELECT` | `match` + `fetch`/`select` | Pattern matching replaces table selection +| `FROM` | Implicit in `match` patterns | Types are specified in the pattern +| `WHERE` | Constraints in `match` | Filtering is part of the pattern +| `JOIN` | Relation patterns | Relations naturally connect entities +| `INNER JOIN` | Required relation patterns | Both sides must exist +| `LEFT JOIN` | Optional patterns with `try` | Use `try` for optional matches +| `RIGHT JOIN` | Optional patterns with `try` | Reverse pattern direction +| `CROSS JOIN` | Disconnected match statements | +| `INSERT` | `insert` | Similar syntax, pattern-based +| `UPDATE` | `update` | Only for single-value attributes +| `DELETE` | `delete` | Pattern-based deletion +| `GROUP BY` | `reduce ... groupby` | Aggregation with grouping +| `HAVING` | `reduce` + `match` | Filter aggregated results +| `ORDER BY` | `sort` | Similar functionality +| `LIMIT` | `limit` | Identical +| `OFFSET` | `offset` | Identical +| `DISTINCT` | `distinct` | Identical +| `COUNT`/`SUM`/`AVG`/`etc. | `reduce` with `count`/`sum`/`mean`/etc. | Similar, assigned to a variable| +| `UNION` | `or` patterns | Pattern disjunction +| `EXISTS` | `not { not { ... } }` | Double negation pattern +| `IN` | `or` with multiple `==` | Pattern disjunction +| `LIKE` | `like` with regex | Uses regex syntax +| `IS NULL` | `not { ... has ... }` | Negation pattern +| `IS NOT NULL` | Implicit in pattern | If matched, it exists +|=== + +== References + +* xref:{page-version}@core-concepts::typeql/query-clauses.adoc[Query Clauses & Pipelining] +* xref:{page-version}@core-concepts::typeql/query-variables-patterns.adoc[Query Variables and Patterns] +* xref:{page-version}@typeql-reference::pipelines/index.adoc[TypeQL Pipeline Reference] +* xref:{page-version}@typeql-reference::patterns/index.adoc[TypeQL Pattern Reference] + diff --git a/core-concepts/modules/ROOT/partials/nav.adoc b/core-concepts/modules/ROOT/partials/nav.adoc index b020c2791..a0374cb3b 100644 --- a/core-concepts/modules/ROOT/partials/nav.adoc +++ b/core-concepts/modules/ROOT/partials/nav.adoc @@ -23,6 +23,8 @@ ** xref:{page-version}@core-concepts::typeql/invalid-patterns.adoc[] // ** xref:{page-version}@core-concepts::typeql/best-practices.adoc[] ** xref:{page-version}@core-concepts::typeql/glossary.adoc[] +** xref:{page-version}@core-concepts::typeql/sql-vs-typeql.adoc[] + * xref:{page-version}@core-concepts::drivers/index.adoc[] ** xref:{page-version}@core-concepts::drivers/overview.adoc[] diff --git a/dependencies/typedb/artifacts.bzl b/dependencies/typedb/artifacts.bzl index 4ad09d0a8..faf62efe6 100644 --- a/dependencies/typedb/artifacts.bzl +++ b/dependencies/typedb/artifacts.bzl @@ -25,5 +25,5 @@ def typedb_artifact(): artifact_name = "typedb-all-{platform}-{version}.{ext}", tag_source = deployment["artifact"]["release"]["download"], commit_source = deployment["artifact"]["snapshot"]["download"], - tag = "3.4.4" + commit = "828fecc98675712b15e4f6a9b0b2e7ae54d19766" ) diff --git a/home/modules/ROOT/pages/get-started/query-composition.adoc b/home/modules/ROOT/pages/get-started/query-composition.adoc index c1f011c38..f9d17584a 100644 --- a/home/modules/ROOT/pages/get-started/query-composition.adoc +++ b/home/modules/ROOT/pages/get-started/query-composition.adoc @@ -720,7 +720,7 @@ fetch { //// [,typeql] ---- -#!test[read, documents] +#!test[read] include::./query-composition.adoc[tag=fetch1] ---- diff --git a/test/runners/typeql_runner.py b/test/runners/typeql_runner.py index 0118d310d..9b372a085 100644 --- a/test/runners/typeql_runner.py +++ b/test/runners/typeql_runner.py @@ -24,7 +24,6 @@ TEST_TXN_READ_KEY = "read" TEST_ROLLBACK_KEY = "rollback" TEST_COUNT_KEY = "count" -TEST_DOCUMENTS_KEY = "documents" TEST_JUMP_KEY = "jump" TEST_FAIL_KEY = "fail_at" TEST_FAIL_COMMIT_VAL = "commit" @@ -93,39 +92,28 @@ def run_failing_queries(self, queries: List[str], type: TransactionType) -> str: return FailureMode.Commit return FailureMode.NoFailure - def run_transaction(self, queries: List[str], type: TransactionType, counted=False, rollback=False, documents=False) -> Union[int, None]: - count_var_name = "automatic_test_count" - if counted: - queries[-1] = queries[-1] + f"\nreduce ${count_var_name} = count;" + def run_transaction(self, queries: List[str], type: TransactionType, rollback=False) -> Union[int, None]: with self.driver.transaction(self.db, type) as tx: try: - promises = [] - results = [] for q in queries: - promises.append(tx.query(q)) - for p in promises: - results.append(p.resolve()) + results = tx.query(q).resolve() + if results.is_ok(): + results = [] + elif results.is_concept_rows(): + results = list(results.as_concept_rows()) + elif results.is_concept_documents(): + results = list(results.as_concept_documents()) + else: + print(f"Unknown result type: {results}") if rollback: tx.rollback() tx.close() elif type == TransactionType.READ: - for r in results: - if documents: - consumed_iterator = list(r.as_concept_documents()) - else: - consumed_iterator = list(r.as_concept_rows()) tx.close() else: tx.commit() - if counted: - if documents: - raise Exception("Counting currently relies on Reduce, which is not compatible with Documents") - if type == TransactionType.READ: - count = consumed_iterator[0].get(count_var_name).get_integer() - else: - last_result = list(results[-1].as_concept_rows()) - count = last_result[0].get(count_var_name).get_integer() - return count + # the count only returned for the count of the last query + return len(results) except Exception as e: raise Exception(f"{e}") from e @@ -162,10 +150,6 @@ def run_test(self, parsed_test: ParsedTest, adoc_path: str): reference_count = int(parsed_test.config[TEST_COUNT_KEY]) counted = True - documents = False - if parsed_test.config.get(TEST_DOCUMENTS_KEY) is not None: - documents = True - if parsed_test.config.get(TEST_FAIL_KEY): ref_failure_mode = FailureMode.NoFailure match parsed_test.config[TEST_FAIL_KEY]: @@ -177,11 +161,11 @@ def run_test(self, parsed_test: ParsedTest, adoc_path: str): if failure_mode != ref_failure_mode: raise RuntimeError(f"[{adoc_path}]: Failure mode: expected {ref_failure_mode} but got {failure_mode}") elif counted == True: - count = self.run_transaction(parsed_test.segments, type, counted, rollback, documents) + count = self.run_transaction(parsed_test.segments, type, rollback) if count != reference_count: raise RuntimeError(f"[{adoc_path}]: Query count: expected {reference_count} but got {count}") else: - self.run_transaction(parsed_test.segments, type, counted, rollback, documents) + self.run_transaction(parsed_test.segments, type, rollback) self.after_run_test(parsed_test) diff --git a/typeql-reference/modules/ROOT/pages/pipelines/fetch.adoc b/typeql-reference/modules/ROOT/pages/pipelines/fetch.adoc index d22f71a06..dc26314b1 100644 --- a/typeql-reference/modules/ROOT/pages/pipelines/fetch.adoc +++ b/typeql-reference/modules/ROOT/pages/pipelines/fetch.adoc @@ -216,7 +216,7 @@ include::{page-version}@reference::example$tql/schema_statements_functions.tql[t [,typeql] ---- -#!test[read, documents] +#!test[read] match $group isa group; fetch { diff --git a/typeql-reference/modules/ROOT/pages/pipelines/insert.adoc b/typeql-reference/modules/ROOT/pages/pipelines/insert.adoc index 244e4cf09..3aac116d0 100644 --- a/typeql-reference/modules/ROOT/pages/pipelines/insert.adoc +++ b/typeql-reference/modules/ROOT/pages/pipelines/insert.adoc @@ -61,7 +61,7 @@ include::{page-version}@reference::example$tql/schema_statements_functions.tql[t [,typeql] ---- -#!test[write, documents] +#!test[write] insert $group isa group, has group-id ""; diff --git a/typeql-reference/modules/ROOT/pages/statements/relates.adoc b/typeql-reference/modules/ROOT/pages/statements/relates.adoc index 36ab78bb4..a5ef0ae26 100644 --- a/typeql-reference/modules/ROOT/pages/statements/relates.adoc +++ b/typeql-reference/modules/ROOT/pages/statements/relates.adoc @@ -100,6 +100,5 @@ The previous query can return results for different role types with the same `