fix(sql): ORDER BY cursor keeps the source column types (#146) - #150
Closed
russimicro wants to merge 1 commit into
Closed
fix(sql): ORDER BY cursor keeps the source column types (#146)#150russimicro wants to merge 1 commit into
russimicro wants to merge 1 commit into
Conversation
…#146) FiveTechSoft#136 materialises a single-table ORDER BY / DISTINCT / LIMIT through build_memory_result(), a helper written for system.* catalogs and sp_* result sets. It types every numeric column as a 4-byte integer and caps the record at 64 KB, so a SELECT * over a user table dropped the decimals of every N(n,d), wrapped anything past 2^31, and failed outright on a wide table. Reported from an ERP whose article table has 187 fields and prices with two decimals. Materialise from the SOURCE field descriptors instead: create a temp table from the source structure, copy the ordered rows into it, close the live source and hand back a cursor over the temp. Types round-trip, and the FiveTechSoft#136 properties hold -- the cursor is static, INDEX ON over it cannot reach the production .cdx, and recnos are 1..N in result order. The temp is registered against the cursor handle and its files (.dbf plus any .cdx/.fpt an application built on the result) are removed by AdsCloseTable, so a data directory does not accumulate one temp per query. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
FiveTechSoft
added a commit
that referenced
this pull request
Jul 30, 2026
Cherry-picked and conflict-resolved against main (post CI fix 54e977c): - #150 fix(sql): ORDER BY cursor keeps source column types - #148 fix(adi): tag ordinals follow creation order - #152 fix(adt): non-.adt extension (.DAT) works end to end - #151 fix(session): create honours absolute path with existing parent (+ #include <vector> so the new unit test builds under clang) - #154 fix(engine): partial SEEK keeps Found() with SET DELETED ON - #155 fix(engine): ordScope bound shorter than key is a prefix - #153 perf(engine): live key count without per-row goto + recno order Also includes the CMakeLists resolution that keeps every new regression case in the unit-test target.
Owner
|
Integrated into main as part of the PR stack merge (9e7ac41). Cherry-picked onto post-CI-fix main, conflict-resolved (CHANGELOG / CMakeLists), and verified locally. Thank you @russimicro. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #146.
Problem
#136materialises a single-tableSELECT ... ORDER BY / DISTINCT / LIMITthrough
build_memory_result(). That helper was written forsystem.*catalogs and
sp_*result sets, where every column is small and integral:The ORDER BY block does pass
sc.decimals = fd.decimals, but the helper ignoresit. So over a user table:
N(n,d)comes back truncated —12345.67reads as12345— and valuespast 2^31 wrap. Silent, which is worse than the error;
we hit it:
Select * From [articulo.dat] as a ... order by a.cnombrearton a187-field table returned ADSCDX/1012.
Change
Materialise from the source field descriptors: create a temp table from the
source structure (
AdsCreateTablewith the projected columns' real type, lengthand decimals), copy the ordered rows in, close the live source, hand back a
cursor over the temp.
Every property #136 was after is kept:
INDEX ONover the result cannot reach theproduction
.cdx;1..Nin result order;only permitted columns;
AdsCloseTableremoves its files, including any.cdx/.fptan applicationbuilt on the result. That is the one thing the memory table gave for free, so
it is done explicitly here (
materialised_cursor_temps/drop_materialised_cursor_temp).The trade against a memory table is that the result lands on disk. For the ERP
workload that is the point — the application indexes and browses the result, and
it can be larger than is comfortable to hold in memory.
build_memory_resultis untouched and still serves its catalog /sp_*callers.
Verification
tests/unit/abi_sql_orderby_types_test.cpp— anN(12,2)column throughSELECT * ... ORDER BY, checking10.50,0.05and12345.67round-trip.Fails before the change (
10,0,12345), passes after.abi_sql_orderby_test.cpp(the #136 tests: materialised recnos, ORDER BY data,source
.cdxuntouched) keeps passing.Full suite on this branch (MSVC x64 Release): 1227/1235. The 8 failures are
pre-existing on
mainand unrelated — 6 ×abi_pritpal_lock_test(remoteconnect, the residual noted in the v1.8.37 release) and 2 ×
abi_server_fs_testwhose teardown threw onremove_allbecause the tempdirectory was held by another process on this machine.
This has been running the reporting ERP's ~60 SQL call sites in production
shape since we adopted v1.8.37.