parser_test.go 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561
  1. package parser
  2. import (
  3. "testing"
  4. "github.com/danfragoso/pizzasql-next/pkg/lexer"
  5. )
  6. func parse(t *testing.T, input string) Statement {
  7. t.Helper()
  8. l := lexer.New(input)
  9. p := New(l)
  10. stmt, err := p.Parse()
  11. if err != nil {
  12. t.Fatalf("parse error: %v", err)
  13. }
  14. return stmt
  15. }
  16. func parseExpr(t *testing.T, input string) Expr {
  17. t.Helper()
  18. // Wrap in SELECT to parse as expression
  19. l := lexer.New("SELECT " + input)
  20. p := New(l)
  21. stmt, err := p.Parse()
  22. if err != nil {
  23. t.Fatalf("parse error: %v", err)
  24. }
  25. sel := stmt.(*SelectStmt)
  26. return sel.Columns[0].Expr
  27. }
  28. // SELECT statement tests
  29. func TestParseSelectStar(t *testing.T) {
  30. stmt := parse(t, "SELECT * FROM users")
  31. sel, ok := stmt.(*SelectStmt)
  32. if !ok {
  33. t.Fatalf("expected SelectStmt, got %T", stmt)
  34. }
  35. if len(sel.Columns) != 1 || !sel.Columns[0].Star {
  36. t.Error("expected SELECT *")
  37. }
  38. if len(sel.From) != 1 || sel.From[0].Name != "users" {
  39. t.Error("expected FROM users")
  40. }
  41. }
  42. func TestParseSelectColumns(t *testing.T) {
  43. stmt := parse(t, "SELECT id, name, email FROM users")
  44. sel := stmt.(*SelectStmt)
  45. if len(sel.Columns) != 3 {
  46. t.Fatalf("expected 3 columns, got %d", len(sel.Columns))
  47. }
  48. cols := []string{"id", "name", "email"}
  49. for i, col := range sel.Columns {
  50. ref, ok := col.Expr.(*ColumnRef)
  51. if !ok {
  52. t.Errorf("column %d: expected ColumnRef", i)
  53. continue
  54. }
  55. if ref.Column != cols[i] {
  56. t.Errorf("column %d: expected %s, got %s", i, cols[i], ref.Column)
  57. }
  58. }
  59. }
  60. func TestParseSelectQualifiedWildcard(t *testing.T) {
  61. stmt := parse(t, "SELECT DISTINCT repo.* FROM repository AS repo LEFT JOIN access ON access.repo_id = repo.id")
  62. sel := stmt.(*SelectStmt)
  63. if !sel.Distinct {
  64. t.Error("expected DISTINCT")
  65. }
  66. if len(sel.Columns) != 1 {
  67. t.Fatalf("expected 1 column, got %d", len(sel.Columns))
  68. }
  69. col := sel.Columns[0]
  70. if col.TableStar != "repo" {
  71. t.Errorf("expected TableStar=repo, got %q", col.TableStar)
  72. }
  73. if col.Star || col.Expr != nil || col.Alias != "" {
  74. t.Errorf("qualified wildcard should not set Star/Expr/Alias: %+v", col)
  75. }
  76. }
  77. func TestParseSelectQualifiedWildcardMixed(t *testing.T) {
  78. stmt := parse(t, "SELECT repo.*, access.mode FROM repository AS repo LEFT JOIN access ON access.repo_id = repo.id")
  79. sel := stmt.(*SelectStmt)
  80. if len(sel.Columns) != 2 {
  81. t.Fatalf("expected 2 columns, got %d", len(sel.Columns))
  82. }
  83. if sel.Columns[0].TableStar != "repo" {
  84. t.Errorf("column 0 TableStar = %q, want repo", sel.Columns[0].TableStar)
  85. }
  86. ref, ok := sel.Columns[1].Expr.(*ColumnRef)
  87. if !ok || ref.Table != "access" || ref.Column != "mode" {
  88. t.Errorf("column 1 = %+v, want access.mode ColumnRef", sel.Columns[1].Expr)
  89. }
  90. }
  91. func TestParseSelectCountStarStillWorks(t *testing.T) {
  92. stmt := parse(t, "SELECT COUNT(*) FROM users")
  93. sel := stmt.(*SelectStmt)
  94. if len(sel.Columns) != 1 {
  95. t.Fatalf("expected 1 column, got %d", len(sel.Columns))
  96. }
  97. col := sel.Columns[0]
  98. if col.TableStar != "" || col.Star {
  99. t.Errorf("COUNT(*) should not be a wildcard: %+v", col)
  100. }
  101. fn, ok := col.Expr.(*FunctionCall)
  102. if !ok || !fn.Star || fn.Name != "COUNT" {
  103. t.Errorf("expected COUNT(*) FunctionCall, got %+v", col.Expr)
  104. }
  105. }
  106. func TestParseSelectWithAlias(t *testing.T) {
  107. stmt := parse(t, "SELECT id AS user_id, name AS full_name FROM users u")
  108. sel := stmt.(*SelectStmt)
  109. if sel.Columns[0].Alias != "user_id" {
  110. t.Errorf("expected alias user_id, got %s", sel.Columns[0].Alias)
  111. }
  112. if sel.Columns[1].Alias != "full_name" {
  113. t.Errorf("expected alias full_name, got %s", sel.Columns[1].Alias)
  114. }
  115. if sel.From[0].Alias != "u" {
  116. t.Errorf("expected table alias u, got %s", sel.From[0].Alias)
  117. }
  118. }
  119. func TestParseSelectDistinct(t *testing.T) {
  120. stmt := parse(t, "SELECT DISTINCT name FROM users")
  121. sel := stmt.(*SelectStmt)
  122. if !sel.Distinct {
  123. t.Error("expected DISTINCT")
  124. }
  125. }
  126. func TestParseSelectWhere(t *testing.T) {
  127. stmt := parse(t, "SELECT * FROM users WHERE id = 1")
  128. sel := stmt.(*SelectStmt)
  129. if sel.Where == nil {
  130. t.Fatal("expected WHERE clause")
  131. }
  132. binary, ok := sel.Where.(*BinaryExpr)
  133. if !ok {
  134. t.Fatalf("expected BinaryExpr, got %T", sel.Where)
  135. }
  136. if binary.Op != lexer.TokenEq {
  137. t.Errorf("expected =, got %v", binary.Op)
  138. }
  139. }
  140. func TestParseSelectWhereComplex(t *testing.T) {
  141. stmt := parse(t, "SELECT * FROM users WHERE id = 1 AND name = 'John' OR active = TRUE")
  142. sel := stmt.(*SelectStmt)
  143. if sel.Where == nil {
  144. t.Fatal("expected WHERE clause")
  145. }
  146. // Should be: (id = 1 AND name = 'John') OR active = TRUE
  147. or, ok := sel.Where.(*BinaryExpr)
  148. if !ok || or.Op != lexer.TokenOR {
  149. t.Fatal("expected OR at top level")
  150. }
  151. }
  152. func TestParseSelectOrderBy(t *testing.T) {
  153. stmt := parse(t, "SELECT * FROM users ORDER BY name ASC, id DESC")
  154. sel := stmt.(*SelectStmt)
  155. if len(sel.OrderBy) != 2 {
  156. t.Fatalf("expected 2 ORDER BY items, got %d", len(sel.OrderBy))
  157. }
  158. if sel.OrderBy[0].Desc {
  159. t.Error("first item should be ASC")
  160. }
  161. if !sel.OrderBy[1].Desc {
  162. t.Error("second item should be DESC")
  163. }
  164. }
  165. func TestParseSelectLimitOffset(t *testing.T) {
  166. stmt := parse(t, "SELECT * FROM users LIMIT 10 OFFSET 20")
  167. sel := stmt.(*SelectStmt)
  168. if sel.Limit == nil {
  169. t.Error("expected LIMIT")
  170. }
  171. if sel.Offset == nil {
  172. t.Error("expected OFFSET")
  173. }
  174. limit := sel.Limit.(*LiteralExpr)
  175. if limit.Value != "10" {
  176. t.Errorf("expected LIMIT 10, got %s", limit.Value)
  177. }
  178. offset := sel.Offset.(*LiteralExpr)
  179. if offset.Value != "20" {
  180. t.Errorf("expected OFFSET 20, got %s", offset.Value)
  181. }
  182. }
  183. func TestParseSelectGroupBy(t *testing.T) {
  184. stmt := parse(t, "SELECT name, COUNT(*) FROM users GROUP BY name")
  185. sel := stmt.(*SelectStmt)
  186. if len(sel.GroupBy) != 1 {
  187. t.Fatalf("expected 1 GROUP BY column, got %d", len(sel.GroupBy))
  188. }
  189. }
  190. func TestParseSelectHaving(t *testing.T) {
  191. stmt := parse(t, "SELECT name, COUNT(*) as cnt FROM users GROUP BY name HAVING COUNT(*) > 5")
  192. sel := stmt.(*SelectStmt)
  193. if sel.Having == nil {
  194. t.Fatal("expected HAVING clause")
  195. }
  196. }
  197. func TestParseSelectJoin(t *testing.T) {
  198. tests := []struct {
  199. input string
  200. joinType JoinType
  201. }{
  202. {"SELECT * FROM a JOIN b ON a.id = b.id", JoinInner},
  203. {"SELECT * FROM a INNER JOIN b ON a.id = b.id", JoinInner},
  204. {"SELECT * FROM a LEFT JOIN b ON a.id = b.id", JoinLeft},
  205. {"SELECT * FROM a LEFT OUTER JOIN b ON a.id = b.id", JoinLeft},
  206. {"SELECT * FROM a RIGHT JOIN b ON a.id = b.id", JoinRight},
  207. {"SELECT * FROM a CROSS JOIN b", JoinCross},
  208. }
  209. for _, tt := range tests {
  210. t.Run(tt.input, func(t *testing.T) {
  211. stmt := parse(t, tt.input)
  212. sel := stmt.(*SelectStmt)
  213. if sel.From[0].Join == nil {
  214. t.Fatal("expected JOIN")
  215. }
  216. if sel.From[0].Join.Type != tt.joinType {
  217. t.Errorf("expected join type %v, got %v", tt.joinType, sel.From[0].Join.Type)
  218. }
  219. })
  220. }
  221. }
  222. // INSERT statement tests
  223. func TestParseInsertValues(t *testing.T) {
  224. stmt := parse(t, "INSERT INTO users (name, age) VALUES ('John', 30)")
  225. ins, ok := stmt.(*InsertStmt)
  226. if !ok {
  227. t.Fatalf("expected InsertStmt, got %T", stmt)
  228. }
  229. if ins.Table.Name != "users" {
  230. t.Errorf("expected table users, got %s", ins.Table.Name)
  231. }
  232. if len(ins.Columns) != 2 {
  233. t.Fatalf("expected 2 columns, got %d", len(ins.Columns))
  234. }
  235. if len(ins.Values) != 1 || len(ins.Values[0]) != 2 {
  236. t.Error("expected 1 row with 2 values")
  237. }
  238. }
  239. func TestParseInsertMultipleRows(t *testing.T) {
  240. stmt := parse(t, "INSERT INTO users VALUES (1, 'John'), (2, 'Jane')")
  241. ins := stmt.(*InsertStmt)
  242. if len(ins.Values) != 2 {
  243. t.Fatalf("expected 2 rows, got %d", len(ins.Values))
  244. }
  245. }
  246. func TestParseInsertOrReplace(t *testing.T) {
  247. stmt := parse(t, "INSERT OR REPLACE INTO users (id, name) VALUES (1, 'John')")
  248. ins := stmt.(*InsertStmt)
  249. if ins.OnConflict != ConflictReplace {
  250. t.Errorf("expected ConflictReplace, got %v", ins.OnConflict)
  251. }
  252. if ins.Table.Name != "users" {
  253. t.Errorf("expected table users, got %s", ins.Table.Name)
  254. }
  255. }
  256. func TestParseInsertOrIgnore(t *testing.T) {
  257. stmt := parse(t, "INSERT OR IGNORE INTO users (id, name) VALUES (1, 'John')")
  258. ins := stmt.(*InsertStmt)
  259. if ins.OnConflict != ConflictIgnore {
  260. t.Errorf("expected ConflictIgnore, got %v", ins.OnConflict)
  261. }
  262. }
  263. func TestParseInsertOrFail(t *testing.T) {
  264. stmt := parse(t, "INSERT OR FAIL INTO users (id, name) VALUES (1, 'John')")
  265. ins := stmt.(*InsertStmt)
  266. if ins.OnConflict != ConflictFail {
  267. t.Errorf("expected ConflictFail, got %v", ins.OnConflict)
  268. }
  269. }
  270. func TestParseInsertOrAbort(t *testing.T) {
  271. stmt := parse(t, "INSERT OR ABORT INTO users (id, name) VALUES (1, 'John')")
  272. ins := stmt.(*InsertStmt)
  273. if ins.OnConflict != ConflictAbort {
  274. t.Errorf("expected ConflictAbort, got %v", ins.OnConflict)
  275. }
  276. }
  277. // UPDATE statement tests
  278. func TestParseUpdate(t *testing.T) {
  279. stmt := parse(t, "UPDATE users SET name = 'John', age = 30 WHERE id = 1")
  280. upd, ok := stmt.(*UpdateStmt)
  281. if !ok {
  282. t.Fatalf("expected UpdateStmt, got %T", stmt)
  283. }
  284. if upd.Table.Name != "users" {
  285. t.Errorf("expected table users, got %s", upd.Table.Name)
  286. }
  287. if len(upd.Set) != 2 {
  288. t.Fatalf("expected 2 assignments, got %d", len(upd.Set))
  289. }
  290. if upd.Where == nil {
  291. t.Error("expected WHERE clause")
  292. }
  293. }
  294. // DELETE statement tests
  295. func TestParseDelete(t *testing.T) {
  296. stmt := parse(t, "DELETE FROM users WHERE id = 1")
  297. del, ok := stmt.(*DeleteStmt)
  298. if !ok {
  299. t.Fatalf("expected DeleteStmt, got %T", stmt)
  300. }
  301. if del.Table.Name != "users" {
  302. t.Errorf("expected table users, got %s", del.Table.Name)
  303. }
  304. if del.Where == nil {
  305. t.Error("expected WHERE clause")
  306. }
  307. }
  308. func TestParseDeleteAll(t *testing.T) {
  309. stmt := parse(t, "DELETE FROM users")
  310. del := stmt.(*DeleteStmt)
  311. if del.Where != nil {
  312. t.Error("expected no WHERE clause")
  313. }
  314. }
  315. // CREATE TABLE tests
  316. func TestParseCreateTable(t *testing.T) {
  317. stmt := parse(t, `CREATE TABLE users (
  318. id INTEGER PRIMARY KEY,
  319. name TEXT NOT NULL,
  320. email VARCHAR(255) UNIQUE,
  321. age INTEGER DEFAULT 0
  322. )`)
  323. create, ok := stmt.(*CreateTableStmt)
  324. if !ok {
  325. t.Fatalf("expected CreateTableStmt, got %T", stmt)
  326. }
  327. if create.Table.Name != "users" {
  328. t.Errorf("expected table users, got %s", create.Table.Name)
  329. }
  330. if len(create.Columns) != 4 {
  331. t.Fatalf("expected 4 columns, got %d", len(create.Columns))
  332. }
  333. // Check id column
  334. if create.Columns[0].Name != "id" {
  335. t.Error("expected first column to be id")
  336. }
  337. if create.Columns[0].Type.Name != "INTEGER" {
  338. t.Error("expected INTEGER type")
  339. }
  340. // Check name column has NOT NULL
  341. found := false
  342. for _, c := range create.Columns[1].Constraints {
  343. if c.Type == ConstraintNotNull {
  344. found = true
  345. }
  346. }
  347. if !found {
  348. t.Error("expected NOT NULL constraint on name")
  349. }
  350. // Check email has VARCHAR(255)
  351. if create.Columns[2].Type.Name != "VARCHAR" || create.Columns[2].Type.Precision != 255 {
  352. t.Error("expected VARCHAR(255) for email")
  353. }
  354. }
  355. func TestParseCreateTableIfNotExists(t *testing.T) {
  356. stmt := parse(t, "CREATE TABLE IF NOT EXISTS users (id INTEGER)")
  357. create := stmt.(*CreateTableStmt)
  358. if !create.IfNotExists {
  359. t.Error("expected IF NOT EXISTS")
  360. }
  361. }
  362. func TestParseCreateTableWithConstraints(t *testing.T) {
  363. stmt := parse(t, `CREATE TABLE orders (
  364. id INTEGER,
  365. user_id INTEGER,
  366. PRIMARY KEY (id),
  367. FOREIGN KEY (user_id) REFERENCES users(id)
  368. )`)
  369. create := stmt.(*CreateTableStmt)
  370. if len(create.Constraints) != 2 {
  371. t.Fatalf("expected 2 table constraints, got %d", len(create.Constraints))
  372. }
  373. // Check PRIMARY KEY
  374. if create.Constraints[0].Type != ConstraintPrimaryKey {
  375. t.Error("expected PRIMARY KEY constraint")
  376. }
  377. // Check FOREIGN KEY
  378. if create.Constraints[1].Type != ConstraintForeignKey {
  379. t.Error("expected FOREIGN KEY constraint")
  380. }
  381. if create.Constraints[1].RefTable != "users" {
  382. t.Errorf("expected reference to users, got %s", create.Constraints[1].RefTable)
  383. }
  384. }
  385. func TestParseCreateTableExplicitNullable(t *testing.T) {
  386. stmt := parse(t, `CREATE TABLE users (
  387. id INTEGER,
  388. full_name TEXT NULL,
  389. nickname TEXT NOT NULL,
  390. created_at TIMESTAMP NULL NOT NULL
  391. )`)
  392. create, ok := stmt.(*CreateTableStmt)
  393. if !ok {
  394. t.Fatalf("expected CreateTableStmt, got %T", stmt)
  395. }
  396. if len(create.Columns) != 4 {
  397. t.Fatalf("expected 4 columns, got %d", len(create.Columns))
  398. }
  399. // full_name TEXT NULL: explicit NULL is a no-op, so no constraint is added.
  400. fullName := create.Columns[1]
  401. if fullName.Name != "full_name" || fullName.Type.Name != "TEXT" {
  402. t.Fatalf("unexpected full_name column: %+v", fullName)
  403. }
  404. if len(fullName.Constraints) != 0 {
  405. t.Errorf("explicit NULL should not produce a constraint, got %d", len(fullName.Constraints))
  406. }
  407. // nickname TEXT NOT NULL still records NOT NULL.
  408. nickname := create.Columns[2]
  409. if len(nickname.Constraints) != 1 || nickname.Constraints[0].Type != ConstraintNotNull {
  410. t.Errorf("expected NOT NULL on nickname, got %+v", nickname.Constraints)
  411. }
  412. // created_at TIMESTAMP NULL NOT NULL: NOT NULL wins regardless of ordering.
  413. created := create.Columns[3]
  414. if len(created.Constraints) != 1 || created.Constraints[0].Type != ConstraintNotNull {
  415. t.Errorf("expected NOT NULL on created_at, got %+v", created.Constraints)
  416. }
  417. }
  418. // DROP TABLE tests
  419. func TestParseDropTable(t *testing.T) {
  420. stmt := parse(t, "DROP TABLE users")
  421. drop, ok := stmt.(*DropTableStmt)
  422. if !ok {
  423. t.Fatalf("expected DropTableStmt, got %T", stmt)
  424. }
  425. if len(drop.Tables) != 1 || drop.Tables[0].Name != "users" {
  426. t.Error("expected DROP TABLE users")
  427. }
  428. }
  429. func TestParseCreateTableDefaultSignedNumeric(t *testing.T) {
  430. stmt := parse(t, `CREATE TABLE repo (
  431. id INTEGER PRIMARY KEY,
  432. max_repo_creation INTEGER DEFAULT -1 NOT NULL,
  433. delta INTEGER DEFAULT +5,
  434. tally INTEGER DEFAULT (-7)
  435. )`)
  436. create, ok := stmt.(*CreateTableStmt)
  437. if !ok {
  438. t.Fatalf("expected CreateTableStmt, got %T", stmt)
  439. }
  440. if len(create.Columns) != 4 {
  441. t.Fatalf("expected 4 columns, got %d", len(create.Columns))
  442. }
  443. // xorm real shape: DEFAULT -1 followed by NOT NULL.
  444. col := create.Columns[1]
  445. if len(col.Constraints) != 2 {
  446. t.Fatalf("expected DEFAULT + NOT NULL, got %d constraints", len(col.Constraints))
  447. }
  448. var defaultExpr Expr
  449. var notNull bool
  450. for _, c := range col.Constraints {
  451. switch c.Type {
  452. case ConstraintDefault:
  453. defaultExpr = c.Default
  454. case ConstraintNotNull:
  455. notNull = true
  456. }
  457. }
  458. if !notNull {
  459. t.Error("expected NOT NULL constraint on max_repo_creation")
  460. }
  461. unary, ok := defaultExpr.(*UnaryExpr)
  462. if !ok || unary.Op != lexer.TokenMinus {
  463. t.Fatalf("expected unary minus default, got %T %+v", defaultExpr, defaultExpr)
  464. }
  465. lit, ok := unary.Operand.(*LiteralExpr)
  466. if !ok || lit.Value != "1" {
  467. t.Fatalf("expected -1 literal, got %+v", unary.Operand)
  468. }
  469. // Positive signed default: DEFAULT +5.
  470. plus, ok := create.Columns[2].Constraints[0].Default.(*UnaryExpr)
  471. if !ok || plus.Op != lexer.TokenPlus {
  472. t.Fatalf("expected unary plus default, got %+v", create.Columns[2].Constraints[0].Default)
  473. }
  474. // Parenthesized signed default: DEFAULT (-7).
  475. paren, ok := create.Columns[3].Constraints[0].Default.(*ParenExpr)
  476. if !ok {
  477. t.Fatalf("expected parenthesized default, got %T", create.Columns[3].Constraints[0].Default)
  478. }
  479. inner, ok := paren.Expr.(*UnaryExpr)
  480. if !ok || inner.Op != lexer.TokenMinus {
  481. t.Fatalf("expected unary minus inside parens, got %T %+v", paren.Expr, paren.Expr)
  482. }
  483. }
  484. func TestParseCreateTableUUIDType(t *testing.T) {
  485. stmt := parse(t, `CREATE TABLE upload (
  486. id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
  487. uuid UUID NULL,
  488. name TEXT NULL
  489. )`)
  490. create, ok := stmt.(*CreateTableStmt)
  491. if !ok {
  492. t.Fatalf("expected CreateTableStmt, got %T", stmt)
  493. }
  494. if len(create.Columns) != 3 {
  495. t.Fatalf("expected 3 columns, got %d", len(create.Columns))
  496. }
  497. uuidCol := create.Columns[1]
  498. if uuidCol.Name != "uuid" {
  499. t.Errorf("column name = %q, want %q", uuidCol.Name, "uuid")
  500. }
  501. if uuidCol.Type.Name != "UUID" {
  502. t.Errorf("column type = %q, want %q", uuidCol.Type.Name, "UUID")
  503. }
  504. if len(uuidCol.Constraints) != 0 {
  505. t.Errorf("explicit NULL should produce no constraints, got %d", len(uuidCol.Constraints))
  506. }
  507. }
  508. func TestParseDropTableIfExists(t *testing.T) {
  509. stmt := parse(t, "DROP TABLE IF EXISTS users")
  510. drop := stmt.(*DropTableStmt)
  511. if !drop.IfExists {
  512. t.Error("expected IF EXISTS")
  513. }
  514. }
  515. // Expression tests
  516. func TestParseExprArithmetic(t *testing.T) {
  517. expr := parseExpr(t, "1 + 2 * 3")
  518. // Should be: 1 + (2 * 3) due to precedence
  519. add, ok := expr.(*BinaryExpr)
  520. if !ok || add.Op != lexer.TokenPlus {
  521. t.Fatal("expected + at top level")
  522. }
  523. mul, ok := add.Right.(*BinaryExpr)
  524. if !ok || mul.Op != lexer.TokenStar {
  525. t.Fatal("expected * on right side")
  526. }
  527. }
  528. func TestParseExprParens(t *testing.T) {
  529. expr := parseExpr(t, "(1 + 2) * 3")
  530. // Should be: (1 + 2) * 3
  531. mul, ok := expr.(*BinaryExpr)
  532. if !ok || mul.Op != lexer.TokenStar {
  533. t.Fatal("expected * at top level")
  534. }
  535. paren, ok := mul.Left.(*ParenExpr)
  536. if !ok {
  537. t.Fatal("expected ParenExpr on left")
  538. }
  539. add, ok := paren.Expr.(*BinaryExpr)
  540. if !ok || add.Op != lexer.TokenPlus {
  541. t.Fatal("expected + inside parens")
  542. }
  543. }
  544. func TestParseExprComparison(t *testing.T) {
  545. tests := []struct {
  546. input string
  547. op lexer.TokenType
  548. }{
  549. {"a = b", lexer.TokenEq},
  550. {"a <> b", lexer.TokenNeq},
  551. {"a != b", lexer.TokenNeq},
  552. {"a < b", lexer.TokenLt},
  553. {"a <= b", lexer.TokenLte},
  554. {"a > b", lexer.TokenGt},
  555. {"a >= b", lexer.TokenGte},
  556. }
  557. for _, tt := range tests {
  558. t.Run(tt.input, func(t *testing.T) {
  559. expr := parseExpr(t, tt.input)
  560. binary, ok := expr.(*BinaryExpr)
  561. if !ok {
  562. t.Fatalf("expected BinaryExpr, got %T", expr)
  563. }
  564. if binary.Op != tt.op {
  565. t.Errorf("expected %v, got %v", tt.op, binary.Op)
  566. }
  567. })
  568. }
  569. }
  570. func TestParseExprIsNull(t *testing.T) {
  571. tests := []struct {
  572. input string
  573. not bool
  574. }{
  575. {"a IS NULL", false},
  576. {"a IS NOT NULL", true},
  577. }
  578. for _, tt := range tests {
  579. t.Run(tt.input, func(t *testing.T) {
  580. expr := parseExpr(t, tt.input)
  581. isNull, ok := expr.(*IsNullExpr)
  582. if !ok {
  583. t.Fatalf("expected IsNullExpr, got %T", expr)
  584. }
  585. if isNull.Not != tt.not {
  586. t.Errorf("expected Not=%v, got %v", tt.not, isNull.Not)
  587. }
  588. })
  589. }
  590. }
  591. func TestParseExprIn(t *testing.T) {
  592. tests := []struct {
  593. input string
  594. not bool
  595. }{
  596. {"a IN (1, 2, 3)", false},
  597. {"a NOT IN (1, 2, 3)", true},
  598. }
  599. for _, tt := range tests {
  600. t.Run(tt.input, func(t *testing.T) {
  601. expr := parseExpr(t, tt.input)
  602. in, ok := expr.(*InExpr)
  603. if !ok {
  604. t.Fatalf("expected InExpr, got %T", expr)
  605. }
  606. if in.Not != tt.not {
  607. t.Errorf("expected Not=%v, got %v", tt.not, in.Not)
  608. }
  609. if len(in.Values) != 3 {
  610. t.Errorf("expected 3 values, got %d", len(in.Values))
  611. }
  612. })
  613. }
  614. }
  615. func TestParseExprBetween(t *testing.T) {
  616. tests := []struct {
  617. input string
  618. not bool
  619. }{
  620. {"a BETWEEN 1 AND 10", false},
  621. {"a NOT BETWEEN 1 AND 10", true},
  622. }
  623. for _, tt := range tests {
  624. t.Run(tt.input, func(t *testing.T) {
  625. expr := parseExpr(t, tt.input)
  626. between, ok := expr.(*BetweenExpr)
  627. if !ok {
  628. t.Fatalf("expected BetweenExpr, got %T", expr)
  629. }
  630. if between.Not != tt.not {
  631. t.Errorf("expected Not=%v, got %v", tt.not, between.Not)
  632. }
  633. })
  634. }
  635. }
  636. func TestParseExprLike(t *testing.T) {
  637. tests := []struct {
  638. input string
  639. not bool
  640. }{
  641. {"name LIKE '%test%'", false},
  642. {"name NOT LIKE '%test%'", true},
  643. }
  644. for _, tt := range tests {
  645. t.Run(tt.input, func(t *testing.T) {
  646. expr := parseExpr(t, tt.input)
  647. like, ok := expr.(*LikeExpr)
  648. if !ok {
  649. t.Fatalf("expected LikeExpr, got %T", expr)
  650. }
  651. if like.Not != tt.not {
  652. t.Errorf("expected Not=%v, got %v", tt.not, like.Not)
  653. }
  654. })
  655. }
  656. }
  657. func TestParseExprCase(t *testing.T) {
  658. expr := parseExpr(t, "CASE WHEN x = 1 THEN 'one' WHEN x = 2 THEN 'two' ELSE 'other' END")
  659. caseExpr, ok := expr.(*CaseExpr)
  660. if !ok {
  661. t.Fatalf("expected CaseExpr, got %T", expr)
  662. }
  663. if len(caseExpr.Whens) != 2 {
  664. t.Errorf("expected 2 WHEN clauses, got %d", len(caseExpr.Whens))
  665. }
  666. if caseExpr.Else == nil {
  667. t.Error("expected ELSE clause")
  668. }
  669. }
  670. func TestParseExprCast(t *testing.T) {
  671. expr := parseExpr(t, "CAST(x AS INTEGER)")
  672. cast, ok := expr.(*CastExpr)
  673. if !ok {
  674. t.Fatalf("expected CastExpr, got %T", expr)
  675. }
  676. if cast.Type.Name != "INTEGER" {
  677. t.Errorf("expected INTEGER type, got %s", cast.Type.Name)
  678. }
  679. }
  680. func TestParseExprFunction(t *testing.T) {
  681. tests := []struct {
  682. input string
  683. name string
  684. argCount int
  685. star bool
  686. distinct bool
  687. }{
  688. {"COUNT(*)", "COUNT", 0, true, false},
  689. {"COUNT(id)", "COUNT", 1, false, false},
  690. {"COUNT(DISTINCT id)", "COUNT", 1, false, true},
  691. {"SUM(amount)", "SUM", 1, false, false},
  692. {"UPPER(name)", "UPPER", 1, false, false},
  693. {"COALESCE(a, b, c)", "COALESCE", 3, false, false},
  694. }
  695. for _, tt := range tests {
  696. t.Run(tt.input, func(t *testing.T) {
  697. expr := parseExpr(t, tt.input)
  698. fn, ok := expr.(*FunctionCall)
  699. if !ok {
  700. t.Fatalf("expected FunctionCall, got %T", expr)
  701. }
  702. if fn.Name != tt.name {
  703. t.Errorf("expected name %s, got %s", tt.name, fn.Name)
  704. }
  705. if len(fn.Args) != tt.argCount {
  706. t.Errorf("expected %d args, got %d", tt.argCount, len(fn.Args))
  707. }
  708. if fn.Star != tt.star {
  709. t.Errorf("expected Star=%v, got %v", tt.star, fn.Star)
  710. }
  711. if fn.Distinct != tt.distinct {
  712. t.Errorf("expected Distinct=%v, got %v", tt.distinct, fn.Distinct)
  713. }
  714. })
  715. }
  716. }
  717. func TestParseExprSubquery(t *testing.T) {
  718. expr := parseExpr(t, "id IN (SELECT user_id FROM orders)")
  719. in, ok := expr.(*InExpr)
  720. if !ok {
  721. t.Fatalf("expected InExpr, got %T", expr)
  722. }
  723. if in.Subquery == nil {
  724. t.Error("expected subquery")
  725. }
  726. }
  727. func TestParseExprExists(t *testing.T) {
  728. expr := parseExpr(t, "EXISTS (SELECT 1 FROM users WHERE id = 1)")
  729. exists, ok := expr.(*ExistsExpr)
  730. if !ok {
  731. t.Fatalf("expected ExistsExpr, got %T", expr)
  732. }
  733. if exists.Subquery == nil {
  734. t.Error("expected subquery")
  735. }
  736. }
  737. func TestParseExprColumnRef(t *testing.T) {
  738. tests := []struct {
  739. input string
  740. table string
  741. column string
  742. }{
  743. {"id", "", "id"},
  744. {"users.id", "users", "id"},
  745. {"u.name", "u", "name"},
  746. }
  747. for _, tt := range tests {
  748. t.Run(tt.input, func(t *testing.T) {
  749. expr := parseExpr(t, tt.input)
  750. ref, ok := expr.(*ColumnRef)
  751. if !ok {
  752. t.Fatalf("expected ColumnRef, got %T", expr)
  753. }
  754. if ref.Table != tt.table {
  755. t.Errorf("expected table %q, got %q", tt.table, ref.Table)
  756. }
  757. if ref.Column != tt.column {
  758. t.Errorf("expected column %q, got %q", tt.column, ref.Column)
  759. }
  760. })
  761. }
  762. }
  763. // Error cases
  764. func TestParseErrors(t *testing.T) {
  765. tests := []struct {
  766. name string
  767. input string
  768. }{
  769. {"missing columns", "SELECT FROM users"},
  770. {"missing VALUES", "INSERT INTO users"},
  771. {"missing SET", "UPDATE users WHERE id = 1"},
  772. {"missing table name", "DELETE FROM WHERE id = 1"},
  773. {"unclosed paren", "SELECT * FROM users WHERE (id = 1"},
  774. {"invalid token", "SELECT @ FROM users"},
  775. }
  776. for _, tt := range tests {
  777. t.Run(tt.name, func(t *testing.T) {
  778. l := lexer.New(tt.input)
  779. p := New(l)
  780. _, err := p.Parse()
  781. if err == nil {
  782. t.Error("expected parse error")
  783. }
  784. })
  785. }
  786. }
  787. // Multiple statements
  788. func TestParseMultiple(t *testing.T) {
  789. input := `
  790. SELECT * FROM users;
  791. INSERT INTO users VALUES (1, 'John');
  792. DELETE FROM users WHERE id = 1
  793. `
  794. l := lexer.New(input)
  795. p := New(l)
  796. stmts, err := p.ParseMultiple()
  797. if err != nil {
  798. t.Fatalf("parse error: %v", err)
  799. }
  800. if len(stmts) != 3 {
  801. t.Errorf("expected 3 statements, got %d", len(stmts))
  802. }
  803. }
  804. func TestParseRejectsTrailingReturning(t *testing.T) {
  805. l := lexer.New("INSERT INTO users (id) VALUES (1) RETURNING id")
  806. if _, err := New(l).Parse(); err == nil {
  807. t.Fatal("expected RETURNING to be rejected before execution")
  808. }
  809. }
  810. func TestParsePostgresCompatibilityClauses(t *testing.T) {
  811. t.Run("alter add column if not exists", func(t *testing.T) {
  812. stmt := parse(t, "ALTER TABLE users ADD COLUMN IF NOT EXISTS revision INTEGER DEFAULT 0")
  813. action := stmt.(*AlterTableStmt).Action.(*AddColumnAction)
  814. if !action.IfNotExists || action.Column.Name != "revision" {
  815. t.Fatalf("unexpected action: %#v", action)
  816. }
  817. })
  818. t.Run("on conflict do update", func(t *testing.T) {
  819. stmt := parse(t, "INSERT INTO users (id, count) VALUES (1, 1) ON CONFLICT (id) DO UPDATE SET count = users.count + 1")
  820. insert := stmt.(*InsertStmt)
  821. if len(insert.ConflictTarget) != 1 || insert.ConflictTarget[0] != "id" || len(insert.ConflictUpdate) != 1 {
  822. t.Fatalf("unexpected conflict clause: %#v", insert)
  823. }
  824. })
  825. t.Run("jsonb cast", func(t *testing.T) {
  826. parse(t, "SELECT CAST('{}' AS JSONB)")
  827. })
  828. }
  829. // Phase 4: PRAGMA and EXPLAIN tests
  830. func TestParsePragmaTableInfo(t *testing.T) {
  831. stmt := parse(t, "PRAGMA table_info(users)")
  832. pragma, ok := stmt.(*PragmaStmt)
  833. if !ok {
  834. t.Fatalf("expected PragmaStmt, got %T", stmt)
  835. }
  836. if pragma.Name != "table_info" {
  837. t.Errorf("expected pragma name 'table_info', got %s", pragma.Name)
  838. }
  839. if pragma.Arg != "users" {
  840. t.Errorf("expected arg 'users', got %s", pragma.Arg)
  841. }
  842. }
  843. func TestParsePragmaTableList(t *testing.T) {
  844. stmt := parse(t, "PRAGMA table_list")
  845. pragma, ok := stmt.(*PragmaStmt)
  846. if !ok {
  847. t.Fatalf("expected PragmaStmt, got %T", stmt)
  848. }
  849. if pragma.Name != "table_list" {
  850. t.Errorf("expected pragma name 'table_list', got %s", pragma.Name)
  851. }
  852. }
  853. func TestParsePragmaDatabaseList(t *testing.T) {
  854. stmt := parse(t, "PRAGMA database_list")
  855. pragma := stmt.(*PragmaStmt)
  856. if pragma.Name != "database_list" {
  857. t.Errorf("expected pragma name 'database_list', got %s", pragma.Name)
  858. }
  859. }
  860. func TestParsePragmaVersion(t *testing.T) {
  861. stmt := parse(t, "PRAGMA version")
  862. pragma := stmt.(*PragmaStmt)
  863. if pragma.Name != "version" {
  864. t.Errorf("expected pragma name 'version', got %s", pragma.Name)
  865. }
  866. }
  867. func TestParseExplain(t *testing.T) {
  868. stmt := parse(t, "EXPLAIN SELECT * FROM users")
  869. explain, ok := stmt.(*ExplainStmt)
  870. if !ok {
  871. t.Fatalf("expected ExplainStmt, got %T", stmt)
  872. }
  873. if explain.QueryPlan {
  874. t.Error("expected QueryPlan to be false")
  875. }
  876. _, ok = explain.Statement.(*SelectStmt)
  877. if !ok {
  878. t.Errorf("expected SelectStmt inside EXPLAIN, got %T", explain.Statement)
  879. }
  880. }
  881. func TestParseExplainQueryPlan(t *testing.T) {
  882. stmt := parse(t, "EXPLAIN QUERY PLAN SELECT * FROM users WHERE id = 1")
  883. explain, ok := stmt.(*ExplainStmt)
  884. if !ok {
  885. t.Fatalf("expected ExplainStmt, got %T", stmt)
  886. }
  887. if !explain.QueryPlan {
  888. t.Error("expected QueryPlan to be true")
  889. }
  890. sel, ok := explain.Statement.(*SelectStmt)
  891. if !ok {
  892. t.Errorf("expected SelectStmt inside EXPLAIN, got %T", explain.Statement)
  893. }
  894. if sel.Where == nil {
  895. t.Error("expected WHERE clause in explained statement")
  896. }
  897. }
  898. func TestParseExplainInsert(t *testing.T) {
  899. stmt := parse(t, "EXPLAIN INSERT INTO users (name) VALUES ('John')")
  900. explain := stmt.(*ExplainStmt)
  901. _, ok := explain.Statement.(*InsertStmt)
  902. if !ok {
  903. t.Errorf("expected InsertStmt inside EXPLAIN, got %T", explain.Statement)
  904. }
  905. }
  906. // Phase 5: Transaction statement tests
  907. func TestParseBegin(t *testing.T) {
  908. stmt := parse(t, "BEGIN")
  909. _, ok := stmt.(*BeginStmt)
  910. if !ok {
  911. t.Fatalf("expected BeginStmt, got %T", stmt)
  912. }
  913. }
  914. func TestParseBeginTransaction(t *testing.T) {
  915. stmt := parse(t, "BEGIN TRANSACTION")
  916. _, ok := stmt.(*BeginStmt)
  917. if !ok {
  918. t.Fatalf("expected BeginStmt, got %T", stmt)
  919. }
  920. }
  921. func TestParseCommit(t *testing.T) {
  922. stmt := parse(t, "COMMIT")
  923. _, ok := stmt.(*CommitStmt)
  924. if !ok {
  925. t.Fatalf("expected CommitStmt, got %T", stmt)
  926. }
  927. }
  928. func TestParseCommitTransaction(t *testing.T) {
  929. stmt := parse(t, "COMMIT TRANSACTION")
  930. _, ok := stmt.(*CommitStmt)
  931. if !ok {
  932. t.Fatalf("expected CommitStmt, got %T", stmt)
  933. }
  934. }
  935. func TestParseRollback(t *testing.T) {
  936. stmt := parse(t, "ROLLBACK")
  937. rollback, ok := stmt.(*RollbackStmt)
  938. if !ok {
  939. t.Fatalf("expected RollbackStmt, got %T", stmt)
  940. }
  941. if rollback.Savepoint != "" {
  942. t.Errorf("expected empty savepoint, got %s", rollback.Savepoint)
  943. }
  944. }
  945. func TestParseRollbackToSavepoint(t *testing.T) {
  946. stmt := parse(t, "ROLLBACK TO SAVEPOINT sp1")
  947. rollback, ok := stmt.(*RollbackStmt)
  948. if !ok {
  949. t.Fatalf("expected RollbackStmt, got %T", stmt)
  950. }
  951. if rollback.Savepoint != "sp1" {
  952. t.Errorf("expected savepoint 'sp1', got %s", rollback.Savepoint)
  953. }
  954. }
  955. func TestParseRollbackTo(t *testing.T) {
  956. stmt := parse(t, "ROLLBACK TO sp1")
  957. rollback := stmt.(*RollbackStmt)
  958. if rollback.Savepoint != "sp1" {
  959. t.Errorf("expected savepoint 'sp1', got %s", rollback.Savepoint)
  960. }
  961. }
  962. func TestParseSavepoint(t *testing.T) {
  963. stmt := parse(t, "SAVEPOINT my_savepoint")
  964. sp, ok := stmt.(*SavepointStmt)
  965. if !ok {
  966. t.Fatalf("expected SavepointStmt, got %T", stmt)
  967. }
  968. if sp.Name != "my_savepoint" {
  969. t.Errorf("expected savepoint name 'my_savepoint', got %s", sp.Name)
  970. }
  971. }
  972. func TestParseReleaseSavepoint(t *testing.T) {
  973. stmt := parse(t, "RELEASE SAVEPOINT sp1")
  974. rel, ok := stmt.(*ReleaseStmt)
  975. if !ok {
  976. t.Fatalf("expected ReleaseStmt, got %T", stmt)
  977. }
  978. if rel.Name != "sp1" {
  979. t.Errorf("expected savepoint name 'sp1', got %s", rel.Name)
  980. }
  981. }
  982. func TestParseRelease(t *testing.T) {
  983. stmt := parse(t, "RELEASE sp1")
  984. rel := stmt.(*ReleaseStmt)
  985. if rel.Name != "sp1" {
  986. t.Errorf("expected savepoint name 'sp1', got %s", rel.Name)
  987. }
  988. }
  989. // Benchmark
  990. func BenchmarkParseSelect(b *testing.B) {
  991. input := `SELECT u.id, u.name, u.email, COUNT(o.id) as order_count
  992. FROM users u
  993. LEFT JOIN orders o ON u.id = o.user_id
  994. WHERE u.active = TRUE AND u.created_at >= '2024-01-01'
  995. GROUP BY u.id, u.name, u.email
  996. HAVING COUNT(o.id) > 5
  997. ORDER BY order_count DESC
  998. LIMIT 100 OFFSET 0`
  999. b.ResetTimer()
  1000. for i := 0; i < b.N; i++ {
  1001. l := lexer.New(input)
  1002. p := New(l)
  1003. _, _ = p.Parse()
  1004. }
  1005. }
  1006. func BenchmarkParseCreateTable(b *testing.B) {
  1007. input := `CREATE TABLE users (
  1008. id INTEGER PRIMARY KEY AUTOINCREMENT,
  1009. name TEXT NOT NULL,
  1010. email VARCHAR(255) UNIQUE,
  1011. age INTEGER DEFAULT 0,
  1012. active BOOLEAN DEFAULT TRUE,
  1013. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  1014. )`
  1015. b.ResetTimer()
  1016. for i := 0; i < b.N; i++ {
  1017. l := lexer.New(input)
  1018. p := New(l)
  1019. _, _ = p.Parse()
  1020. }
  1021. }
  1022. // CREATE INDEX tests
  1023. func TestParseCreateIndex(t *testing.T) {
  1024. stmt := parse(t, "CREATE INDEX idx_email ON users (email)")
  1025. idx, ok := stmt.(*CreateIndexStmt)
  1026. if !ok {
  1027. t.Fatalf("expected CreateIndexStmt, got %T", stmt)
  1028. }
  1029. if idx.Name != "idx_email" {
  1030. t.Errorf("expected index name idx_email, got %s", idx.Name)
  1031. }
  1032. if idx.Table != "users" {
  1033. t.Errorf("expected table users, got %s", idx.Table)
  1034. }
  1035. if len(idx.Columns) != 1 || idx.Columns[0].Name != "email" {
  1036. t.Error("expected column email")
  1037. }
  1038. if idx.Unique {
  1039. t.Error("expected non-unique index")
  1040. }
  1041. if idx.IfNotExists {
  1042. t.Error("expected IfNotExists to be false")
  1043. }
  1044. }
  1045. func TestParseCreateUniqueIndex(t *testing.T) {
  1046. stmt := parse(t, "CREATE UNIQUE INDEX idx_email ON users (email)")
  1047. idx, ok := stmt.(*CreateIndexStmt)
  1048. if !ok {
  1049. t.Fatalf("expected CreateIndexStmt, got %T", stmt)
  1050. }
  1051. if !idx.Unique {
  1052. t.Error("expected unique index")
  1053. }
  1054. }
  1055. func TestParseCreateIndexIfNotExists(t *testing.T) {
  1056. stmt := parse(t, "CREATE INDEX IF NOT EXISTS idx_email ON users (email)")
  1057. idx, ok := stmt.(*CreateIndexStmt)
  1058. if !ok {
  1059. t.Fatalf("expected CreateIndexStmt, got %T", stmt)
  1060. }
  1061. if !idx.IfNotExists {
  1062. t.Error("expected IfNotExists to be true")
  1063. }
  1064. }
  1065. func TestParseCreateIndexMultiColumn(t *testing.T) {
  1066. stmt := parse(t, "CREATE INDEX idx_name_email ON users (name, email)")
  1067. idx, ok := stmt.(*CreateIndexStmt)
  1068. if !ok {
  1069. t.Fatalf("expected CreateIndexStmt, got %T", stmt)
  1070. }
  1071. if len(idx.Columns) != 2 {
  1072. t.Fatalf("expected 2 columns, got %d", len(idx.Columns))
  1073. }
  1074. if idx.Columns[0].Name != "name" {
  1075. t.Errorf("expected first column name, got %s", idx.Columns[0].Name)
  1076. }
  1077. if idx.Columns[1].Name != "email" {
  1078. t.Errorf("expected second column email, got %s", idx.Columns[1].Name)
  1079. }
  1080. }
  1081. func TestParseCreateIndexWithDesc(t *testing.T) {
  1082. stmt := parse(t, "CREATE INDEX idx_created ON users (created_at DESC)")
  1083. idx, ok := stmt.(*CreateIndexStmt)
  1084. if !ok {
  1085. t.Fatalf("expected CreateIndexStmt, got %T", stmt)
  1086. }
  1087. if len(idx.Columns) != 1 {
  1088. t.Fatalf("expected 1 column, got %d", len(idx.Columns))
  1089. }
  1090. if !idx.Columns[0].Desc {
  1091. t.Error("expected DESC ordering")
  1092. }
  1093. }
  1094. // DROP INDEX tests
  1095. func TestParseDropIndex(t *testing.T) {
  1096. stmt := parse(t, "DROP INDEX idx_email")
  1097. drop, ok := stmt.(*DropIndexStmt)
  1098. if !ok {
  1099. t.Fatalf("expected DropIndexStmt, got %T", stmt)
  1100. }
  1101. if drop.Name != "idx_email" {
  1102. t.Errorf("expected index name idx_email, got %s", drop.Name)
  1103. }
  1104. if drop.IfExists {
  1105. t.Error("expected IfExists to be false")
  1106. }
  1107. }
  1108. func TestParseDropIndexIfExists(t *testing.T) {
  1109. stmt := parse(t, "DROP INDEX IF EXISTS idx_email")
  1110. drop, ok := stmt.(*DropIndexStmt)
  1111. if !ok {
  1112. t.Fatalf("expected DropIndexStmt, got %T", stmt)
  1113. }
  1114. if !drop.IfExists {
  1115. t.Error("expected IfExists to be true")
  1116. }
  1117. }
  1118. // Subquery in FROM clause tests
  1119. func TestParseSelectFromSubquery(t *testing.T) {
  1120. stmt := parse(t, "SELECT * FROM (SELECT id, name FROM users) AS u")
  1121. sel, ok := stmt.(*SelectStmt)
  1122. if !ok {
  1123. t.Fatalf("expected SelectStmt, got %T", stmt)
  1124. }
  1125. if len(sel.From) != 1 {
  1126. t.Fatalf("expected 1 FROM item, got %d", len(sel.From))
  1127. }
  1128. if sel.From[0].Subquery == nil {
  1129. t.Fatal("expected subquery in FROM")
  1130. }
  1131. if sel.From[0].Alias != "u" {
  1132. t.Errorf("expected alias 'u', got '%s'", sel.From[0].Alias)
  1133. }
  1134. // Check subquery
  1135. subquery := sel.From[0].Subquery
  1136. if len(subquery.Columns) != 2 {
  1137. t.Errorf("expected 2 columns in subquery, got %d", len(subquery.Columns))
  1138. }
  1139. if len(subquery.From) != 1 || subquery.From[0].Name != "users" {
  1140. t.Error("expected subquery FROM users")
  1141. }
  1142. }
  1143. func TestParseSelectFromSubqueryWithWhere(t *testing.T) {
  1144. stmt := parse(t, "SELECT name FROM (SELECT id, name FROM users WHERE active = TRUE) AS active_users WHERE id > 10")
  1145. sel, ok := stmt.(*SelectStmt)
  1146. if !ok {
  1147. t.Fatalf("expected SelectStmt, got %T", stmt)
  1148. }
  1149. if sel.From[0].Subquery == nil {
  1150. t.Fatal("expected subquery in FROM")
  1151. }
  1152. // Check outer WHERE clause
  1153. if sel.Where == nil {
  1154. t.Error("expected outer WHERE clause")
  1155. }
  1156. // Check subquery WHERE clause
  1157. if sel.From[0].Subquery.Where == nil {
  1158. t.Error("expected subquery WHERE clause")
  1159. }
  1160. }
  1161. func TestParseSelectFromSubqueryComplex(t *testing.T) {
  1162. stmt := parse(t, "SELECT u.name, u.total FROM (SELECT user_id, SUM(amount) AS total FROM orders GROUP BY user_id) AS u")
  1163. sel, ok := stmt.(*SelectStmt)
  1164. if !ok {
  1165. t.Fatalf("expected SelectStmt, got %T", stmt)
  1166. }
  1167. if sel.From[0].Subquery == nil {
  1168. t.Fatal("expected subquery in FROM")
  1169. }
  1170. subquery := sel.From[0].Subquery
  1171. if len(subquery.GroupBy) == 0 {
  1172. t.Error("expected GROUP BY in subquery")
  1173. }
  1174. // Check that columns reference the alias
  1175. if len(sel.Columns) != 2 {
  1176. t.Fatalf("expected 2 columns, got %d", len(sel.Columns))
  1177. }
  1178. }
  1179. func TestParseSelectFromNestedSubquery(t *testing.T) {
  1180. stmt := parse(t, "SELECT * FROM (SELECT * FROM (SELECT id FROM users) AS inner_q) AS outer_q")
  1181. sel, ok := stmt.(*SelectStmt)
  1182. if !ok {
  1183. t.Fatalf("expected SelectStmt, got %T", stmt)
  1184. }
  1185. if sel.From[0].Subquery == nil {
  1186. t.Fatal("expected subquery in FROM")
  1187. }
  1188. // Check nested subquery
  1189. outerSubquery := sel.From[0].Subquery
  1190. if len(outerSubquery.From) == 0 || outerSubquery.From[0].Subquery == nil {
  1191. t.Error("expected nested subquery")
  1192. }
  1193. }
  1194. // ALTER TABLE tests
  1195. func TestParseAlterTableAddColumn(t *testing.T) {
  1196. stmt := parse(t, "ALTER TABLE users ADD COLUMN age INTEGER")
  1197. alter, ok := stmt.(*AlterTableStmt)
  1198. if !ok {
  1199. t.Fatalf("expected AlterTableStmt, got %T", stmt)
  1200. }
  1201. if alter.Table != "users" {
  1202. t.Errorf("expected table users, got %s", alter.Table)
  1203. }
  1204. action, ok := alter.Action.(*AddColumnAction)
  1205. if !ok {
  1206. t.Fatalf("expected AddColumnAction, got %T", alter.Action)
  1207. }
  1208. if action.Column.Name != "age" {
  1209. t.Errorf("expected column name age, got %s", action.Column.Name)
  1210. }
  1211. if action.Column.Type.Name != "INTEGER" {
  1212. t.Errorf("expected column type INTEGER, got %s", action.Column.Type.Name)
  1213. }
  1214. }
  1215. func TestParseAlterTableAddColumnOptional(t *testing.T) {
  1216. stmt := parse(t, "ALTER TABLE users ADD age INTEGER")
  1217. alter, ok := stmt.(*AlterTableStmt)
  1218. if !ok {
  1219. t.Fatalf("expected AlterTableStmt, got %T", stmt)
  1220. }
  1221. action, ok := alter.Action.(*AddColumnAction)
  1222. if !ok {
  1223. t.Fatalf("expected AddColumnAction, got %T", alter.Action)
  1224. }
  1225. if action.Column.Name != "age" {
  1226. t.Errorf("expected column name age, got %s", action.Column.Name)
  1227. }
  1228. }
  1229. func TestParseAlterTableDropColumn(t *testing.T) {
  1230. stmt := parse(t, "ALTER TABLE users DROP COLUMN email")
  1231. alter, ok := stmt.(*AlterTableStmt)
  1232. if !ok {
  1233. t.Fatalf("expected AlterTableStmt, got %T", stmt)
  1234. }
  1235. action, ok := alter.Action.(*DropColumnAction)
  1236. if !ok {
  1237. t.Fatalf("expected DropColumnAction, got %T", alter.Action)
  1238. }
  1239. if action.Column != "email" {
  1240. t.Errorf("expected column email, got %s", action.Column)
  1241. }
  1242. }
  1243. func TestParseAlterTableRename(t *testing.T) {
  1244. stmt := parse(t, "ALTER TABLE users RENAME TO customers")
  1245. alter, ok := stmt.(*AlterTableStmt)
  1246. if !ok {
  1247. t.Fatalf("expected AlterTableStmt, got %T", stmt)
  1248. }
  1249. action, ok := alter.Action.(*RenameTableAction)
  1250. if !ok {
  1251. t.Fatalf("expected RenameTableAction, got %T", alter.Action)
  1252. }
  1253. if action.NewName != "customers" {
  1254. t.Errorf("expected new name customers, got %s", action.NewName)
  1255. }
  1256. }
  1257. func TestParseAlterTableRenameColumn(t *testing.T) {
  1258. stmt := parse(t, "ALTER TABLE users RENAME COLUMN name TO full_name")
  1259. alter, ok := stmt.(*AlterTableStmt)
  1260. if !ok {
  1261. t.Fatalf("expected AlterTableStmt, got %T", stmt)
  1262. }
  1263. action, ok := alter.Action.(*RenameColumnAction)
  1264. if !ok {
  1265. t.Fatalf("expected RenameColumnAction, got %T", alter.Action)
  1266. }
  1267. if action.OldName != "name" {
  1268. t.Errorf("expected old name 'name', got %s", action.OldName)
  1269. }
  1270. if action.NewName != "full_name" {
  1271. t.Errorf("expected new name 'full_name', got %s", action.NewName)
  1272. }
  1273. }
  1274. // ATTACH/DETACH DATABASE tests
  1275. func TestParseAttach(t *testing.T) {
  1276. stmt := parse(t, "ATTACH DATABASE 'test.db' AS testdb")
  1277. attach, ok := stmt.(*AttachStmt)
  1278. if !ok {
  1279. t.Fatalf("expected AttachStmt, got %T", stmt)
  1280. }
  1281. if attach.FilePath != "test.db" {
  1282. t.Errorf("expected file path 'test.db', got '%s'", attach.FilePath)
  1283. }
  1284. if attach.Alias != "testdb" {
  1285. t.Errorf("expected alias 'testdb', got '%s'", attach.Alias)
  1286. }
  1287. }
  1288. func TestParseAttachOptional(t *testing.T) {
  1289. stmt := parse(t, "ATTACH 'another.db' AS other")
  1290. attach, ok := stmt.(*AttachStmt)
  1291. if !ok {
  1292. t.Fatalf("expected AttachStmt, got %T", stmt)
  1293. }
  1294. if attach.FilePath != "another.db" {
  1295. t.Errorf("expected file path 'another.db', got '%s'", attach.FilePath)
  1296. }
  1297. if attach.Alias != "other" {
  1298. t.Errorf("expected alias 'other', got '%s'", attach.Alias)
  1299. }
  1300. }
  1301. func TestParseDetach(t *testing.T) {
  1302. stmt := parse(t, "DETACH DATABASE testdb")
  1303. detach, ok := stmt.(*DetachStmt)
  1304. if !ok {
  1305. t.Fatalf("expected DetachStmt, got %T", stmt)
  1306. }
  1307. if detach.Alias != "testdb" {
  1308. t.Errorf("expected alias 'testdb', got '%s'", detach.Alias)
  1309. }
  1310. }
  1311. func TestParseDetachOptional(t *testing.T) {
  1312. stmt := parse(t, "DETACH other")
  1313. detach, ok := stmt.(*DetachStmt)
  1314. if !ok {
  1315. t.Fatalf("expected DetachStmt, got %T", stmt)
  1316. }
  1317. if detach.Alias != "other" {
  1318. t.Errorf("expected alias 'other', got '%s'", detach.Alias)
  1319. }
  1320. }