mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-03 04:59:46 +08:00
🐛 fix(data-grid): 修复 schema 数据源 DDL 查看异常
- 表页入口:查看 DDL 不再依赖 dbName,支持金仓/PG 等 schema 数据源 - 标识符解析:新增 quote-safe qualified name 拆分,避免引号内点号被误拆 - DDL 兼容:PG、HighGo、VastBase 使用安全拆分处理 schema.table - 自定义驱动:补齐 custom HighGo DDL 查询时的数据库上下文 - 测试覆盖:新增 schema 表、视图 fallback、dotted 标识符等回归用例
This commit is contained in:
@@ -104,6 +104,27 @@ describe('DataGrid layout', () => {
|
||||
expect(tableMarkup).toContain('data-grid-ddl-action="true"');
|
||||
expect(tableMarkup).toContain('查看 DDL');
|
||||
|
||||
const schemaTableMarkup = renderToStaticMarkup(
|
||||
<DataGrid
|
||||
data={[
|
||||
{
|
||||
__gonavi_row_key__: 'row-1',
|
||||
id: 1,
|
||||
name: 'alpha',
|
||||
},
|
||||
]}
|
||||
columnNames={['id', 'name']}
|
||||
loading={false}
|
||||
tableName="public.users"
|
||||
dbName=""
|
||||
connectionId="conn-1"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(schemaTableMarkup).toContain('data-grid-ddl-action="true"');
|
||||
expect(schemaTableMarkup).toContain('查看 DDL');
|
||||
expect(schemaTableMarkup).toContain('data-grid-page-find="true"');
|
||||
|
||||
const queryMarkup = renderToStaticMarkup(
|
||||
<DataGrid
|
||||
data={[
|
||||
|
||||
@@ -1133,7 +1133,7 @@ const DataGrid: React.FC<DataGridProps> = ({
|
||||
const isQueryResultExport = exportScope === 'queryResult';
|
||||
const canImport = exportScope === 'table' && !!tableName;
|
||||
const canExport = !!connectionId && (isQueryResultExport || !!tableName);
|
||||
const canViewDdl = exportScope === 'table' && !!connectionId && !!dbName && !!tableName;
|
||||
const canViewDdl = exportScope === 'table' && !!connectionId && !!tableName;
|
||||
const filteredExportSql = useMemo(() => String(exportSqlWithFilter || '').trim(), [exportSqlWithFilter]);
|
||||
const hasFilteredExportSql = exportScope === 'table' && filteredExportSql.length > 0;
|
||||
|
||||
|
||||
@@ -184,6 +184,16 @@ func normalizeSchemaAndTableByType(dbType string, dbName string, tableName strin
|
||||
}
|
||||
}
|
||||
|
||||
if dbType == "postgres" || dbType == "highgo" || dbType == "vastbase" {
|
||||
schema, table := db.SplitSQLQualifiedName(rawTable)
|
||||
if schema != "" && table != "" {
|
||||
return schema, table
|
||||
}
|
||||
if table != "" {
|
||||
return "public", table
|
||||
}
|
||||
}
|
||||
|
||||
if parts := strings.SplitN(rawTable, ".", 2); len(parts) == 2 {
|
||||
schema := strings.TrimSpace(parts[0])
|
||||
table := strings.TrimSpace(parts[1])
|
||||
@@ -214,7 +224,7 @@ func buildRunConfigForDDL(config connection.ConnectionConfig, dbType string, dbN
|
||||
if strings.EqualFold(strings.TrimSpace(config.Type), "custom") {
|
||||
// custom 连接的 dbName 语义依赖 driver,尽量在常见驱动上对齐内置类型行为。
|
||||
switch dbType {
|
||||
case "mysql", "mariadb", "diros", "sphinx", "postgres", "kingbase", "vastbase", "dameng", "clickhouse":
|
||||
case "mysql", "mariadb", "diros", "sphinx", "postgres", "kingbase", "highgo", "vastbase", "dameng", "clickhouse":
|
||||
if strings.TrimSpace(dbName) != "" {
|
||||
runConfig.Database = strings.TrimSpace(dbName)
|
||||
}
|
||||
@@ -928,6 +938,12 @@ func resolveCreateStatementWithFallback(dbInst db.Database, config connection.Co
|
||||
return sqlStr, nil
|
||||
}
|
||||
|
||||
if supportsViewCreateStatementLookup(dbType) {
|
||||
if viewDDL, ok := tryGetViewCreateStatement(dbInst, config, dbName, schemaName, pureTableName); ok {
|
||||
return viewDDL, nil
|
||||
}
|
||||
}
|
||||
|
||||
if !supportsCreateStatementFallback(dbType) {
|
||||
if sourceErr != nil {
|
||||
return "", sourceErr
|
||||
@@ -962,6 +978,15 @@ func supportsCreateStatementFallback(dbType string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func supportsViewCreateStatementLookup(dbType string) bool {
|
||||
switch dbType {
|
||||
case "mysql", "mariadb", "diros", "sphinx", "postgres", "kingbase", "highgo", "vastbase", "sqlserver", "oracle", "dameng", "sqlite", "duckdb", "clickhouse":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func shouldFallbackCreateStatement(dbType string, ddl string) bool {
|
||||
if !supportsCreateStatementFallback(dbType) {
|
||||
return false
|
||||
@@ -971,7 +996,7 @@ func shouldFallbackCreateStatement(dbType string, ddl string) bool {
|
||||
if trimmed == "" {
|
||||
return true
|
||||
}
|
||||
if hasCreateTableHead(trimmed) {
|
||||
if hasCreateTableOrViewHead(trimmed) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -984,7 +1009,7 @@ func shouldFallbackCreateStatement(dbType string, ddl string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func hasCreateTableHead(sqlText string) bool {
|
||||
func hasCreateTableOrViewHead(sqlText string) bool {
|
||||
lines := strings.Split(sqlText, "\n")
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
@@ -994,7 +1019,10 @@ func hasCreateTableHead(sqlText string) bool {
|
||||
if strings.HasPrefix(line, "--") || strings.HasPrefix(line, "/*") || strings.HasPrefix(line, "*") {
|
||||
continue
|
||||
}
|
||||
return strings.HasPrefix(strings.ToLower(line), "create table")
|
||||
lower := strings.ToLower(line)
|
||||
return strings.HasPrefix(lower, "create table") ||
|
||||
strings.HasPrefix(lower, "create view") ||
|
||||
strings.HasPrefix(lower, "create or replace view")
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -13,18 +13,23 @@ type fakeCreateStatementDB struct {
|
||||
createErr error
|
||||
columns []connection.ColumnDefinition
|
||||
columnsErr error
|
||||
queryRows []map[string]interface{}
|
||||
queryErr error
|
||||
|
||||
createSchema string
|
||||
createTable string
|
||||
colsSchema string
|
||||
colsTable string
|
||||
columnsCalls int
|
||||
queries []string
|
||||
}
|
||||
|
||||
func (f *fakeCreateStatementDB) Connect(config connection.ConnectionConfig) error { return nil }
|
||||
func (f *fakeCreateStatementDB) Close() error { return nil }
|
||||
func (f *fakeCreateStatementDB) Ping() error { return nil }
|
||||
func (f *fakeCreateStatementDB) Query(query string) ([]map[string]interface{}, []string, error) {
|
||||
return nil, nil, nil
|
||||
f.queries = append(f.queries, query)
|
||||
return f.queryRows, []string{"ddl"}, f.queryErr
|
||||
}
|
||||
func (f *fakeCreateStatementDB) Exec(query string) (int64, error) { return 0, nil }
|
||||
func (f *fakeCreateStatementDB) GetDatabases() ([]string, error) { return nil, nil }
|
||||
@@ -35,6 +40,7 @@ func (f *fakeCreateStatementDB) GetCreateStatement(dbName, tableName string) (st
|
||||
return f.createSQL, f.createErr
|
||||
}
|
||||
func (f *fakeCreateStatementDB) GetColumns(dbName, tableName string) ([]connection.ColumnDefinition, error) {
|
||||
f.columnsCalls++
|
||||
f.colsSchema = dbName
|
||||
f.colsTable = tableName
|
||||
return f.columns, f.columnsErr
|
||||
@@ -80,6 +86,46 @@ func TestResolveDDLDBType_CustomDriverAlias(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeSchemaAndTableByType_PGLikeQuotedQualifiedName(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
dbType string
|
||||
tableName string
|
||||
wantSchema string
|
||||
wantTable string
|
||||
}{
|
||||
{name: "postgres quoted dots", dbType: "postgres", tableName: `"sales.schema"."order.items"`, wantSchema: "sales.schema", wantTable: "order.items"},
|
||||
{name: "highgo escaped quoted", dbType: "highgo", tableName: `\"sales\".\"orders\"`, wantSchema: "sales", wantTable: "orders"},
|
||||
{name: "vastbase quoted table only", dbType: "vastbase", tableName: `"order.items"`, wantSchema: "public", wantTable: "order.items"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
gotSchema, gotTable := normalizeSchemaAndTableByType(tt.dbType, "", tt.tableName)
|
||||
if gotSchema != tt.wantSchema || gotTable != tt.wantTable {
|
||||
t.Fatalf("normalizeSchemaAndTableByType(%q,%q)=(%q,%q),want=(%q,%q)", tt.dbType, tt.tableName, gotSchema, gotTable, tt.wantSchema, tt.wantTable)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildRunConfigForDDL_CustomHighGoUsesDatabase(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
got := buildRunConfigForDDL(connection.ConnectionConfig{
|
||||
Type: "custom",
|
||||
Driver: "highgo",
|
||||
Database: "default_db",
|
||||
}, "highgo", "target_db")
|
||||
if got.Database != "target_db" {
|
||||
t.Fatalf("expected custom highgo DDL database target_db, got %q", got.Database)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveCreateStatementWithFallback_CustomKingbaseUsesPublicSchema(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -130,6 +176,124 @@ func TestResolveCreateStatementWithFallback_KeepQualifiedSchema(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveCreateStatementWithFallback_PGLikeQuotedQualifiedName(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dbInst := &fakeCreateStatementDB{
|
||||
createSQL: "-- SHOW CREATE TABLE not fully supported for PostgreSQL in this MVP.",
|
||||
columns: []connection.ColumnDefinition{
|
||||
{Name: "id", Type: "integer", Nullable: "NO", Key: "PRI"},
|
||||
},
|
||||
}
|
||||
|
||||
ddl, err := resolveCreateStatementWithFallback(dbInst, connection.ConnectionConfig{
|
||||
Type: "postgres",
|
||||
}, "", `"sales.schema"."order.items"`)
|
||||
if err != nil {
|
||||
t.Fatalf("resolveCreateStatementWithFallback() unexpected error: %v", err)
|
||||
}
|
||||
if dbInst.createSchema != "sales.schema" || dbInst.createTable != "order.items" {
|
||||
t.Fatalf("expected create target sales.schema.order.items, got %q.%q", dbInst.createSchema, dbInst.createTable)
|
||||
}
|
||||
if dbInst.colsSchema != "sales.schema" || dbInst.colsTable != "order.items" {
|
||||
t.Fatalf("expected column target sales.schema.order.items, got %q.%q", dbInst.colsSchema, dbInst.colsTable)
|
||||
}
|
||||
if !strings.Contains(ddl, `CREATE TABLE "sales.schema"."order.items"`) {
|
||||
t.Fatalf("expected fallback DDL with quoted dotted identifiers, got: %s", ddl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveCreateStatementWithFallback_ReturnsCreateViewDirectly(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dbInst := &fakeCreateStatementDB{
|
||||
createSQL: "CREATE VIEW sales.orders_v AS SELECT 1;",
|
||||
columnsErr: errors.New("should not be called"),
|
||||
}
|
||||
|
||||
ddl, err := resolveCreateStatementWithFallback(dbInst, connection.ConnectionConfig{Type: "postgres"}, "", "sales.orders_v")
|
||||
if err != nil {
|
||||
t.Fatalf("resolveCreateStatementWithFallback() unexpected error: %v", err)
|
||||
}
|
||||
if ddl != dbInst.createSQL {
|
||||
t.Fatalf("expected original create view DDL, got: %s", ddl)
|
||||
}
|
||||
if dbInst.columnsCalls != 0 {
|
||||
t.Fatalf("CREATE VIEW path should not call GetColumns, calls=%d", dbInst.columnsCalls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveCreateStatementWithFallback_PGLikeViewHelperBeforeColumnFallback(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dbInst := &fakeCreateStatementDB{
|
||||
createSQL: "SHOW CREATE TABLE not directly supported in PostgreSQL",
|
||||
columnsErr: errors.New("should not be called"),
|
||||
queryRows: []map[string]interface{}{
|
||||
{"ddl": "SELECT id FROM sales.orders"},
|
||||
},
|
||||
}
|
||||
|
||||
ddl, err := resolveCreateStatementWithFallback(dbInst, connection.ConnectionConfig{Type: "postgres"}, "", "sales.orders_v")
|
||||
if err != nil {
|
||||
t.Fatalf("resolveCreateStatementWithFallback() unexpected error: %v", err)
|
||||
}
|
||||
if !strings.Contains(ddl, `CREATE VIEW "sales"."orders_v" AS SELECT id FROM sales.orders`) {
|
||||
t.Fatalf("expected CREATE VIEW DDL from view helper, got: %s", ddl)
|
||||
}
|
||||
if dbInst.columnsCalls != 0 {
|
||||
t.Fatalf("view helper path should not call GetColumns, calls=%d", dbInst.columnsCalls)
|
||||
}
|
||||
if len(dbInst.queries) == 0 || !strings.Contains(dbInst.queries[0], "pg_get_viewdef") {
|
||||
t.Fatalf("expected pg_get_viewdef query, got: %v", dbInst.queries)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveCreateStatementWithFallback_PGLikeViewHelperKeepsQuotedDottedName(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dbInst := &fakeCreateStatementDB{
|
||||
createSQL: "SHOW CREATE TABLE not directly supported in PostgreSQL",
|
||||
columnsErr: errors.New("should not be called"),
|
||||
queryRows: []map[string]interface{}{
|
||||
{"ddl": "SELECT 1"},
|
||||
},
|
||||
}
|
||||
|
||||
ddl, err := resolveCreateStatementWithFallback(dbInst, connection.ConnectionConfig{Type: "postgres"}, "", `"sales.schema"."order.items"`)
|
||||
if err != nil {
|
||||
t.Fatalf("resolveCreateStatementWithFallback() unexpected error: %v", err)
|
||||
}
|
||||
if !strings.Contains(ddl, `CREATE VIEW "sales.schema"."order.items" AS SELECT 1`) {
|
||||
t.Fatalf("expected CREATE VIEW DDL to keep quoted dotted identifiers, got: %s", ddl)
|
||||
}
|
||||
if dbInst.columnsCalls != 0 {
|
||||
t.Fatalf("view helper path should not call GetColumns, calls=%d", dbInst.columnsCalls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveCreateStatementWithFallback_PGLikeViewHelperMissFallsBackToColumns(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dbInst := &fakeCreateStatementDB{
|
||||
createSQL: "SHOW CREATE TABLE not directly supported in PostgreSQL",
|
||||
columns: []connection.ColumnDefinition{
|
||||
{Name: "id", Type: "bigint", Nullable: "NO", Key: "PRI"},
|
||||
},
|
||||
}
|
||||
|
||||
ddl, err := resolveCreateStatementWithFallback(dbInst, connection.ConnectionConfig{Type: "postgres"}, "", "sales.orders")
|
||||
if err != nil {
|
||||
t.Fatalf("resolveCreateStatementWithFallback() unexpected error: %v", err)
|
||||
}
|
||||
if !strings.Contains(ddl, `CREATE TABLE "sales"."orders"`) {
|
||||
t.Fatalf("expected CREATE TABLE fallback after view helper miss, got: %s", ddl)
|
||||
}
|
||||
if dbInst.columnsCalls != 1 {
|
||||
t.Fatalf("expected one GetColumns call after view helper miss, calls=%d", dbInst.columnsCalls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveCreateStatementWithFallback_NoFallbackForMySQL(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
@@ -1661,8 +1661,8 @@ func tryGetViewCreateStatement(
|
||||
continue
|
||||
}
|
||||
if looksLikeSelectOrWith(createSQL) {
|
||||
qualifiedView := qualifyTable(schemaName, viewName)
|
||||
createSQL = fmt.Sprintf("CREATE VIEW %s AS %s", quoteQualifiedIdentByType(config.Type, qualifiedView), strings.TrimSuffix(strings.TrimSpace(createSQL), ";"))
|
||||
dbType := resolveDDLDBType(config)
|
||||
createSQL = fmt.Sprintf("CREATE VIEW %s AS %s", quoteTableIdentByType(dbType, schemaName, viewName), strings.TrimSuffix(strings.TrimSpace(createSQL), ";"))
|
||||
}
|
||||
return ensureSQLTerminator(createSQL), true
|
||||
}
|
||||
|
||||
@@ -88,6 +88,11 @@ func SplitKingbaseQualifiedName(raw string) (schema string, table string) {
|
||||
return splitKingbaseQualifiedNameCommon(raw)
|
||||
}
|
||||
|
||||
// SplitSQLQualifiedName splits a schema-qualified SQL identifier without splitting dots inside quotes.
|
||||
func SplitSQLQualifiedName(raw string) (schema string, table string) {
|
||||
return splitSQLQualifiedNameCommon(raw)
|
||||
}
|
||||
|
||||
func splitKingbaseQualifiedNameCommon(raw string) (schema string, table string) {
|
||||
text := strings.TrimSpace(raw)
|
||||
if text == "" {
|
||||
@@ -114,6 +119,124 @@ func splitKingbaseQualifiedNameCommon(raw string) (schema string, table string)
|
||||
return schemaPart, tablePart
|
||||
}
|
||||
|
||||
func splitSQLQualifiedNameCommon(raw string) (schema string, table string) {
|
||||
text := normalizeSQLIdentifierEscapes(strings.TrimSpace(raw))
|
||||
if text == "" {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
sep := findSQLQualifiedSeparator(text)
|
||||
if sep < 0 {
|
||||
return "", normalizeSQLIdentPartCommon(text)
|
||||
}
|
||||
|
||||
schemaPart := normalizeSQLIdentPartCommon(text[:sep])
|
||||
tablePart := normalizeSQLIdentPartCommon(text[sep+1:])
|
||||
|
||||
if tablePart == "" {
|
||||
if schemaPart == "" {
|
||||
return "", normalizeSQLIdentPartCommon(text)
|
||||
}
|
||||
return "", schemaPart
|
||||
}
|
||||
if schemaPart == "" {
|
||||
return "", tablePart
|
||||
}
|
||||
return schemaPart, tablePart
|
||||
}
|
||||
|
||||
func normalizeSQLIdentifierEscapes(raw string) string {
|
||||
value := strings.TrimSpace(raw)
|
||||
for i := 0; i < 4; i++ {
|
||||
next := strings.TrimSpace(value)
|
||||
next = strings.ReplaceAll(next, `\\\"`, `\"`)
|
||||
next = strings.ReplaceAll(next, `\"`, `"`)
|
||||
if next == value {
|
||||
break
|
||||
}
|
||||
value = next
|
||||
}
|
||||
return strings.TrimSpace(value)
|
||||
}
|
||||
|
||||
func normalizeSQLIdentPartCommon(raw string) string {
|
||||
value := normalizeSQLIdentifierEscapes(strings.TrimSpace(raw))
|
||||
if value == "" {
|
||||
return ""
|
||||
}
|
||||
if len(value) >= 2 {
|
||||
first := value[0]
|
||||
last := value[len(value)-1]
|
||||
switch {
|
||||
case first == '"' && last == '"':
|
||||
return strings.TrimSpace(strings.ReplaceAll(value[1:len(value)-1], `""`, `"`))
|
||||
case first == '`' && last == '`':
|
||||
return strings.TrimSpace(strings.ReplaceAll(value[1:len(value)-1], "``", "`"))
|
||||
case first == '[' && last == ']':
|
||||
return strings.TrimSpace(strings.ReplaceAll(value[1:len(value)-1], "]]", "]"))
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func findSQLQualifiedSeparator(raw string) int {
|
||||
inDouble := false
|
||||
inBacktick := false
|
||||
inBracket := false
|
||||
|
||||
for i := 0; i < len(raw); i++ {
|
||||
ch := raw[i]
|
||||
|
||||
if inDouble {
|
||||
if ch == '\\' && i+1 < len(raw) && raw[i+1] == '"' {
|
||||
inDouble = false
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if ch == '"' {
|
||||
if i+1 < len(raw) && raw[i+1] == '"' {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
inDouble = false
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if inBacktick {
|
||||
if ch == '`' {
|
||||
inBacktick = false
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if inBracket {
|
||||
if ch == ']' {
|
||||
inBracket = false
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch ch {
|
||||
case '\\':
|
||||
if i+1 < len(raw) && raw[i+1] == '"' {
|
||||
inDouble = true
|
||||
i++
|
||||
}
|
||||
case '"':
|
||||
inDouble = true
|
||||
case '`':
|
||||
inBacktick = true
|
||||
case '[':
|
||||
inBracket = true
|
||||
case '.':
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
func findKingbaseQualifiedSeparator(raw string) int {
|
||||
inDouble := false
|
||||
inBacktick := false
|
||||
|
||||
@@ -51,6 +51,30 @@ func TestSplitKingbaseQualifiedNameCommon(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitSQLQualifiedName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
in string
|
||||
wantSchema string
|
||||
wantTable string
|
||||
}{
|
||||
{name: "plain", in: "sales.orders", wantSchema: "sales", wantTable: "orders"},
|
||||
{name: "quoted dots", in: `"sales.schema"."order.items"`, wantSchema: "sales.schema", wantTable: "order.items"},
|
||||
{name: "escaped quoted dots", in: `\"sales.schema\".\"order.items\"`, wantSchema: "sales.schema", wantTable: "order.items"},
|
||||
{name: "quoted table only with dot", in: `"order.items"`, wantSchema: "", wantTable: "order.items"},
|
||||
{name: "escaped quoted", in: `\"sales\".\"orders\"`, wantSchema: "sales", wantTable: "orders"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotSchema, gotTable := SplitSQLQualifiedName(tt.in)
|
||||
if gotSchema != tt.wantSchema || gotTable != tt.wantTable {
|
||||
t.Fatalf("SplitSQLQualifiedName(%q)=(%q,%q),want=(%q,%q)", tt.in, gotSchema, gotTable, tt.wantSchema, tt.wantTable)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildKingbaseSearchPathCommon(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
Reference in New Issue
Block a user