fix(xugu): match primary keys across catalog case

This commit is contained in:
t8y2
2026-09-02 17:02:03 +08:00
committed by GitHub
parent 061041e1d7
commit f5113def38
2 changed files with 37 additions and 2 deletions
+20 -2
View File
@@ -2765,7 +2765,7 @@ func (s *server) getColumns(schema, table string) ([]columnInfo, error) {
item.DataType = normalizeXuguColumnType(item.DataType, varying)
item.IsNullable = !truthy(notNull)
item.DefaultOnNull = xuguInt(onNull)
item.IsPrimaryKey = primaryKeys[item.Name]
item.IsPrimaryKey = xuguPrimaryKeyMatches(item.Name, primaryKeys)
item.NumericPrecision, item.NumericScale, item.CharacterMaximumLength = decodeXuguScale(item.DataType, scale)
result = append(result, item)
}
@@ -2802,7 +2802,7 @@ func (s *server) columnsFromSelect(schema, table string, primaryKeys map[string]
item := columnInfo{
Name: columnType.Name(),
DataType: columnType.DatabaseTypeName(),
IsPrimaryKey: primaryKeys[columnType.Name()],
IsPrimaryKey: xuguPrimaryKeyMatches(columnType.Name(), primaryKeys),
}
if nullable, ok := columnType.Nullable(); ok {
item.IsNullable = nullable
@@ -2860,6 +2860,24 @@ func (s *server) primaryKeyColumns(schema, table string) (map[string]bool, error
return result, rows.Err()
}
// Xugu may report an unquoted primary-key name with a different case from
// ALL_COLUMNS (for example, DEFINE contains "ID" while COL_NAME is "id").
// Exact matches always win so quoted identifiers that differ only by case stay
// distinct; a case-insensitive fallback is used only when it identifies one
// primary-key column.
func xuguPrimaryKeyMatches(columnName string, primaryKeys map[string]bool) bool {
if primaryKeys[columnName] {
return true
}
matches := 0
for primaryKey := range primaryKeys {
if strings.EqualFold(primaryKey, columnName) {
matches++
}
}
return matches == 1
}
func (s *server) listIndexes(schema, table string) ([]indexInfo, error) {
catalogSchema, catalogTable, err := s.resolveCatalogTableName(schema, table)
if err != nil {
+17
View File
@@ -949,6 +949,23 @@ func TestGetColumnsFallsBackWhenOnNullMetadataIsUnavailable(t *testing.T) {
}
}
func TestXuguPrimaryKeyMatchesColumnCaseWhenCatalogsDisagree(t *testing.T) {
primaryKeys := map[string]bool{"ID": true}
if !xuguPrimaryKeyMatches("id", primaryKeys) {
t.Fatal("expected an unquoted primary key to match the column despite case differences")
}
if !xuguPrimaryKeyMatches("ID", primaryKeys) {
t.Fatal("expected an exact primary-key match")
}
}
func TestXuguPrimaryKeyMatchingDoesNotGuessAmbiguousCase(t *testing.T) {
primaryKeys := map[string]bool{"ID": true, "id": true}
if xuguPrimaryKeyMatches("Id", primaryKeys) {
t.Fatal("must not choose between primary-key names that differ only by case")
}
}
func TestIndexSQLUsesLowPrivilegeDictionary(t *testing.T) {
sqlText := strings.ToUpper(xuguListIndexesSQL)