| 
									
										
										
										
											2024-02-28 05:16:00 +08:00
										 |  |  | package sql | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2024-05-15 05:05:29 +08:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"sort" | 
					
						
							| 
									
										
										
										
											2024-02-28 05:16:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-06 20:27:28 +08:00
										 |  |  | 	"github.com/dolthub/vitess/go/vt/sqlparser" | 
					
						
							| 
									
										
										
										
											2024-05-23 05:18:46 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/log" | 
					
						
							| 
									
										
										
										
											2024-02-28 05:16:00 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-23 05:18:46 +08:00
										 |  |  | var logger = log.New("sql_expr") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-28 05:16:00 +08:00
										 |  |  | // TablesList returns a list of tables for the sql statement
 | 
					
						
							|  |  |  | func TablesList(rawSQL string) ([]string, error) { | 
					
						
							| 
									
										
										
										
											2025-02-06 20:27:28 +08:00
										 |  |  | 	stmt, err := sqlparser.Parse(rawSQL) | 
					
						
							| 
									
										
										
										
											2024-02-28 05:16:00 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2025-02-06 20:27:28 +08:00
										 |  |  | 		logger.Error("error parsing sql: %s", err.Error(), "sql", rawSQL) | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("error parsing sql: %s", err.Error()) | 
					
						
							| 
									
										
										
										
											2024-02-28 05:16:00 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-05-03 20:08:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-06 20:27:28 +08:00
										 |  |  | 	tables := make(map[string]struct{}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	walkSubtree := func(node sqlparser.SQLNode) error { | 
					
						
							|  |  |  | 		err = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { | 
					
						
							|  |  |  | 			switch v := node.(type) { | 
					
						
							|  |  |  | 			case *sqlparser.AliasedTableExpr: | 
					
						
							|  |  |  | 				if tableName, ok := v.Expr.(sqlparser.TableName); ok { | 
					
						
							|  |  |  | 					tables[tableName.Name.String()] = struct{}{} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			case *sqlparser.TableName: | 
					
						
							|  |  |  | 				tables[v.Name.String()] = struct{}{} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return true, nil | 
					
						
							|  |  |  | 		}, node) | 
					
						
							| 
									
										
										
										
											2024-05-03 20:08:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-06 20:27:28 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			logger.Error("error walking sql", "error", err, "node", node) | 
					
						
							|  |  |  | 			return fmt.Errorf("failed to parse SQL expression: %w", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-05-03 20:08:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-06 20:27:28 +08:00
										 |  |  | 	if err := walkSubtree(stmt); err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2024-05-03 20:08:07 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-02-28 05:16:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-06 20:27:28 +08:00
										 |  |  | 	result := make([]string, 0, len(tables)) | 
					
						
							|  |  |  | 	for table := range tables { | 
					
						
							|  |  |  | 		// Remove 'dual' table if it exists
 | 
					
						
							|  |  |  | 		// This is a special table in MySQL that always returns a single row with a single column
 | 
					
						
							|  |  |  | 		// See: https://dev.mysql.com/doc/refman/5.7/en/select.html#:~:text=You%20are%20permitted%20to%20specify%20DUAL%20as%20a%20dummy%20table%20name%20in%20situations%20where%20no%20tables%20are%20referenced
 | 
					
						
							|  |  |  | 		if table != "dual" { | 
					
						
							|  |  |  | 			result = append(result, table) | 
					
						
							| 
									
										
										
										
											2024-05-03 02:48:05 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-06 20:27:28 +08:00
										 |  |  | 	sort.Strings(result) | 
					
						
							| 
									
										
										
										
											2024-05-02 20:43:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-06 20:27:28 +08:00
										 |  |  | 	logger.Debug("tables found in sql", "tables", tables) | 
					
						
							| 
									
										
										
										
											2024-05-02 20:43:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-06 20:27:28 +08:00
										 |  |  | 	return result, nil | 
					
						
							| 
									
										
										
										
											2024-05-02 20:43:20 +08:00
										 |  |  | } |