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.
		
		
		
		
		
			
		
			
				
					
					
						
							349 lines
						
					
					
						
							9.0 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							349 lines
						
					
					
						
							9.0 KiB
						
					
					
				
								package engine
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"context"
							 | 
						|
									"strings"
							 | 
						|
									"testing"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								// TestComprehensiveSQLSuite tests all kinds of SQL patterns to ensure robustness
							 | 
						|
								func TestComprehensiveSQLSuite(t *testing.T) {
							 | 
						|
									engine := NewTestSQLEngine()
							 | 
						|
								
							 | 
						|
									testCases := []struct {
							 | 
						|
										name        string
							 | 
						|
										sql         string
							 | 
						|
										shouldPanic bool
							 | 
						|
										shouldError bool
							 | 
						|
										desc        string
							 | 
						|
									}{
							 | 
						|
										// =========== BASIC QUERIES ===========
							 | 
						|
										{
							 | 
						|
											name:        "Basic_Select_All",
							 | 
						|
											sql:         "SELECT * FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Basic select all columns",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Basic_Select_Column",
							 | 
						|
											sql:         "SELECT id FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Basic select single column",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Basic_Select_Multiple_Columns",
							 | 
						|
											sql:         "SELECT id, status FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Basic select multiple columns",
							 | 
						|
										},
							 | 
						|
								
							 | 
						|
										// =========== ARITHMETIC EXPRESSIONS (FIXED) ===========
							 | 
						|
										{
							 | 
						|
											name:        "Arithmetic_Multiply_FIXED",
							 | 
						|
											sql:         "SELECT id*2 FROM user_events",
							 | 
						|
											shouldPanic: false, // Fixed: no longer panics
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "FIXED: Arithmetic multiplication works",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Arithmetic_Add",
							 | 
						|
											sql:         "SELECT id+10 FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Arithmetic addition works",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Arithmetic_Subtract",
							 | 
						|
											sql:         "SELECT id-5 FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Arithmetic subtraction works",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Arithmetic_Divide",
							 | 
						|
											sql:         "SELECT id/3 FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Arithmetic division works",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Arithmetic_Complex",
							 | 
						|
											sql:         "SELECT id*2+10 FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Complex arithmetic expression works",
							 | 
						|
										},
							 | 
						|
								
							 | 
						|
										// =========== STRING OPERATIONS ===========
							 | 
						|
										{
							 | 
						|
											name:        "String_Concatenation",
							 | 
						|
											sql:         "SELECT 'hello' || 'world' FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "String concatenation",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "String_Column_Concat",
							 | 
						|
											sql:         "SELECT status || '_suffix' FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Column string concatenation",
							 | 
						|
										},
							 | 
						|
								
							 | 
						|
										// =========== FUNCTIONS ===========
							 | 
						|
										{
							 | 
						|
											name:        "Function_LENGTH",
							 | 
						|
											sql:         "SELECT LENGTH('hello') FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "LENGTH function with literal",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Function_LENGTH_Column",
							 | 
						|
											sql:         "SELECT LENGTH(status) FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "LENGTH function with column",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Function_UPPER",
							 | 
						|
											sql:         "SELECT UPPER('hello') FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "UPPER function",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Function_Nested",
							 | 
						|
											sql:         "SELECT LENGTH(UPPER('hello')) FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Nested functions",
							 | 
						|
										},
							 | 
						|
								
							 | 
						|
										// =========== FUNCTIONS WITH ARITHMETIC ===========
							 | 
						|
										{
							 | 
						|
											name:        "Function_Arithmetic",
							 | 
						|
											sql:         "SELECT LENGTH('hello') + 10 FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Function with arithmetic",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Function_Arithmetic_Complex",
							 | 
						|
											sql:         "SELECT LENGTH(status) * 2 + 5 FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Function with complex arithmetic",
							 | 
						|
										},
							 | 
						|
								
							 | 
						|
										// =========== TABLE REFERENCES ===========
							 | 
						|
										{
							 | 
						|
											name:        "Table_Simple",
							 | 
						|
											sql:         "SELECT * FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Simple table reference",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Table_With_Database",
							 | 
						|
											sql:         "SELECT * FROM ecommerce.user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Table with database qualifier",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Table_Quoted",
							 | 
						|
											sql:         `SELECT * FROM "user_events"`,
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Quoted table name",
							 | 
						|
										},
							 | 
						|
								
							 | 
						|
										// =========== WHERE CLAUSES ===========
							 | 
						|
										{
							 | 
						|
											name:        "Where_Simple",
							 | 
						|
											sql:         "SELECT * FROM user_events WHERE id = 1",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Simple WHERE clause",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Where_String",
							 | 
						|
											sql:         "SELECT * FROM user_events WHERE status = 'active'",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "WHERE clause with string",
							 | 
						|
										},
							 | 
						|
								
							 | 
						|
										// =========== LIMIT/OFFSET ===========
							 | 
						|
										{
							 | 
						|
											name:        "Limit_Only",
							 | 
						|
											sql:         "SELECT * FROM user_events LIMIT 10",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "LIMIT clause only",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Limit_Offset",
							 | 
						|
											sql:         "SELECT * FROM user_events LIMIT 10 OFFSET 5",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "LIMIT with OFFSET",
							 | 
						|
										},
							 | 
						|
								
							 | 
						|
										// =========== DATETIME FUNCTIONS ===========
							 | 
						|
										{
							 | 
						|
											name:        "DateTime_CURRENT_DATE",
							 | 
						|
											sql:         "SELECT CURRENT_DATE FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "CURRENT_DATE function",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "DateTime_NOW",
							 | 
						|
											sql:         "SELECT NOW() FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "NOW() function",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "DateTime_EXTRACT",
							 | 
						|
											sql:         "SELECT EXTRACT(YEAR FROM CURRENT_DATE) FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "EXTRACT function",
							 | 
						|
										},
							 | 
						|
								
							 | 
						|
										// =========== EDGE CASES ===========
							 | 
						|
										{
							 | 
						|
											name:        "Empty_String",
							 | 
						|
											sql:         "SELECT '' FROM user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Empty string literal",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Multiple_Spaces",
							 | 
						|
											sql:         "SELECT    id    FROM    user_events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Query with multiple spaces",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Mixed_Case",
							 | 
						|
											sql:         "Select ID from User_Events",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "Mixed case SQL",
							 | 
						|
										},
							 | 
						|
								
							 | 
						|
										// =========== SHOW STATEMENTS ===========
							 | 
						|
										{
							 | 
						|
											name:        "Show_Databases",
							 | 
						|
											sql:         "SHOW DATABASES",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "SHOW DATABASES statement",
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Show_Tables",
							 | 
						|
											sql:         "SHOW TABLES",
							 | 
						|
											shouldPanic: false,
							 | 
						|
											shouldError: false,
							 | 
						|
											desc:        "SHOW TABLES statement",
							 | 
						|
										},
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									var panicTests []string
							 | 
						|
									var errorTests []string
							 | 
						|
									var successTests []string
							 | 
						|
								
							 | 
						|
									for _, tc := range testCases {
							 | 
						|
										t.Run(tc.name, func(t *testing.T) {
							 | 
						|
											// Capture panics
							 | 
						|
											var panicValue interface{}
							 | 
						|
											func() {
							 | 
						|
												defer func() {
							 | 
						|
													if r := recover(); r != nil {
							 | 
						|
														panicValue = r
							 | 
						|
													}
							 | 
						|
												}()
							 | 
						|
								
							 | 
						|
												result, err := engine.ExecuteSQL(context.Background(), tc.sql)
							 | 
						|
								
							 | 
						|
												if tc.shouldPanic {
							 | 
						|
													if panicValue == nil {
							 | 
						|
														t.Errorf("FAIL: Expected panic for %s, but query completed normally", tc.desc)
							 | 
						|
														panicTests = append(panicTests, "FAIL: "+tc.desc)
							 | 
						|
														return
							 | 
						|
													} else {
							 | 
						|
														t.Logf("PASS: EXPECTED PANIC: %s - %v", tc.desc, panicValue)
							 | 
						|
														panicTests = append(panicTests, "PASS: "+tc.desc+" (reproduced)")
							 | 
						|
														return
							 | 
						|
													}
							 | 
						|
												}
							 | 
						|
								
							 | 
						|
												if panicValue != nil {
							 | 
						|
													t.Errorf("FAIL: Unexpected panic for %s: %v", tc.desc, panicValue)
							 | 
						|
													panicTests = append(panicTests, "FAIL: "+tc.desc+" (unexpected panic)")
							 | 
						|
													return
							 | 
						|
												}
							 | 
						|
								
							 | 
						|
												if tc.shouldError {
							 | 
						|
													if err == nil && (result == nil || result.Error == nil) {
							 | 
						|
														t.Errorf("FAIL: Expected error for %s, but query succeeded", tc.desc)
							 | 
						|
														errorTests = append(errorTests, "FAIL: "+tc.desc)
							 | 
						|
														return
							 | 
						|
													} else {
							 | 
						|
														t.Logf("PASS: Expected error: %s", tc.desc)
							 | 
						|
														errorTests = append(errorTests, "PASS: "+tc.desc)
							 | 
						|
														return
							 | 
						|
													}
							 | 
						|
												}
							 | 
						|
								
							 | 
						|
												if err != nil {
							 | 
						|
													t.Errorf("FAIL: Unexpected error for %s: %v", tc.desc, err)
							 | 
						|
													errorTests = append(errorTests, "FAIL: "+tc.desc+" (unexpected error)")
							 | 
						|
													return
							 | 
						|
												}
							 | 
						|
								
							 | 
						|
												if result != nil && result.Error != nil {
							 | 
						|
													t.Errorf("FAIL: Unexpected result error for %s: %v", tc.desc, result.Error)
							 | 
						|
													errorTests = append(errorTests, "FAIL: "+tc.desc+" (unexpected result error)")
							 | 
						|
													return
							 | 
						|
												}
							 | 
						|
								
							 | 
						|
												t.Logf("PASS: Success: %s", tc.desc)
							 | 
						|
												successTests = append(successTests, "PASS: "+tc.desc)
							 | 
						|
											}()
							 | 
						|
										})
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Summary report
							 | 
						|
									separator := strings.Repeat("=", 80)
							 | 
						|
									t.Log("\n" + separator)
							 | 
						|
									t.Log("COMPREHENSIVE SQL TEST SUITE SUMMARY")
							 | 
						|
									t.Log(separator)
							 | 
						|
									t.Logf("Total Tests: %d", len(testCases))
							 | 
						|
									t.Logf("Successful: %d", len(successTests))
							 | 
						|
									t.Logf("Panics: %d", len(panicTests))
							 | 
						|
									t.Logf("Errors: %d", len(errorTests))
							 | 
						|
									t.Log(separator)
							 | 
						|
								
							 | 
						|
									if len(panicTests) > 0 {
							 | 
						|
										t.Log("\nPANICS TO FIX:")
							 | 
						|
										for _, test := range panicTests {
							 | 
						|
											t.Log("   " + test)
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									if len(errorTests) > 0 {
							 | 
						|
										t.Log("\nERRORS TO INVESTIGATE:")
							 | 
						|
										for _, test := range errorTests {
							 | 
						|
											t.Log("   " + test)
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								}
							 |