github.com/aacfactory/fns-contrib/databases/sql@v1.2.84/dac/specifications/predicate.go (about) 1 package specifications 2 3 import ( 4 "bytes" 5 "database/sql" 6 "fmt" 7 "github.com/aacfactory/errors" 8 "github.com/aacfactory/fns-contrib/databases/sql/dac/conditions" 9 "github.com/aacfactory/fns/commons/bytex" 10 "github.com/valyala/bytebufferpool" 11 "io" 12 "strings" 13 ) 14 15 type Predicate struct { 16 conditions.Predicate 17 } 18 19 func (p Predicate) Render(ctx Context, w io.Writer) (argument []any, err error) { 20 column, hasColumn := ctx.Localization(p.Field) 21 if !hasColumn { 22 err = errors.Warning("sql: predicate render failed").WithCause(fmt.Errorf("%s was not found in localization", p.Field)) 23 return 24 } 25 _, _ = w.Write(bytex.FromString(column[0])) 26 _, _ = w.Write(SPACE) 27 _, _ = w.Write(bytex.FromString(p.Operator.String())) 28 _, _ = w.Write(SPACE) 29 30 switch expr := p.Expression.(type) { 31 case conditions.Literal: 32 _, _ = w.Write(bytex.FromString(expr.String())) 33 break 34 case sql.NamedArg: 35 _, _ = w.Write(AT) 36 _, _ = w.Write(bytex.FromString(expr.Name)) 37 argument = append(argument, expr) 38 break 39 case conditions.QueryExpr: 40 sub, subErr := QueryExpr{expr}.Render(ctx, w) 41 if subErr != nil { 42 err = errors.Warning("sql: predicate render failed").WithCause(subErr) 43 return 44 } 45 argument = append(argument, sub...) 46 break 47 case []any: 48 if p.Operator != conditions.BETWEEN && p.Operator != conditions.IN && p.Operator != conditions.NOTIN { 49 err = errors.Warning("sql: predicate render failed").WithCause(fmt.Errorf("%s only can has one expression", p.Field)) 50 return 51 } 52 exprLen := len(expr) 53 if exprLen == 0 { 54 err = errors.Warning("sql: predicate render failed").WithCause(fmt.Errorf("%s only can has no expression", p.Field)) 55 return 56 } 57 if exprLen == 1 { 58 queryExpr, isQueryExpr := expr[0].(QueryExpr) 59 if isQueryExpr { 60 sub, subErr := queryExpr.Render(ctx, w) 61 if subErr != nil { 62 err = errors.Warning("sql: predicate render failed").WithCause(subErr) 63 return 64 } 65 argument = append(argument, sub...) 66 break 67 } 68 } 69 70 exprs := make([][]byte, 0, len(expr)) 71 for _, e := range expr { 72 switch se := e.(type) { 73 case conditions.Literal: 74 exprs = append(exprs, bytex.FromString(se.String())) 75 break 76 case sql.NamedArg: 77 err = errors.Warning("sql: predicate render failed").WithCause(fmt.Errorf("%s only can has named arg", p.Field)) 78 return 79 case conditions.QueryExpr: 80 sbb := bytebufferpool.Get() 81 sub, subErr := QueryExpr{se}.Render(ctx, sbb) 82 if subErr != nil { 83 bytebufferpool.Put(sbb) 84 err = errors.Warning("sql: predicate render failed").WithCause(subErr) 85 return 86 } 87 subQuery := sbb.String() 88 bytebufferpool.Put(sbb) 89 if len(expr) == 1 { 90 subQuery = subQuery[strings.IndexByte(subQuery, '(')+1 : strings.LastIndexByte(subQuery, ')')] 91 } 92 exprs = append(exprs, bytex.FromString(subQuery)) 93 argument = append(argument, sub...) 94 break 95 default: 96 exprs = append(exprs, bytex.FromString(ctx.NextQueryPlaceholder())) 97 argument = append(argument, se) 98 break 99 } 100 } 101 102 _, _ = w.Write(LB) 103 _, _ = w.Write(bytes.Join(exprs, COMMA)) 104 _, _ = w.Write(RB) 105 break 106 default: 107 _, _ = w.Write(bytex.FromString(ctx.NextQueryPlaceholder())) 108 argument = append(argument, expr) 109 break 110 } 111 112 return 113 }