1use sqlparser::{
3 ast::{self, SelectItem, SetExpr, Statement, TableFactor, TableWithJoins},
4 parser::ParserError,
5};
6
7use std::{error::Error, fmt::Display};
8
9use crate::{
10 expr::{Expr, ExprError},
11 ic::{Instruction, IntermediateCode},
12 identifier::IdentifierError,
13 parser::parse,
14 value::{Value, ValueError},
15 vm::RegisterIndex,
16};
17
18#[derive(Debug)]
20pub enum ParserOrCodegenError {
21 ParserError(ParserError),
22 CodegenError(CodegenError),
23}
24
25impl Display for ParserOrCodegenError {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 match self {
28 Self::ParserError(e) => write!(f, "{}", e),
29 Self::CodegenError(e) => write!(f, "{}", e),
30 }
31 }
32}
33
34impl Error for ParserOrCodegenError {}
35
36impl From<ParserError> for ParserOrCodegenError {
37 fn from(e: ParserError) -> Self {
38 Self::ParserError(e)
39 }
40}
41
42impl From<CodegenError> for ParserOrCodegenError {
43 fn from(e: CodegenError) -> Self {
44 Self::CodegenError(e)
45 }
46}
47
48pub fn codegen_str(code: &str) -> Result<Vec<IntermediateCode>, ParserOrCodegenError> {
50 let ast = parse(code)?;
51 Ok(ast
52 .into_iter()
53 .map(|stmt| codegen_ast(&stmt))
54 .collect::<Result<Vec<_>, CodegenError>>()?)
55}
56
57pub fn codegen_ast(ast: &Statement) -> Result<IntermediateCode, CodegenError> {
59 let mut instrs = Vec::<Instruction>::new();
60
61 let mut current_reg = RegisterIndex::default();
62
63 match ast {
64 Statement::CreateTable {
65 or_replace: _,
67 temporary: _,
69 external: _,
70 global: _,
71 if_not_exists,
72 name,
73 columns,
74 constraints: _,
76 hive_distribution: _,
77 hive_formats: _,
78 table_properties: _,
79 with_options: _,
80 file_format: _,
81 location: _,
82 query: _,
83 without_rowid: _,
84 like: _,
85 engine: _,
86 default_charset: _,
87 collation: _,
88 on_commit: _,
89 } => {
90 let table_reg_index = current_reg;
91 instrs.push(Instruction::Empty {
92 index: table_reg_index,
93 });
94 current_reg = current_reg.next_index();
95
96 let col_reg_index = current_reg;
97 current_reg = current_reg.next_index();
98 for col in columns {
99 instrs.push(Instruction::ColumnDef {
100 index: col_reg_index,
101 name: col.name.value.as_str().into(),
102 data_type: col.data_type.clone(),
103 });
104
105 for option in col.options.iter() {
106 instrs.push(Instruction::AddColumnOption {
107 index: col_reg_index,
108 option: option.clone(),
109 });
110 }
111
112 instrs.push(Instruction::AddColumn {
113 table_reg_index,
114 col_index: col_reg_index,
115 });
116 }
117
118 instrs.push(Instruction::NewTable {
119 index: table_reg_index,
120 name: name.0.clone().try_into()?,
121 exists_ok: *if_not_exists,
122 });
123 Ok(())
124 }
125 Statement::Insert {
126 or: _,
127 into: _,
128 table_name,
129 columns,
130 overwrite: _,
131 source,
132 partitioned: _,
133 after_columns: _,
134 table: _,
135 on: _,
136 } => {
137 let table_reg_index = current_reg;
138 instrs.push(Instruction::Source {
139 index: table_reg_index,
140 name: table_name.0.clone().try_into()?,
141 });
142 current_reg = current_reg.next_index();
143
144 let insert_reg_index = current_reg;
145 instrs.push(Instruction::InsertDef {
146 table_reg_index,
147 index: insert_reg_index,
148 });
149 current_reg = current_reg.next_index();
150
151 for col in columns {
152 instrs.push(Instruction::ColumnInsertDef {
153 insert_index: insert_reg_index,
154 col_name: col.value.as_str().into(),
155 })
156 }
157
158 match source.as_ref() {
160 ast::Query {
161 body: ast::SetExpr::Values(values),
162 ..
163 } => {
164 for row in values.0.clone() {
165 let row_reg = current_reg;
166 current_reg = current_reg.next_index();
167
168 instrs.push(Instruction::RowDef {
169 insert_index: insert_reg_index,
170 row_index: row_reg,
171 });
172
173 for value in row {
174 instrs.push(Instruction::AddValue {
175 row_index: row_reg,
176 expr: value.try_into()?,
177 });
178 }
179 }
180 Ok(())
181 }
182 _ => Err(CodegenError::UnsupportedStatementForm(
183 "Only insert with values is supported.",
184 ast.to_string(),
185 )),
186 }?;
187
188 instrs.push(Instruction::Insert {
189 index: insert_reg_index,
190 });
191
192 Ok(())
193 }
194 Statement::Query(query) => {
195 let mut table_reg_index = current_reg;
197 current_reg = current_reg.next_index();
198
199 match &query.body {
200 SetExpr::Select(select) => {
201 match select.from.as_slice() {
202 [TableWithJoins { relation, joins }] => {
203 if !joins.is_empty() {
204 return Err(CodegenError::UnsupportedStatementForm(
206 "Joins are not supported yet",
207 select.to_string(),
208 ));
209 }
210
211 match relation {
212 TableFactor::Table {
213 name,
214 alias: _,
216 args: _,
217 with_hints: _,
218 } => instrs.push(Instruction::Source {
219 index: table_reg_index,
220 name: name.0.clone().try_into()?,
221 }),
222 TableFactor::Derived { .. } => {
223 return Err(CodegenError::UnsupportedStatementForm(
225 "Derived tables are not supportd yet",
226 relation.to_string(),
227 ));
228 }
229 TableFactor::NestedJoin(_) => {
230 return Err(CodegenError::UnsupportedStatementForm(
232 "Nested JOINs are not supportd yet",
233 relation.to_string(),
234 ));
235 }
236 TableFactor::TableFunction { .. } => {
237 return Err(CodegenError::UnsupportedStatementForm(
239 "Table functions are not supportd yet",
240 relation.to_string(),
241 ));
242 }
243 TableFactor::UNNEST { .. } => {
244 return Err(CodegenError::UnsupportedStatementForm(
246 "UNNEST are not supportd yet",
247 relation.to_string(),
248 ));
249 }
250 }
251 }
252 &[] => instrs.push(Instruction::NonExistent {
253 index: table_reg_index,
254 }),
255 _ => {
256 return Err(CodegenError::UnsupportedStatementForm(
258 "Only select from a single table is supported for now",
259 format!("{:?}", select.from),
260 ));
261 }
262 }
263
264 if let Some(expr) = select.selection.clone() {
265 instrs.push(Instruction::Filter {
266 index: table_reg_index,
267 expr: expr.try_into()?,
268 })
269 }
270
271 for group_by in select.group_by.clone() {
272 instrs.push(Instruction::GroupBy {
273 index: table_reg_index,
274 expr: group_by.try_into()?,
275 });
276 }
277
278 if let Some(expr) = select.having.clone() {
279 instrs.push(Instruction::Filter {
280 index: table_reg_index,
281 expr: expr.try_into()?,
282 })
283 }
284
285 if !select.projection.is_empty() {
286 let original_table_reg_index = table_reg_index;
287 table_reg_index = current_reg;
288 current_reg = current_reg.next_index();
289
290 instrs.push(Instruction::Empty {
291 index: table_reg_index,
292 });
293
294 for projection in select.projection.clone() {
295 instrs.push(Instruction::Project {
296 input: original_table_reg_index,
297 output: table_reg_index,
298 expr: match projection {
299 SelectItem::UnnamedExpr(ref expr) => expr.clone().try_into()?,
300 SelectItem::ExprWithAlias { ref expr, .. } => {
301 expr.clone().try_into()?
302 }
303 SelectItem::QualifiedWildcard(_) => Expr::Wildcard,
304 SelectItem::Wildcard => Expr::Wildcard,
305 },
306 alias: match projection {
307 SelectItem::UnnamedExpr(_) => None,
308 SelectItem::ExprWithAlias { alias, .. } => {
309 Some(alias.value.as_str().into())
310 }
311 SelectItem::QualifiedWildcard(name) => {
312 return Err(CodegenError::UnsupportedStatementForm(
313 "Qualified wildcards are not supported yet",
314 name.to_string(),
315 ))
316 }
317 SelectItem::Wildcard => None,
318 },
319 })
320 }
321
322 if select.distinct {
323 return Err(CodegenError::UnsupportedStatementForm(
324 "DISTINCT is not supported yet",
325 select.to_string(),
326 ));
327 }
328 }
329 }
330 SetExpr::Values(exprs) => {
331 if exprs.0.len() == 1 && exprs.0[0].len() == 1 {
332 let expr: Expr = exprs.0[0][0].clone().try_into()?;
333 instrs.push(Instruction::Expr {
334 index: table_reg_index,
335 expr,
336 });
337 } else {
338 return Err(CodegenError::UnsupportedStatementForm(
343 "Selecting more than one value is not supported yet",
344 exprs.to_string(),
345 ));
346 }
347 }
348 SetExpr::Query(query) => {
349 return Err(CodegenError::UnsupportedStatementForm(
352 "Query within a query not supported yet",
353 query.to_string(),
354 ));
355 }
356 SetExpr::SetOperation {
357 op: _,
358 all: _,
359 left: _,
360 right: _,
361 } => {
362 return Err(CodegenError::UnsupportedStatementForm(
364 "Set operations are not supported yet",
365 query.to_string(),
366 ));
367 }
368 SetExpr::Insert(insert) => {
369 return Err(CodegenError::UnsupportedStatementForm(
372 "Insert within query not supported yet",
373 insert.to_string(),
374 ));
375 }
376 };
377
378 for order_by in query.order_by.clone() {
379 instrs.push(Instruction::Order {
380 index: table_reg_index,
381 expr: order_by.expr.try_into()?,
382 ascending: order_by.asc.unwrap_or(true),
383 });
384 }
386
387 if let Some(limit) = query.limit.clone() {
388 if let ast::Expr::Value(val) = limit.clone() {
389 if let Value::Int64(limit) = val.clone().try_into()? {
390 instrs.push(Instruction::Limit {
391 index: table_reg_index,
392 limit: limit as u64,
393 });
394 } else {
395 return Err(CodegenError::Expr(ExprError::Value(ValueError {
397 reason: "Only constant integer LIMITs are supported",
398 value: val,
399 })));
400 }
401 } else {
402 return Err(CodegenError::Expr(ExprError::Expr {
404 reason: "Only constant integer LIMITs are supported",
405 expr: limit,
406 }));
407 }
408 }
409
410 instrs.push(Instruction::Return {
411 index: table_reg_index,
412 });
413
414 Ok(())
415 }
416 Statement::CreateSchema {
417 schema_name,
418 if_not_exists,
419 } => {
420 instrs.push(Instruction::NewSchema {
421 schema_name: schema_name.0.clone().try_into()?,
422 exists_ok: *if_not_exists,
423 });
424 Ok(())
425 }
426 _ => Err(CodegenError::UnsupportedStatement(ast.to_string())),
427 }?;
428
429 Ok(IntermediateCode { instrs })
430}
431
432#[derive(Debug)]
434pub enum CodegenError {
435 UnsupportedStatement(String),
436 UnsupportedStatementForm(&'static str, String),
437 InvalidIdentifier(IdentifierError),
438 Expr(ExprError),
439}
440
441impl Display for CodegenError {
442 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
443 match self {
444 CodegenError::UnsupportedStatement(s) => write!(f, "Unsupported statement: {}", s),
445 CodegenError::InvalidIdentifier(i) => {
446 write!(f, "{}", i)
447 }
448 CodegenError::UnsupportedStatementForm(reason, statement) => {
449 write!(f, "Unsupported: {} (Got: '{}')", reason, statement)
450 }
451 CodegenError::Expr(e) => write!(f, "{}", e),
452 }
453 }
454}
455
456impl From<IdentifierError> for CodegenError {
457 fn from(i: IdentifierError) -> Self {
458 CodegenError::InvalidIdentifier(i)
459 }
460}
461
462impl From<ExprError> for CodegenError {
463 fn from(e: ExprError) -> Self {
464 CodegenError::Expr(e)
465 }
466}
467
468impl From<ValueError> for CodegenError {
469 fn from(v: ValueError) -> Self {
470 CodegenError::Expr(v.into())
471 }
472}
473
474impl Error for CodegenError {}
475
476#[cfg(test)]
477mod tests {
478 use sqlparser::ast::{ColumnOption, ColumnOptionDef, DataType};
479
480 use pretty_assertions::assert_eq;
481
482 use crate::{
483 codegen::codegen_ast,
484 expr::{BinOp, Expr},
485 ic::Instruction,
486 identifier::{ColumnRef, SchemaRef, TableRef},
487 parser::parse,
488 value::Value,
489 vm::RegisterIndex,
490 };
491
492 fn check_single_statement(query: &str, callback: impl Fn(&[Instruction])) {
493 let parsed = parse(query).unwrap();
494 assert_eq!(parsed.len(), 1);
495
496 let statement = &parsed[0];
497 let ic = codegen_ast(&statement).unwrap();
498 callback(ic.instrs.as_slice());
499 }
500
501 #[test]
502 fn create_schema() {
503 check_single_statement("CREATE SCHEMA abc", |instrs| {
504 assert_eq!(
505 instrs,
506 &[Instruction::NewSchema {
507 schema_name: SchemaRef("abc".into()),
508 exists_ok: false,
509 }]
510 )
511 });
512
513 check_single_statement("CREATE SCHEMA IF NOT EXISTS abcd", |instrs| {
514 assert_eq!(
515 instrs,
516 &[Instruction::NewSchema {
517 schema_name: SchemaRef("abcd".into()),
518 exists_ok: true,
519 }]
520 )
521 });
522 }
523
524 #[test]
525 fn create_table() {
526 check_single_statement(
527 "CREATE TABLE
528 IF NOT EXISTS table1
529 (
530 col1 INTEGER PRIMARY KEY NOT NULL,
531 col2 STRING NOT NULL,
532 col3 INTEGER UNIQUE
533 )",
534 |instrs| {
535 assert_eq!(
536 instrs,
537 &[
538 Instruction::Empty {
539 index: RegisterIndex::default()
540 },
541 Instruction::ColumnDef {
542 index: RegisterIndex::default().next_index(),
543 name: "col1".into(),
544 data_type: DataType::Int(None),
545 },
546 Instruction::AddColumnOption {
547 index: RegisterIndex::default().next_index(),
548 option: ColumnOptionDef {
549 name: None,
550 option: ColumnOption::Unique { is_primary: true }
551 }
552 },
553 Instruction::AddColumnOption {
554 index: RegisterIndex::default().next_index(),
555 option: ColumnOptionDef {
556 name: None,
557 option: ColumnOption::NotNull
558 }
559 },
560 Instruction::AddColumn {
561 table_reg_index: RegisterIndex::default(),
562 col_index: RegisterIndex::default().next_index(),
563 },
564 Instruction::ColumnDef {
565 index: RegisterIndex::default().next_index(),
566 name: "col2".into(),
567 data_type: DataType::String,
568 },
569 Instruction::AddColumnOption {
570 index: RegisterIndex::default().next_index(),
571 option: ColumnOptionDef {
572 name: None,
573 option: ColumnOption::NotNull
574 }
575 },
576 Instruction::AddColumn {
577 table_reg_index: RegisterIndex::default(),
578 col_index: RegisterIndex::default().next_index(),
579 },
580 Instruction::ColumnDef {
581 index: RegisterIndex::default().next_index(),
582 name: "col3".into(),
583 data_type: DataType::Int(None),
584 },
585 Instruction::AddColumnOption {
586 index: RegisterIndex::default().next_index(),
587 option: ColumnOptionDef {
588 name: None,
589 option: ColumnOption::Unique { is_primary: false }
590 }
591 },
592 Instruction::AddColumn {
593 table_reg_index: RegisterIndex::default(),
594 col_index: RegisterIndex::default().next_index(),
595 },
596 Instruction::NewTable {
597 index: RegisterIndex::default(),
598 name: TableRef {
599 schema_name: None,
600 table_name: "table1".into()
601 },
602 exists_ok: true,
603 }
604 ]
605 )
606 },
607 );
608 }
609
610 #[test]
611 fn insert_values() {
612 check_single_statement(
613 "
614 INSERT INTO table1 VALUES
615 (2, 'bar'),
616 (3, 'baz')
617 ",
618 |instrs| {
619 assert_eq!(
620 instrs,
621 &[
622 Instruction::Source {
623 index: RegisterIndex::default(),
624 name: TableRef {
625 schema_name: None,
626 table_name: "table1".into()
627 }
628 },
629 Instruction::InsertDef {
630 table_reg_index: RegisterIndex::default(),
631 index: RegisterIndex::default().next_index(),
632 },
633 Instruction::RowDef {
634 insert_index: RegisterIndex::default().next_index(),
635 row_index: RegisterIndex::default().next_index().next_index(),
636 },
637 Instruction::AddValue {
638 row_index: RegisterIndex::default().next_index().next_index(),
639 expr: Expr::Value(Value::Int64(2)),
640 },
641 Instruction::AddValue {
642 row_index: RegisterIndex::default().next_index().next_index(),
643 expr: Expr::Value(Value::String("bar".to_owned())),
644 },
645 Instruction::RowDef {
646 insert_index: RegisterIndex::default().next_index(),
647 row_index: RegisterIndex::default()
648 .next_index()
649 .next_index()
650 .next_index(),
651 },
652 Instruction::AddValue {
653 row_index: RegisterIndex::default()
654 .next_index()
655 .next_index()
656 .next_index(),
657 expr: Expr::Value(Value::Int64(3)),
658 },
659 Instruction::AddValue {
660 row_index: RegisterIndex::default()
661 .next_index()
662 .next_index()
663 .next_index(),
664 expr: Expr::Value(Value::String("baz".to_owned())),
665 },
666 Instruction::Insert {
667 index: RegisterIndex::default().next_index()
668 },
669 ]
670 )
671 },
672 );
673
674 check_single_statement(
675 "
676 INSERT INTO table1 (col1, col2) VALUES
677 (2, 'bar'),
678 (3, 'baz')
679 ",
680 |instrs| {
681 assert_eq!(
682 instrs,
683 &[
684 Instruction::Source {
685 index: RegisterIndex::default(),
686 name: TableRef {
687 schema_name: None,
688 table_name: "table1".into()
689 }
690 },
691 Instruction::InsertDef {
692 table_reg_index: RegisterIndex::default(),
693 index: RegisterIndex::default().next_index(),
694 },
695 Instruction::ColumnInsertDef {
696 insert_index: RegisterIndex::default().next_index(),
697 col_name: "col1".into(),
698 },
699 Instruction::ColumnInsertDef {
700 insert_index: RegisterIndex::default().next_index(),
701 col_name: "col2".into(),
702 },
703 Instruction::RowDef {
704 insert_index: RegisterIndex::default().next_index(),
705 row_index: RegisterIndex::default().next_index().next_index(),
706 },
707 Instruction::AddValue {
708 row_index: RegisterIndex::default().next_index().next_index(),
709 expr: Expr::Value(Value::Int64(2)),
710 },
711 Instruction::AddValue {
712 row_index: RegisterIndex::default().next_index().next_index(),
713 expr: Expr::Value(Value::String("bar".to_owned())),
714 },
715 Instruction::RowDef {
716 insert_index: RegisterIndex::default().next_index(),
717 row_index: RegisterIndex::default()
718 .next_index()
719 .next_index()
720 .next_index(),
721 },
722 Instruction::AddValue {
723 row_index: RegisterIndex::default()
724 .next_index()
725 .next_index()
726 .next_index(),
727 expr: Expr::Value(Value::Int64(3)),
728 },
729 Instruction::AddValue {
730 row_index: RegisterIndex::default()
731 .next_index()
732 .next_index()
733 .next_index(),
734 expr: Expr::Value(Value::String("baz".to_owned())),
735 },
736 Instruction::Insert {
737 index: RegisterIndex::default().next_index()
738 },
739 ]
740 )
741 },
742 );
743 }
744
745 #[test]
746 fn select() {
747 check_single_statement("SELECT 1", |instrs| {
748 assert_eq!(
749 instrs,
750 &[
751 Instruction::NonExistent {
752 index: RegisterIndex::default()
753 },
754 Instruction::Empty {
755 index: RegisterIndex::default().next_index()
756 },
757 Instruction::Project {
758 input: RegisterIndex::default(),
759 output: RegisterIndex::default().next_index(),
760 expr: Expr::Value(Value::Int64(1)),
761 alias: None
762 },
763 Instruction::Return {
764 index: RegisterIndex::default().next_index()
765 },
766 ]
767 )
768 });
769
770 check_single_statement("SELECT * FROM table1", |instrs| {
771 assert_eq!(
772 instrs,
773 &[
774 Instruction::Source {
775 index: RegisterIndex::default(),
776 name: TableRef {
777 schema_name: None,
778 table_name: "table1".into()
779 }
780 },
781 Instruction::Empty {
782 index: RegisterIndex::default().next_index()
783 },
784 Instruction::Project {
785 input: RegisterIndex::default(),
786 output: RegisterIndex::default().next_index(),
787 expr: Expr::Wildcard,
788 alias: None
789 },
790 Instruction::Return {
791 index: RegisterIndex::default().next_index(),
792 }
793 ]
794 )
795 });
796
797 check_single_statement("SELECT * FROM table1 WHERE col1 = 1", |instrs| {
798 assert_eq!(
799 instrs,
800 &[
801 Instruction::Source {
802 index: RegisterIndex::default(),
803 name: TableRef {
804 schema_name: None,
805 table_name: "table1".into()
806 }
807 },
808 Instruction::Filter {
809 index: RegisterIndex::default(),
810 expr: Expr::Binary {
811 left: Box::new(Expr::ColumnRef(ColumnRef {
812 schema_name: None,
813 table_name: None,
814 col_name: "col1".into(),
815 },)),
816 op: BinOp::Equal,
817 right: Box::new(Expr::Value(Value::Int64(1)))
818 },
819 },
820 Instruction::Empty {
821 index: RegisterIndex::default().next_index()
822 },
823 Instruction::Project {
824 input: RegisterIndex::default(),
825 output: RegisterIndex::default().next_index(),
826 expr: Expr::Wildcard,
827 alias: None
828 },
829 Instruction::Return {
830 index: RegisterIndex::default().next_index(),
831 }
832 ]
833 )
834 });
835
836 check_single_statement(
837 "SELECT col2, col3
838 FROM table1
839 WHERE col1 = 1
840 ",
841 |instrs| {
842 assert_eq!(
843 instrs,
844 &[
845 Instruction::Source {
846 index: RegisterIndex::default(),
847 name: TableRef {
848 schema_name: None,
849 table_name: "table1".into()
850 }
851 },
852 Instruction::Filter {
853 index: RegisterIndex::default(),
854 expr: Expr::Binary {
855 left: Box::new(Expr::ColumnRef(ColumnRef {
856 schema_name: None,
857 table_name: None,
858 col_name: "col1".into(),
859 },)),
860 op: BinOp::Equal,
861 right: Box::new(Expr::Value(Value::Int64(1)))
862 },
863 },
864 Instruction::Empty {
865 index: RegisterIndex::default().next_index()
866 },
867 Instruction::Project {
868 input: RegisterIndex::default(),
869 output: RegisterIndex::default().next_index(),
870 expr: Expr::ColumnRef(ColumnRef {
871 schema_name: None,
872 table_name: None,
873 col_name: "col2".into(),
874 }),
875 alias: None
876 },
877 Instruction::Project {
878 input: RegisterIndex::default(),
879 output: RegisterIndex::default().next_index(),
880 expr: Expr::ColumnRef(ColumnRef {
881 schema_name: None,
882 table_name: None,
883 col_name: "col3".into(),
884 }),
885 alias: None
886 },
887 Instruction::Return {
888 index: RegisterIndex::default().next_index(),
889 }
890 ]
891 )
892 },
893 );
894
895 check_single_statement(
896 "SELECT col2, col3
897 FROM table1
898 WHERE col1 = 1 AND col2 = 2
899 ",
900 |instrs| {
901 assert_eq!(
902 instrs,
903 &[
904 Instruction::Source {
905 index: RegisterIndex::default(),
906 name: TableRef {
907 schema_name: None,
908 table_name: "table1".into()
909 }
910 },
911 Instruction::Filter {
912 index: RegisterIndex::default(),
913 expr: Expr::Binary {
914 left: Box::new(Expr::Binary {
915 left: Box::new(Expr::ColumnRef(ColumnRef {
916 schema_name: None,
917 table_name: None,
918 col_name: "col1".into(),
919 },)),
920 op: BinOp::Equal,
921 right: Box::new(Expr::Value(Value::Int64(1)))
922 }),
923 op: BinOp::And,
924 right: Box::new(Expr::Binary {
925 left: Box::new(Expr::ColumnRef(ColumnRef {
926 schema_name: None,
927 table_name: None,
928 col_name: "col2".into(),
929 },)),
930 op: BinOp::Equal,
931 right: Box::new(Expr::Value(Value::Int64(2)))
932 })
933 },
934 },
935 Instruction::Empty {
936 index: RegisterIndex::default().next_index()
937 },
938 Instruction::Project {
939 input: RegisterIndex::default(),
940 output: RegisterIndex::default().next_index(),
941 expr: Expr::ColumnRef(ColumnRef {
942 schema_name: None,
943 table_name: None,
944 col_name: "col2".into(),
945 }),
946 alias: None
947 },
948 Instruction::Project {
949 input: RegisterIndex::default(),
950 output: RegisterIndex::default().next_index(),
951 expr: Expr::ColumnRef(ColumnRef {
952 schema_name: None,
953 table_name: None,
954 col_name: "col3".into(),
955 }),
956 alias: None
957 },
958 Instruction::Return {
959 index: RegisterIndex::default().next_index(),
960 }
961 ]
962 )
963 },
964 );
965
966 check_single_statement(
967 "SELECT col2, col3
968 FROM table1
969 WHERE col1 = 1 OR col2 = 2
970 ",
971 |instrs| {
972 assert_eq!(
973 instrs,
974 &[
975 Instruction::Source {
976 index: RegisterIndex::default(),
977 name: TableRef {
978 schema_name: None,
979 table_name: "table1".into()
980 }
981 },
982 Instruction::Filter {
983 index: RegisterIndex::default(),
984 expr: Expr::Binary {
985 left: Box::new(Expr::Binary {
986 left: Box::new(Expr::ColumnRef(ColumnRef {
987 schema_name: None,
988 table_name: None,
989 col_name: "col1".into(),
990 },)),
991 op: BinOp::Equal,
992 right: Box::new(Expr::Value(Value::Int64(1)))
993 }),
994 op: BinOp::Or,
995 right: Box::new(Expr::Binary {
996 left: Box::new(Expr::ColumnRef(ColumnRef {
997 schema_name: None,
998 table_name: None,
999 col_name: "col2".into(),
1000 },)),
1001 op: BinOp::Equal,
1002 right: Box::new(Expr::Value(Value::Int64(2)))
1003 })
1004 },
1005 },
1006 Instruction::Empty {
1007 index: RegisterIndex::default().next_index()
1008 },
1009 Instruction::Project {
1010 input: RegisterIndex::default(),
1011 output: RegisterIndex::default().next_index(),
1012 expr: Expr::ColumnRef(ColumnRef {
1013 schema_name: None,
1014 table_name: None,
1015 col_name: "col2".into(),
1016 }),
1017 alias: None
1018 },
1019 Instruction::Project {
1020 input: RegisterIndex::default(),
1021 output: RegisterIndex::default().next_index(),
1022 expr: Expr::ColumnRef(ColumnRef {
1023 schema_name: None,
1024 table_name: None,
1025 col_name: "col3".into(),
1026 }),
1027 alias: None
1028 },
1029 Instruction::Return {
1030 index: RegisterIndex::default().next_index(),
1031 }
1032 ]
1033 )
1034 },
1035 );
1036
1037 check_single_statement(
1038 "SELECT col2, col3
1039 FROM table1
1040 WHERE col1 = 1
1041 ORDER BY col2
1042 LIMIT 100
1043 ",
1044 |instrs| {
1045 assert_eq!(
1046 instrs,
1047 &[
1048 Instruction::Source {
1049 index: RegisterIndex::default(),
1050 name: TableRef {
1051 schema_name: None,
1052 table_name: "table1".into()
1053 }
1054 },
1055 Instruction::Filter {
1056 index: RegisterIndex::default(),
1057 expr: Expr::Binary {
1058 left: Box::new(Expr::ColumnRef(ColumnRef {
1059 schema_name: None,
1060 table_name: None,
1061 col_name: "col1".into(),
1062 },)),
1063 op: BinOp::Equal,
1064 right: Box::new(Expr::Value(Value::Int64(1)))
1065 },
1066 },
1067 Instruction::Empty {
1068 index: RegisterIndex::default().next_index()
1069 },
1070 Instruction::Project {
1071 input: RegisterIndex::default(),
1072 output: RegisterIndex::default().next_index(),
1073 expr: Expr::ColumnRef(ColumnRef {
1074 schema_name: None,
1075 table_name: None,
1076 col_name: "col2".into(),
1077 }),
1078 alias: None
1079 },
1080 Instruction::Project {
1081 input: RegisterIndex::default(),
1082 output: RegisterIndex::default().next_index(),
1083 expr: Expr::ColumnRef(ColumnRef {
1084 schema_name: None,
1085 table_name: None,
1086 col_name: "col3".into(),
1087 }),
1088 alias: None
1089 },
1090 Instruction::Order {
1091 index: RegisterIndex::default().next_index(),
1092 expr: Expr::ColumnRef(ColumnRef {
1093 schema_name: None,
1094 table_name: None,
1095 col_name: "col2".into(),
1096 }),
1097 ascending: true
1098 },
1099 Instruction::Limit {
1100 index: RegisterIndex::default().next_index(),
1101 limit: 100,
1102 },
1103 Instruction::Return {
1104 index: RegisterIndex::default().next_index(),
1105 }
1106 ]
1107 )
1108 },
1109 );
1110
1111 check_single_statement(
1112 "SELECT col2, MAX(col3) AS max_col3
1113 FROM table1
1114 WHERE col1 = 1
1115 GROUP BY col2
1116 HAVING MAX(col3) > 10
1117 ",
1118 |instrs| {
1119 assert_eq!(
1120 instrs,
1121 &[
1122 Instruction::Source {
1123 index: RegisterIndex::default(),
1124 name: TableRef {
1125 schema_name: None,
1126 table_name: "table1".into()
1127 }
1128 },
1129 Instruction::Filter {
1130 index: RegisterIndex::default(),
1131 expr: Expr::Binary {
1132 left: Box::new(Expr::ColumnRef(ColumnRef {
1133 schema_name: None,
1134 table_name: None,
1135 col_name: "col1".into(),
1136 },)),
1137 op: BinOp::Equal,
1138 right: Box::new(Expr::Value(Value::Int64(1)))
1139 },
1140 },
1141 Instruction::GroupBy {
1142 index: RegisterIndex::default(),
1143 expr: Expr::ColumnRef(ColumnRef {
1144 schema_name: None,
1145 table_name: None,
1146 col_name: "col2".into(),
1147 })
1148 },
1149 Instruction::Filter {
1150 index: RegisterIndex::default(),
1151 expr: Expr::Binary {
1152 left: Box::new(Expr::Function {
1153 name: "MAX".into(),
1154 args: vec![Expr::ColumnRef(ColumnRef {
1155 schema_name: None,
1156 table_name: None,
1157 col_name: "col3".into(),
1158 })]
1159 }),
1160 op: BinOp::GreaterThan,
1161 right: Box::new(Expr::Value(Value::Int64(10)))
1162 },
1163 },
1164 Instruction::Empty {
1165 index: RegisterIndex::default().next_index()
1166 },
1167 Instruction::Project {
1168 input: RegisterIndex::default(),
1169 output: RegisterIndex::default().next_index(),
1170 expr: Expr::ColumnRef(ColumnRef {
1171 schema_name: None,
1172 table_name: None,
1173 col_name: "col2".into(),
1174 }),
1175 alias: None
1176 },
1177 Instruction::Project {
1178 input: RegisterIndex::default(),
1179 output: RegisterIndex::default().next_index(),
1180 expr: Expr::Function {
1181 name: "MAX".into(),
1182 args: vec![Expr::ColumnRef(ColumnRef {
1183 schema_name: None,
1184 table_name: None,
1185 col_name: "col3".into(),
1186 })]
1187 },
1188 alias: Some("max_col3".into())
1189 },
1190 Instruction::Return {
1191 index: RegisterIndex::default().next_index(),
1192 }
1193 ]
1194 )
1195 },
1196 );
1197 }
1198}