-
Notifications
You must be signed in to change notification settings - Fork 105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(go/adbc/driver/snowflake): Add support for table constraints when calling GetObjects #1455
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -408,7 +408,6 @@ func toField(name string, isnullable bool, dataType string, numPrec, numPrecRadi | |
} | ||
|
||
func toXdbcDataType(dt arrow.DataType) (xdbcType internal.XdbcDataType) { | ||
xdbcType = internal.XdbcDataType_XDBC_UNKNOWN_TYPE | ||
switch dt.ID() { | ||
case arrow.EXTENSION: | ||
return toXdbcDataType(dt.(arrow.ExtensionType).StorageType()) | ||
|
@@ -640,7 +639,8 @@ func (c *cnxn) getColumnsMetadata(ctx context.Context, matchingCatalogNames []st | |
err = rows.Scan(&data.TblType, &data.Dbname, &data.Schema, &data.TblName, &data.ColName, | ||
&data.OrdinalPos, &data.IsNullable, &data.DataType, &data.NumericPrec, | ||
&data.NumericPrecRadix, &data.NumericScale, &data.IsIdent, &data.IdentGen, | ||
&data.IdentIncrement, &data.CharMaxLength, &data.CharOctetLength, &data.DatetimePrec, &data.Comment) | ||
&data.IdentIncrement, &data.CharMaxLength, &data.CharOctetLength, &data.DatetimePrec, &data.Comment, | ||
&data.ConstraintName, &data.ConstraintType) | ||
if err != nil { | ||
return nil, errToAdbcErr(adbc.StatusIO, err) | ||
} | ||
|
@@ -701,10 +701,16 @@ func prepareTablesSQL(matchingCatalogNames []string, catalog *string, dbSchema * | |
if query != "" { | ||
query += " UNION ALL " | ||
} | ||
query += `SELECT * FROM "` + strings.ReplaceAll(catalog_name, "\"", "\"\"") + `".INFORMATION_SCHEMA.TABLES` | ||
query += `SELECT T.*, K.constraint_name, K.constraint_type FROM "` + strings.ReplaceAll(catalog_name, "\"", "\"\"") + `".INFORMATION_SCHEMA.TABLES AS T | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As per the schema, |
||
LEFT OUTER JOIN | ||
"` + strings.ReplaceAll(catalog_name, "\"", "\"\"") + `".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND t.table_name = K.table_name` | ||
} | ||
|
||
query = `SELECT table_catalog, table_schema, table_name, table_type FROM (` + query + `)` | ||
query = `SELECT table_catalog, table_schema, table_name, table_type, constraint_name, constraint_type FROM (` + query + `)` | ||
conditions, queryArgs := prepareFilterConditions(adbc.ObjectDepthTables, catalog, dbSchema, tableName, nil, tableType) | ||
if conditions != "" { | ||
query += " WHERE " + conditions | ||
|
@@ -719,22 +725,30 @@ func prepareColumnsSQL(matchingCatalogNames []string, catalog *string, dbSchema | |
prefixQuery += " UNION ALL " | ||
} | ||
prefixQuery += `SELECT T.table_type, | ||
C.* | ||
C.*, | ||
K.constraint_name, K.constraint_type | ||
FROM | ||
"` + strings.ReplaceAll(catalog_name, "\"", "\"\"") + `".INFORMATION_SCHEMA.TABLES AS T | ||
JOIN | ||
"` + strings.ReplaceAll(catalog_name, "\"", "\"\"") + `".INFORMATION_SCHEMA.COLUMNS AS C | ||
ON | ||
T.table_catalog = C.table_catalog | ||
AND T.table_schema = C.table_schema | ||
AND t.table_name = C.table_name` | ||
AND T.table_name = C.table_name | ||
LEFT OUTER JOIN | ||
"` + strings.ReplaceAll(catalog_name, "\"", "\"\"") + `".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND T.table_name = K.table_name` | ||
} | ||
|
||
prefixQuery = `SELECT table_type, table_catalog, table_schema, table_name, column_name, | ||
ordinal_position, is_nullable::boolean, data_type, numeric_precision, | ||
numeric_precision_radix, numeric_scale, is_identity::boolean, | ||
identity_generation, identity_increment, | ||
character_maximum_length, character_octet_length, datetime_precision, comment FROM (` + prefixQuery + `)` | ||
character_maximum_length, character_octet_length, datetime_precision, comment, | ||
constraint_name, constraint_type FROM (` + prefixQuery + `)` | ||
ordering := ` ORDER BY table_catalog, table_schema, table_name, ordinal_position` | ||
conditions, queryArgs := prepareFilterConditions(adbc.ObjectDepthColumns, catalog, dbSchema, tableName, columnName, tableType) | ||
query := prefixQuery | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -158,15 +158,25 @@ func TestPrepareTablesSQLWithNoFilter(t *testing.T) { | |
tableNamePattern := "" | ||
tableType := make([]string, 0) | ||
|
||
expected := `SELECT table_catalog, table_schema, table_name, table_type | ||
FROM | ||
( | ||
SELECT * FROM "DEMO_DB".INFORMATION_SCHEMA.TABLES | ||
UNION ALL | ||
SELECT * FROM "DEMOADB".INFORMATION_SCHEMA.TABLES | ||
UNION ALL | ||
SELECT * FROM "DEMO'DB".INFORMATION_SCHEMA.TABLES | ||
)` | ||
expected := `SELECT table_catalog, table_schema, table_name, table_type, constraint_name, constraint_type FROM (SELECT T.*, K.constraint_name, K.constraint_type FROM "DEMO_DB".INFORMATION_SCHEMA.TABLES AS T | ||
LEFT OUTER JOIN | ||
"DEMO_DB".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND t.table_name = K.table_name UNION ALL SELECT T.*, K.constraint_name, K.constraint_type FROM "DEMOADB".INFORMATION_SCHEMA.TABLES AS T | ||
LEFT OUTER JOIN | ||
"DEMOADB".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND t.table_name = K.table_name UNION ALL SELECT T.*, K.constraint_name, K.constraint_type FROM "DEMO'DB".INFORMATION_SCHEMA.TABLES AS T | ||
LEFT OUTER JOIN | ||
"DEMO'DB".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND t.table_name = K.table_name)` | ||
actual, queryArgs := prepareTablesSQL(catalogNames[:], &catalogPattern, &schemaPattern, &tableNamePattern, tableType[:]) | ||
|
||
println("Query Args", queryArgs) | ||
|
@@ -180,16 +190,25 @@ func TestPrepareTablesSQLWithNoTableTypeFilter(t *testing.T) { | |
tableNamePattern := "ADBC-TABLE" | ||
tableType := make([]string, 0) | ||
|
||
expected := `SELECT table_catalog, table_schema, table_name, table_type | ||
FROM | ||
( | ||
SELECT * FROM "DEMO_DB".INFORMATION_SCHEMA.TABLES | ||
UNION ALL | ||
SELECT * FROM "DEMOADB".INFORMATION_SCHEMA.TABLES | ||
UNION ALL | ||
SELECT * FROM "DEMO'DB".INFORMATION_SCHEMA.TABLES | ||
) | ||
WHERE TABLE_CATALOG ILIKE ? AND TABLE_SCHEMA ILIKE ? AND TABLE_NAME ILIKE ? ` | ||
expected := `SELECT table_catalog, table_schema, table_name, table_type, constraint_name, constraint_type FROM (SELECT T.*, K.constraint_name, K.constraint_type FROM "DEMO_DB".INFORMATION_SCHEMA.TABLES AS T | ||
LEFT OUTER JOIN | ||
"DEMO_DB".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND t.table_name = K.table_name UNION ALL SELECT T.*, K.constraint_name, K.constraint_type FROM "DEMOADB".INFORMATION_SCHEMA.TABLES AS T | ||
LEFT OUTER JOIN | ||
"DEMOADB".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND t.table_name = K.table_name UNION ALL SELECT T.*, K.constraint_name, K.constraint_type FROM "DEMO'DB".INFORMATION_SCHEMA.TABLES AS T | ||
LEFT OUTER JOIN | ||
"DEMO'DB".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND t.table_name = K.table_name) WHERE TABLE_CATALOG ILIKE ? AND TABLE_SCHEMA ILIKE ? AND TABLE_NAME ILIKE ? ` | ||
actual, queryArgs := prepareTablesSQL(catalogNames[:], &catalogPattern, &schemaPattern, &tableNamePattern, tableType[:]) | ||
|
||
stringqueryArgs := make([]string, len(queryArgs)) // Pre-allocate the right size | ||
|
@@ -208,16 +227,26 @@ func TestPrepareTablesSQL(t *testing.T) { | |
tableNamePattern := "ADBC-TABLE" | ||
tableType := [2]string{"BASE TABLE", "VIEW"} | ||
|
||
expected := `SELECT table_catalog, table_schema, table_name, table_type | ||
FROM | ||
( | ||
SELECT * FROM "DEMO_DB".INFORMATION_SCHEMA.TABLES | ||
UNION ALL | ||
SELECT * FROM "DEMOADB".INFORMATION_SCHEMA.TABLES | ||
UNION ALL | ||
SELECT * FROM "DEMO'DB".INFORMATION_SCHEMA.TABLES | ||
) | ||
WHERE TABLE_CATALOG ILIKE ? AND TABLE_SCHEMA ILIKE ? AND TABLE_NAME ILIKE ? AND TABLE_TYPE IN ('BASE TABLE','VIEW')` | ||
expected := `SELECT table_catalog, table_schema, table_name, table_type, constraint_name, constraint_type FROM (SELECT T.*, K.constraint_name, K.constraint_type FROM "DEMO_DB".INFORMATION_SCHEMA.TABLES AS T | ||
LEFT OUTER JOIN | ||
"DEMO_DB".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND t.table_name = K.table_name UNION ALL SELECT T.*, K.constraint_name, K.constraint_type FROM "DEMOADB".INFORMATION_SCHEMA.TABLES AS T | ||
LEFT OUTER JOIN | ||
"DEMOADB".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND t.table_name = K.table_name UNION ALL SELECT T.*, K.constraint_name, K.constraint_type FROM "DEMO'DB".INFORMATION_SCHEMA.TABLES AS T | ||
LEFT OUTER JOIN | ||
"DEMO'DB".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND t.table_name = K.table_name) | ||
WHERE TABLE_CATALOG ILIKE ? AND TABLE_SCHEMA ILIKE ? AND TABLE_NAME ILIKE ? AND TABLE_TYPE IN ('BASE TABLE','VIEW')` | ||
actual, queryArgs := prepareTablesSQL(catalogNames[:], &catalogPattern, &schemaPattern, &tableNamePattern, tableType[:]) | ||
|
||
stringqueryArgs := make([]string, len(queryArgs)) // Pre-allocate the right size | ||
|
@@ -238,29 +267,44 @@ func TestPrepareColumnsSQLNoFilter(t *testing.T) { | |
tableType := make([]string, 0) | ||
|
||
expected := `SELECT table_type, table_catalog, table_schema, table_name, column_name, | ||
ordinal_position, is_nullable::boolean, data_type, numeric_precision, | ||
numeric_precision_radix, numeric_scale, is_identity::boolean, | ||
identity_generation, identity_increment, | ||
character_maximum_length, character_octet_length, datetime_precision, comment | ||
FROM | ||
( | ||
SELECT T.table_type, C.* | ||
FROM | ||
"DEMO_DB".INFORMATION_SCHEMA.TABLES AS T | ||
JOIN | ||
"DEMO_DB".INFORMATION_SCHEMA.COLUMNS AS C | ||
ON | ||
T.table_catalog = C.table_catalog AND T.table_schema = C.table_schema AND t.table_name = C.table_name | ||
UNION ALL | ||
SELECT T.table_type, C.* | ||
FROM | ||
"DEMOADB".INFORMATION_SCHEMA.TABLES AS T | ||
JOIN | ||
"DEMOADB".INFORMATION_SCHEMA.COLUMNS AS C | ||
ON | ||
T.table_catalog = C.table_catalog AND T.table_schema = C.table_schema AND t.table_name = C.table_name | ||
) | ||
ORDER BY table_catalog, table_schema, table_name, ordinal_position` | ||
ordinal_position, is_nullable::boolean, data_type, numeric_precision, | ||
numeric_precision_radix, numeric_scale, is_identity::boolean, | ||
identity_generation, identity_increment, | ||
character_maximum_length, character_octet_length, datetime_precision, comment, | ||
constraint_name, constraint_type FROM (SELECT T.table_type, | ||
C.*, | ||
K.constraint_name, K.constraint_type | ||
FROM | ||
"DEMO_DB".INFORMATION_SCHEMA.TABLES AS T | ||
JOIN | ||
"DEMO_DB".INFORMATION_SCHEMA.COLUMNS AS C | ||
ON | ||
T.table_catalog = C.table_catalog | ||
AND T.table_schema = C.table_schema | ||
AND T.table_name = C.table_name | ||
LEFT OUTER JOIN | ||
"DEMO_DB".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND T.table_name = K.table_name UNION ALL SELECT T.table_type, | ||
C.*, | ||
K.constraint_name, K.constraint_type | ||
FROM | ||
"DEMOADB".INFORMATION_SCHEMA.TABLES AS T | ||
JOIN | ||
"DEMOADB".INFORMATION_SCHEMA.COLUMNS AS C | ||
ON | ||
T.table_catalog = C.table_catalog | ||
AND T.table_schema = C.table_schema | ||
AND T.table_name = C.table_name | ||
LEFT OUTER JOIN | ||
"DEMOADB".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND T.table_name = K.table_name) | ||
ORDER BY table_catalog, table_schema, table_name, ordinal_position` | ||
actual, queryArgs := prepareColumnsSQL(catalogNames[:], &catalogPattern, &schemaPattern, &tableNamePattern, &columnNamePattern, tableType[:]) | ||
|
||
println("Query Args", queryArgs) | ||
|
@@ -276,30 +320,45 @@ func TestPrepareColumnsSQL(t *testing.T) { | |
tableType := [2]string{"BASE TABLE", "VIEW"} | ||
|
||
expected := `SELECT table_type, table_catalog, table_schema, table_name, column_name, | ||
ordinal_position, is_nullable::boolean, data_type, numeric_precision, | ||
numeric_precision_radix, numeric_scale, is_identity::boolean, | ||
identity_generation, identity_increment, | ||
character_maximum_length, character_octet_length, datetime_precision, comment | ||
FROM | ||
( | ||
SELECT T.table_type, C.* | ||
FROM | ||
"DEMO_DB".INFORMATION_SCHEMA.TABLES AS T | ||
JOIN | ||
"DEMO_DB".INFORMATION_SCHEMA.COLUMNS AS C | ||
ON | ||
T.table_catalog = C.table_catalog AND T.table_schema = C.table_schema AND t.table_name = C.table_name | ||
UNION ALL | ||
SELECT T.table_type, C.* | ||
FROM | ||
"DEMOADB".INFORMATION_SCHEMA.TABLES AS T | ||
JOIN | ||
"DEMOADB".INFORMATION_SCHEMA.COLUMNS AS C | ||
ON | ||
T.table_catalog = C.table_catalog AND T.table_schema = C.table_schema AND t.table_name = C.table_name | ||
) | ||
WHERE TABLE_CATALOG ILIKE ? AND TABLE_SCHEMA ILIKE ? AND TABLE_NAME ILIKE ? AND COLUMN_NAME ILIKE ? AND TABLE_TYPE IN ('BASE TABLE','VIEW') | ||
ORDER BY table_catalog, table_schema, table_name, ordinal_position` | ||
ordinal_position, is_nullable::boolean, data_type, numeric_precision, | ||
numeric_precision_radix, numeric_scale, is_identity::boolean, | ||
identity_generation, identity_increment, | ||
character_maximum_length, character_octet_length, datetime_precision, comment, | ||
constraint_name, constraint_type FROM (SELECT T.table_type, | ||
C.*, | ||
K.constraint_name, K.constraint_type | ||
FROM | ||
"DEMO_DB".INFORMATION_SCHEMA.TABLES AS T | ||
JOIN | ||
"DEMO_DB".INFORMATION_SCHEMA.COLUMNS AS C | ||
ON | ||
T.table_catalog = C.table_catalog | ||
AND T.table_schema = C.table_schema | ||
AND T.table_name = C.table_name | ||
LEFT OUTER JOIN | ||
"DEMO_DB".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND T.table_name = K.table_name UNION ALL SELECT T.table_type, | ||
C.*, | ||
K.constraint_name, K.constraint_type | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding a test similar to TestMetadataGetObjectsColumnsXdbc will be helpful to verify the table constraints are returned correctly. Adding tests in the CSharp layer would also work. |
||
FROM | ||
"DEMOADB".INFORMATION_SCHEMA.TABLES AS T | ||
JOIN | ||
"DEMOADB".INFORMATION_SCHEMA.COLUMNS AS C | ||
ON | ||
T.table_catalog = C.table_catalog | ||
AND T.table_schema = C.table_schema | ||
AND T.table_name = C.table_name | ||
LEFT OUTER JOIN | ||
"DEMOADB".INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS K | ||
ON | ||
T.table_catalog = K.table_catalog | ||
AND T.table_schema = K.table_schema | ||
AND T.table_name = K.table_name) | ||
WHERE TABLE_CATALOG ILIKE ? AND TABLE_SCHEMA ILIKE ? AND TABLE_NAME ILIKE ? AND COLUMN_NAME ILIKE ? AND TABLE_TYPE IN ('BASE TABLE','VIEW') | ||
ORDER BY table_catalog, table_schema, table_name, ordinal_position` | ||
actual, queryArgs := prepareColumnsSQL(catalogNames[:], &catalogPattern, &schemaPattern, &tableNamePattern, &columnNamePattern, tableType[:]) | ||
|
||
stringqueryArgs := make([]string, len(queryArgs)) // Pre-allocate the right size | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TableInfo struct doesn't currently capture table constraints.
I couldn't locate them being appended to tableConstraintsBuilder which seems to be marked as unimplemented.