From 991247facf63837141cbd9415d8b0c337e9a5f79 Mon Sep 17 00:00:00 2001 From: chrislu Date: Wed, 3 Sep 2025 00:40:03 -0700 Subject: [PATCH] fix tests --- weed/query/engine/engine.go | 108 ++++++++++++++++++----- weed/query/engine/real_namespace_test.go | 4 +- 2 files changed, 89 insertions(+), 23 deletions(-) diff --git a/weed/query/engine/engine.go b/weed/query/engine/engine.go index eed5aeb67..586b3cb4b 100644 --- a/weed/query/engine/engine.go +++ b/weed/query/engine/engine.go @@ -204,8 +204,42 @@ const ( // ParseSQL uses PostgreSQL parser to parse SQL statements func ParseSQL(sql string) (Statement, error) { sql = strings.TrimSpace(sql) + sqlUpper := strings.ToUpper(sql) + + // Handle SHOW statements first (before PostgreSQL parser since pg doesn't support SHOW) + if strings.HasPrefix(sqlUpper, "SHOW DATABASES") || strings.HasPrefix(sqlUpper, "SHOW SCHEMAS") { + return &ShowStatement{Type: "databases"}, nil + } + if strings.HasPrefix(sqlUpper, "SHOW TABLES") { + stmt := &ShowStatement{Type: "tables"} + // Handle "SHOW TABLES FROM database" syntax + if strings.Contains(sqlUpper, "FROM") { + partsUpper := strings.Fields(sqlUpper) + partsOriginal := strings.Fields(sql) // Use original casing + for i, part := range partsUpper { + if part == "FROM" && i+1 < len(partsOriginal) { + // Remove quotes if present (PostgreSQL uses double quotes, MySQL uses backticks) + dbName := strings.Trim(partsOriginal[i+1], "\"'`") + stmt.OnTable.Name = stringValue(dbName) + break + } + } + } + return stmt, nil + } + + // Handle DDL statements by parsing SQL text patterns (before PostgreSQL parser) + if strings.HasPrefix(sqlUpper, "CREATE TABLE") { + return parseCreateTableFromSQL(sql) + } + if strings.HasPrefix(sqlUpper, "DROP TABLE") { + return parseDropTableFromSQL(sql) + } + if strings.HasPrefix(sqlUpper, "ALTER TABLE") { + return parseAlterTableFromSQL(sql) + } - // Parse with pg_query_go + // Parse with pg_query_go for SELECT and other standard PostgreSQL statements result, err := pg_query.Parse(sql) if err != nil { return nil, fmt.Errorf("PostgreSQL parse error: %v", err) @@ -223,26 +257,6 @@ func ParseSQL(sql string) (Statement, error) { return convertSelectStatement(selectStmt), nil } - // Handle DDL statements by parsing SQL text patterns - sqlUpper := strings.ToUpper(sql) - if strings.HasPrefix(sqlUpper, "CREATE TABLE") { - return parseCreateTableFromSQL(sql) - } - if strings.HasPrefix(sqlUpper, "DROP TABLE") { - return parseDropTableFromSQL(sql) - } - if strings.HasPrefix(sqlUpper, "ALTER TABLE") { - return parseAlterTableFromSQL(sql) - } - - // Handle SHOW statements - if strings.HasPrefix(sqlUpper, "SHOW DATABASES") || strings.HasPrefix(sqlUpper, "SHOW SCHEMAS") { - return &ShowStatement{Type: "databases"}, nil - } - if strings.HasPrefix(sqlUpper, "SHOW TABLES") { - return &ShowStatement{Type: "tables"}, nil - } - return nil, fmt.Errorf("unsupported statement type") } @@ -282,9 +296,61 @@ func convertSelectStatement(stmt *pg_query.SelectStmt) *SelectStatement { } } + // Convert WHERE clause + if stmt.GetWhereClause() != nil { + s.Where = &WhereClause{ + Expr: convertExpressionNode(stmt.GetWhereClause()), + } + } + + // Convert LIMIT clause + if stmt.GetLimitCount() != nil { + s.Limit = &LimitClause{ + Rowcount: convertExpressionNode(stmt.GetLimitCount()), + } + } + return s } +// convertExpressionNode converts PostgreSQL parser expression nodes to our internal ExprNode types +func convertExpressionNode(node *pg_query.Node) ExprNode { + if node == nil { + return nil + } + + // Handle different expression types + if aConst := node.GetAConst(); aConst != nil { + // Handle constants (numbers, strings) + if aConst.GetIval() != nil { + return &SQLVal{ + Type: IntVal, + Val: []byte(fmt.Sprintf("%d", aConst.GetIval().GetIval())), + } + } + if aConst.GetSval() != nil { + return &SQLVal{ + Type: StrVal, + Val: []byte(aConst.GetSval().GetSval()), + } + } + } + + if columnRef := node.GetColumnRef(); columnRef != nil { + // Handle column references + return &ColName{ + Name: stringValue("column"), // Simplified - would need more complex parsing + } + } + + // For now, return a simple placeholder for other expression types + // In a full implementation, we'd handle all PostgreSQL expression types + return &SQLVal{ + Type: StrVal, + Val: []byte(""), + } +} + func parseCreateTableFromSQL(sql string) (*DDLStatement, error) { parts := strings.Fields(sql) if len(parts) < 3 { diff --git a/weed/query/engine/real_namespace_test.go b/weed/query/engine/real_namespace_test.go index acf398219..6c88ef612 100644 --- a/weed/query/engine/real_namespace_test.go +++ b/weed/query/engine/real_namespace_test.go @@ -37,8 +37,8 @@ func TestRealNamespaceDiscovery(t *testing.T) { func TestRealTopicDiscovery(t *testing.T) { engine := NewSQLEngine("localhost:8888") - // Test SHOW TABLES with real topic discovery (use backticks for reserved keyword) - result, err := engine.ExecuteSQL(context.Background(), "SHOW TABLES FROM `default`") + // Test SHOW TABLES with real topic discovery (use double quotes for PostgreSQL) + result, err := engine.ExecuteSQL(context.Background(), "SHOW TABLES FROM \"default\"") if err != nil { t.Fatalf("SHOW TABLES failed: %v", err) }