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 d6255ac0a fix(c/driver/postgresql): Ensure schema ordering is 
consisent and respects case sensitivity of table names (#2028)
d6255ac0a is described below

commit d6255ac0a10825f98846f112f13ffd0dc013e3f5
Author: Dewey Dunnington <[email protected]>
AuthorDate: Tue Jul 23 22:27:06 2024 -0300

    fix(c/driver/postgresql): Ensure schema ordering is consisent and respects 
case sensitivity of table names (#2028)
    
    Fixes #2006.
---
 c/driver/postgresql/connection.cc         | 20 +++++++++------
 c/driver/postgresql/postgresql_test.cc    | 41 +++++++++++++++++++++++++++++++
 c/validation/adbc_validation_statement.cc |  6 ++---
 3 files changed, 57 insertions(+), 10 deletions(-)

diff --git a/c/driver/postgresql/connection.cc 
b/c/driver/postgresql/connection.cc
index e5e524beb..443e37aad 100644
--- a/c/driver/postgresql/connection.cc
+++ b/c/driver/postgresql/connection.cc
@@ -1146,19 +1146,25 @@ AdbcStatusCode PostgresConnection::GetTableSchema(const 
char* catalog,
                                                   struct AdbcError* error) {
   AdbcStatusCode final_status = ADBC_STATUS_OK;
 
+  char* quoted = PQescapeIdentifier(conn_, table_name, strlen(table_name));
+  std::string table_name_str(quoted);
+  PQfreemem(quoted);
+
+  if (db_schema != nullptr) {
+    quoted = PQescapeIdentifier(conn_, db_schema, strlen(db_schema));
+    table_name_str = std::string(quoted) + "." + table_name_str;
+    PQfreemem(quoted);
+  }
+
   std::string query =
       "SELECT attname, atttypid "
       "FROM pg_catalog.pg_class AS cls "
       "INNER JOIN pg_catalog.pg_attribute AS attr ON cls.oid = attr.attrelid "
       "INNER JOIN pg_catalog.pg_type AS typ ON attr.atttypid = typ.oid "
-      "WHERE attr.attnum >= 0 AND cls.oid = $1::regclass::oid";
+      "WHERE attr.attnum >= 0 AND cls.oid = $1::regclass::oid "
+      "ORDER BY attr.attnum";
 
-  std::vector<std::string> params;
-  if (db_schema != nullptr) {
-    params.push_back(std::string(db_schema) + "." + table_name);
-  } else {
-    params.push_back(table_name);
-  }
+  std::vector<std::string> params = {table_name_str};
 
   PqResultHelper result_helper =
       PqResultHelper{conn_, std::string(query.c_str()), params, error};
diff --git a/c/driver/postgresql/postgresql_test.cc 
b/c/driver/postgresql/postgresql_test.cc
index 48a15d693..ab95d3e65 100644
--- a/c/driver/postgresql/postgresql_test.cc
+++ b/c/driver/postgresql/postgresql_test.cc
@@ -673,6 +673,47 @@ TEST_F(PostgresConnectionTest, MetadataSetCurrentDbSchema) 
{
   ASSERT_THAT(AdbcStatementRelease(&statement.value, &error), 
IsOkStatus(&error));
 }
 
+TEST_F(PostgresConnectionTest, MetadataGetSchemaCaseSensitiveTable) {
+  ASSERT_THAT(AdbcConnectionNew(&connection, &error), IsOkStatus(&error));
+  ASSERT_THAT(AdbcConnectionInit(&connection, &database, &error), 
IsOkStatus(&error));
+
+  // Create sample table
+  {
+    adbc_validation::Handle<struct AdbcStatement> statement;
+    ASSERT_THAT(AdbcStatementNew(&connection, &statement.value, &error),
+                IsOkStatus(&error));
+
+    ASSERT_THAT(AdbcStatementSetSqlQuery(&statement.value,
+                                         "DROP TABLE IF EXISTS \"Uppercase\"", 
&error),
+                IsOkStatus(&error));
+    ASSERT_THAT(AdbcStatementExecuteQuery(&statement.value, nullptr, nullptr, 
&error),
+                IsOkStatus(&error));
+
+    ASSERT_THAT(
+        AdbcStatementSetSqlQuery(
+            &statement.value, "CREATE TABLE \"Uppercase\" (ints INT, strs 
TEXT)", &error),
+        IsOkStatus(&error));
+    ASSERT_THAT(AdbcStatementExecuteQuery(&statement.value, nullptr, nullptr, 
&error),
+                IsOkStatus(&error));
+  }
+
+  // Check its schema
+  nanoarrow::UniqueSchema schema;
+  ASSERT_THAT(AdbcConnectionGetTableSchema(&connection, nullptr, nullptr, 
"Uppercase",
+                                           schema.get(), &error),
+              IsOkStatus(&error));
+
+  ASSERT_NE(schema->release, nullptr);
+  ASSERT_STREQ(schema->format, "+s");
+  ASSERT_EQ(schema->n_children, 2);
+  ASSERT_STREQ(schema->children[0]->format, "i");
+  ASSERT_STREQ(schema->children[1]->format, "u");
+  ASSERT_STREQ(schema->children[0]->name, "ints");
+  ASSERT_STREQ(schema->children[1]->name, "strs");
+
+  // Do we have to release the connection here?
+}
+
 TEST_F(PostgresConnectionTest, MetadataGetStatistics) {
   if (!quirks()->supports_statistics()) {
     GTEST_SKIP();
diff --git a/c/validation/adbc_validation_statement.cc 
b/c/validation/adbc_validation_statement.cc
index 333baf141..8965e95a0 100644
--- a/c/validation/adbc_validation_statement.cc
+++ b/c/validation/adbc_validation_statement.cc
@@ -2065,15 +2065,15 @@ void 
StatementTest::TestSqlPrepareErrorParamCountMismatch() {
 void StatementTest::TestSqlQueryEmpty() {
   ASSERT_THAT(AdbcStatementNew(&connection, &statement, &error), 
IsOkStatus(&error));
 
-  ASSERT_THAT(quirks()->DropTable(&connection, "QUERYEMPTY", &error), 
IsOkStatus(&error));
+  ASSERT_THAT(quirks()->DropTable(&connection, "queryempty", &error), 
IsOkStatus(&error));
   ASSERT_THAT(
-      AdbcStatementSetSqlQuery(&statement, "CREATE TABLE QUERYEMPTY (FOO 
INT)", &error),
+      AdbcStatementSetSqlQuery(&statement, "CREATE TABLE queryempty (FOO 
INT)", &error),
       IsOkStatus(&error));
   ASSERT_THAT(AdbcStatementExecuteQuery(&statement, nullptr, nullptr, &error),
               IsOkStatus(&error));
 
   ASSERT_THAT(
-      AdbcStatementSetSqlQuery(&statement, "SELECT * FROM QUERYEMPTY WHERE 
1=0", &error),
+      AdbcStatementSetSqlQuery(&statement, "SELECT * FROM queryempty WHERE 
1=0", &error),
       IsOkStatus(&error));
   {
     StreamReader reader;

Reply via email to