Skip to content

cookbook(orm): fast-queries DBF example (index-ordered nav + AOF) + vendored ORM refresh#95

Merged
Admnwk merged 1 commit into
FiveTechSoft:mainfrom
Admnwk:feat/orm-aof-ordscope-example
Jun 26, 2026
Merged

cookbook(orm): fast-queries DBF example (index-ordered nav + AOF) + vendored ORM refresh#95
Admnwk merged 1 commit into
FiveTechSoft:mainfrom
Admnwk:feat/orm-aof-ordscope-example

Conversation

@Admnwk

@Admnwk Admnwk commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Adds a new cookbook example cookbook/orm/dbf/fast_queries_dbf.prg showing the companion ORM's two navigational fast paths on a DBF back-end, and refreshes the vendored ORM sources it needs.

What it demonstrates (all automatic — same query builder, no new API)

  • Index-ordered navigation (OrdScope): ORDER BY an indexed column walks the table in index order instead of reading every row and sorting in memory, so ORDER BY is free and LIMIT stops early. A range on the ordered column is pushed to the engine as an index scope (AdsSetScope).
  • Advantage Optimized Filter (AOF): a WHERE in the optimizable subset (= != < <= > >=, IN, AND/OR of those) is pushed to the engine's AOF; in client/server mode only matching rows travel the wire.

The example reads the ORM's instrumentation counters to prove the optimized path actually fired (e.g. "top 5 by balance ... records walked: 5 of 12 (stopped early)").

Files

  • cookbook/orm/dbf/fast_queries_dbf.prg — new example (English, same style as crud_dbf.prg).
  • examples/orm/src/navexec.prg, examples/orm/src/hbo_ace.prg — refreshed from the companion ORM (brings the AOF + OrdScope code).

Verification

Builds and runs green against the engine (DBF back-end), exit 0; all sections produce correct, ordered results and the counters confirm early-stop and server-side filtering.

…efresh vendored navexec/hbo_ace

New DBF example demonstrating the ORM's navigational fast paths: index-ordered navigation (ORDER BY an indexed column walks in index order, LIMIT stops early, ranges become AdsSetScope index bounds) and the Advantage Optimized Filter (WHERE pushed to the engine). It proves the optimized path fired via the ORM instrumentation counters. Refreshes the vendored examples/orm/src/navexec.prg and hbo_ace.prg from the companion ORM so the example builds with the AOF/OrdScope code. Builds and runs green against the engine.
@Admnwk Admnwk merged commit 8e7e2b8 into FiveTechSoft:main Jun 26, 2026
5 checks passed
@Admnwk Admnwk deleted the feat/orm-aof-ordscope-example branch June 26, 2026 05:40

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces navigational fast paths (OrdScope and Advantage Optimized Filters) for the Harbour ORM over OpenADS, including a cookbook example, new ACE API wrappers in C, and query optimization logic in navexec.prg. The review feedback highlights critical safety issues in the newly added C functions (HBO_DDGETFIELDPROP, HBO_DDCREATE, HBO_DDADDTABLE, and HBO_DDSETFIELDPROP) where string parameters retrieved via hb_parc are not checked for NULL before being passed to the underlying ACE APIs, which could result in segmentation faults if parameters are omitted or passed as NIL.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +605 to +607
if( AdsDDGetFieldProperty( ( ADSHANDLE ) hb_parnint( 1 ),
( UNSIGNED8 * ) hb_parc( 2 ), ( UNSIGNED8 * ) hb_parc( 3 ),
( UNSIGNED16 ) hb_parni( 4 ), szBuf, &usLen ) == 0 )

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The parameters cTable (parameter 2) and cField (parameter 3) retrieved via hb_parc can be NULL if they are omitted or passed as NIL. Passing NULL directly to AdsDDGetFieldProperty will cause a segmentation fault / crash. We should check both pointers for NULL before calling the API.

   const char * szTable = hb_parc( 2 );
   const char * szField = hb_parc( 3 );
   if( szTable && szField && AdsDDGetFieldProperty( ( ADSHANDLE ) hb_parnint( 1 ),
          ( UNSIGNED8 * ) szTable, ( UNSIGNED8 * ) szField,
          ( UNSIGNED16 ) hb_parni( 4 ), szBuf, &usLen ) == 0 )

Comment on lines +621 to +623
ADSHANDLE hConn = 0;
UNSIGNED32 ulRc = AdsDDCreate( ( UNSIGNED8 * ) hb_parc( 1 ), 0, NULL, &hConn );
hb_retnint( ulRc == 0 ? ( HB_MAXINT ) hConn : 0 );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The parameter cDictPath (parameter 1) retrieved via hb_parc can be NULL if omitted or passed as NIL. Passing NULL directly to AdsDDCreate will cause a segmentation fault / crash. We should check the pointer for NULL before calling the API.

   const char * szPath = hb_parc( 1 );
   ADSHANDLE    hConn  = 0;
   UNSIGNED32   ulRc   = 1;
   if( szPath )
      ulRc = AdsDDCreate( ( UNSIGNED8 * ) szPath, 0, NULL, &hConn );
   hb_retnint( ulRc == 0 ? ( HB_MAXINT ) hConn : 0 );

Comment on lines +628 to +630
hb_retl( AdsDDAddTable( ( ADSHANDLE ) hb_parnint( 1 ),
( UNSIGNED8 * ) hb_parc( 2 ), ( UNSIGNED8 * ) hb_parc( 3 ),
0, 0, NULL, NULL ) == 0 );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The parameters cAlias (parameter 2) and cTablePath (parameter 3) retrieved via hb_parc can be NULL if omitted or passed as NIL. Passing NULL directly to AdsDDAddTable will cause a segmentation fault / crash. We should check both pointers for NULL before calling the API.

   const char * szAlias = hb_parc( 2 );
   const char * szPath  = hb_parc( 3 );
   hb_retl( szAlias && szPath && AdsDDAddTable( ( ADSHANDLE ) hb_parnint( 1 ),
      ( UNSIGNED8 * ) szAlias, ( UNSIGNED8 * ) szPath,
      0, 0, NULL, NULL ) == 0 );

Comment on lines +635 to +638
hb_retl( AdsDDSetFieldProperty( ( ADSHANDLE ) hb_parnint( 1 ),
( UNSIGNED8 * ) hb_parc( 2 ), ( UNSIGNED8 * ) hb_parc( 3 ),
( UNSIGNED16 ) hb_parni( 4 ),
( void * ) hb_parc( 5 ), ( UNSIGNED16 ) hb_parclen( 5 ) ) == 0 );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The parameters cTable (parameter 2), cField (parameter 3), and cValor (parameter 5) retrieved via hb_parc can be NULL if omitted or passed as NIL. Passing NULL directly to AdsDDSetFieldProperty will cause a segmentation fault / crash. We should check all three pointers for NULL before calling the API.

   const char * szTable = hb_parc( 2 );
   const char * szField = hb_parc( 3 );
   const char * szVal   = hb_parc( 5 );
   hb_retl( szTable && szField && szVal && AdsDDSetFieldProperty( ( ADSHANDLE ) hb_parnint( 1 ),
      ( UNSIGNED8 * ) szTable, ( UNSIGNED8 * ) szField,
      ( UNSIGNED16 ) hb_parni( 4 ),
      ( void * ) szVal, ( UNSIGNED16 ) hb_parclen( 5 ) ) == 0 );

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