diff --git a/c/driver/common/utils.c b/c/driver/common/utils.c index ad82e7929a..bb3dd3f0e2 100644 --- a/c/driver/common/utils.c +++ b/c/driver/common/utils.c @@ -76,6 +76,12 @@ struct AdbcErrorDetails { int capacity; }; +bool StringViewEquals(struct ArrowStringView stringView, const char* str) { + int64_t len = (int64_t)strlen(str); + return len == stringView.size_bytes && + !strncmp(stringView.data, str, stringView.size_bytes); +} + static void ReleaseErrorWithDetails(struct AdbcError* error) { struct AdbcErrorDetails* details = (struct AdbcErrorDetails*)error->private_data; free(details->message); @@ -1006,8 +1012,7 @@ struct AdbcGetObjectsCatalog* AdbcGetObjectsDataGetCatalogByName( if (catalog_name != NULL) { for (int64_t i = 0; i < get_objects_data->n_catalogs; i++) { struct AdbcGetObjectsCatalog* catalog = get_objects_data->catalogs[i]; - struct ArrowStringView name = catalog->catalog_name; - if (!strncmp(name.data, catalog_name, name.size_bytes)) { + if (StringViewEquals(catalog->catalog_name, catalog_name)) { return catalog; } } @@ -1025,8 +1030,7 @@ struct AdbcGetObjectsSchema* AdbcGetObjectsDataGetSchemaByName( if (catalog != NULL) { for (int64_t i = 0; i < catalog->n_db_schemas; i++) { struct AdbcGetObjectsSchema* schema = catalog->catalog_db_schemas[i]; - struct ArrowStringView name = schema->db_schema_name; - if (!strncmp(name.data, schema_name, name.size_bytes)) { + if (StringViewEquals(schema->db_schema_name, schema_name)) { return schema; } } @@ -1045,8 +1049,7 @@ struct AdbcGetObjectsTable* AdbcGetObjectsDataGetTableByName( if (schema != NULL) { for (int64_t i = 0; i < schema->n_db_schema_tables; i++) { struct AdbcGetObjectsTable* table = schema->db_schema_tables[i]; - struct ArrowStringView name = table->table_name; - if (!strncmp(name.data, table_name, name.size_bytes)) { + if (StringViewEquals(table->table_name, table_name)) { return table; } } @@ -1066,8 +1069,7 @@ struct AdbcGetObjectsColumn* AdbcGetObjectsDataGetColumnByName( if (table != NULL) { for (int64_t i = 0; i < table->n_table_columns; i++) { struct AdbcGetObjectsColumn* column = table->table_columns[i]; - struct ArrowStringView name = column->column_name; - if (!strncmp(name.data, column_name, name.size_bytes)) { + if (StringViewEquals(column->column_name, column_name)) { return column; } } @@ -1087,8 +1089,7 @@ struct AdbcGetObjectsConstraint* AdbcGetObjectsDataGetConstraintByName( if (table != NULL) { for (int64_t i = 0; i < table->n_table_constraints; i++) { struct AdbcGetObjectsConstraint* constraint = table->table_constraints[i]; - struct ArrowStringView name = constraint->constraint_name; - if (!strncmp(name.data, constraint_name, name.size_bytes)) { + if (StringViewEquals(constraint->constraint_name, constraint_name)) { return constraint; } } diff --git a/c/driver/common/utils_test.cc b/c/driver/common/utils_test.cc index d5c202bf2e..489af163fd 100644 --- a/c/driver/common/utils_test.cc +++ b/c/driver/common/utils_test.cc @@ -167,3 +167,84 @@ TEST(ErrorDetails, RoundTripValues) { error.release(&error); } + +// https://github.com/apache/arrow-adbc/issues/1100 +TEST(AdbcGetObjectsData, GetObjectsByName) { + // Mock objects where the names being compared share the same prefix + struct AdbcGetObjectsData mock_data; + struct AdbcGetObjectsCatalog mock_catalog; + struct AdbcGetObjectsSchema mock_schema; + struct AdbcGetObjectsTable mock_table, mock_table_suffix; + struct AdbcGetObjectsColumn mock_column, mock_column_suffix; + struct AdbcGetObjectsConstraint mock_constraint, mock_constraint_suffix; + + mock_catalog.catalog_name = {"mock_catalog", (int64_t)strlen("mock_catalog")}; + mock_schema.db_schema_name = {"mock_schema", (int64_t)strlen("mock_schema")}; + mock_table.table_name = {"table", (int64_t)strlen("table")}; + mock_table_suffix.table_name = {"table_suffix", (int64_t)strlen("table_suffix")}; + mock_column.column_name = {"column", (int64_t)strlen("column")}; + mock_column_suffix.column_name = {"column_suffix", (int64_t)strlen("column_suffix")}; + mock_constraint.constraint_name = {"constraint", (int64_t)strlen("constraint")}; + mock_constraint_suffix.constraint_name = {"constraint_suffix", + (int64_t)strlen("constraint_suffix")}; + + struct AdbcGetObjectsCatalog* catalogs[] = {&mock_catalog}; + mock_data.catalogs = catalogs; + mock_data.n_catalogs = 1; + + struct AdbcGetObjectsSchema* schemas[] = {&mock_schema}; + mock_catalog.catalog_db_schemas = schemas; + mock_catalog.n_db_schemas = 1; + + struct AdbcGetObjectsTable* tables[] = {&mock_table, &mock_table_suffix}; + mock_schema.db_schema_tables = tables; + mock_schema.n_db_schema_tables = 2; + + struct AdbcGetObjectsColumn* columns[] = {&mock_column, &mock_column_suffix}; + mock_table.table_columns = columns; + mock_table.n_table_columns = 2; + + struct AdbcGetObjectsConstraint* constraints[] = {&mock_constraint, + &mock_constraint_suffix}; + mock_table.table_constraints = constraints; + mock_table.n_table_constraints = 2; + + EXPECT_EQ(AdbcGetObjectsDataGetTableByName(&mock_data, "mock_catalog", "mock_schema", + "table"), + &mock_table); + EXPECT_EQ(AdbcGetObjectsDataGetTableByName(&mock_data, "mock_catalog", "mock_schema", + "table_suffix"), + &mock_table_suffix); + EXPECT_EQ(AdbcGetObjectsDataGetTableByName(&mock_data, "mock_catalog", "mock_schema", + "nonexistent"), + nullptr); + + EXPECT_EQ(AdbcGetObjectsDataGetCatalogByName(&mock_data, "mock_catalog"), + &mock_catalog); + EXPECT_EQ(AdbcGetObjectsDataGetCatalogByName(&mock_data, "nonexistent"), nullptr); + + EXPECT_EQ(AdbcGetObjectsDataGetSchemaByName(&mock_data, "mock_catalog", "mock_schema"), + &mock_schema); + EXPECT_EQ(AdbcGetObjectsDataGetSchemaByName(&mock_data, "mock_catalog", "nonexistent"), + nullptr); + + EXPECT_EQ(AdbcGetObjectsDataGetColumnByName(&mock_data, "mock_catalog", "mock_schema", + "table", "column"), + &mock_column); + EXPECT_EQ(AdbcGetObjectsDataGetColumnByName(&mock_data, "mock_catalog", "mock_schema", + "table", "column_suffix"), + &mock_column_suffix); + EXPECT_EQ(AdbcGetObjectsDataGetColumnByName(&mock_data, "mock_catalog", "mock_schema", + "table", "nonexistent"), + nullptr); + + EXPECT_EQ(AdbcGetObjectsDataGetConstraintByName(&mock_data, "mock_catalog", + "mock_schema", "table", "constraint"), + &mock_constraint); + EXPECT_EQ(AdbcGetObjectsDataGetConstraintByName( + &mock_data, "mock_catalog", "mock_schema", "table", "constraint_suffix"), + &mock_constraint_suffix); + EXPECT_EQ(AdbcGetObjectsDataGetConstraintByName(&mock_data, "mock_catalog", + "mock_schema", "table", "nonexistent"), + nullptr); +}