This is an automated email from the ASF dual-hosted git repository.
lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git
The following commit(s) were added to refs/heads/main by this push:
new 0ac3fdea8 chore(c/validation): add quirk for identifier quoting (#4504)
0ac3fdea8 is described below
commit 0ac3fdea816499b9ef6a3f951a5c6e9842dda06b
Author: Fredrik Fornwall <[email protected]>
AuthorDate: Tue Jul 14 03:33:55 2026 +0200
chore(c/validation): add quirk for identifier quoting (#4504)
Add a identifier quoting hook whose default reproduces the current ANSI
double-quoted identifier quoting.
Signed-off-by: Fredrik Fornwall <[email protected]>
---
c/validation/adbc_validation.h | 6 ++
c/validation/adbc_validation_statement.cc | 143 +++++++++++++++++++-----------
2 files changed, 95 insertions(+), 54 deletions(-)
diff --git a/c/validation/adbc_validation.h b/c/validation/adbc_validation.h
index 27f8f2543..5fcaa0ad8 100644
--- a/c/validation/adbc_validation.h
+++ b/c/validation/adbc_validation.h
@@ -167,6 +167,12 @@ class DriverQuirks {
return default_sql;
}
+ /// \brief Quote a SQL identifier (table or column name) for the driver's
+ /// dialect. Defaults to ANSI SQL double-quoting.
+ virtual std::string QuoteIdentifier(std::string_view name) const {
+ return '"' + std::string(name) + '"';
+ }
+
/// \brief For a given Arrow type of ingested data, what Arrow type
/// will the database return when that column is selected?
virtual ArrowType IngestSelectRoundTripType(ArrowType ingest_type) const {
diff --git a/c/validation/adbc_validation_statement.cc
b/c/validation/adbc_validation_statement.cc
index a154b9cab..4c19ff0ad 100644
--- a/c/validation/adbc_validation_statement.cc
+++ b/c/validation/adbc_validation_statement.cc
@@ -151,11 +151,13 @@ void StatementTest::TestSqlIngestType(SchemaField field,
ASSERT_THAT(rows_affected,
::testing::AnyOf(::testing::Eq(values.size()),
::testing::Eq(-1)));
- ASSERT_THAT(
- AdbcStatementSetSqlQuery(
- &statement, "SELECT * FROM \"bulk_ingest\" ORDER BY \"col\" ASC
NULLS FIRST",
- &error),
- IsOkStatus(&error));
+ ASSERT_THAT(AdbcStatementSetSqlQuery(
+ &statement,
+ ("SELECT * FROM " + quirks()->QuoteIdentifier("bulk_ingest")
+
+ " ORDER BY " + quirks()->QuoteIdentifier("col") + " ASC
NULLS FIRST")
+ .c_str(),
+ &error),
+ IsOkStatus(&error));
{
StreamReader reader;
ASSERT_THAT(AdbcStatementExecuteQuery(&statement, &reader.stream.value,
@@ -363,11 +365,13 @@ void StatementTest::TestSqlIngestTemporalType(const char*
timezone) {
ASSERT_THAT(rows_affected,
::testing::AnyOf(::testing::Eq(values.size()),
::testing::Eq(-1)));
- ASSERT_THAT(
- AdbcStatementSetSqlQuery(
- &statement, "SELECT * FROM \"bulk_ingest\" ORDER BY \"col\" ASC
NULLS FIRST",
- &error),
- IsOkStatus(&error));
+ ASSERT_THAT(AdbcStatementSetSqlQuery(
+ &statement,
+ ("SELECT * FROM " + quirks()->QuoteIdentifier("bulk_ingest")
+
+ " ORDER BY " + quirks()->QuoteIdentifier("col") + " ASC
NULLS FIRST")
+ .c_str(),
+ &error),
+ IsOkStatus(&error));
{
StreamReader reader;
ASSERT_THAT(AdbcStatementExecuteQuery(&statement, &reader.stream.value,
@@ -510,11 +514,13 @@ void StatementTest::TestSqlIngestInterval() {
ASSERT_THAT(rows_affected,
::testing::AnyOf(::testing::Eq(values.size()),
::testing::Eq(-1)));
- ASSERT_THAT(
- AdbcStatementSetSqlQuery(
- &statement, "SELECT * FROM \"bulk_ingest\" ORDER BY \"col\" ASC
NULLS FIRST",
- &error),
- IsOkStatus(&error));
+ ASSERT_THAT(AdbcStatementSetSqlQuery(
+ &statement,
+ ("SELECT * FROM " + quirks()->QuoteIdentifier("bulk_ingest")
+
+ " ORDER BY " + quirks()->QuoteIdentifier("col") + " ASC
NULLS FIRST")
+ .c_str(),
+ &error),
+ IsOkStatus(&error));
{
StreamReader reader;
ASSERT_THAT(AdbcStatementExecuteQuery(&statement, &reader.stream.value,
@@ -593,7 +599,9 @@ void StatementTest::TestSqlIngestStreamZeroArrays() {
IsOkStatus(&error));
ASSERT_THAT(
- AdbcStatementSetSqlQuery(&statement, "SELECT * FROM \"bulk_ingest\"",
&error),
+ AdbcStatementSetSqlQuery(
+ &statement,
+ ("SELECT * FROM " +
quirks()->QuoteIdentifier("bulk_ingest")).c_str(), &error),
IsOkStatus(&error));
{
@@ -716,7 +724,9 @@ void StatementTest::TestSqlIngestAppend() {
// Read data back
ASSERT_THAT(
- AdbcStatementSetSqlQuery(&statement, "SELECT * FROM \"bulk_ingest\"",
&error),
+ AdbcStatementSetSqlQuery(
+ &statement,
+ ("SELECT * FROM " +
quirks()->QuoteIdentifier("bulk_ingest")).c_str(), &error),
IsOkStatus(&error));
{
StreamReader reader;
@@ -776,7 +786,9 @@ void StatementTest::TestSqlIngestReplace() {
// Read data back
ASSERT_THAT(
- AdbcStatementSetSqlQuery(&statement, "SELECT * FROM \"bulk_ingest\"",
&error),
+ AdbcStatementSetSqlQuery(
+ &statement,
+ ("SELECT * FROM " +
quirks()->QuoteIdentifier("bulk_ingest")).c_str(), &error),
IsOkStatus(&error));
{
StreamReader reader;
@@ -822,7 +834,9 @@ void StatementTest::TestSqlIngestReplace() {
// Read data back
ASSERT_THAT(
- AdbcStatementSetSqlQuery(&statement, "SELECT * FROM \"bulk_ingest\"",
&error),
+ AdbcStatementSetSqlQuery(
+ &statement,
+ ("SELECT * FROM " +
quirks()->QuoteIdentifier("bulk_ingest")).c_str(), &error),
IsOkStatus(&error));
{
StreamReader reader;
@@ -896,7 +910,9 @@ void StatementTest::TestSqlIngestCreateAppend() {
// Read data back
ASSERT_THAT(
- AdbcStatementSetSqlQuery(&statement, "SELECT * FROM \"bulk_ingest\"",
&error),
+ AdbcStatementSetSqlQuery(
+ &statement,
+ ("SELECT * FROM " +
quirks()->QuoteIdentifier("bulk_ingest")).c_str(), &error),
IsOkStatus(&error));
{
StreamReader reader;
@@ -1047,7 +1063,10 @@ void StatementTest::TestSqlIngestMultipleConnections() {
ASSERT_THAT(
AdbcStatementSetSqlQuery(
&statement,
- "SELECT * FROM \"bulk_ingest\" ORDER BY \"int64s\" DESC NULLS
LAST", &error),
+ ("SELECT * FROM " + quirks()->QuoteIdentifier("bulk_ingest") + "
ORDER BY " +
+ quirks()->QuoteIdentifier("int64s") + " DESC NULLS LAST")
+ .c_str(),
+ &error),
IsOkStatus(&error));
{
@@ -1088,11 +1107,13 @@ void StatementTest::TestSqlIngestSample() {
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementNew(&connection, &statement, &error),
IsOkStatus(&error));
- ASSERT_THAT(
- AdbcStatementSetSqlQuery(
- &statement, "SELECT * FROM \"bulk_ingest\" ORDER BY int64s ASC NULLS
FIRST",
- &error),
- IsOkStatus(&error));
+ ASSERT_THAT(AdbcStatementSetSqlQuery(
+ &statement,
+ ("SELECT * FROM " + quirks()->QuoteIdentifier("bulk_ingest")
+
+ " ORDER BY int64s ASC NULLS FIRST")
+ .c_str(),
+ &error),
+ IsOkStatus(&error));
StreamReader reader;
ASSERT_THAT(AdbcStatementExecuteQuery(&statement, &reader.stream.value,
&reader.rows_affected, &error),
@@ -2002,8 +2023,8 @@ void StatementTest::TestSqlPrepareUpdate() {
IsOkStatus(&error));
// Prepare
- std::string query =
- "INSERT INTO \"bulk_ingest\" VALUES (" + quirks()->BindParameter(0) +
")";
+ std::string query = "INSERT INTO " +
quirks()->QuoteIdentifier("bulk_ingest") +
+ " VALUES (" + quirks()->BindParameter(0) + ")";
ASSERT_THAT(AdbcStatementSetSqlQuery(&statement, query.c_str(), &error),
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementPrepare(&statement, &error), IsOkStatus(&error));
@@ -2020,7 +2041,9 @@ void StatementTest::TestSqlPrepareUpdate() {
// Read data back
ASSERT_THAT(
- AdbcStatementSetSqlQuery(&statement, "SELECT * FROM \"bulk_ingest\"",
&error),
+ AdbcStatementSetSqlQuery(
+ &statement,
+ ("SELECT * FROM " +
quirks()->QuoteIdentifier("bulk_ingest")).c_str(), &error),
IsOkStatus(&error));
{
StreamReader reader;
@@ -2098,8 +2121,8 @@ void StatementTest::TestSqlPrepareUpdateStream() {
MakeStream(&stream.value, &schema.value, std::move(batches));
// Prepare
- std::string query =
- "INSERT INTO \"bulk_ingest\" VALUES (" + quirks()->BindParameter(0) +
")";
+ std::string query = "INSERT INTO " +
quirks()->QuoteIdentifier("bulk_ingest") +
+ " VALUES (" + quirks()->BindParameter(0) + ")";
ASSERT_THAT(AdbcStatementSetSqlQuery(&statement, query.c_str(), &error),
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementPrepare(&statement, &error), IsOkStatus(&error));
@@ -2112,7 +2135,9 @@ void StatementTest::TestSqlPrepareUpdateStream() {
// Read data back
ASSERT_THAT(
- AdbcStatementSetSqlQuery(&statement, "SELECT * FROM \"bulk_ingest\"",
&error),
+ AdbcStatementSetSqlQuery(
+ &statement,
+ ("SELECT * FROM " +
quirks()->QuoteIdentifier("bulk_ingest")).c_str(), &error),
IsOkStatus(&error));
{
StreamReader reader;
@@ -2446,17 +2471,19 @@ void StatementTest::TestSqlQueryInsertRollback() {
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementNew(&connection, &statement, &error),
IsOkStatus(&error));
- ASSERT_THAT(AdbcStatementSetSqlQuery(&statement,
- "CREATE TABLE \"rollbacktest\" (a
INT)", &error),
+ std::string table = quirks()->QuoteIdentifier("rollbacktest");
+ ASSERT_THAT(AdbcStatementSetSqlQuery(
+ &statement, ("CREATE TABLE " + table + " (a INT)").c_str(),
&error),
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementExecuteQuery(&statement, nullptr, nullptr, &error),
IsOkStatus(&error));
ASSERT_THAT(AdbcConnectionCommit(&connection, &error), IsOkStatus(&error));
- ASSERT_THAT(AdbcStatementSetSqlQuery(
- &statement, "INSERT INTO \"rollbacktest\" (a) VALUES (1)",
&error),
- IsOkStatus(&error));
+ ASSERT_THAT(
+ AdbcStatementSetSqlQuery(
+ &statement, ("INSERT INTO " + table + " (a) VALUES (1)").c_str(),
&error),
+ IsOkStatus(&error));
ASSERT_THAT(AdbcStatementExecuteQuery(&statement, nullptr, nullptr, &error),
IsOkStatus(&error));
@@ -2464,7 +2491,7 @@ void StatementTest::TestSqlQueryInsertRollback() {
adbc_validation::StreamReader reader;
ASSERT_THAT(
- AdbcStatementSetSqlQuery(&statement, "SELECT * FROM \"rollbacktest\"",
&error),
+ AdbcStatementSetSqlQuery(&statement, ("SELECT * FROM " + table).c_str(),
&error),
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementExecuteQuery(&statement, &reader.stream.value,
&reader.rows_affected, &error),
@@ -2544,23 +2571,26 @@ void StatementTest::TestSqlQueryRowsAffectedDelete() {
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementNew(&connection, &statement, &error),
IsOkStatus(&error));
- ASSERT_THAT(AdbcStatementSetSqlQuery(&statement,
- "CREATE TABLE \"delete_test\" (foo
INT)", &error),
+ std::string table = quirks()->QuoteIdentifier("delete_test");
+ ASSERT_THAT(AdbcStatementSetSqlQuery(
+ &statement, ("CREATE TABLE " + table + " (foo
INT)").c_str(), &error),
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementExecuteQuery(&statement, nullptr, nullptr, &error),
IsOkStatus(&error));
ASSERT_THAT(
AdbcStatementSetSqlQuery(
- &statement, "INSERT INTO \"delete_test\" (foo) VALUES (1), (2), (3),
(4), (5)",
+ &statement,
+ ("INSERT INTO " + table + " (foo) VALUES (1), (2), (3), (4),
(5)").c_str(),
&error),
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementExecuteQuery(&statement, nullptr, nullptr, &error),
IsOkStatus(&error));
- ASSERT_THAT(AdbcStatementSetSqlQuery(
- &statement, "DELETE FROM \"delete_test\" WHERE foo >= 3",
&error),
- IsOkStatus(&error));
+ ASSERT_THAT(
+ AdbcStatementSetSqlQuery(
+ &statement, ("DELETE FROM " + table + " WHERE foo >= 3").c_str(),
&error),
+ IsOkStatus(&error));
int64_t rows_affected = 0;
ASSERT_THAT(AdbcStatementExecuteQuery(&statement, nullptr, &rows_affected,
&error),
@@ -2573,23 +2603,26 @@ void
StatementTest::TestSqlQueryRowsAffectedDeleteStream() {
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementNew(&connection, &statement, &error),
IsOkStatus(&error));
- ASSERT_THAT(AdbcStatementSetSqlQuery(&statement,
- "CREATE TABLE \"delete_test\" (foo
INT)", &error),
+ std::string table = quirks()->QuoteIdentifier("delete_test");
+ ASSERT_THAT(AdbcStatementSetSqlQuery(
+ &statement, ("CREATE TABLE " + table + " (foo
INT)").c_str(), &error),
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementExecuteQuery(&statement, nullptr, nullptr, &error),
IsOkStatus(&error));
ASSERT_THAT(
AdbcStatementSetSqlQuery(
- &statement, "INSERT INTO \"delete_test\" (foo) VALUES (1), (2), (3),
(4), (5)",
+ &statement,
+ ("INSERT INTO " + table + " (foo) VALUES (1), (2), (3), (4),
(5)").c_str(),
&error),
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementExecuteQuery(&statement, nullptr, nullptr, &error),
IsOkStatus(&error));
- ASSERT_THAT(AdbcStatementSetSqlQuery(
- &statement, "DELETE FROM \"delete_test\" WHERE foo >= 3",
&error),
- IsOkStatus(&error));
+ ASSERT_THAT(
+ AdbcStatementSetSqlQuery(
+ &statement, ("DELETE FROM " + table + " WHERE foo >= 3").c_str(),
&error),
+ IsOkStatus(&error));
adbc_validation::StreamReader reader;
ASSERT_THAT(
@@ -2607,6 +2640,8 @@ void StatementTest::TestTransactions() {
ASSERT_THAT(quirks()->DropTable(&connection, "bulk_ingest", &error),
IsOkStatus(&error));
+ std::string table = quirks()->QuoteIdentifier("bulk_ingest");
+
if (quirks()->supports_get_option()) {
auto autocommit =
ConnectionGetOption(&connection, ADBC_CONNECTION_OPTION_AUTOCOMMIT,
&error);
@@ -2642,7 +2677,7 @@ void StatementTest::TestTransactions() {
ASSERT_THAT(AdbcStatementNew(&connection, &statement.value, &error),
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementSetSqlQuery(&statement.value,
- "SELECT * FROM \"bulk_ingest\"",
&error),
+ ("SELECT * FROM " + table).c_str(),
&error),
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementExecuteQuery(&statement.value,
&reader.stream.value,
&reader.rows_affected, &error),
@@ -2659,7 +2694,7 @@ void StatementTest::TestTransactions() {
CHECK_OK(AdbcStatementNew(&connection2.value,
&statement.value, &error));
CHECK_OK(AdbcStatementSetSqlQuery(
- &statement.value, "SELECT * FROM \"bulk_ingest\"",
&error));
+ &statement.value, ("SELECT * FROM " + table).c_str(),
&error));
CHECK_OK(AdbcStatementExecuteQuery(&statement.value,
&reader.stream.value,
&reader.rows_affected,
&error));
return ADBC_STATUS_OK;
@@ -2678,7 +2713,7 @@ void StatementTest::TestTransactions() {
CHECK_OK(AdbcStatementNew(&connection, &statement.value,
&error));
CHECK_OK(AdbcStatementSetSqlQuery(
- &statement.value, "SELECT * FROM \"bulk_ingest\"",
&error));
+ &statement.value, ("SELECT * FROM " + table).c_str(),
&error));
CHECK_OK(AdbcStatementExecuteQuery(&statement.value,
&reader.stream.value,
&reader.rows_affected,
&error));
return ADBC_STATUS_OK;
@@ -2701,7 +2736,7 @@ void StatementTest::TestTransactions() {
ASSERT_THAT(AdbcStatementNew(&connection2.value, &statement.value, &error),
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementSetSqlQuery(&statement.value,
- "SELECT * FROM \"bulk_ingest\"",
&error),
+ ("SELECT * FROM " + table).c_str(),
&error),
IsOkStatus(&error));
ASSERT_THAT(AdbcStatementExecuteQuery(&statement.value,
&reader.stream.value,
&reader.rows_affected, &error),