1use crate::*;
2use std::{mem, ops};
3use Instruction::*;
4
5pub fn c_check(b: &Block, e: &mut Expr) {
7 if e.checked {
8 return;
9 }
10 e.is_constant = true;
11 match &mut e.exp {
12 ExprIs::BuiltinCall(name, args) => {
13 if let Some((dk, _cf)) = b.db.builtins.get(name) {
14 e.data_type = *dk as DataType;
15 for pe in args {
16 c_check(b, pe);
17 if !pe.is_constant {
18 e.is_constant = false;
19 }
20 }
21 } else {
22 panic!("unknown function {}", name);
23 }
24 }
25 ExprIs::Binary(op, b1, b2) => {
26 c_check(b, b1);
27 c_check(b, b2);
28 e.is_constant = b1.is_constant && b2.is_constant;
29 let t1 = b1.data_type;
30 let t2 = b2.data_type;
31 if data_kind(t1) != data_kind(t2) && *op != Token::VBar {
32 panic!("binary op type mismatch")
33 }
34 e.data_type = match op {
35 Token::Less
36 | Token::LessEqual
37 | Token::GreaterEqual
38 | Token::Greater
39 | Token::Equal
40 | Token::NotEqual => BOOL,
41 Token::And | Token::Or => {
42 if t1 != BOOL {
43 panic!("AND/OR need bool operands")
44 }
45 BOOL
46 }
47 Token::Plus | Token::Times | Token::Minus | Token::Divide | Token::Percent => t1,
48 Token::VBar => {
49 if data_kind(t1) == DataKind::Binary {
50 BINARY
51 } else {
52 STRING
53 }
54 }
55 _ => panic!(),
56 }
57 }
58 ExprIs::Local(x) => {
59 e.data_type = b.local_typ[*x];
60 }
61 ExprIs::Const(x) => {
62 e.data_type = match *x {
63 Value::Bool(_) => BOOL,
64 Value::Int(_) => INT,
65 Value::Float(_) => DOUBLE,
66 Value::String(_) => STRING,
67 Value::RcBinary(_) => BINARY,
68 Value::ArcBinary(_) => BINARY,
69 _ => NONE,
70 }
71 }
72 ExprIs::Case(x, els) => {
73 c_check(b, els);
74 if !els.is_constant {
75 e.is_constant = false;
76 }
77 e.data_type = els.data_type;
78 for (w, t) in x {
79 c_check(b, w);
80 if !w.is_constant {
81 e.is_constant = false;
82 }
83 c_check(b, t);
84 if !t.is_constant {
85 e.is_constant = false;
86 }
87 if data_kind(e.data_type) != data_kind(t.data_type) {
88 panic!("CASE branch type mismatch");
89 }
90 }
91 }
92 ExprIs::Not(x) => {
93 c_check(b, x);
94 e.is_constant = x.is_constant;
95 e.data_type = BOOL;
96 }
97 ExprIs::Minus(x) => {
98 c_check(b, x);
99 e.is_constant = x.is_constant;
100 e.data_type = x.data_type;
101 }
102 ExprIs::FuncCall(name, parms) => {
103 let f = c_function(&b.db, name);
104 e.data_type = f.return_type;
105 if parms.len() != f.param_count {
106 panic!(
107 "function parameter count mismatch expected {} got {}",
108 f.param_count,
109 parms.len()
110 );
111 }
112 for (i, a) in parms.iter_mut().enumerate() {
113 c_check(b, a);
114 let (t, et) = (data_kind(a.data_type), data_kind(f.local_typ[i]));
115 if t != et {
116 panic!("function param type mismatch expected {:?} got {:?}", et, t);
117 }
118 if !a.is_constant {
119 e.is_constant = false;
120 }
121 }
122 }
123 ExprIs::ColName(x) => {
124 e.is_constant = false;
125 let (col, data_type) = name_to_colnum(b, x);
126 e.col = col;
127 e.data_type = data_type;
128 }
129 _ => panic!(),
130 }
131 e.checked = true;
132}
133
134fn c_builtin_value(b: &Block, name: &str, args: &mut [Expr]) -> CExpPtr<Value> {
136 if let Some((_dk, CompileFunc::Value(cf))) = b.db.builtins.get(name) {
137 return cf(b, args);
138 }
139 panic!()
140}
141
142pub fn c_value(b: &Block, e: &mut Expr) -> CExpPtr<Value> {
144 match b.kind(e) {
145 DataKind::Bool => Box::new(cexp::BoolToVal(c_bool(b, e))),
146 DataKind::Int => Box::new(cexp::IntToVal(c_int(b, e))),
147 DataKind::Float => Box::new(cexp::FloatToVal(c_float(b, e))),
148 _ => match &mut e.exp {
149 ExprIs::ColName(x) => {
150 let (off, typ) = name_to_col(b, x);
151 let size = data_size(typ);
152 match data_kind(typ) {
153 DataKind::String => Box::new(cexp::ColumnString { off, size }),
154 DataKind::Binary => Box::new(cexp::ColumnBinary { off, size }),
155 _ => panic!(),
156 }
157 }
158 ExprIs::Const(x) => Box::new(cexp::Const((*x).clone())),
159 ExprIs::Local(x) => Box::new(cexp::Local(*x)),
160 ExprIs::Binary(op, b1, b2) => {
161 let c1 = c_value(b, b1);
162 let c2 = c_value(b, b2);
163 match op {
164 Token::VBar => {
165 if data_kind(b1.data_type) == DataKind::Binary {
166 Box::new(cexp::BinConcat(c1, c2))
167 } else {
168 Box::new(cexp::Concat(c1, c2))
169 }
170 }
171 _ => panic!("invalid operator {:?}", op),
172 }
173 }
174 ExprIs::FuncCall(name, parms) => c_call(b, name, parms),
175 ExprIs::Case(list, els) => c_case(b, list, els, c_value),
176 ExprIs::BuiltinCall(name, parms) => c_builtin_value(b, name, parms),
177 _ => panic!(),
178 },
179 }
180}
181
182pub fn c_int(b: &Block, e: &mut Expr) -> CExpPtr<i64> {
184 if b.kind(e) != DataKind::Int {
185 panic!("int type expected")
186 }
187 match &mut e.exp {
188 ExprIs::ColName(x) => {
189 let (off, typ) = name_to_col(b, x);
190 let size = data_size(typ);
191 match size {
192 8 => Box::new(cexp::ColumnI64 { off }),
193 1 => Box::new(cexp::ColumnI8 { off }),
194 _ => Box::new(cexp::ColumnI { off, size }),
195 }
196 }
197 ExprIs::Const(Value::Int(b)) => Box::new(cexp::Const::<i64>(*b)),
198 ExprIs::Local(num) => Box::new(cexp::Local(*num)),
199 ExprIs::Binary(op, b1, b2) => c_arithmetic(b, *op, b1, b2, c_int),
200 ExprIs::Minus(x) => Box::new(cexp::Minus::<i64>(c_int(b, x))),
201 ExprIs::Case(w, e) => c_case(b, w, e, c_int),
202 ExprIs::FuncCall(n, a) => Box::new(cexp::ValToInt(c_call(b, n, a))),
203 ExprIs::BuiltinCall(n, a) => c_builtin_int(b, n, a),
204 _ => panic!(),
205 }
206}
207
208pub fn c_float(b: &Block, e: &mut Expr) -> CExpPtr<f64> {
210 if b.kind(e) != DataKind::Float {
211 panic!("float type expected")
212 }
213 match &mut e.exp {
214 ExprIs::ColName(x) => {
215 let (off, typ) = name_to_col(b, x);
216 match data_size(typ) {
217 8 => Box::new(cexp::ColumnF64 { off }),
218 4 => Box::new(cexp::ColumnF32 { off }),
219 _ => panic!(),
220 }
221 }
222 ExprIs::Local(num) => Box::new(cexp::Local(*num)),
223 ExprIs::Binary(op, b1, b2) => c_arithmetic(b, *op, b1, b2, c_float),
224 ExprIs::Minus(x) => Box::new(cexp::Minus::<f64>(c_float(b, x))),
225 ExprIs::Case(w, e) => c_case(b, w, e, c_float),
226 ExprIs::FuncCall(n, a) => Box::new(cexp::ValToFloat(c_call(b, n, a))),
227 ExprIs::BuiltinCall(n, a) => c_builtin_float(b, n, a),
228 _ => panic!(),
229 }
230}
231
232pub fn c_bool(b: &Block, e: &mut Expr) -> CExpPtr<bool> {
234 if b.kind(e) != DataKind::Bool {
235 panic!("bool type expected")
236 }
237 match &mut e.exp {
238 ExprIs::ColName(x) => {
239 let (off, _typ) = name_to_col(b, x);
240 Box::new(cexp::ColumnBool { off })
241 }
242 ExprIs::Const(Value::Bool(b)) => Box::new(cexp::Const::<bool>(*b)),
243 ExprIs::Local(x) => Box::new(cexp::Local(*x)),
244 ExprIs::Binary(op, b1, b2) => {
245 if *op == Token::Or || *op == Token::And {
246 let c1 = c_bool(b, b1);
247 let c2 = c_bool(b, b2);
248 match op {
249 Token::Or => Box::new(cexp::Or(c1, c2)),
250 Token::And => Box::new(cexp::And(c1, c2)),
251 _ => panic!(),
252 }
253 } else {
254 match b.kind(b1) {
255 DataKind::Bool => c_compare(b, *op, b1, b2, c_bool),
256 DataKind::Int => c_compare(b, *op, b1, b2, c_int),
257 DataKind::Float => c_compare(b, *op, b1, b2, c_float),
258 _ => c_compare(b, *op, b1, b2, c_value),
259 }
260 }
261 }
262 ExprIs::Not(x) => Box::new(cexp::Not(c_bool(b, x))),
263 ExprIs::FuncCall(name, parms) => Box::new(cexp::ValToBool(c_call(b, name, parms))),
264 ExprIs::Case(list, els) => c_case(b, list, els, c_bool),
265 _ => panic!(),
266 }
267}
268
269fn c_arithmetic<T>(
271 b: &Block,
272 op: Token,
273 e1: &mut Expr,
274 e2: &mut Expr,
275 cexp: fn(&Block, &mut Expr) -> CExpPtr<T>,
276) -> CExpPtr<T>
277where
278 T: 'static
279 + ops::Add<Output = T>
280 + ops::Sub<Output = T>
281 + ops::Mul<Output = T>
282 + ops::Div<Output = T>
283 + ops::Rem<Output = T>,
284{
285 let c1 = cexp(b, e1);
286 let c2 = cexp(b, e2);
287 match op {
288 Token::Plus => Box::new(cexp::Add::<T>(c1, c2)),
289 Token::Minus => Box::new(cexp::Sub::<T>(c1, c2)),
290 Token::Times => Box::new(cexp::Mul::<T>(c1, c2)),
291 Token::Divide => Box::new(cexp::Div::<T>(c1, c2)),
292 Token::Percent => Box::new(cexp::Rem::<T>(c1, c2)),
293 _ => panic!(),
294 }
295}
296
297fn c_compare<T>(
299 b: &Block,
300 op: Token,
301 e1: &mut Expr,
302 e2: &mut Expr,
303 cexp: fn(&Block, &mut Expr) -> CExpPtr<T>,
304) -> CExpPtr<bool>
305where
306 T: 'static + std::cmp::PartialOrd,
307{
308 let c1 = cexp(b, e1);
309 let c2 = cexp(b, e2);
310 match op {
311 Token::Equal => Box::new(cexp::Equal::<T>(c1, c2)),
312 Token::NotEqual => Box::new(cexp::NotEqual::<T>(c1, c2)),
313 Token::Less => Box::new(cexp::Less::<T>(c1, c2)),
314 Token::Greater => Box::new(cexp::Greater::<T>(c1, c2)),
315 Token::LessEqual => Box::new(cexp::LessEqual::<T>(c1, c2)),
316 Token::GreaterEqual => Box::new(cexp::GreaterEqual::<T>(c1, c2)),
317 _ => panic!(),
318 }
319}
320
321fn c_case<T>(
323 b: &Block,
324 wes: &mut [(Expr, Expr)],
325 els: &mut Expr,
326 cexp: fn(&Block, &mut Expr) -> CExpPtr<T>,
327) -> CExpPtr<T>
328where
329 T: 'static,
330{
331 let mut whens = Vec::new();
332 for (be, ve) in wes {
333 let cb = c_bool(b, be);
334 let v = cexp(b, ve);
335 whens.push((cb, v));
336 }
337 let els = cexp(b, els);
338 Box::new(cexp::Case::<T> { whens, els })
339}
340
341fn c_builtin_int(b: &Block, name: &str, args: &mut [Expr]) -> CExpPtr<i64> {
343 if let Some((_dk, CompileFunc::Int(cf))) = b.db.builtins.get(name) {
344 return cf(b, args);
345 }
346 panic!()
347}
348
349fn c_builtin_float(b: &Block, name: &str, args: &mut [Expr]) -> CExpPtr<f64> {
351 if let Some((_dk, CompileFunc::Float(cf))) = b.db.builtins.get(name) {
352 return cf(b, args);
353 }
354 panic!()
355}
356
357pub fn c_update(
359 b: &mut Block,
360 tname: &ObjRef,
361 assigns: &mut [(String, Expr)],
362 wher: &mut Option<Expr>,
363) {
364 let t = c_table(b, tname);
365 let from = CTableExpression::Base(t.clone());
366 let save = mem::replace(&mut b.from, Some(from));
367 let mut se = Vec::new();
368 for (name, exp) in assigns.iter_mut() {
369 if let Some(cnum) = t.info.colmap.get(name) {
370 let exp = c_value(b, exp);
371 se.push((*cnum, exp));
372 } else {
373 panic!("update column name not found");
374 }
375 }
376 let (w, index_from) = c_where(b, Some(t), wher);
377 let mut from = mem::replace(&mut b.from, save);
378 if index_from.is_some() {
379 from = index_from;
380 }
381 b.dop(DO::Update(se, from.unwrap(), w));
382}
383
384pub fn c_delete(b: &mut Block, tname: &ObjRef, wher: &mut Option<Expr>) {
386 let t = c_table(b, tname);
387 let from = Some(CTableExpression::Base(t.clone()));
388 let save = mem::replace(&mut b.from, from);
389 let (w, index_from) = c_where(b, Some(t), wher);
390 let mut from = mem::replace(&mut b.from, save);
391 if index_from.is_some() {
392 from = index_from;
393 }
394 b.dop(DO::Delete(from.unwrap(), w));
395}
396
397pub fn c_set(b: &mut Block, mut se: FromExpression) {
399 if se.from.is_none() {
400 for (i, e) in se.exps.iter_mut().enumerate() {
402 let (lnum, op) = se.assigns[i];
404 let ek = data_kind(b.local_typ[lnum]);
405 let ce = c_value(b, e);
406 let ak = b.kind(e);
407 if ek != ak {
408 panic!("cannot assign {:?} to {:?}", ak, ek);
409 }
410 match op {
411 AssignOp::Assign => b.add(AssignLocal(lnum, ce)),
412 AssignOp::Append => b.add(AppendLocal(lnum, ce)),
413 AssignOp::Inc => b.add(IncLocal(lnum, ce)),
414 AssignOp::Dec => b.add(DecLocal(lnum, ce)),
415 }
416 }
417 } else {
418 let cte = c_select(b, se);
419 b.add(Set(Box::new(cte)));
420 }
421}
422
423pub fn c_select(b: &mut Block, mut x: FromExpression) -> CFromExpression {
425 let mut from = x.from.map(|mut te| c_te(b, &mut te));
426 let table = match &from {
427 Some(CTableExpression::Base(t)) => Some(t.clone()),
428 _ => None,
429 };
430 let save = mem::replace(&mut b.from, from);
432 let mut exps = Vec::new();
433 for (i, e) in x.exps.iter_mut().enumerate() {
434 exps.push(c_value(b, e));
435 if !x.assigns.is_empty() {
436 let (lnum, _) = x.assigns[i];
438 let ek = data_kind(b.local_typ[lnum]);
439 let ak = data_kind(e.data_type);
440 if ek != ak {
441 panic!("cannot assign {:?} to {:?}", ak, ek);
442 }
443 }
444 }
445 let (wher, index_from) = c_where(b, table, &mut x.wher);
446 let mut orderby = Vec::new();
447 let mut desc = Vec::new();
448 for (e, a) in &mut x.orderby {
449 let e = c_value(b, e);
450 orderby.push(e);
451 desc.push(*a);
452 }
453 from = mem::replace(&mut b.from, save);
454 if index_from.is_some() {
455 from = index_from;
456 }
457 CFromExpression {
458 colnames: x.colnames,
459 assigns: x.assigns,
460 exps,
461 from,
462 wher,
463 orderby,
464 desc,
465 }
466}
467
468pub fn c_where(
470 b: &Block,
471 table: Option<Rc<Table>>,
472 wher: &mut Option<Expr>,
473) -> (Option<CExpPtr<bool>>, Option<CTableExpression>) {
474 if let Some(we) = wher {
475 if b.kind(we) != DataKind::Bool {
476 panic!("WHERE expression must be bool")
477 }
478 if let Some(table) = table {
479 table.index_from(b, we)
480 } else {
481 (Some(c_bool(b, we)), None)
482 }
483 } else {
484 (None, None)
485 }
486}
487
488pub fn c_te(b: &Block, te: &mut TableExpression) -> CTableExpression {
490 match te {
491 TableExpression::Values(x) => {
492 let mut cm = Vec::new();
493 for r in x {
494 let mut cr = Vec::new();
495 for e in r {
496 let ce = c_value(b, e);
497 cr.push(ce);
498 }
499 cm.push(cr);
500 }
501 CTableExpression::Values(cm)
502 }
503 TableExpression::Base(x) => {
504 let t = c_table(b, x);
505 CTableExpression::Base(t)
506 }
507 }
508}
509
510pub fn c_table(b: &Block, name: &ObjRef) -> Rc<Table> {
512 if let Some(t) = b.db.get_table(name) {
513 t
514 } else {
515 panic!("table {} not found", name.str())
516 }
517}
518
519pub fn c_function(db: &DB, name: &ObjRef) -> Rc<Function> {
521 if let Some(r) = db.get_function(name) {
522 let (compiled, src) = { (r.compiled.get(), r.source.clone()) };
523 if !compiled {
524 r.compiled.set(true);
525 let mut p = Parser::new(&src, db);
526 p.function_name = Some(name);
527 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
528 p.parse_function();
529 }));
530 if let Err(x) = result {
531 r.compiled.set(false);
532 std::panic::panic_any(if let Some(sqe) = x.downcast_ref::<SqlError>() {
533 sqe.clone()
534 } else if let Some(s) = x.downcast_ref::<&str>() {
535 p.make_error((*s).to_string())
536 } else if let Some(s) = x.downcast_ref::<String>() {
537 p.make_error(s.to_string())
538 } else {
539 p.make_error("unrecognised/unexpected error".to_string())
540 });
541 }
542 *r.ilist.borrow_mut() = p.b.ilist;
543 }
544 r
545 } else {
546 panic!("function {} not found", name.str())
547 }
548}
549
550pub fn name_to_col(b: &Block, name: &str) -> (usize, DataType) {
552 if let Some(CTableExpression::Base(t)) = &b.from {
553 let info = &t.info;
554 if let Some(num) = info.get(name) {
555 let colnum = *num;
556 if colnum == usize::MAX {
557 return (0, INT);
558 }
559 return (info.off[colnum], info.typ[colnum]);
560 }
561 }
562 panic!("Name '{}' not found", name)
563}
564
565pub fn name_to_colnum(b: &Block, name: &str) -> (usize, DataType) {
567 if let Some(CTableExpression::Base(t)) = &b.from {
568 let info = &t.info;
569 if let Some(num) = info.get(name) {
570 let colnum = *num;
571 if colnum == usize::MAX {
572 return (colnum, INT);
573 }
574 return (colnum, info.typ[colnum]);
575 }
576 }
577 panic!("Name '{}' not found", name)
578}
579
580pub fn c_call(b: &Block, name: &ObjRef, parms: &mut Vec<Expr>) -> CExpPtr<Value> {
582 let fp = c_function(&b.db, name);
583 let mut pv = Vec::new();
584 let mut pk = Vec::new();
585 for e in parms {
586 pk.push(b.kind(e));
587 let ce = c_value(b, e);
588 pv.push(ce);
589 }
590 if fp.return_type == NONE {
591 panic!("function with no RETURN type cannot be used in expression");
592 }
593 b.check_types(&fp, &pk);
594 Box::new(cexp::Call { fp, pv })
595}
596
597pub fn push(b: &mut Block, e: &mut Expr) -> DataKind {
599 if b.parse_only {
600 return DataKind::None;
601 }
602 let k = b.kind(e);
603 match &mut e.exp {
604 ExprIs::Const(x) => {
605 b.add(PushConst((*x).clone()));
606 }
607 ExprIs::Binary(_, _, _) => match k {
608 DataKind::Int => {
609 let ce = c_int(b, e);
610 b.add(PushInt(ce));
611 }
612 DataKind::Float => {
613 let ce = c_float(b, e);
614 b.add(PushFloat(ce));
615 }
616 DataKind::Bool => {
617 let ce = c_bool(b, e);
618 b.add(PushBool(ce));
619 }
620 _ => {
621 let ce = c_value(b, e);
622 b.add(PushValue(ce));
623 }
624 },
625 ExprIs::FuncCall(name, parms) => {
626 let rp = c_function(&b.db, name);
627 {
628 for e in parms.iter_mut() {
629 push(b, e);
630 }
631 }
632 b.add(Call(rp));
633 }
634 ExprIs::Local(x) => {
635 b.add(PushLocal(*x));
636 }
637 _ => {
638 let ce = c_value(b, e);
639 b.add(PushValue(ce));
640 }
641 }
642 k
643}
644
645pub fn c_for(b: &mut Block, se: FromExpression, start_id: usize, break_id: usize, for_id: usize) {
647 let mut cse = c_select(b, se);
648 let orderbylen = cse.orderby.len();
649 if orderbylen == 0 {
650 b.add(ForInit(for_id, Box::new(cse.from.unwrap())));
651 b.set_jump(start_id);
652 let info = Box::new(ForNextInfo {
653 for_id,
654 assigns: cse.assigns,
655 exps: cse.exps,
656 wher: cse.wher,
657 });
658 b.add(ForNext(break_id, info));
659 } else {
660 let assigns = mem::take(&mut cse.assigns);
661 b.add(ForSortInit(for_id, Box::new(cse)));
662 b.set_jump(start_id);
663 let info = Box::new((for_id, orderbylen, assigns));
664 b.add(ForSortNext(break_id, info));
665 }
666}