Skip to content

SQLRDD: sort keys like REF_NR+DTOS(DATUM) by their columns - #2122

Merged
RobertvanderHulst merged 1 commit into
X-Sharp:devfrom
ecosSystem:homebase/sqlrdd-dtos-order
Oct 27, 2026
Merged

RobertvanderHulst merged 1 commit into
X-Sharp:devfrom
ecosSystem:homebase/sqlrdd-dtos-order

Conversation

@ecosSystem

Copy link
Copy Markdown
Contributor

An order whose key contains a function was sorted by the SQL translation of the whole key text, e.g. ORDER BY [REF_NR] + CONVERT(char(8),[DATUM],112). The server cannot read that order from the index on (REF_NR, DATUM), so it computed and sorted the text for the whole order on every page and every GoBottom(). Keys like this are very common in xBase applications: our ERP has 115 tags with DTOS().

Change

  • Sorting: A key that only concatenates columns and DTOS(column) is now sorted by the columns themselves. DTOS() keeps the order of the date and the other parts are fixed-width columns, so the order is the same and the server can use the index. The new SqlDbExpression.KeyTerms describes such a key.
  • Seek and scope conditions: These are now built per part for such keys as well. The column-aware conditions so far only handled keys without any function. The DTOS() part is compared as its yyyymmdd text.
  • Full-length key values: The column-aware conditions are now also used when the value has the full key length. A relation seek on REF_NR+DTOS(DATUM) becomes [REF_NR] = ... AND CONVERT(char(8),[DATUM],112) = ... instead of a comparison on the concatenated text that no index can serve. A value longer than the key parts still uses the condition on the whole key text.

Measurements

KDKONTO copy with 103,000 rows, tag REF_NR+DTOS(BEL_DAT)+BEL_ART+BEL_NR, server time per query:

before after
first page (GoTop) 25 ms < 1 ms
seek on REF_NR 27 ms < 1 ms

Testing

For all 115 DTOS() tags of our ERP I compared the old and the new build:

  • the recno sequence of a full read (13,193 rows),
  • Seek, soft seek, SeekLast and the number of matching keys for 40 sampled keys in 5 prefix lengths each (7,552 checks).

All results are identical.

🤖 Generated with Claude Code

An order whose key contains a function was sorted by the SQL translation of the
whole key text, e.g. ORDER BY [REF_NR] + CONVERT(char(8),[DATUM],112). The
server cannot read that order from the index on (REF_NR, DATUM), so it computed
and sorted the text for the whole order on every page and every GoBottom().

A key that only concatenates columns and DTOS(column) is now sorted by the
columns themselves: DTOS() keeps the order of the date and the other parts are
fixed-width columns, so the order is the same and the server can use the index.
SqlDbExpression.KeyTerms describes such a key.

Seek and scope conditions on these keys are built per part as well (the
column-aware conditions so far only handled keys without any function), the
DTOS() part compared as its yyyymmdd text, and now also for a value of the full
key length: a relation seek on REF_NR+DTOS(DATUM) becomes
[REF_NR] = ... AND CONVERT(char(8),[DATUM],112) = ... instead of a comparison
on the concatenated text that no index can serve. A value longer than the key
parts still uses the condition on the whole key text.

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