Skip to content

Commit 595ffec

Browse files
committed
guid: add VARBINARY wire test, drop dead SQL_C_BINARY dispatch arms
Test coverage: - BindGuidToVarcharOctets16 — binds SQL_C_GUID to VARCHAR(16) CHARACTER SET OCTETS (the wire form of native FB4+ VARBINARY(16)). The existing BindGuidToCharOctets16 only covers the fixed CHAR(16) (SQL_TEXT) slot; this exercises convGuidToBinary writing into a SQL_VARYING (length- prefixed) wire buffer. Round-trips clean via UUID_TO_CHAR. Dead-code removal: - Drop the wire-side `to->conciseType == SQL_C_BINARY` arm. Native FB4+ BINARY/VARBINARY reach the dispatch as subtype-1 / sqllen-16 OCTETS (caught by the branch above); the only type that yields conciseType SQL_C_BINARY is a binary BLOB, which is not a sane GUID-bind target. - Drop the app-side `case SQL_C_BINARY` arm. That output direction is unreachable until column-side SQL_GUID mapping (T5-5 / #287) lands; convGuidToString / convGuidToStringW already cover what exists today. convGuidToBinary stays (still used by the OCTETS wire branch). Verified: all 4 GuidParamBindingTest cases pass and the full suite shows no regressions (203 passed, 0 failed) on FB 5.0.3 locally.
1 parent f08e69e commit 595ffec

2 files changed

Lines changed: 55 additions & 11 deletions

File tree

OdbcConvert.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,20 +1001,19 @@ ADRESS_FUNCTION OdbcConvert::getAdressFunction(DescRecord * from, DescRecord * t
10011001
}
10021002
break;
10031003
case SQL_C_GUID:
1004-
// Wire-side (input parameter binding) — Firebird's IPD describes the slot
1005-
// as either BINARY(16) / CHAR(16) OCTETS, a text VARCHAR/CHAR, or (FB4+)
1006-
// genuine BINARY. Route to dedicated wire-only conversions; leave the
1007-
// pre-existing convGuidToString / convGuidToStringW untouched for the
1008-
// app-side fetch path below.
1004+
// Wire-side (input parameter binding) — Firebird's IPD describes the
1005+
// slot as either (VAR)BINARY(16) / (VAR)CHAR(16) CHARACTER SET OCTETS
1006+
// (subtype 1, sqllen 16) or a text VARCHAR/CHAR. Route to dedicated
1007+
// wire-only conversions; leave the pre-existing convGuidToString /
1008+
// convGuidToStringW untouched for the app-side fetch path below.
10091009
if ( to->isIndicatorSqlDa )
10101010
{
1011-
// BINARY(16) / CHAR(16) CHARACTER SET OCTETS — 16 raw bytes
1011+
// BINARY(16) / VARBINARY(16) — i.e. (VAR)CHAR(16) CHARACTER SET
1012+
// OCTETS, which is how Firebird represents native FB4+ BINARY types
1013+
// on the wire (subtype 1, sqllen 16). Send 16 raw canonical bytes.
10121014
if ( to->headSqlVarPtr->getSqlSubtype() == 1
10131015
&& to->headSqlVarPtr->getSqlLen() == 16 )
10141016
return &OdbcConvert::convGuidToBinary;
1015-
// FB4+ BINARY/VARBINARY described directly as SQL_C_BINARY
1016-
if ( to->conciseType == SQL_C_BINARY )
1017-
return &OdbcConvert::convGuidToBinary;
10181017
// Text wire (VARCHAR/CHAR, any charset) — 36-char canonical UUID.
10191018
// setTypeText() converts SQL_VARYING to SQL_TEXT so convGuidToVarString
10201019
// can write the bytes without a length prefix.
@@ -1031,8 +1030,6 @@ ADRESS_FUNCTION OdbcConvert::getAdressFunction(DescRecord * from, DescRecord * t
10311030
return &OdbcConvert::convGuidToString;
10321031
case SQL_C_WCHAR:
10331032
return &OdbcConvert::convGuidToStringW;
1034-
case SQL_C_BINARY:
1035-
return &OdbcConvert::convGuidToBinary;
10361033
default:
10371034
return &OdbcConvert::notYetImplemented;
10381035
}

tests/test_guid_and_binary.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,53 @@ TEST_F(GuidParamBindingTest, BindGuidToUuidToCharRoundtrip) {
608608
<< "Got: '" << text << "' — this is the corruption pattern from issue #295.";
609609
}
610610

611+
// Bind SQL_C_GUID to a VARCHAR(16) CHARACTER SET OCTETS parameter — the
612+
// wire form of a native FB4+ VARBINARY(16). Unlike CHAR(16) OCTETS (a
613+
// fixed SQL_TEXT slot, covered by BindGuidToCharOctets16), this is a
614+
// SQL_VARYING slot, so it exercises convGuidToBinary writing into a
615+
// length-prefixed wire buffer. Both hit the same subtype-1 / sqllen-16
616+
// dispatch branch but with different on-wire layouts.
617+
TEST_F(GuidParamBindingTest, BindGuidToVarcharOctets16) {
618+
REQUIRE_FIREBIRD_CONNECTION();
619+
620+
TempTable table(this, "TEST_PB_GUID_VOCT",
621+
"ID INTEGER NOT NULL PRIMARY KEY, "
622+
"VAL VARCHAR(16) CHARACTER SET OCTETS");
623+
624+
SQLGUID guid = makeKnownGuid();
625+
SQLLEN guidInd = sizeof(guid);
626+
SQLINTEGER id = 1;
627+
SQLLEN idInd = sizeof(id);
628+
629+
SQLRETURN ret = SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT,
630+
SQL_C_SLONG, SQL_INTEGER, 0, 0, &id, sizeof(id), &idInd);
631+
ASSERT_TRUE(SQL_SUCCEEDED(ret));
632+
ret = SQLBindParameter(hStmt, 2, SQL_PARAM_INPUT,
633+
SQL_C_GUID, SQL_GUID, 16, 0, &guid, sizeof(guid), &guidInd);
634+
ASSERT_TRUE(SQL_SUCCEEDED(ret)) << GetOdbcError(SQL_HANDLE_STMT, hStmt);
635+
636+
ret = SQLExecDirect(hStmt,
637+
(SQLCHAR*)"INSERT INTO TEST_PB_GUID_VOCT (ID, VAL) VALUES (?, ?)", SQL_NTS);
638+
ASSERT_TRUE(SQL_SUCCEEDED(ret)) << GetOdbcError(SQL_HANDLE_STMT, hStmt);
639+
Commit();
640+
ReallocStmt();
641+
642+
ExecDirect("SELECT UUID_TO_CHAR(VAL) FROM TEST_PB_GUID_VOCT WHERE ID = 1");
643+
ret = SQLFetch(hStmt);
644+
ASSERT_TRUE(SQL_SUCCEEDED(ret)) << GetOdbcError(SQL_HANDLE_STMT, hStmt);
645+
646+
SQLCHAR buf[64] = {};
647+
SQLLEN ind = 0;
648+
ret = SQLGetData(hStmt, 1, SQL_C_CHAR, buf, sizeof(buf), &ind);
649+
ASSERT_TRUE(SQL_SUCCEEDED(ret));
650+
651+
std::string text((char*)buf);
652+
while (!text.empty() && text.back() == ' ') text.pop_back();
653+
EXPECT_EQ(text, kCanonicalText)
654+
<< "VARBINARY(16) (VARCHAR(16) OCTETS) GUID round-trip failed. "
655+
<< "Got: '" << text << "'";
656+
}
657+
611658
// Test: DECFLOAT column insertion and retrieval on Firebird 4+
612659
TEST_F(Fb4PlusTest, DecfloatInsertAndRetrieve) {
613660
GTEST_SKIP() << "Requires Phase 8: SQL_GUID type mapping and FB4+ types (not yet merged)";

0 commit comments

Comments
 (0)