1package exql 2 3import ( 4 "bytes" 5 "reflect" 6 "sync" 7 "text/template" 8 9 db "upper.io/db.v3" 10 "upper.io/db.v3/internal/cache" 11) 12 13// Type is the type of SQL query the statement represents. 14type Type uint 15 16// Values for Type. 17const ( 18 NoOp = Type(iota) 19 20 Truncate 21 DropTable 22 DropDatabase 23 Count 24 Insert 25 Select 26 Update 27 Delete 28 29 SQL 30) 31 32type ( 33 // Limit represents the SQL limit in a query. 34 Limit int 35 // Offset represents the SQL offset in a query. 36 Offset int 37) 38 39// Template is an SQL template. 40type Template struct { 41 AndKeyword string 42 AscKeyword string 43 AssignmentOperator string 44 ClauseGroup string 45 ClauseOperator string 46 ColumnAliasLayout string 47 ColumnSeparator string 48 ColumnValue string 49 CountLayout string 50 DeleteLayout string 51 DescKeyword string 52 DropDatabaseLayout string 53 DropTableLayout string 54 GroupByLayout string 55 IdentifierQuote string 56 IdentifierSeparator string 57 InsertLayout string 58 JoinLayout string 59 OnLayout string 60 OrKeyword string 61 OrderByLayout string 62 SelectLayout string 63 SortByColumnLayout string 64 TableAliasLayout string 65 TruncateLayout string 66 UpdateLayout string 67 UsingLayout string 68 ValueQuote string 69 ValueSeparator string 70 WhereLayout string 71 72 ComparisonOperator map[db.ComparisonOperator]string 73 74 templateMutex sync.RWMutex 75 templateMap map[string]*template.Template 76 77 *cache.Cache 78} 79 80func (layout *Template) MustCompile(templateText string, data interface{}) string { 81 var b bytes.Buffer 82 83 v, ok := layout.getTemplate(templateText) 84 if !ok || true { 85 v = template. 86 Must(template.New(""). 87 Funcs(map[string]interface{}{ 88 "defined": func(in Fragment) bool { 89 if in == nil || reflect.ValueOf(in).IsNil() { 90 return false 91 } 92 if check, ok := in.(hasIsEmpty); ok { 93 if check.IsEmpty() { 94 return false 95 } 96 } 97 return true 98 }, 99 "compile": func(in Fragment) (string, error) { 100 s, err := layout.doCompile(in) 101 if err != nil { 102 return "", err 103 } 104 return s, nil 105 }, 106 }). 107 Parse(templateText)) 108 109 layout.setTemplate(templateText, v) 110 } 111 112 if err := v.Execute(&b, data); err != nil { 113 panic("There was an error compiling the following template:\n" + templateText + "\nError was: " + err.Error()) 114 } 115 116 return b.String() 117} 118 119func (t *Template) getTemplate(k string) (*template.Template, bool) { 120 t.templateMutex.RLock() 121 defer t.templateMutex.RUnlock() 122 123 if t.templateMap == nil { 124 t.templateMap = make(map[string]*template.Template) 125 } 126 127 v, ok := t.templateMap[k] 128 return v, ok 129} 130 131func (t *Template) setTemplate(k string, v *template.Template) { 132 t.templateMutex.Lock() 133 defer t.templateMutex.Unlock() 134 135 t.templateMap[k] = v 136} 137