executor_test.go 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408
  1. package executor
  2. import (
  3. "fmt"
  4. "testing"
  5. "time"
  6. "github.com/danfragoso/pizzasql-next/pkg/lexer"
  7. "github.com/danfragoso/pizzasql-next/pkg/parser"
  8. "github.com/danfragoso/pizzasql-next/pkg/storage"
  9. )
  10. func parse(t *testing.T, sql string) parser.Statement {
  11. t.Helper()
  12. l := lexer.New(sql)
  13. p := parser.New(l)
  14. stmt, err := p.Parse()
  15. if err != nil {
  16. t.Fatalf("parse error: %v", err)
  17. }
  18. return stmt
  19. }
  20. // execSQL parses and executes a SQL string, used by benchmarks
  21. func execSQL(exec *Executor, sql string) (*Result, error) {
  22. l := lexer.New(sql)
  23. p := parser.New(l)
  24. stmt, err := p.Parse()
  25. if err != nil {
  26. return nil, fmt.Errorf("parse error: %w", err)
  27. }
  28. return exec.Execute(stmt)
  29. }
  30. // Test expression evaluation without database
  31. func TestEvalLiteral(t *testing.T) {
  32. exec := &Executor{}
  33. tests := []struct {
  34. input string
  35. expected interface{}
  36. }{
  37. {"42", int64(42)},
  38. {"3.14", 3.14},
  39. {"'hello'", "hello"},
  40. {"TRUE", true},
  41. {"FALSE", false},
  42. }
  43. for _, tt := range tests {
  44. t.Run(tt.input, func(t *testing.T) {
  45. stmt := parse(t, "SELECT "+tt.input)
  46. sel := stmt.(*parser.SelectStmt)
  47. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  48. if err != nil {
  49. t.Errorf("evalExpr error: %v", err)
  50. return
  51. }
  52. if val != tt.expected {
  53. t.Errorf("expected %v (%T), got %v (%T)", tt.expected, tt.expected, val, val)
  54. }
  55. })
  56. }
  57. }
  58. func TestEvalArithmetic(t *testing.T) {
  59. exec := &Executor{}
  60. tests := []struct {
  61. input string
  62. expected float64
  63. }{
  64. {"1 + 2", 3},
  65. {"5 - 3", 2},
  66. {"4 * 3", 12},
  67. {"10 / 2", 5},
  68. {"1 + 2 * 3", 7},
  69. {"(1 + 2) * 3", 9},
  70. {"-5", -5},
  71. {"10 % 3", 1},
  72. }
  73. for _, tt := range tests {
  74. t.Run(tt.input, func(t *testing.T) {
  75. stmt := parse(t, "SELECT "+tt.input)
  76. sel := stmt.(*parser.SelectStmt)
  77. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  78. if err != nil {
  79. t.Errorf("evalExpr error: %v", err)
  80. return
  81. }
  82. if toFloat(val) != tt.expected {
  83. t.Errorf("expected %v, got %v", tt.expected, val)
  84. }
  85. })
  86. }
  87. }
  88. func TestEvalComparison(t *testing.T) {
  89. exec := &Executor{}
  90. tests := []struct {
  91. input string
  92. expected bool
  93. }{
  94. {"1 = 1", true},
  95. {"1 = 2", false},
  96. {"1 <> 2", true},
  97. {"1 < 2", true},
  98. {"2 > 1", true},
  99. {"1 <= 1", true},
  100. {"1 >= 1", true},
  101. {"'a' = 'a'", true},
  102. {"'a' < 'b'", true},
  103. }
  104. for _, tt := range tests {
  105. t.Run(tt.input, func(t *testing.T) {
  106. stmt := parse(t, "SELECT "+tt.input)
  107. sel := stmt.(*parser.SelectStmt)
  108. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  109. if err != nil {
  110. t.Errorf("evalExpr error: %v", err)
  111. return
  112. }
  113. if toBool(val) != tt.expected {
  114. t.Errorf("expected %v, got %v", tt.expected, val)
  115. }
  116. })
  117. }
  118. }
  119. func TestEvalLogical(t *testing.T) {
  120. exec := &Executor{}
  121. tests := []struct {
  122. input string
  123. expected bool
  124. }{
  125. {"TRUE AND TRUE", true},
  126. {"TRUE AND FALSE", false},
  127. {"TRUE OR FALSE", true},
  128. {"FALSE OR FALSE", false},
  129. {"NOT TRUE", false},
  130. {"NOT FALSE", true},
  131. {"1 = 1 AND 2 = 2", true},
  132. {"1 = 1 OR 1 = 2", true},
  133. }
  134. for _, tt := range tests {
  135. t.Run(tt.input, func(t *testing.T) {
  136. stmt := parse(t, "SELECT "+tt.input)
  137. sel := stmt.(*parser.SelectStmt)
  138. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  139. if err != nil {
  140. t.Errorf("evalExpr error: %v", err)
  141. return
  142. }
  143. if toBool(val) != tt.expected {
  144. t.Errorf("expected %v, got %v", tt.expected, val)
  145. }
  146. })
  147. }
  148. }
  149. func TestEvalFunctions(t *testing.T) {
  150. exec := &Executor{}
  151. tests := []struct {
  152. input string
  153. expected interface{}
  154. }{
  155. {"UPPER('hello')", "HELLO"},
  156. {"LOWER('HELLO')", "hello"},
  157. {"LENGTH('hello')", int64(5)},
  158. {"ABS(-5)", float64(5)},
  159. {"COALESCE(NULL, 'default')", "default"},
  160. {"COALESCE('value', 'default')", "value"},
  161. {"NULLIF(1, 1)", nil},
  162. {"NULLIF(1, 2)", int64(1)},
  163. {"IFNULL(NULL, 'default')", "default"},
  164. {"IFNULL('value', 'default')", "value"},
  165. {"TYPEOF(42)", "integer"},
  166. {"TYPEOF(3.14)", "real"},
  167. {"TYPEOF('hello')", "text"},
  168. {"TYPEOF(NULL)", "null"},
  169. {"TRIM(' hello ')", "hello"},
  170. {"SUBSTR('hello', 2, 3)", "ell"},
  171. {"REPLACE('hello', 'l', 'L')", "heLLo"},
  172. }
  173. for _, tt := range tests {
  174. t.Run(tt.input, func(t *testing.T) {
  175. stmt := parse(t, "SELECT "+tt.input)
  176. sel := stmt.(*parser.SelectStmt)
  177. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  178. if err != nil {
  179. t.Errorf("evalExpr error: %v", err)
  180. return
  181. }
  182. if val != tt.expected {
  183. t.Errorf("expected %v (%T), got %v (%T)", tt.expected, tt.expected, val, val)
  184. }
  185. })
  186. }
  187. }
  188. func TestEvalCase(t *testing.T) {
  189. exec := &Executor{}
  190. tests := []struct {
  191. input string
  192. expected interface{}
  193. }{
  194. {"CASE WHEN TRUE THEN 'yes' ELSE 'no' END", "yes"},
  195. {"CASE WHEN FALSE THEN 'yes' ELSE 'no' END", "no"},
  196. {"CASE WHEN 1 = 1 THEN 'one' WHEN 1 = 2 THEN 'two' ELSE 'other' END", "one"},
  197. {"CASE 1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'other' END", "one"},
  198. {"CASE 2 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'other' END", "two"},
  199. }
  200. for _, tt := range tests {
  201. t.Run(tt.input, func(t *testing.T) {
  202. stmt := parse(t, "SELECT "+tt.input)
  203. sel := stmt.(*parser.SelectStmt)
  204. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  205. if err != nil {
  206. t.Errorf("evalExpr error: %v", err)
  207. return
  208. }
  209. if val != tt.expected {
  210. t.Errorf("expected %v, got %v", tt.expected, val)
  211. }
  212. })
  213. }
  214. }
  215. func TestEvalIn(t *testing.T) {
  216. exec := &Executor{}
  217. tests := []struct {
  218. input string
  219. expected bool
  220. }{
  221. {"1 IN (1, 2, 3)", true},
  222. {"4 IN (1, 2, 3)", false},
  223. {"1 NOT IN (1, 2, 3)", false},
  224. {"4 NOT IN (1, 2, 3)", true},
  225. {"'a' IN ('a', 'b', 'c')", true},
  226. }
  227. for _, tt := range tests {
  228. t.Run(tt.input, func(t *testing.T) {
  229. stmt := parse(t, "SELECT "+tt.input)
  230. sel := stmt.(*parser.SelectStmt)
  231. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  232. if err != nil {
  233. t.Errorf("evalExpr error: %v", err)
  234. return
  235. }
  236. if toBool(val) != tt.expected {
  237. t.Errorf("expected %v, got %v", tt.expected, val)
  238. }
  239. })
  240. }
  241. }
  242. func TestEvalBetween(t *testing.T) {
  243. exec := &Executor{}
  244. tests := []struct {
  245. input string
  246. expected bool
  247. }{
  248. {"5 BETWEEN 1 AND 10", true},
  249. {"0 BETWEEN 1 AND 10", false},
  250. {"11 BETWEEN 1 AND 10", false},
  251. {"5 NOT BETWEEN 1 AND 10", false},
  252. {"0 NOT BETWEEN 1 AND 10", true},
  253. }
  254. for _, tt := range tests {
  255. t.Run(tt.input, func(t *testing.T) {
  256. stmt := parse(t, "SELECT "+tt.input)
  257. sel := stmt.(*parser.SelectStmt)
  258. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  259. if err != nil {
  260. t.Errorf("evalExpr error: %v", err)
  261. return
  262. }
  263. if toBool(val) != tt.expected {
  264. t.Errorf("expected %v, got %v", tt.expected, val)
  265. }
  266. })
  267. }
  268. }
  269. func TestEvalLike(t *testing.T) {
  270. exec := &Executor{}
  271. tests := []struct {
  272. input string
  273. expected bool
  274. }{
  275. {"'hello' LIKE 'hello'", true},
  276. {"'hello' LIKE 'h%'", true},
  277. {"'hello' LIKE '%o'", true},
  278. {"'hello' LIKE '%ll%'", true},
  279. {"'hello' LIKE 'h_llo'", true},
  280. {"'hello' LIKE 'world'", false},
  281. {"'hello' NOT LIKE 'world'", true},
  282. }
  283. for _, tt := range tests {
  284. t.Run(tt.input, func(t *testing.T) {
  285. stmt := parse(t, "SELECT "+tt.input)
  286. sel := stmt.(*parser.SelectStmt)
  287. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  288. if err != nil {
  289. t.Errorf("evalExpr error: %v", err)
  290. return
  291. }
  292. if toBool(val) != tt.expected {
  293. t.Errorf("expected %v, got %v", tt.expected, val)
  294. }
  295. })
  296. }
  297. }
  298. func TestEvalIsNull(t *testing.T) {
  299. exec := &Executor{}
  300. tests := []struct {
  301. input string
  302. expected bool
  303. }{
  304. {"NULL IS NULL", true},
  305. {"1 IS NULL", false},
  306. {"NULL IS NOT NULL", false},
  307. {"1 IS NOT NULL", true},
  308. }
  309. for _, tt := range tests {
  310. t.Run(tt.input, func(t *testing.T) {
  311. stmt := parse(t, "SELECT "+tt.input)
  312. sel := stmt.(*parser.SelectStmt)
  313. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  314. if err != nil {
  315. t.Errorf("evalExpr error: %v", err)
  316. return
  317. }
  318. if toBool(val) != tt.expected {
  319. t.Errorf("expected %v, got %v", tt.expected, val)
  320. }
  321. })
  322. }
  323. }
  324. func TestEvalCast(t *testing.T) {
  325. exec := &Executor{}
  326. tests := []struct {
  327. input string
  328. expected interface{}
  329. }{
  330. {"CAST(3.14 AS INTEGER)", int64(3)},
  331. {"CAST(42 AS REAL)", float64(42)},
  332. {"CAST(123 AS TEXT)", "123"},
  333. }
  334. for _, tt := range tests {
  335. t.Run(tt.input, func(t *testing.T) {
  336. stmt := parse(t, "SELECT "+tt.input)
  337. sel := stmt.(*parser.SelectStmt)
  338. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  339. if err != nil {
  340. t.Errorf("evalExpr error: %v", err)
  341. return
  342. }
  343. if val != tt.expected {
  344. t.Errorf("expected %v (%T), got %v (%T)", tt.expected, tt.expected, val, val)
  345. }
  346. })
  347. }
  348. }
  349. func TestEvalWithRow(t *testing.T) {
  350. exec := &Executor{}
  351. row := map[string]interface{}{
  352. "id": int64(1),
  353. "name": "John",
  354. "age": 30,
  355. "active": true,
  356. }
  357. tests := []struct {
  358. input string
  359. expected interface{}
  360. }{
  361. {"id", int64(1)},
  362. {"name", "John"},
  363. {"age", 30},
  364. {"active", true},
  365. {"id + 1", float64(2)},
  366. {"age * 2", float64(60)},
  367. {"name = 'John'", true},
  368. {"age > 25", true},
  369. {"active AND age > 20", true},
  370. }
  371. for _, tt := range tests {
  372. t.Run(tt.input, func(t *testing.T) {
  373. stmt := parse(t, "SELECT "+tt.input)
  374. sel := stmt.(*parser.SelectStmt)
  375. val, err := exec.evalExpr(sel.Columns[0].Expr, row)
  376. if err != nil {
  377. t.Errorf("evalExpr error: %v", err)
  378. return
  379. }
  380. // Handle numeric comparisons
  381. if expected, ok := tt.expected.(float64); ok {
  382. if toFloat(val) != expected {
  383. t.Errorf("expected %v, got %v", tt.expected, val)
  384. }
  385. } else if val != tt.expected {
  386. t.Errorf("expected %v (%T), got %v (%T)", tt.expected, tt.expected, val, val)
  387. }
  388. })
  389. }
  390. }
  391. func TestResultString(t *testing.T) {
  392. result := NewResult("SELECT")
  393. result.AddColumn("id")
  394. result.AddColumn("name")
  395. result.AddRow(int64(1), "Alice")
  396. result.AddRow(int64(2), "Bob")
  397. output := result.String()
  398. // Check that output contains expected elements
  399. if output == "" {
  400. t.Error("expected non-empty output")
  401. }
  402. if result.RowCount != 2 {
  403. t.Errorf("expected 2 rows, got %d", result.RowCount)
  404. }
  405. }
  406. func TestMatchLike(t *testing.T) {
  407. tests := []struct {
  408. s string
  409. pattern string
  410. expected bool
  411. }{
  412. {"hello", "hello", true},
  413. {"hello", "h%", true},
  414. {"hello", "%o", true},
  415. {"hello", "%ll%", true},
  416. {"hello", "h_llo", true},
  417. {"hello", "H%", true}, // case insensitive
  418. {"hello", "world", false},
  419. {"", "%", true},
  420. {"abc", "a%c", true},
  421. {"abc", "a_c", true},
  422. {"abc", "__c", true},
  423. {"abc", "___", true},
  424. {"abc", "____", false},
  425. }
  426. for _, tt := range tests {
  427. t.Run(tt.s+"_"+tt.pattern, func(t *testing.T) {
  428. got := matchLike(tt.s, tt.pattern)
  429. if got != tt.expected {
  430. t.Errorf("matchLike(%q, %q) = %v, want %v", tt.s, tt.pattern, got, tt.expected)
  431. }
  432. })
  433. }
  434. }
  435. // Phase 4: SQLite function tests
  436. func TestEvalSQLiteFunctions(t *testing.T) {
  437. exec := &Executor{}
  438. tests := []struct {
  439. input string
  440. expected interface{}
  441. isInt bool // for RANDOM which returns int64
  442. }{
  443. // PRINTF
  444. {"PRINTF('%d', 42)", "42", false},
  445. {"PRINTF('%s', 'hello')", "hello", false},
  446. {"PRINTF('%d + %d = %d', 1, 2, 3)", "1 + 2 = 3", false},
  447. // HEX
  448. {"HEX('ABC')", "414243", false},
  449. {"HEX('hello')", "68656C6C6F", false},
  450. // INSTR
  451. {"INSTR('hello world', 'world')", int64(7), false},
  452. {"INSTR('hello', 'x')", int64(0), false},
  453. {"INSTR('hello', 'l')", int64(3), false},
  454. // ROUND
  455. {"ROUND(3.14159)", float64(3), false},
  456. {"ROUND(3.14159, 2)", float64(3.14), false},
  457. {"ROUND(3.5)", float64(4), false},
  458. // CONCAT
  459. {"CONCAT('hello', ' ', 'world')", "hello world", false},
  460. {"CONCAT('a', 'b', 'c')", "abc", false},
  461. // MAX/MIN (scalar versions)
  462. {"MAX(1, 5, 3)", int64(5), false},
  463. {"MIN(1, 5, 3)", int64(1), false},
  464. {"MAX('a', 'c', 'b')", "c", false},
  465. }
  466. for _, tt := range tests {
  467. t.Run(tt.input, func(t *testing.T) {
  468. stmt := parse(t, "SELECT "+tt.input)
  469. sel := stmt.(*parser.SelectStmt)
  470. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  471. if err != nil {
  472. t.Errorf("evalExpr error: %v", err)
  473. return
  474. }
  475. if val != tt.expected {
  476. t.Errorf("expected %v (%T), got %v (%T)", tt.expected, tt.expected, val, val)
  477. }
  478. })
  479. }
  480. }
  481. func TestEvalRandom(t *testing.T) {
  482. exec := &Executor{}
  483. stmt := parse(t, "SELECT RANDOM()")
  484. sel := stmt.(*parser.SelectStmt)
  485. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  486. if err != nil {
  487. t.Fatalf("evalExpr error: %v", err)
  488. }
  489. // RANDOM() should return an int64
  490. if _, ok := val.(int64); !ok {
  491. t.Errorf("RANDOM() should return int64, got %T", val)
  492. }
  493. }
  494. func TestEvalGlob(t *testing.T) {
  495. exec := &Executor{}
  496. tests := []struct {
  497. input string
  498. expected bool
  499. }{
  500. {"GLOB('*.txt', 'file.txt')", true},
  501. {"GLOB('*.txt', 'file.doc')", false},
  502. {"GLOB('hello*', 'hello world')", true},
  503. {"GLOB('h?llo', 'hello')", true},
  504. {"GLOB('h?llo', 'hallo')", true},
  505. {"GLOB('[abc]*', 'apple')", true},
  506. {"GLOB('[abc]*', 'dog')", false},
  507. }
  508. for _, tt := range tests {
  509. t.Run(tt.input, func(t *testing.T) {
  510. stmt := parse(t, "SELECT "+tt.input)
  511. sel := stmt.(*parser.SelectStmt)
  512. val, err := exec.evalExpr(sel.Columns[0].Expr, nil)
  513. if err != nil {
  514. t.Errorf("evalExpr error: %v", err)
  515. return
  516. }
  517. if toBool(val) != tt.expected {
  518. t.Errorf("expected %v, got %v", tt.expected, val)
  519. }
  520. })
  521. }
  522. }
  523. func TestMatchGlob(t *testing.T) {
  524. tests := []struct {
  525. pattern string
  526. s string
  527. expected bool
  528. }{
  529. {"*", "anything", true},
  530. {"*", "", true},
  531. {"?", "a", true},
  532. {"?", "ab", false},
  533. {"a*b", "ab", true},
  534. {"a*b", "aXXXb", true},
  535. {"a*b", "aXXXc", false},
  536. {"[abc]", "a", true},
  537. {"[abc]", "d", false},
  538. {"[^abc]", "d", true},
  539. {"[^abc]", "a", false},
  540. {"*.go", "main.go", true},
  541. {"*.go", "main.txt", false},
  542. }
  543. for _, tt := range tests {
  544. t.Run(tt.pattern+"_"+tt.s, func(t *testing.T) {
  545. got := matchGlob(tt.pattern, tt.s)
  546. if got != tt.expected {
  547. t.Errorf("matchGlob(%q, %q) = %v, want %v", tt.pattern, tt.s, got, tt.expected)
  548. }
  549. })
  550. }
  551. }
  552. // Test subquery expressions
  553. func TestEvalSubqueryExpr(t *testing.T) {
  554. pool, err := storage.NewKVPool("localhost:8085", 5, 5*time.Second)
  555. if err != nil {
  556. t.Skip("PizzaKV not available, skipping subquery tests")
  557. }
  558. defer pool.Close()
  559. schema := storage.NewSchemaManager(pool, "test_subquery_db")
  560. table := storage.NewTableManager(pool, schema, "test_subquery_db")
  561. exec := New(schema, table)
  562. // Setup test tables
  563. execSQL(exec, "DROP TABLE IF EXISTS products")
  564. execSQL(exec, "DROP TABLE IF EXISTS categories")
  565. _, err = execSQL(exec, "CREATE TABLE categories (id INTEGER PRIMARY KEY, name TEXT)")
  566. if err != nil {
  567. t.Fatalf("failed to create categories: %v", err)
  568. }
  569. _, err = execSQL(exec, "CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, category_id INTEGER, price REAL)")
  570. if err != nil {
  571. t.Fatalf("failed to create products: %v", err)
  572. }
  573. // Insert test data
  574. execSQL(exec, "INSERT INTO categories VALUES (1, 'Electronics')")
  575. execSQL(exec, "INSERT INTO categories VALUES (2, 'Books')")
  576. execSQL(exec, "INSERT INTO categories VALUES (3, 'Clothing')")
  577. execSQL(exec, "INSERT INTO products VALUES (1, 'Laptop', 1, 999.99)")
  578. execSQL(exec, "INSERT INTO products VALUES (2, 'Phone', 1, 599.99)")
  579. execSQL(exec, "INSERT INTO products VALUES (3, 'Novel', 2, 19.99)")
  580. execSQL(exec, "INSERT INTO products VALUES (4, 'T-Shirt', 3, 29.99)")
  581. // Test scalar subquery
  582. t.Run("scalar_subquery", func(t *testing.T) {
  583. result, err := execSQL(exec, "SELECT (SELECT MAX(price) FROM products)")
  584. if err != nil {
  585. t.Fatalf("query failed: %v", err)
  586. }
  587. if result.RowCount != 1 {
  588. t.Errorf("expected 1 row, got %d", result.RowCount)
  589. }
  590. if result.Rows[0][0] != 999.99 {
  591. t.Errorf("expected 999.99, got %v", result.Rows[0][0])
  592. }
  593. })
  594. // Test IN subquery
  595. t.Run("in_subquery", func(t *testing.T) {
  596. result, err := execSQL(exec, "SELECT name FROM products WHERE category_id IN (SELECT id FROM categories WHERE name = 'Electronics')")
  597. if err != nil {
  598. t.Fatalf("query failed: %v", err)
  599. }
  600. if result.RowCount != 2 {
  601. t.Errorf("expected 2 rows, got %d", result.RowCount)
  602. }
  603. })
  604. // Test NOT IN subquery
  605. t.Run("not_in_subquery", func(t *testing.T) {
  606. result, err := execSQL(exec, "SELECT name FROM products WHERE category_id NOT IN (SELECT id FROM categories WHERE name = 'Electronics')")
  607. if err != nil {
  608. t.Fatalf("query failed: %v", err)
  609. }
  610. if result.RowCount != 2 {
  611. t.Errorf("expected 2 rows, got %d", result.RowCount)
  612. }
  613. })
  614. // Test EXISTS subquery
  615. t.Run("exists_subquery", func(t *testing.T) {
  616. result, err := execSQL(exec, "SELECT EXISTS (SELECT 1 FROM products WHERE price > 500)")
  617. if err != nil {
  618. t.Fatalf("query failed: %v", err)
  619. }
  620. if result.RowCount != 1 {
  621. t.Errorf("expected 1 row, got %d", result.RowCount)
  622. }
  623. if result.Rows[0][0] != true {
  624. t.Errorf("expected true, got %v", result.Rows[0][0])
  625. }
  626. })
  627. // Test EXISTS with no matches
  628. t.Run("exists_no_match", func(t *testing.T) {
  629. result, err := execSQL(exec, "SELECT EXISTS (SELECT 1 FROM products WHERE price > 10000)")
  630. if err != nil {
  631. t.Fatalf("query failed: %v", err)
  632. }
  633. if result.Rows[0][0] != false {
  634. t.Errorf("expected false, got %v", result.Rows[0][0])
  635. }
  636. })
  637. // Cleanup
  638. execSQL(exec, "DROP TABLE IF EXISTS products")
  639. execSQL(exec, "DROP TABLE IF EXISTS categories")
  640. }
  641. // Benchmark
  642. func BenchmarkEvalExpr(b *testing.B) {
  643. exec := &Executor{}
  644. stmt := parse(&testing.T{}, "SELECT (1 + 2) * 3 - 4 / 2")
  645. sel := stmt.(*parser.SelectStmt)
  646. expr := sel.Columns[0].Expr
  647. b.ResetTimer()
  648. for i := 0; i < b.N; i++ {
  649. exec.evalExpr(expr, nil)
  650. }
  651. }
  652. // BenchmarkIndexVsNoIndex compares query performance with and without indexes.
  653. // Requires a running PizzaKV instance at localhost:8085.
  654. func BenchmarkIndexVsNoIndex(b *testing.B) {
  655. pool, err := storage.NewKVPool("localhost:8085", 5, 5*time.Second)
  656. if err != nil {
  657. b.Skip("PizzaKV not available, skipping index benchmark")
  658. }
  659. defer pool.Close()
  660. schema := storage.NewSchemaManager(pool, "bench_db")
  661. table := storage.NewTableManager(pool, schema, "bench_db")
  662. exec := New(schema, table)
  663. // Cleanup first to ensure fresh state
  664. execSQL(exec, "DROP INDEX IF EXISTS idx_bench_status")
  665. execSQL(exec, "DROP TABLE IF EXISTS bench_users")
  666. _, err = execSQL(exec, "CREATE TABLE bench_users (id INTEGER PRIMARY KEY, name TEXT, email TEXT, status TEXT)")
  667. if err != nil {
  668. b.Fatalf("failed to create table: %v", err)
  669. }
  670. // Insert 1000 rows
  671. statuses := []string{"active", "inactive", "pending", "suspended"}
  672. for i := 1; i <= 1000; i++ {
  673. status := statuses[i%len(statuses)]
  674. _, err := execSQL(exec, fmt.Sprintf("INSERT INTO bench_users (id, name, email, status) VALUES (%d, 'User%d', 'user%d@test.com', '%s')", i, i, i, status))
  675. if err != nil {
  676. b.Fatalf("failed to insert row %d: %v", i, err)
  677. }
  678. }
  679. // Benchmark WITHOUT index
  680. b.Run("NoIndex", func(b *testing.B) {
  681. for i := 0; i < b.N; i++ {
  682. _, err := execSQL(exec, "SELECT * FROM bench_users WHERE status = 'active'")
  683. if err != nil {
  684. b.Fatalf("query failed: %v", err)
  685. }
  686. }
  687. })
  688. // Create index on status column
  689. _, err = execSQL(exec, "CREATE INDEX idx_bench_status ON bench_users (status)")
  690. if err != nil {
  691. b.Fatalf("failed to create index: %v", err)
  692. }
  693. // Benchmark WITH index
  694. b.Run("WithIndex", func(b *testing.B) {
  695. for i := 0; i < b.N; i++ {
  696. _, err := execSQL(exec, "SELECT * FROM bench_users WHERE status = 'active'")
  697. if err != nil {
  698. b.Fatalf("query failed: %v", err)
  699. }
  700. }
  701. })
  702. // Cleanup
  703. execSQL(exec, "DROP INDEX IF EXISTS idx_bench_status")
  704. execSQL(exec, "DROP TABLE IF EXISTS bench_users")
  705. }
  706. // BenchmarkIndexVsNoIndexLargeTable tests with more rows
  707. func BenchmarkIndexVsNoIndexLargeTable(b *testing.B) {
  708. pool, err := storage.NewKVPool("localhost:8085", 5, 5*time.Second)
  709. if err != nil {
  710. b.Skip("PizzaKV not available, skipping index benchmark")
  711. }
  712. defer pool.Close()
  713. schema := storage.NewSchemaManager(pool, "bench_db")
  714. table := storage.NewTableManager(pool, schema, "bench_db")
  715. exec := New(schema, table)
  716. // Cleanup first to ensure fresh state
  717. execSQL(exec, "DROP INDEX IF EXISTS idx_bench_category")
  718. execSQL(exec, "DROP TABLE IF EXISTS bench_large")
  719. _, err = execSQL(exec, "CREATE TABLE bench_large (id INTEGER PRIMARY KEY, category INTEGER, value TEXT)")
  720. if err != nil {
  721. b.Fatalf("failed to create table: %v", err)
  722. }
  723. // Insert 5000 rows with 100 distinct categories
  724. for i := 1; i <= 5000; i++ {
  725. category := i % 100
  726. _, err := execSQL(exec, fmt.Sprintf("INSERT INTO bench_large (id, category, value) VALUES (%d, %d, 'value_%d')", i, category, i))
  727. if err != nil {
  728. b.Fatalf("failed to insert row %d: %v", i, err)
  729. }
  730. }
  731. // Benchmark WITHOUT index (should scan all 5000 rows)
  732. b.Run("NoIndex_5000rows", func(b *testing.B) {
  733. for i := 0; i < b.N; i++ {
  734. _, err := execSQL(exec, "SELECT * FROM bench_large WHERE category = 42")
  735. if err != nil {
  736. b.Fatalf("query failed: %v", err)
  737. }
  738. }
  739. })
  740. // Create index
  741. _, err = execSQL(exec, "CREATE INDEX idx_bench_category ON bench_large (category)")
  742. if err != nil {
  743. b.Fatalf("failed to create index: %v", err)
  744. }
  745. // Benchmark WITH index (should only retrieve ~50 rows)
  746. b.Run("WithIndex_5000rows", func(b *testing.B) {
  747. for i := 0; i < b.N; i++ {
  748. _, err := execSQL(exec, "SELECT * FROM bench_large WHERE category = 42")
  749. if err != nil {
  750. b.Fatalf("query failed: %v", err)
  751. }
  752. }
  753. })
  754. // Cleanup
  755. execSQL(exec, "DROP INDEX IF EXISTS idx_bench_category")
  756. execSQL(exec, "DROP TABLE IF EXISTS bench_large")
  757. }
  758. // Test transaction statements
  759. func TestTransactions(t *testing.T) {
  760. pool, err := storage.NewKVPool("localhost:8085", 5, 5*time.Second)
  761. if err != nil {
  762. t.Skip("PizzaKV not available, skipping transaction tests")
  763. }
  764. defer pool.Close()
  765. schema := storage.NewSchemaManager(pool, "test_tx_db")
  766. table := storage.NewTableManager(pool, schema, "test_tx_db")
  767. exec := New(schema, table)
  768. // Setup test table
  769. execSQL(exec, "DROP TABLE IF EXISTS tx_test")
  770. _, err = execSQL(exec, "CREATE TABLE tx_test (id INTEGER PRIMARY KEY, value TEXT)")
  771. if err != nil {
  772. t.Fatalf("failed to create table: %v", err)
  773. }
  774. t.Run("begin_transaction", func(t *testing.T) {
  775. result, err := execSQL(exec, "BEGIN")
  776. if err != nil {
  777. t.Fatalf("BEGIN failed: %v", err)
  778. }
  779. if result.CommandTag != "BEGIN" {
  780. t.Errorf("expected StatementType 'BEGIN', got '%s'", result.CommandTag)
  781. }
  782. if !exec.inTransaction {
  783. t.Error("expected inTransaction to be true")
  784. }
  785. // Rollback to reset state
  786. execSQL(exec, "ROLLBACK")
  787. })
  788. t.Run("begin_transaction_keyword", func(t *testing.T) {
  789. result, err := execSQL(exec, "BEGIN TRANSACTION")
  790. if err != nil {
  791. t.Fatalf("BEGIN TRANSACTION failed: %v", err)
  792. }
  793. if result.CommandTag != "BEGIN" {
  794. t.Errorf("expected StatementType 'BEGIN', got '%s'", result.CommandTag)
  795. }
  796. execSQL(exec, "ROLLBACK")
  797. })
  798. t.Run("commit_transaction", func(t *testing.T) {
  799. // Clean up any previous data
  800. execSQL(exec, "DELETE FROM tx_test WHERE id = 1")
  801. execSQL(exec, "BEGIN")
  802. _, err := execSQL(exec, "INSERT INTO tx_test (id, value) VALUES (1, 'test1')")
  803. if err != nil {
  804. t.Fatalf("INSERT failed: %v", err)
  805. }
  806. result, err := execSQL(exec, "COMMIT")
  807. if err != nil {
  808. t.Fatalf("COMMIT failed: %v", err)
  809. }
  810. if result.CommandTag != "COMMIT" {
  811. t.Errorf("expected StatementType 'COMMIT', got '%s'", result.CommandTag)
  812. }
  813. if exec.inTransaction {
  814. t.Error("expected inTransaction to be false after COMMIT")
  815. }
  816. // Verify data was committed
  817. checkResult, _ := execSQL(exec, "SELECT * FROM tx_test WHERE id = 1")
  818. if checkResult.RowCount != 1 {
  819. t.Errorf("expected 1 row after commit, got %d", checkResult.RowCount)
  820. }
  821. })
  822. t.Run("rollback_transaction", func(t *testing.T) {
  823. // Clean up any previous data
  824. execSQL(exec, "DELETE FROM tx_test WHERE id = 2")
  825. execSQL(exec, "BEGIN")
  826. _, err := execSQL(exec, "INSERT INTO tx_test (id, value) VALUES (2, 'test2')")
  827. if err != nil {
  828. t.Fatalf("INSERT failed: %v", err)
  829. }
  830. result, err := execSQL(exec, "ROLLBACK")
  831. if err != nil {
  832. t.Fatalf("ROLLBACK failed: %v", err)
  833. }
  834. if result.CommandTag != "ROLLBACK" {
  835. t.Errorf("expected StatementType 'ROLLBACK', got '%s'", result.CommandTag)
  836. }
  837. if exec.inTransaction {
  838. t.Error("expected inTransaction to be false after ROLLBACK")
  839. }
  840. // Verify data was NOT committed (rollback currently doesn't undo changes due to PizzaKV limitations)
  841. // This is a known limitation - the transaction log is built but rollback doesn't restore state
  842. checkResult, _ := execSQL(exec, "SELECT * FROM tx_test WHERE id = 2")
  843. // Note: In the current implementation, rollback doesn't actually undo changes
  844. // This test documents current behavior
  845. if checkResult.RowCount == 0 {
  846. t.Log("ROLLBACK successfully prevented data persistence (ideal)")
  847. } else {
  848. t.Log("ROLLBACK did not undo changes (current limitation)")
  849. }
  850. })
  851. t.Run("savepoint_create", func(t *testing.T) {
  852. execSQL(exec, "BEGIN")
  853. result, err := execSQL(exec, "SAVEPOINT sp1")
  854. if err != nil {
  855. t.Fatalf("SAVEPOINT failed: %v", err)
  856. }
  857. if result.CommandTag != "SAVEPOINT" {
  858. t.Errorf("expected StatementType 'SAVEPOINT', got '%s'", result.CommandTag)
  859. }
  860. if len(exec.savepoints) != 1 || exec.savepoints[0] != "sp1" {
  861. t.Errorf("expected savepoint 'sp1', got %v", exec.savepoints)
  862. }
  863. execSQL(exec, "ROLLBACK")
  864. })
  865. t.Run("nested_savepoints", func(t *testing.T) {
  866. execSQL(exec, "BEGIN")
  867. execSQL(exec, "SAVEPOINT sp1")
  868. execSQL(exec, "SAVEPOINT sp2")
  869. execSQL(exec, "SAVEPOINT sp3")
  870. if len(exec.savepoints) != 3 {
  871. t.Errorf("expected 3 savepoints, got %d", len(exec.savepoints))
  872. }
  873. if exec.savepoints[2] != "sp3" {
  874. t.Errorf("expected last savepoint to be 'sp3', got '%s'", exec.savepoints[2])
  875. }
  876. execSQL(exec, "ROLLBACK")
  877. })
  878. t.Run("rollback_to_savepoint", func(t *testing.T) {
  879. execSQL(exec, "BEGIN")
  880. execSQL(exec, "INSERT INTO tx_test (id, value) VALUES (10, 'before_sp')")
  881. execSQL(exec, "SAVEPOINT sp1")
  882. execSQL(exec, "INSERT INTO tx_test (id, value) VALUES (11, 'after_sp')")
  883. result, err := execSQL(exec, "ROLLBACK TO sp1")
  884. if err != nil {
  885. t.Fatalf("ROLLBACK TO failed: %v", err)
  886. }
  887. if result.CommandTag != "ROLLBACK" {
  888. t.Errorf("expected StatementType 'ROLLBACK', got '%s'", result.CommandTag)
  889. }
  890. // Should still be in transaction
  891. if !exec.inTransaction {
  892. t.Error("expected to still be in transaction after ROLLBACK TO")
  893. }
  894. execSQL(exec, "ROLLBACK")
  895. })
  896. t.Run("release_savepoint", func(t *testing.T) {
  897. execSQL(exec, "BEGIN")
  898. execSQL(exec, "SAVEPOINT sp1")
  899. execSQL(exec, "SAVEPOINT sp2")
  900. result, err := execSQL(exec, "RELEASE sp1")
  901. if err != nil {
  902. t.Fatalf("RELEASE failed: %v", err)
  903. }
  904. if result.CommandTag != "RELEASE" {
  905. t.Errorf("expected StatementType 'RELEASE', got '%s'", result.CommandTag)
  906. }
  907. // Releasing sp1 should also remove sp2 (all nested savepoints)
  908. if len(exec.savepoints) != 0 {
  909. t.Errorf("expected no savepoints after RELEASE, got %d", len(exec.savepoints))
  910. }
  911. execSQL(exec, "ROLLBACK")
  912. })
  913. t.Run("release_savepoint_explicit", func(t *testing.T) {
  914. execSQL(exec, "BEGIN")
  915. execSQL(exec, "SAVEPOINT sp1")
  916. result, err := execSQL(exec, "RELEASE SAVEPOINT sp1")
  917. if err != nil {
  918. t.Fatalf("RELEASE SAVEPOINT failed: %v", err)
  919. }
  920. if result.CommandTag != "RELEASE" {
  921. t.Errorf("expected StatementType 'RELEASE', got '%s'", result.CommandTag)
  922. }
  923. execSQL(exec, "ROLLBACK")
  924. })
  925. // Cleanup
  926. execSQL(exec, "DROP TABLE IF EXISTS tx_test")
  927. }
  928. // Test subqueries in FROM clause
  929. func TestSubqueryInFrom(t *testing.T) {
  930. pool, err := storage.NewKVPool("localhost:8085", 5, 5*time.Second)
  931. if err != nil {
  932. t.Skip("PizzaKV not available, skipping subquery in FROM tests")
  933. }
  934. defer pool.Close()
  935. schema := storage.NewSchemaManager(pool, "test_subquery_from_db")
  936. table := storage.NewTableManager(pool, schema, "test_subquery_from_db")
  937. exec := New(schema, table)
  938. // Setup test table
  939. execSQL(exec, "DROP TABLE IF EXISTS employees")
  940. _, err = execSQL(exec, "CREATE TABLE employees (id INTEGER PRIMARY KEY, name TEXT, department TEXT, salary INTEGER)")
  941. if err != nil {
  942. t.Fatalf("failed to create table: %v", err)
  943. }
  944. // Insert test data
  945. execSQL(exec, "INSERT INTO employees (id, name, department, salary) VALUES (1, 'Alice', 'Engineering', 100000)")
  946. execSQL(exec, "INSERT INTO employees (id, name, department, salary) VALUES (2, 'Bob', 'Engineering', 90000)")
  947. execSQL(exec, "INSERT INTO employees (id, name, department, salary) VALUES (3, 'Charlie', 'Sales', 80000)")
  948. execSQL(exec, "INSERT INTO employees (id, name, department, salary) VALUES (4, 'Diana', 'Sales', 75000)")
  949. t.Run("simple_subquery_from", func(t *testing.T) {
  950. result, err := execSQL(exec, "SELECT * FROM (SELECT name, department FROM employees) AS emp")
  951. if err != nil {
  952. t.Fatalf("query failed: %v", err)
  953. }
  954. if result.RowCount != 4 {
  955. t.Errorf("expected 4 rows, got %d", result.RowCount)
  956. }
  957. if len(result.Columns) != 2 {
  958. t.Errorf("expected 2 columns, got %d", len(result.Columns))
  959. }
  960. })
  961. t.Run("subquery_with_where", func(t *testing.T) {
  962. result, err := execSQL(exec, "SELECT name FROM (SELECT id, name, salary FROM employees WHERE salary > 80000) AS high_earners")
  963. if err != nil {
  964. t.Fatalf("query failed: %v", err)
  965. }
  966. if result.RowCount != 2 {
  967. t.Errorf("expected 2 rows, got %d", result.RowCount)
  968. }
  969. })
  970. t.Run("subquery_with_outer_where", func(t *testing.T) {
  971. result, err := execSQL(exec, "SELECT * FROM (SELECT name, department FROM employees) AS emp WHERE department = 'Engineering'")
  972. if err != nil {
  973. t.Fatalf("query failed: %v", err)
  974. }
  975. if result.RowCount != 2 {
  976. t.Errorf("expected 2 rows, got %d", result.RowCount)
  977. }
  978. })
  979. t.Run("subquery_select_specific_columns", func(t *testing.T) {
  980. result, err := execSQL(exec, "SELECT name FROM (SELECT id, name, department FROM employees WHERE department = 'Sales') AS sales_emp")
  981. if err != nil {
  982. t.Fatalf("query failed: %v", err)
  983. }
  984. if result.RowCount != 2 {
  985. t.Errorf("expected 2 rows, got %d", result.RowCount)
  986. }
  987. if len(result.Columns) != 1 || result.Columns[0] != "name" {
  988. t.Errorf("expected column 'name', got %v", result.Columns)
  989. }
  990. })
  991. t.Run("nested_subquery", func(t *testing.T) {
  992. result, err := execSQL(exec, "SELECT * FROM (SELECT * FROM (SELECT name FROM employees) AS inner_q) AS outer_q")
  993. if err != nil {
  994. t.Fatalf("query failed: %v", err)
  995. }
  996. if result.RowCount != 4 {
  997. t.Errorf("expected 4 rows, got %d", result.RowCount)
  998. }
  999. })
  1000. // Cleanup
  1001. execSQL(exec, "DROP TABLE IF EXISTS employees")
  1002. }
  1003. // Test ALTER TABLE statements
  1004. func TestAlterTable(t *testing.T) {
  1005. pool, err := storage.NewKVPool("localhost:8085", 5, 5*time.Second)
  1006. if err != nil {
  1007. t.Skip("PizzaKV not available, skipping ALTER TABLE tests")
  1008. }
  1009. defer pool.Close()
  1010. schema := storage.NewSchemaManager(pool, "test_alter_db")
  1011. table := storage.NewTableManager(pool, schema, "test_alter_db")
  1012. exec := New(schema, table)
  1013. // Setup test table
  1014. execSQL(exec, "DROP TABLE IF EXISTS test_alter")
  1015. _, err = execSQL(exec, "CREATE TABLE test_alter (id INTEGER PRIMARY KEY, name TEXT)")
  1016. if err != nil {
  1017. t.Fatalf("failed to create table: %v", err)
  1018. }
  1019. t.Run("add_column", func(t *testing.T) {
  1020. _, err := execSQL(exec, "ALTER TABLE test_alter ADD COLUMN age INTEGER")
  1021. if err != nil {
  1022. t.Fatalf("ALTER TABLE ADD COLUMN failed: %v", err)
  1023. }
  1024. // Verify column was added
  1025. tSchema, err := schema.GetSchema("test_alter")
  1026. if err != nil {
  1027. t.Fatalf("failed to get schema: %v", err)
  1028. }
  1029. found := false
  1030. for _, col := range tSchema.Columns {
  1031. if col.Name == "age" {
  1032. found = true
  1033. if col.Type != "INTEGER" {
  1034. t.Errorf("expected type INTEGER, got %s", col.Type)
  1035. }
  1036. break
  1037. }
  1038. }
  1039. if !found {
  1040. t.Error("column 'age' not found after ADD COLUMN")
  1041. }
  1042. })
  1043. t.Run("add_column_optional_keyword", func(t *testing.T) {
  1044. _, err := execSQL(exec, "ALTER TABLE test_alter ADD email TEXT")
  1045. if err != nil {
  1046. t.Fatalf("ALTER TABLE ADD failed: %v", err)
  1047. }
  1048. // Verify column was added
  1049. tSchema, _ := schema.GetSchema("test_alter")
  1050. found := false
  1051. for _, col := range tSchema.Columns {
  1052. if col.Name == "email" {
  1053. found = true
  1054. break
  1055. }
  1056. }
  1057. if !found {
  1058. t.Error("column 'email' not found after ADD")
  1059. }
  1060. })
  1061. t.Run("rename_column", func(t *testing.T) {
  1062. _, err := execSQL(exec, "ALTER TABLE test_alter RENAME COLUMN name TO full_name")
  1063. if err != nil {
  1064. t.Fatalf("ALTER TABLE RENAME COLUMN failed: %v", err)
  1065. }
  1066. // Verify column was renamed
  1067. tSchema, _ := schema.GetSchema("test_alter")
  1068. hasOld := false
  1069. hasNew := false
  1070. for _, col := range tSchema.Columns {
  1071. if col.Name == "name" {
  1072. hasOld = true
  1073. }
  1074. if col.Name == "full_name" {
  1075. hasNew = true
  1076. }
  1077. }
  1078. if hasOld {
  1079. t.Error("old column 'name' still exists after RENAME COLUMN")
  1080. }
  1081. if !hasNew {
  1082. t.Error("new column 'full_name' not found after RENAME COLUMN")
  1083. }
  1084. })
  1085. t.Run("drop_column", func(t *testing.T) {
  1086. _, err := execSQL(exec, "ALTER TABLE test_alter DROP COLUMN email")
  1087. if err != nil {
  1088. t.Fatalf("ALTER TABLE DROP COLUMN failed: %v", err)
  1089. }
  1090. // Verify column was dropped
  1091. tSchema, _ := schema.GetSchema("test_alter")
  1092. for _, col := range tSchema.Columns {
  1093. if col.Name == "email" {
  1094. t.Error("column 'email' still exists after DROP COLUMN")
  1095. }
  1096. }
  1097. })
  1098. t.Run("rename_table", func(t *testing.T) {
  1099. _, err := execSQL(exec, "ALTER TABLE test_alter RENAME TO test_renamed")
  1100. if err != nil {
  1101. t.Fatalf("ALTER TABLE RENAME TO failed: %v", err)
  1102. }
  1103. // Verify old table doesn't exist
  1104. _, err = schema.GetSchema("test_alter")
  1105. if err == nil {
  1106. t.Error("old table 'test_alter' still exists after RENAME TO")
  1107. }
  1108. // Verify new table exists
  1109. _, err = schema.GetSchema("test_renamed")
  1110. if err != nil {
  1111. t.Errorf("new table 'test_renamed' not found after RENAME TO: %v", err)
  1112. }
  1113. // Cleanup with new name
  1114. execSQL(exec, "DROP TABLE IF EXISTS test_renamed")
  1115. })
  1116. // Final cleanup
  1117. execSQL(exec, "DROP TABLE IF EXISTS test_alter")
  1118. execSQL(exec, "DROP TABLE IF EXISTS test_renamed")
  1119. }
  1120. // Test ATTACH/DETACH DATABASE statements
  1121. func TestAttachDetach(t *testing.T) {
  1122. pool, err := storage.NewKVPool("localhost:8085", 5, 5*time.Second)
  1123. if err != nil {
  1124. t.Skip("PizzaKV not available, skipping ATTACH/DETACH tests")
  1125. }
  1126. defer pool.Close()
  1127. schema := storage.NewSchemaManager(pool, "test_main_db")
  1128. table := storage.NewTableManager(pool, schema, "test_main_db")
  1129. exec := New(schema, table)
  1130. // Create a table in main database
  1131. execSQL(exec, "DROP TABLE IF EXISTS main_table")
  1132. _, err = execSQL(exec, "CREATE TABLE main_table (id INTEGER PRIMARY KEY, data TEXT)")
  1133. if err != nil {
  1134. t.Fatalf("failed to create main table: %v", err)
  1135. }
  1136. execSQL(exec, "INSERT INTO main_table (id, data) VALUES (1, 'main data')")
  1137. t.Run("attach_database", func(t *testing.T) {
  1138. result, err := execSQL(exec, "ATTACH DATABASE 'test_other_db' AS other")
  1139. if err != nil {
  1140. t.Fatalf("ATTACH DATABASE failed: %v", err)
  1141. }
  1142. if result.CommandTag != "ATTACH" {
  1143. t.Errorf("expected command tag 'ATTACH', got '%s'", result.CommandTag)
  1144. }
  1145. // Verify database is attached
  1146. if _, exists := exec.attachedDatabases["other"]; !exists {
  1147. t.Error("database 'other' not found in attached databases")
  1148. }
  1149. })
  1150. t.Run("attach_duplicate_alias", func(t *testing.T) {
  1151. _, err := execSQL(exec, "ATTACH DATABASE 'test_dup_db' AS other")
  1152. if err == nil {
  1153. t.Error("expected error when attaching with duplicate alias")
  1154. }
  1155. })
  1156. t.Run("attach_reserved_alias", func(t *testing.T) {
  1157. _, err := execSQL(exec, "ATTACH DATABASE 'test_temp_db' AS temp")
  1158. if err == nil {
  1159. t.Error("expected error when using reserved alias 'temp'")
  1160. }
  1161. })
  1162. t.Run("detach_database", func(t *testing.T) {
  1163. result, err := execSQL(exec, "DETACH DATABASE other")
  1164. if err != nil {
  1165. t.Fatalf("DETACH DATABASE failed: %v", err)
  1166. }
  1167. if result.CommandTag != "DETACH" {
  1168. t.Errorf("expected command tag 'DETACH', got '%s'", result.CommandTag)
  1169. }
  1170. // Verify database is detached
  1171. if _, exists := exec.attachedDatabases["other"]; exists {
  1172. t.Error("database 'other' still attached after DETACH")
  1173. }
  1174. })
  1175. t.Run("detach_nonexistent", func(t *testing.T) {
  1176. _, err := execSQL(exec, "DETACH DATABASE nonexistent")
  1177. if err == nil {
  1178. t.Error("expected error when detaching nonexistent database")
  1179. }
  1180. })
  1181. t.Run("detach_main_database", func(t *testing.T) {
  1182. _, err := execSQL(exec, "DETACH DATABASE main")
  1183. if err == nil {
  1184. t.Error("expected error when detaching main database")
  1185. }
  1186. })
  1187. t.Run("attach_without_database_keyword", func(t *testing.T) {
  1188. result, err := execSQL(exec, "ATTACH 'test_short_db' AS short")
  1189. if err != nil {
  1190. t.Fatalf("ATTACH (without DATABASE) failed: %v", err)
  1191. }
  1192. if result.CommandTag != "ATTACH" {
  1193. t.Errorf("expected command tag 'ATTACH', got '%s'", result.CommandTag)
  1194. }
  1195. // Cleanup
  1196. execSQL(exec, "DETACH short")
  1197. })
  1198. t.Run("detach_without_database_keyword", func(t *testing.T) {
  1199. execSQL(exec, "ATTACH 'test_det_db' AS det")
  1200. result, err := execSQL(exec, "DETACH det")
  1201. if err != nil {
  1202. t.Fatalf("DETACH (without DATABASE) failed: %v", err)
  1203. }
  1204. if result.CommandTag != "DETACH" {
  1205. t.Errorf("expected command tag 'DETACH', got '%s'", result.CommandTag)
  1206. }
  1207. })
  1208. // Cleanup
  1209. execSQL(exec, "DROP TABLE IF EXISTS main_table")
  1210. }
  1211. func TestDistinct(t *testing.T) {
  1212. // Simple test without requiring KV connection
  1213. exec := &Executor{}
  1214. // Test applyDistinct function directly
  1215. t.Run("ApplyDistinct", func(t *testing.T) {
  1216. rows := [][]interface{}{
  1217. {"a", 1},
  1218. {"b", 2},
  1219. {"a", 1}, // duplicate
  1220. {"c", 3},
  1221. {"b", 2}, // duplicate
  1222. }
  1223. result := exec.applyDistinct(rows)
  1224. if len(result) != 3 {
  1225. t.Errorf("expected 3 unique rows, got %d", len(result))
  1226. }
  1227. // Check that we have the expected unique rows
  1228. expected := map[string]bool{
  1229. "a\x001": true,
  1230. "b\x002": true,
  1231. "c\x003": true,
  1232. }
  1233. for _, row := range result {
  1234. key := fmt.Sprintf("%v\x00%v", row[0], row[1])
  1235. if !expected[key] {
  1236. t.Errorf("unexpected row in result: %v", row)
  1237. }
  1238. }
  1239. })
  1240. }