[Fdo-trac] [fdo-trac] #228: MySQL Defect : Can't retreive tablename in joined query

FDO trac_fdo at osgeo.org
Tue Oct 13 07:58:57 PDT 2026


#228: MySQL Defect : Can't retreive tablename in joined query
----------------------------+-------------------------
 Reporter:  bscott          |        Owner:  danstoica
     Type:  defect          |       Status:  closed
 Priority:  major           |    Milestone:  3.4.0
Component:  MySQL Provider  |      Version:  3.2.0
 Severity:  4               |   Resolution:  fixed
 Keywords:                  |  External ID:
----------------------------+-------------------------
Changes (by jng):

 * resolution:   => fixed
 * status:  new => closed

Comment:

 In [changeset:"8399" 8399]:
 {{{#!CommitTicketReference repository="" revision="8399"
 Fix joined queries reporting indistinguishable column names

 A native FdoISQLCommand query that selects a same-named column from more
 than
 one table reports that one name for every one of them, and
 FdoISQLDataReader
 resolves a column name to the first column that has it, so every column
 after
 the first was unreachable by name. That is FDO ticket #228, which asked
 either
 for a table-qualified name from GetColumnName() or for some other way to
 tell
 the columns apart. A table-qualified name was not taken: it changes what a
 caller receives for every query, it means nothing for a select-list item
 that is
 an expression (the reporter's own ticket comment gives "table1.column1 +
 table2.column2" as the case that rules it out), and it needs a new table-
 name
 output on the rdbi_describe_slct contract that every driver would have to
 supply. The readers already had the disambiguation both interfaces need -
 a
 repeat of a select-list name gets a "$<n>" suffix, so a join reports
 SHARED_COL, SHARED_COL$1, SHARED_COL$2 - and two defects sat behind it, so
 the
 GenericRdbms path was broken for the second repeat and the King Oracle
 path did
 not disambiguate at all.

 FdoRdbmsSQLDataReader::GenerateUniqueName() wrote the digit of its suffix
 with
 "*(dest + propsize + 1 + idx) = buffer[idx++]", which reads and increments
 idx
 without a sequence point; GCC evaluates the right-hand side first, so the
 digit
 went one slot past the NUL terminator and the name did not change. A two-
 table
 join therefore reported SHARED_COL and a malformed SHARED_COL$, and
 because the
 name was never replaced, the retry loop that looks for a name the result
 set
 does not already use never terminated: a query with three same-named
 select-list
 items hung in ExecuteReader() indefinitely (the loop's counter was
 observed
 climbing past 25 with the name unchanged). The same expression in the
 sibling
 "name too long" branch also left a gap at dest[2]. Both branches now copy
 the
 digit and advance the index in separate statements.

 c_KgOraSQLDataReader, which is the King Oracle provider's own reader
 rather than
 a subclass of the GenericRdbms one, returned the OCI column name for every
 ordinal and nothing more, so its name-to-index lookup reached only the
 first
 column of a repeated name - the original symptom of the ticket, unfixed.

 Because the suffix is produced by the shared reader, the GenericRdbms fix
 covers every provider that reads a native query through it (MySQL,
 PostGIS,
 ODBC and SQL Server Spatial); King Oracle needed its own.

 Provider:
 * Providers/GenericRdbms/Src/Fdo/Other/FdoRdbmsSQLDataReader.cpp:
   GenerateUniqueName() copies each digit into dest with the index advanced
 in a
   second statement, in both the suffix and the "too long" branch, and the
   sequence-point hazard is noted in a comment. The generated names are
   unchanged - first repeat "$1", second "$2" - so no other caller of this
   reader is affected.
 * Providers/KingOracle/src/Provider/c_KgOraSQLDataReader.cpp,
 c_KgOraSQLDataReader.h: the
   constructor builds a new m_ColumnNames collection that holds the
 reported name
   of every result set column in ordinal order, via the new
   MakeUniqueColumnName(), which suffixes a name that a previous column
 already
   used (case-insensitively, matching the collection's own lookup). The
   recognized-type and SDO_GEOMETRY branches add that same name to
 m_SqlColumns,
   so the name a caller is given is the name that resolves to its own
 column.
   GetColumnName() returns the reported name and now range-checks its
 index;
   it previously passed the ordinal to OCI unvalidated. m_ColumnNames is an
   FdoPtr, so the new collection is released with the reader, and only
 private
   headers changed (the class lives under src/Provider, not the installed
   inc/KingOracle tree), so no shipped layout moves.

 Tests:
 * Providers/GenericRdbms/Src/UnitTest/Common/FdoSqlCmdTest.cpp,
 FdoSqlCmdTest.h:
   FdoSqlCmdTest::QueryJoinedColumns (new), in the shared provider suite:
 three
   tables are each given a key_col and a shared_col, one row is inserted
 into
   each, and a three-way join selects shared_col three times. It asserts
 the
   reported names are SHARED_COL, SHARED_COL$1 and SHARED_COL$2, that each
 name
   reads its own column through GetInt32, and that ExecuteReader() returns
 at
   all. It fails before the fix - with two tables the name is "SHARED_COL$"
 and
   with three the reader never returns. Registered in the base suite, so
 MySQL,
   PostGIS, ODBC and SQL Server Spatial all inherit it. The precondition
 uses
   DROP TABLE IF EXISTS inside a catch: a plain failed DROP aborts a
 PostgreSQL
   transaction and would poison every statement after it, while the clause
 itself
   is newer than some servers this suite targets.
 * Providers/GenericRdbms/Src/UnitTest/Odbc/OdbcFdoSqlCmdTest.h: a no-op
   override of QueryJoinedColumns for OdbcAccessFdoSqlCmdTest, alongside
 the
   stubs it already has for the other tests that fixture cannot run because
 it
   has no SQL-command support.
 * Providers/KingOracle/src/KgOraUnitTest/SelectTests.cpp, SelectTests.h:
   SelectTests::SelectJoinedColumns (new) for King Oracle: the same three-
 way
   join against Oracle XE 11g, asserting the same three names and that each
 reads
   its own value. It failed before the provider fix with the second column
   reported as SHARED_COL.
 * Providers/KingOracle/src/KgOraUnitTest/InsertUpdateDeleteTests.cpp:
   AddBatchRow (was MakeBatchRow returning a Detached raw pointer) now
 builds the
   row of a batch insert into an FdoPtr and adds it from there.
   FdoCollection::Add() takes a reference of its own and does not consume
 the
   caller's, so the reference the row factory made was left with no owner -
 11
   direct LeakSanitizer records of 32 bytes, one per row of the four
 InsertBatch
   tests, each anchoring its row's parameter values, their data values, the
   FdoGeometryValue and the FGF byte array behind it. This fixes a leak
   introduced with r8398's batch-insert tests and leaves their assertions
   unchanged.

 Verified in the baseline ubuntu22 Debug (ASan) build container against the
 dbs
 compose MySQL 5.6, PostGIS and Oracle XE 11g. FdoSqlCmdTest goes from OK
 (9) to
 OK (10) for MySQL and runs OK (9) for PostGIS; the full MySql and PostGis
 suites
 are OK (249) and OK (140) with no direct leak record and no record whose
 stack
 refers to the changed code (their LeakSanitizer totals are unchanged at
 46236
 bytes in 491 allocations and 105212 bytes in 942). KgOraUnitTest is OK
 (39) with
 SelectTests OK (3), up from OK (2), and its LeakSanitizer total goes from
 6284
 bytes in 132 allocations (11 direct, 121 indirect) to 0 bytes.
 UnitTestOdbc
 builds with the new override.

 Fixes #228
 }}}
-- 
Ticket URL: <https://trac.osgeo.org/fdo/ticket/228#comment:3>
FDO <http://fdo.osgeo.org/>
Feature Data Objects


More information about the fdo-trac mailing list