You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							166 lines
						
					
					
						
							4.8 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							166 lines
						
					
					
						
							4.8 KiB
						
					
					
				| package engine | |
| 
 | |
| import ( | |
| 	"context" | |
| 	"fmt" | |
| 	"strings" | |
| 
 | |
| 	"github.com/seaweedfs/seaweedfs/weed/query/sqltypes" | |
| ) | |
| 
 | |
| // executeDescribeStatement handles DESCRIBE table commands | |
| // Shows table schema in PostgreSQL-compatible format | |
| func (e *SQLEngine) executeDescribeStatement(ctx context.Context, tableName string, database string) (*QueryResult, error) { | |
| 	if database == "" { | |
| 		database = e.catalog.GetCurrentDatabase() | |
| 		if database == "" { | |
| 			database = "default" | |
| 		} | |
| 	} | |
| 
 | |
| 	// Auto-discover and register topic if not already in catalog (same logic as SELECT) | |
| 	if _, err := e.catalog.GetTableInfo(database, tableName); err != nil { | |
| 		// Topic not in catalog, try to discover and register it | |
| 		if regErr := e.discoverAndRegisterTopic(ctx, database, tableName); regErr != nil { | |
| 			fmt.Printf("Warning: Failed to discover topic %s.%s: %v\n", database, tableName, regErr) | |
| 			return &QueryResult{Error: fmt.Errorf("topic %s.%s not found and auto-discovery failed: %v", database, tableName, regErr)}, regErr | |
| 		} | |
| 	} | |
| 
 | |
| 	// Get flat schema and key columns from broker | |
| 	flatSchema, keyColumns, _, err := e.catalog.brokerClient.GetTopicSchema(ctx, database, tableName) | |
| 	if err != nil { | |
| 		return &QueryResult{Error: err}, err | |
| 	} | |
| 
 | |
| 	// System columns to include in DESCRIBE output | |
| 	systemColumns := []struct { | |
| 		Name  string | |
| 		Type  string | |
| 		Extra string | |
| 	}{ | |
| 		{"_ts", "TIMESTAMP", "System column: Message timestamp"}, | |
| 		{"_key", "VARBINARY", "System column: Message key"}, | |
| 		{"_source", "VARCHAR(255)", "System column: Data source (parquet/log)"}, | |
| 	} | |
| 
 | |
| 	// If no schema is defined, include _value field | |
| 	if flatSchema == nil { | |
| 		systemColumns = append(systemColumns, struct { | |
| 			Name  string | |
| 			Type  string | |
| 			Extra string | |
| 		}{SW_COLUMN_NAME_VALUE, "VARBINARY", "Raw message value (no schema defined)"}) | |
| 	} | |
| 
 | |
| 	// Calculate total rows: schema fields + system columns | |
| 	totalRows := len(systemColumns) | |
| 	if flatSchema != nil { | |
| 		totalRows += len(flatSchema.Fields) | |
| 	} | |
| 
 | |
| 	// Create key column lookup map | |
| 	keyColumnMap := make(map[string]bool) | |
| 	for _, keyCol := range keyColumns { | |
| 		keyColumnMap[keyCol] = true | |
| 	} | |
| 
 | |
| 	result := &QueryResult{ | |
| 		Columns: []string{"Field", "Type", "Null", "Key", "Default", "Extra"}, | |
| 		Rows:    make([][]sqltypes.Value, totalRows), | |
| 	} | |
| 
 | |
| 	rowIndex := 0 | |
| 
 | |
| 	// Add schema fields - mark key columns appropriately | |
| 	if flatSchema != nil { | |
| 		for _, field := range flatSchema.Fields { | |
| 			sqlType := e.convertMQTypeToSQL(field.Type) | |
| 			isKey := keyColumnMap[field.Name] | |
| 			keyType := "" | |
| 			if isKey { | |
| 				keyType = "PRI" // Primary key | |
| 			} | |
| 			extra := "Data field" | |
| 			if isKey { | |
| 				extra = "Key field" | |
| 			} | |
| 
 | |
| 			result.Rows[rowIndex] = []sqltypes.Value{ | |
| 				sqltypes.NewVarChar(field.Name), | |
| 				sqltypes.NewVarChar(sqlType), | |
| 				sqltypes.NewVarChar("YES"), | |
| 				sqltypes.NewVarChar(keyType), | |
| 				sqltypes.NewVarChar("NULL"), | |
| 				sqltypes.NewVarChar(extra), | |
| 			} | |
| 			rowIndex++ | |
| 		} | |
| 	} | |
| 
 | |
| 	// Add system columns | |
| 	for _, sysCol := range systemColumns { | |
| 		result.Rows[rowIndex] = []sqltypes.Value{ | |
| 			sqltypes.NewVarChar(sysCol.Name),  // Field | |
| 			sqltypes.NewVarChar(sysCol.Type),  // Type | |
| 			sqltypes.NewVarChar("YES"),        // Null | |
| 			sqltypes.NewVarChar("SYS"),        // Key - mark as system column | |
| 			sqltypes.NewVarChar("NULL"),       // Default | |
| 			sqltypes.NewVarChar(sysCol.Extra), // Extra - description | |
| 		} | |
| 		rowIndex++ | |
| 	} | |
| 
 | |
| 	return result, nil | |
| } | |
| 
 | |
| // Enhanced executeShowStatementWithDescribe handles SHOW statements including DESCRIBE | |
| func (e *SQLEngine) executeShowStatementWithDescribe(ctx context.Context, stmt *ShowStatement) (*QueryResult, error) { | |
| 	switch strings.ToUpper(stmt.Type) { | |
| 	case "DATABASES": | |
| 		return e.showDatabases(ctx) | |
| 	case "TABLES": | |
| 		// Parse FROM clause for database specification, or use current database context | |
| 		database := "" | |
| 		// Check if there's a database specified in SHOW TABLES FROM database | |
| 		if stmt.Schema != "" { | |
| 			// Use schema field if set by parser | |
| 			database = stmt.Schema | |
| 		} else { | |
| 			// Try to get from OnTable.Name with proper nil checks | |
| 			if stmt.OnTable.Name != nil { | |
| 				if nameStr := stmt.OnTable.Name.String(); nameStr != "" { | |
| 					database = nameStr | |
| 				} else { | |
| 					database = e.catalog.GetCurrentDatabase() | |
| 				} | |
| 			} else { | |
| 				database = e.catalog.GetCurrentDatabase() | |
| 			} | |
| 		} | |
| 		if database == "" { | |
| 			// Use current database context | |
| 			database = e.catalog.GetCurrentDatabase() | |
| 		} | |
| 		return e.showTables(ctx, database) | |
| 	case "COLUMNS": | |
| 		// SHOW COLUMNS FROM table is equivalent to DESCRIBE | |
| 		var tableName, database string | |
| 
 | |
| 		// Safely extract table name and database with proper nil checks | |
| 		if stmt.OnTable.Name != nil { | |
| 			tableName = stmt.OnTable.Name.String() | |
| 			if stmt.OnTable.Qualifier != nil { | |
| 				database = stmt.OnTable.Qualifier.String() | |
| 			} | |
| 		} | |
| 
 | |
| 		if tableName != "" { | |
| 			return e.executeDescribeStatement(ctx, tableName, database) | |
| 		} | |
| 		fallthrough | |
| 	default: | |
| 		err := fmt.Errorf("unsupported SHOW statement: %s", stmt.Type) | |
| 		return &QueryResult{Error: err}, err | |
| 	} | |
| }
 |