an ORM-free SQL experience
at main 2.4 kB view raw
1package norm 2 3import "fmt" 4 5type op string 6 7type Expr struct { 8 kind ExprKind 9 10 ident *IdentExpr 11 binary *BinExpr 12 value *ValueExpr 13} 14 15func (e Expr) String() string { 16 switch e.kind { 17 case exprKindIdent: 18 return e.ident.String() 19 case exprKindBinary: 20 return e.binary.String() 21 case exprKindValue: 22 return e.value.String() 23 } 24 25 // unreachable 26 return "" 27} 28 29func (e Expr) Binds() []any { 30 switch e.kind { 31 case exprKindIdent: 32 return e.ident.Binds() 33 case exprKindBinary: 34 return e.binary.Binds() 35 case exprKindValue: 36 return e.value.Binds() 37 } 38 39 // unreachable 40 return nil 41} 42 43type ExprKind int 44 45const ( 46 exprKindIdent ExprKind = iota 47 exprKindBinary 48 exprKindValue 49) 50 51type IdentExpr string 52 53func (i IdentExpr) String() string { 54 return string(i) 55} 56 57func (i IdentExpr) Binds() []any { 58 return nil 59} 60 61func (i IdentExpr) AsExpr() Expr { 62 return Expr{ 63 kind: exprKindIdent, 64 ident: &i, 65 } 66} 67 68type ValueExpr struct { 69 inner any 70} 71 72func (v ValueExpr) String() string { 73 return "?" 74} 75 76func (v ValueExpr) Binds() []any { 77 return []any{v.inner} 78} 79 80func (v ValueExpr) AsExpr() Expr { 81 return Expr{ 82 kind: exprKindValue, 83 value: &v, 84 } 85} 86 87type BinExpr struct { 88 left Expr 89 op op 90 right Expr 91} 92 93func (b BinExpr) String() string { 94 return fmt.Sprintf("(%s) %s (%s)", b.left.String(), b.op, b.right.String()) 95} 96 97func (b BinExpr) Binds() []any { 98 binds := b.left.Binds() 99 binds = append(binds, b.right.Binds()...) 100 return binds 101} 102 103func (b BinExpr) AsExpr() Expr { 104 return Expr{ 105 kind: exprKindBinary, 106 binary: &b, 107 } 108} 109 110func buildBinExpr(left IdentExpr, op op, right any) Expr { 111 return BinExpr{left.AsExpr(), op, ValueExpr{right}.AsExpr()}.AsExpr() 112} 113func Eq(left string, right any) Expr { return buildBinExpr(IdentExpr(left), "=", right) } 114func Neq(left string, right any) Expr { return buildBinExpr(IdentExpr(left), "<>", right) } 115func Gt(left string, right any) Expr { return buildBinExpr(IdentExpr(left), ">", right) } 116func Gte(left string, right any) Expr { return buildBinExpr(IdentExpr(left), ">=", right) } 117func Lt(left string, right any) Expr { return buildBinExpr(IdentExpr(left), "<", right) } 118func Lte(left string, right any) Expr { return buildBinExpr(IdentExpr(left), "<=", right) } 119 120func (l Expr) And(r Expr) Expr { return BinExpr{l, "AND", r}.AsExpr() } 121func (l Expr) Or(r Expr) Expr { return BinExpr{l, "OR", r}.AsExpr() }