Skip to content

SQLRDD: keep the rest of a FOR condition after a parenthesized group - #2118

Merged
RobertvanderHulst merged 1 commit into
X-Sharp:devfrom
ecosSystem:homebase/sqlrdd-expr-parens
Oct 24, 2026
Merged

RobertvanderHulst merged 1 commit into
X-Sharp:devfrom
ecosSystem:homebase/sqlrdd-expr-parens

Conversation

@ecosSystem

@ecosSystem ecosSystem commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

A FOR condition was cut off after its first parenthesized group. Base is dev; independent of #2115 and #2116.

Problem

SqlDbExpression.GetExpression() ended the expression at every EoExpr token. That is right for the end of a function argument, but the tokenizer also emits EoExpr for the ) of a plain group. Everything after the first group was dropped without an error:

!(LKNZ=='') .AND. (UST==1)   ->   Not ([LKNZ] = '')

The order then contained rows that the DBF/ADS index does not. Example: LANDDB has 252 rows; the tag above should contain 4 of them, the SQLRDD order contained 38. Any condition of the form !(...) .AND. ..., (... .OR. ...) .AND. ... or EMPTY(x) rewritten as (x == '') .AND. ... was affected.

Fix

  • GetExpression() counts the groups it opens (BoExpr with (). An EoExpr with ) closes one of these groups. Only an EoExpr that closes no group still ends the expression. Function arguments behave as before.
  • SQLKey removed the outer parentheses whenever the text started with ( and ended with ). Now that the whole condition is kept, that turns (A) AND (B) into A) AND (B. It now removes them only when they enclose the whole text (new helper IsEnclosed(), which skips string literals).

Testing

Tested against an ERP with 297 tables and about 1065 tags, imported from DBF into SQL Server. For every tag I compared OrderKeyCount() on the SQLRDD with DBFCDX on the original CDX.

  • Before the fix, 15 tags differed. All of them have a condition with a group followed by more conditions.
  • After the fix, all tags match.
  • GoTop, Skip, GoBottom and Skip(-n) work on every order.

4 tables could not be compared tag by tag: their CDX contains ADS full-text (FTS) indexes on memo fields, which DBFCDX cannot open. On those tables only the row counts and navigation were checked.

🤖 Generated with Claude Code

SqlDbExpression.GetExpression() treated every EoExpr token as the end of the
expression, including the ")" of a plain parenthesized group. A condition like
!(LKNZ=='') .AND. (UST==1) was therefore translated to Not ([LKNZ] = '') and the
order silently contained rows the DBF/ADS index does not (LANDDB: 38 keys
instead of 4). GetExpression now counts the groups it opens and only ends the
expression at an EoExpr that does not close one of them.

SQLKey stripped an outer pair of parentheses whenever the text started with "("
and ended with ")", which turns "(A) AND (B)" into "A) AND (B" once the whole
condition is kept; it now strips them only when they enclose the whole text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@RobertvanderHulst
RobertvanderHulst merged commit cd4cacf into X-Sharp:dev Oct 24, 2026
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.

2 participants