Skip to content

Opencypher tck#3368

Merged
lvca merged 19 commits intomainfrom
opencypher-tck
Feb 7, 2026
Merged

Opencypher tck#3368
lvca merged 19 commits intomainfrom
opencypher-tck

Conversation

@lvca
Copy link
Contributor

@lvca lvca commented Feb 7, 2026

I think I'm done for today with OpenCypher TCK...

lvca added 18 commits February 6, 2026 10:24
Reached much better compliance with the latest changes:

```
=======================================================
         OpenCypher TCK Compliance Report
=======================================================
Total scenarios:  3897
Passed:           1908 (48%)
Failed:           1939 (49%)
Skipped:          50 (1%)
-------------------------------------------------------
By category:
  clauses/call                               2/ 52 passed (3%)
  clauses/create                            64/ 78 passed (82%)
  clauses/delete                            24/ 41 passed (58%)
  clauses/match                            292/381 passed (76%)
  clauses/match-where                       25/ 34 passed (73%)
  clauses/merge                             47/ 75 passed (62%)
  clauses/remove                            29/ 33 passed (87%)
  clauses/return                            35/ 63 passed (55%)
  clauses/return-orderby                    23/ 35 passed (65%)
  clauses/return-skip-limit                 26/ 31 passed (83%)
  clauses/set                               30/ 53 passed (56%)
  clauses/union                              8/ 12 passed (66%)
  clauses/unwind                            10/ 14 passed (71%)
  clauses/with                              14/ 29 passed (48%)
  clauses/with-orderBy                     124/292 passed (42%)
  clauses/with-skip-limit                    7/  9 passed (77%)
  clauses/with-where                        10/ 19 passed (52%)
  expressions/aggregation                   23/ 35 passed (65%)
  expressions/boolean                      150/150 passed (100%)
  expressions/comparison                    36/ 72 passed (50%)
  expressions/conditional                   13/ 13 passed (100%)
  expressions/existentialSubqueries          4/ 10 passed (40%)
  expressions/graph                         32/ 61 passed (52%)
  expressions/list                         120/185 passed (64%)
  expressions/literals                     120/131 passed (91%)
  expressions/map                           28/ 44 passed (63%)
  expressions/mathematical                   3/  6 passed (50%)
  expressions/null                          44/ 44 passed (100%)
  expressions/path                           0/  7 passed (0%)
  expressions/pattern                       19/ 50 passed (38%)
  expressions/precedence                    20/121 passed (16%)
  expressions/quantifier                   478/604 passed (79%)
  expressions/string                        22/ 32 passed (68%)
  expressions/temporal                       0/1004 passed (0%)
  expressions/typeConversion                19/ 47 passed (40%)
  useCases/countingSubgraphMatches           6/ 11 passed (54%)
  useCases/triadicSelection                  1/ 19 passed (5%)
=======================================================
```
@lvca lvca added this to the 26.2.1 milestone Feb 7, 2026
@lvca lvca self-assigned this Feb 7, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @lvca, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly advances the OpenCypher compatibility by implementing several key features and refining existing behaviors to align with the Cypher TCK (Transactional Consistency Kit). The changes span across expression evaluation, temporal type handling, SET clause functionality, and semantic validation, ensuring more accurate and compliant query execution within the ArcadeDB engine.

Highlights

  • Enhanced Cypher SET Clause: The SET clause now fully supports property assignment (SET n.prop = value), map replacement (SET n = {map}), map merging (SET n += {map}), and label assignment (SET n:Label). This includes complex logic for changing vertex types when labels are added or removed.
  • Improved Temporal Type Handling and Arithmetic: Significant improvements have been made to temporal type parsing, storage, and arithmetic. This includes more accurate duration calculations (component-based comparison, new parsing formats), consistent timezone handling for DateTime and Time constructors, and refined truncation/adjustment logic with nanosecond precision. Temporal arithmetic now correctly integrates with expression evaluation.
  • Richer Expression Evaluation and Comparison: The evaluation of various expressions has been refined to align with Cypher's three-valued logic (3VL) and specific type behaviors. This includes correct handling of IN operator for lists, strict integer type validation for list indices, and comprehensive comparison rules for ORDER BY (including NaN, lists, booleans, and cross-type ordering).
  • Advanced Cypher Function Support: New Cypher functions substring(), percentileDisc(), and percentileCont() have been implemented. Existing functions like properties() and range() received enhanced argument validation and broader applicability. Temporal constructor functions now use a frozen statement time for consistent results.
  • Robust Semantic Validation: The Cypher semantic validator has been expanded to enforce more rules, such as consistent return columns in UNION queries, proper variable scoping in WITH clauses (including ORDER BY and SET/DELETE operations), detection of duplicate column aliases, and requiring aliases for non-variable expressions in WITH when aggregations are present.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • engine/src/main/java/com/arcadedb/query/opencypher/Labels.java
    • Modified getLabels to return an empty list for unlabeled nodes (types 'Vertex' or 'V').
    • Filtered out base types ('Vertex', 'V') when retrieving labels from supertypes for multi-label vertices.
  • engine/src/main/java/com/arcadedb/query/opencypher/ast/ArithmeticExpression.java
    • Updated evaluateTemporalArithmetic to accept the operator as a parameter and made it public static.
    • Changed numeric DIVIDE and MODULO operations to follow IEEE 754 standards for division by zero (e.g., Double.NaN for modulo by zero).
  • engine/src/main/java/com/arcadedb/query/opencypher/ast/ComparisonExpression.java
    • Adjusted temporal type comparison to return false/true for equality/inequality of incompatible types, and null for ordering comparisons.
    • Implemented lexicographic comparison for lists, including null propagation and length-based ordering.
  • engine/src/main/java/com/arcadedb/query/opencypher/ast/FunctionCallExpression.java
    • Added originalFunctionName field to preserve the original casing of function names.
    • Updated getText() to use originalFunctionName for accurate string representation.
  • engine/src/main/java/com/arcadedb/query/opencypher/ast/InExpression.java
    • Refactored evaluateTernary to correctly handle single list expressions on the RHS and multiple list literal items.
    • Added deep equality comparison for lists within the valuesEqual helper method.
  • engine/src/main/java/com/arcadedb/query/opencypher/ast/ListIndexExpression.java
    • Introduced strict type validation for list indices, requiring integer types and throwing IllegalArgumentException for floats or booleans.
  • engine/src/main/java/com/arcadedb/query/opencypher/ast/PropertyAccessExpression.java
    • Added convertFromStorage utility to automatically convert ArcadeDB-stored temporal values (e.g., String for CypherDateTime) back to their Cypher temporal types during property access.
    • Applied convertFromStorage when retrieving properties from Document objects.
  • engine/src/main/java/com/arcadedb/query/opencypher/ast/SetClause.java
    • Introduced SetType enum to distinguish between property assignment, map replacement, map merging, and label assignment.
    • Updated SetItem to include constructors and fields for all SetType variants.
    • Expanded Javadoc examples to reflect new SET clause capabilities.
  • engine/src/main/java/com/arcadedb/query/opencypher/ast/StringMatchExpression.java
    • Refactored string matching (STARTS WITH, ENDS WITH, CONTAINS) to use evaluateTernary and return null for null or non-string operands, adhering to 3VL.
  • engine/src/main/java/com/arcadedb/query/opencypher/executor/CypherExecutionPlan.java
    • Added hasWithPrecedingMatch() check to determine if a WITH clause appears before a MATCH clause.
    • Modified the optimizer path to bypass optimization if WITH precedes MATCH, ensuring correct variable scope and execution order.
  • engine/src/main/java/com/arcadedb/query/opencypher/executor/CypherFunctionFactory.java
    • Added substring, percentileDisc, and percentileCont as Cypher-specific functions.
    • Enhanced properties() function to handle Result objects and throw TypeError for invalid arguments.
    • Improved range() function with validation for integer arguments and non-null values.
    • Implemented SubstringFunction, PercentileDiscFunction, and PercentileContFunction.
    • Temporal constructor functions (date, localtime, time, localdatetime, datetime, duration) now use a frozen $statementTime for consistent results and handle null arguments.
    • Updated time.truncate() and datetime.truncate() to correctly apply timezone adjustments from map arguments.
    • Integrated TemporalUtil.computeNanos for precise nanosecond adjustments in temporal map operations.
  • engine/src/main/java/com/arcadedb/query/opencypher/executor/ExpressionEvaluator.java
    • Modified evaluateArithmetic to delegate temporal arithmetic to ArithmeticExpression.evaluateTemporalArithmetic for non-numeric operands.
    • Aligned numeric DIVIDE and MODULO behavior with changes in ArithmeticExpression.java.
  • engine/src/main/java/com/arcadedb/query/opencypher/executor/steps/CreateStep.java
    • Updated convertTemporalForStorage to handle collections and arrays of temporal values.
    • Changed CypherDateTime storage to String format to preserve timezone information.
    • Ensured that null property values are not stored in the database.
  • engine/src/main/java/com/arcadedb/query/opencypher/executor/steps/MergeStep.java
    • Refactored applySetClause to dispatch operations based on the SetType of each item.
    • Implemented logic for REPLACE_MAP, MERGE_MAP, and LABELS operations, including the creation of new vertices and transfer of data for label changes.
  • engine/src/main/java/com/arcadedb/query/opencypher/executor/steps/OrderByStep.java
    • Modified extractValue to use convertFromStorage for correct temporal value retrieval.
    • Enhanced compareValues to handle NaN (sorts before null), perform lexicographic comparison for lists, and compare temporal values using their compareTo method.
    • Introduced typeRank for consistent cross-type comparison ordering.
  • engine/src/main/java/com/arcadedb/query/opencypher/executor/steps/SetStep.java
    • Refactored applySetOperations into dedicated helper methods (applyPropertySet, applyReplaceMap, applyMergeMap, applyLabels) for clarity and modularity.
    • Implemented the full logic for label assignment (SET n:Label), which involves creating a new vertex with the composite type, copying properties and edges, and deleting the original vertex.
  • engine/src/main/java/com/arcadedb/query/opencypher/parser/CypherASTBuilder.java
    • Extended visitSetClause to parse new SET item types: SetPropsContext (SET n = {map}), AddPropContext (SET n += {map}), SetLabelsContext (SET n:Label), and SetLabelsIsContext (SET n IS Label).
    • Refined list literal parsing within maps to evaluate immediately only if all elements are simple literals, otherwise keeping them as Expression objects for runtime evaluation.
  • engine/src/main/java/com/arcadedb/query/opencypher/parser/CypherExpressionBuilder.java
    • Adjusted the parsing precedence for list literals and function invocations to correctly handle complex expressions like [date({...}), date({...})].
  • engine/src/main/java/com/arcadedb/query/opencypher/parser/CypherSemanticValidator.java
    • Added validateUnion to check for invalid mixing of UNION and UNION ALL and ensure consistent return column names across subqueries.
    • Enhanced validateVariableScope to correctly handle ORDER BY scope within WITH clauses and validate variables in SET and DELETE clauses.
    • Introduced validateColumnNames to detect duplicate aliases in RETURN and WITH clauses.
    • Added validateExpressionAliases to ensure non-variable expressions (especially aggregations) in WITH clauses are aliased.
    • Added checkAggregationInOrderBy to prevent aggregation functions in ORDER BY clauses after RETURN.
  • engine/src/main/java/com/arcadedb/query/opencypher/temporal/CypherDateTime.java
    • Improved parse method to correctly handle ZonedDateTime parsing with named timezones.
    • Refined fromMap to apply timezone conversions before field overrides and manage base temporal values with or without timezone information.
    • Utilized TemporalUtil.computeNanos for accurate nanosecond adjustments.
  • engine/src/main/java/com/arcadedb/query/opencypher/temporal/CypherDuration.java
    • Added support for an alternative date-based duration format (e.g., P1-2-3T4:5:6.7).
    • Updated fromComponents to use an average days per month for fractional month calculations.
    • Modified compareTo to perform component-by-component comparison (months, days, seconds, nanos) as per Cypher specification, rather than approximate total nanoseconds.
    • Improved toString method to correctly format negative seconds with positive nanoseconds.
  • engine/src/main/java/com/arcadedb/query/opencypher/temporal/CypherLocalDateTime.java
    • Integrated TemporalUtil.computeNanos for precise nanosecond adjustments in fromMap.
  • engine/src/main/java/com/arcadedb/query/opencypher/temporal/CypherLocalTime.java
    • Integrated TemporalUtil.computeNanos for precise nanosecond adjustments in fromMap.
  • engine/src/main/java/com/arcadedb/query/opencypher/temporal/CypherTime.java
    • Changed now() and parse() (when no offset is provided) to default to ZoneOffset.UTC for deterministic behavior.
    • Enhanced fromMap to handle timezone conversions and field overrides more accurately, especially when a base time with timezone is provided.
    • Utilized TemporalUtil.computeNanos for accurate nanosecond adjustments.
  • engine/src/main/java/com/arcadedb/query/opencypher/temporal/TemporalUtil.java
    • Overhauled duration calculation methods (durationInMonths, durationInDays, durationInSeconds, durationBetween) to ensure accurate and DST-aware computations across various temporal types.
    • Introduced computeNanos for calculating total nanoseconds from map fields.
    • Added helper methods (resolveDateTime, toZonedDateTime, getReferenceDate, toInstant) for robust temporal calculations and conversions.
  • engine/src/test/java/com/arcadedb/query/opencypher/OpenCypherAdvancedFunctionTest.java
    • Updated toBooleanFunctionWithNumber test to assert TypeError as per Cypher specification, reflecting correct behavior.
  • engine/src/test/java/com/arcadedb/query/opencypher/OpenCypherExpressionTest.java
    • Adjusted arithmeticDivision and combinedMapWithArithmetic tests to align with Cypher's integer division rules (truncation).
Activity
  • The author, lvca, has been working on improving OpenCypher TCK compliance, as indicated by the PR title and description.
  • This pull request represents a significant chunk of work, with numerous changes across various core components of the Cypher query engine, including AST, executor steps, functions, and temporal utilities.
  • The changes suggest a focused effort on bringing the Cypher implementation closer to the official specification, particularly concerning complex data types and query clauses.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@mergify
Copy link
Contributor

mergify bot commented Feb 7, 2026

🧪 CI Insights

Here's what we observed from your CI run for a969961.

🟢 All jobs passed!

But CI Insights is watching 👀

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is an impressive and extensive pull request that significantly improves OpenCypher TCK compliance. The changes cover a wide range of areas, including major correctness fixes for temporal types, list operations, three-valued logic, and semantic validation. The implementation of new SET clause features is also a great addition. I have two suggestions for improvement: one is a correctness fix for the new substring function, and the other is a refactoring suggestion to reduce code duplication for temporal type conversion.

Comment on lines 870 to 877
final int start = ((Number) args[1]).intValue();
if (start < 0 || start > str.length())
return "";
if (args.length == 3 && args[2] != null) {
final int length = ((Number) args[2]).intValue();
return str.substring(start, Math.min(start + length, str.length()));
}
return str.substring(start);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The implementation of substring() does not correctly handle negative start indices. According to the Cypher specification, a negative start value should be treated as an offset from the end of the string. The current implementation returns an empty string for any negative start. Additionally, it does not check for negative length values, which should raise an error.

      int start = ((Number) args[1]).intValue();
      if (start < 0) {
        start = str.length() + start;
      }

      if (start < 0 || start >= str.length()) {
        return "";
      }

      if (args.length == 3 && args[2] != null) {
        final int length = ((Number) args[2]).intValue();
        if (length < 0) {
          throw new CommandExecutionException("substring() length cannot be negative, but was: " + length);
        }
        if (length == 0) {
          return "";
        }
        return str.substring(start, Math.min(start + length, str.length()));
      }
      return str.substring(start);

Comment on lines +148 to 212
* Convert ArcadeDB-stored values back to Cypher temporal types for proper comparison.
* Duration, LocalTime, and Time are stored as Strings because ArcadeDB
* doesn't have native binary types for them.
*/
private static Object convertFromStorage(final Object value) {
// Handle collections (lists/arrays of temporal values)
if (value instanceof java.util.Collection<?> collection) {
final java.util.List<Object> converted = new java.util.ArrayList<>(collection.size());
for (final Object item : collection) {
converted.add(convertFromStorage(item));
}
return converted;
}
if (value instanceof Object[] array) {
final Object[] converted = new Object[array.length];
for (int i = 0; i < array.length; i++) {
converted[i] = convertFromStorage(array[i]);
}
return converted;
}

// Handle single values
if (value instanceof LocalDate ld)
return new CypherDate(ld);
if (value instanceof LocalDateTime ldt)
return new CypherLocalDateTime(ldt);
if (value instanceof String str) {
// Duration strings start with P (ISO-8601)
if (str.length() > 1 && str.charAt(0) == 'P') {
try {
return CypherDuration.parse(str);
} catch (final Exception ignored) {
// Not a valid duration string
}
}
// DateTime strings: contain 'T' with date part before it and timezone/offset
final int tIdx = str.indexOf('T');
if (tIdx >= 4 && tIdx < str.length() - 1 && Character.isDigit(str.charAt(0))) {
try {
return CypherDateTime.parse(str);
} catch (final Exception ignored) {
// Not a valid datetime string
}
}
// Time strings: HH:MM:SS[.nanos][+/-offset] or HH:MM:SS[.nanos]Z
if (str.length() >= 8 && str.charAt(2) == ':' && str.charAt(5) == ':') {
// Check if it has a timezone offset
final boolean hasOffset = str.contains("+") || str.contains("-") || str.endsWith("Z");
if (hasOffset) {
try {
return CypherTime.parse(str);
} catch (final Exception ignored) {
// Not a valid time string
}
} else {
try {
return CypherLocalTime.parse(str);
} catch (final Exception ignored) {
// Not a valid local time string
}
}
}
}
return value;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The convertFromStorage method is a duplicate of the one found in PropertyAccessExpression. This duplication increases maintenance overhead. Consider refactoring this method into a shared utility class, such as TemporalUtil, so it can be reused by both OrderByStep and PropertyAccessExpression.

@claude
Copy link

claude bot commented Feb 7, 2026

Code Review - OpenCypher TCK Improvements

I've reviewed PR #3368 which implements improvements to OpenCypher temporal handling and TCK compatibility. Here's my detailed feedback:

Positive Aspects

  1. Comprehensive Temporal Type Handling

    • Excellent improvement to temporal comparison logic in ComparisonExpression.java (lines 115-118)
    • Proper distinction between equality checks (return false/true) and ordering operations (return null) for incompatible temporal types
    • Follows OpenCypher specification correctly
  2. Statement Time Consistency

    • Smart implementation of getStatementTime() in CypherFunctionFactory.java (lines 96-109)
    • Ensures temporal constructors return frozen time throughout query execution
    • Using context variables is the right approach for maintaining consistency
  3. Collection Support

    • Well-designed recursive handling of temporal values in collections/arrays
    • Consistent pattern across PropertyAccessExpression.java, CreateStep.java, and OrderByStep.java
    • Properly handles nested structures
  4. Duration Comparison Logic

    • Fixed comparison in CypherDuration.java (lines 644-654) to follow Cypher spec
    • Component-by-component comparison is correct (no cross-component normalization)
    • Much better than the previous approximate nanosecond conversion
  5. Timezone Handling Improvements

    • Sophisticated logic in CypherDateTime.fromMap() and CypherTime.fromMap()
    • Proper distinction between withZoneSameInstant vs withZoneSameLocal
    • Correctly tracks whether base values have timezone info

⚠️ Issues & Concerns

1. Potential Performance Impact

CypherExpressionBuilder.java (lines 383-477): The new parsing logic performs many sequential checks with recursive tree walking. This could impact query compilation performance significantly.

// Multiple spine walks in sequence:
findTopLevelExpression6(ctx)
findTopLevelExpression5(ctx)
findTopLevelExpression4(ctx)
findTopLevelExpression3(ctx)
findTopLevelExpression2(ctx)
// Then recursive searches...

Recommendation: Consider caching parse results or restructuring to reduce tree traversals. Profile this with complex queries to ensure acceptable performance.

2. Storage Format Inconsistency

CreateStep.java (line 245): DateTime values are now stored as strings to preserve timezone info:

if (value instanceof CypherDateTime)
  return value.toString(); // Store as String to preserve timezone info

Issues:

  • This breaks consistency with other temporal types (LocalDate, LocalDateTime stored as native types)
  • String storage prevents efficient temporal indexing and comparisons at storage level
  • May cause issues with existing data migration
  • Could lead to subtle bugs if other code expects native temporal types

Recommendation: Consider storing as ZonedDateTime or implement a custom binary serialization format that preserves timezone. If string storage is necessary, document this thoroughly and ensure all read paths handle it consistently.

3. Exception Handling

PropertyAccessExpression.java (lines 62-77), OrderByStep.java (lines 315-342): Multiple try-catch blocks with Exception ignored pattern:

try {
  return CypherDateTime.parse(str);
} catch (final Exception ignored) {
  // Not a valid datetime string
}

Issues:

  • Catching broad Exception can hide unexpected errors
  • Silent failures may make debugging difficult
  • Multiple sequential parse attempts add overhead

Recommendation:

  • Use specific exception types (DateTimeParseException)
  • Consider logging at TRACE level for debugging
  • Add fast-path checks before attempting parsing (e.g., regex pre-validation)

4. Fractional Month Calculation

CypherDuration.java (line 633):

double totalDays = weeks * 7 + days + fracMonths * (365.2425 / 12);

Issue: This uses average days per month (30.436875), which differs from the previous approximation (30 days). While more accurate, this could cause behavior changes for existing queries.

Recommendation: Document this change in release notes as it may affect duration calculations. Consider adding tests for fractional month edge cases.

5. Null Handling in Temporal Constructors

CypherFunctionFactory.java: Added null checks across all temporal constructors (lines 118-120, 129-131, etc.):

if (args[0] == null)
  return null;

Good practice! This follows Cypher semantics correctly. ✅

6. Time Truncation Zone Handling

CypherFunctionFactory.java (lines 1379-1191, 1452-1208): The truncate functions now support timezone override in the adjustment map.

Issue: The logic is complex and timezone handling differs between base extraction and final result. Ensure this matches OpenCypher TCK expectations exactly.

🔍 Code Quality Observations

  1. Code Style: Generally follows project conventions with final keyword usage ✅

  2. Comments: Good inline documentation for complex logic ✅

  3. Code Duplication: The convertFromStorage() logic is duplicated in three places:

    • PropertyAccessExpression.java
    • OrderByStep.java
    • (Similar pattern in CreateStep.java for reverse direction)

    Recommendation: Extract to a shared utility class like TemporalConversionUtil to reduce duplication and ensure consistency.

🧪 Test Coverage Concerns

The PR description states "I think I'm done for today with OpenCypher TCK..." but I don't see test files in this PR.

Critical questions:

  • Are there existing TCK tests that now pass with these changes?
  • Are there new unit tests covering the edge cases (timezone conversions, null handling, incompatible temporal comparisons)?
  • Have regression tests been run to ensure no breakage?

Recommendation: Add or reference test coverage for:

  • Temporal comparison edge cases (different types)
  • Statement time consistency (multiple calls in same query)
  • DateTime string storage/retrieval round-trip
  • Duration parsing with alternative format
  • Collection handling with temporal values
  • Timezone conversion scenarios

🔒 Security Assessment

No security concerns identified. The code:

  • Doesn't expose sensitive data ✅
  • Has proper input validation for date/time parsing ✅
  • Uses safe exception handling ✅

📊 Performance Considerations

  1. Parser complexity: New expression parsing logic may slow compilation
  2. String conversion overhead: DateTime string storage adds serialization cost
  3. Multiple parse attempts: Try-catch pattern in type detection could be optimized

Recommendation: Add performance benchmarks for:

  • Query compilation time with complex expressions
  • Temporal value read/write throughput
  • Large collection handling with temporal values

📝 Documentation Needs

  1. Update documentation about DateTime string storage format
  2. Document statement time behavior for temporal functions
  3. Add examples for new duration parsing format
  4. Note the fractional month calculation change

Action Items

Must fix before merge:

  1. ⚠️ Reconsider DateTime string storage approach - significant architectural change
  2. Add test coverage or reference passing TCK tests
  3. Extract duplicated convertFromStorage() logic to utility class

Should address:
4. Profile and optimize expression parsing performance
5. Use specific exception types instead of broad Exception
6. Add inline documentation for complex timezone conversion logic

Nice to have:
7. Add performance benchmarks
8. Update user-facing documentation

🎯 Overall Assessment

This is a substantial improvement to OpenCypher temporal handling with thoughtful solutions for timezone handling and TCK compliance. The code shows good understanding of Cypher semantics.

Main concerns:

  • DateTime string storage is a significant architectural change that needs careful consideration
  • Missing test evidence in this PR
  • Parser performance impact unknown

Recommendation: Request test results and consider alternative to string storage for DateTime before merging.


Reviewed by Claude Code - automated code review

@lvca lvca marked this pull request as ready for review February 7, 2026 21:37
@lvca lvca merged commit c8b8ce5 into main Feb 7, 2026
19 of 23 checks passed
@lvca lvca deleted the opencypher-tck branch February 7, 2026 21:38
robfrank pushed a commit that referenced this pull request Feb 17, 2026
* test: including official opencypher tck

* fix: fixed many issues with opencypher from TCK tests

* fix: fixed broken tests from OpenCyphr TCK

* fix: more opencypher issues from tck tests

* fix: opencypher tck more tests pass now

Reached much better compliance with the latest changes:

```
=======================================================
         OpenCypher TCK Compliance Report
=======================================================
Total scenarios:  3897
Passed:           1908 (48%)
Failed:           1939 (49%)
Skipped:          50 (1%)
-------------------------------------------------------
By category:
  clauses/call                               2/ 52 passed (3%)
  clauses/create                            64/ 78 passed (82%)
  clauses/delete                            24/ 41 passed (58%)
  clauses/match                            292/381 passed (76%)
  clauses/match-where                       25/ 34 passed (73%)
  clauses/merge                             47/ 75 passed (62%)
  clauses/remove                            29/ 33 passed (87%)
  clauses/return                            35/ 63 passed (55%)
  clauses/return-orderby                    23/ 35 passed (65%)
  clauses/return-skip-limit                 26/ 31 passed (83%)
  clauses/set                               30/ 53 passed (56%)
  clauses/union                              8/ 12 passed (66%)
  clauses/unwind                            10/ 14 passed (71%)
  clauses/with                              14/ 29 passed (48%)
  clauses/with-orderBy                     124/292 passed (42%)
  clauses/with-skip-limit                    7/  9 passed (77%)
  clauses/with-where                        10/ 19 passed (52%)
  expressions/aggregation                   23/ 35 passed (65%)
  expressions/boolean                      150/150 passed (100%)
  expressions/comparison                    36/ 72 passed (50%)
  expressions/conditional                   13/ 13 passed (100%)
  expressions/existentialSubqueries          4/ 10 passed (40%)
  expressions/graph                         32/ 61 passed (52%)
  expressions/list                         120/185 passed (64%)
  expressions/literals                     120/131 passed (91%)
  expressions/map                           28/ 44 passed (63%)
  expressions/mathematical                   3/  6 passed (50%)
  expressions/null                          44/ 44 passed (100%)
  expressions/path                           0/  7 passed (0%)
  expressions/pattern                       19/ 50 passed (38%)
  expressions/precedence                    20/121 passed (16%)
  expressions/quantifier                   478/604 passed (79%)
  expressions/string                        22/ 32 passed (68%)
  expressions/temporal                       0/1004 passed (0%)
  expressions/typeConversion                19/ 47 passed (40%)
  useCases/countingSubgraphMatches           6/ 11 passed (54%)
  useCases/triadicSelection                  1/ 19 passed (5%)
=======================================================
```

* fix: opencypher implemented missing temporal functions + precedence

Issue #3357 and #3355

* fix: opencypher implemented more missing functions

Issue #3357 and #3355

* fix: opencypher more code fixed thank to the tck

* fix: OpenCypher fixed temporal functions (from TCK results)

(cherry picked from commit c8b8ce5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant