Skip to content

Support collect(role) in InPS evaluation: install and implement TBSS_collect as an iteration symbol #96

Description

@bero

OCL collect over a role - self.child->collect(parent), or the implicit form self.child.parent, which BoldOclSemantics rewrites into the same collect node - cannot be evaluated in the persistence layer. CanEvaluateInPS answers False on every engine and Bold falls back to in-memory evaluation, which is correct but fetches the whole intermediate collection for large sets. Split out of #43, where the investigation showed this is a missing feature, not an engine bug.

Current state

  • TBSS_collect exists in Source/PMapper/SQL/BoldSqlSymbols.pas only as a commented-out placeholder (one of ~48 TBSS_* names inside a single { } block, lines ~455-520 - not declarations), so nothing installs it in the SQL symbol dictionary. TBoldSqlNodeResolver.VisitTBoldSqlIteration therefore raises InPs SQLSymbol 'collect' not found and TBoldSystemDefaultMapper.CanEvaluateInPS reports False.
  • collect(attribute) (self.child->collect(aString)) already works: the OCL semantics turn it into member navigation (TBoldSqlMember), so no iteration node is built.
  • The regression test Test.BoldLinks.TTestBoldLinks.TestCanEvaluateInPS_CollectRole_NoFalsePositive pins the current answer (False, all engines) and prints GetBoldLastFailureReason. When this feature lands, that test flips to expecting True and the fetch results must be compared with in-memory evaluation.

Where it slots in

The installed iterations (select, reject, exists, forAll, orderBy) are TBSS_Iteration descendants: ResolveObjectMapper returns Args[0].ObjectMapper (the source collection's class) and BuildWCFOrQuery shapes the loop variable's query (see TBSS_Exists.BuildWCFOrQuery: takes the loop var's query, adds the body's WCF, wraps it as EXISTS). collect(role) differs in one respect: the result is the other end's class, so

  • TBSS_collect must become a TBSS_Iteration descendant whose ResolveObjectMapper returns the object mapper of the body expression (Args[1], the role's other end), not of the source;
  • BuildWCFOrQuery must produce a query over the other end's table constrained by the link: for a single-valued role stored as an embedded foreign key, a join from the source rows' BOLD_ID to the other end's id column; for a multi-valued role, a join through the link table (or the reverse embedded key on the other end). TBoldLinkDefaultMapper / TBoldDirectMultiLinkDefaultMapper know the columns; TBSS_ListOperations.CreateBoldIdMatchWCF shows the id-matching WCF shape already used for includes;
  • the node maker path for the implicit form (BoldOclSemantics.pas sets OperationName := 'Collect') must reach the same symbol - check the name lookup is case-insensitive or aligned;
  • duplicates: OCL collect yields a bag; decide whether the SQL form may return distinct ids (Bold object lists are sets of locators anyway) and document it;
  • install the symbol in the initialization list next to the other iterations.

Acceptance

  • CanEvaluateInPS('self.child->collect(parent)') is True on SQLite and SQL Server; TestCanEvaluateInPS_CollectRole_NoFalsePositive inverted accordingly (and renamed)
  • A fetch with the expression as an in-PS condition returns the same object set as in-memory evaluation, for single-valued and multi-valued roles
  • Dedicated cases for empty and null links (the fixture has none that the tested expressions traverse)
  • The implicit form self.child.parent takes the same path
  • TestCanEvaluateInPS_MultiNavigation gets real assertions instead of Assert.Pass
  • Full suite green on both engines; scenarios green under DebugUniDAC

Implemented in 27ab038

TBoldSqlSymbol gained LoopVarIsEnclosing and ResolveResultObjectMapper; TBSS_collect is a TBSS_Iteration descendant (loop variable continues the source query, result mapper = body's other end, body query taken over with DISTINCT = set semantics), installed after TBSS_Reject. A body that yields no objects is refused with sCollectBodyMustYieldObjectsInPS. Verified green: SQLite and SQL Server full suites (2181/2179/2 ignored/0 failed), DebugUniDAC fixtures 12/12 and Test.BoldLinks 85/85 over the UniDAC adapter.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions