From 63f2d04651cd7d7acfde69dd1b56aea907d6204a Mon Sep 17 00:00:00 2001 From: go-jet Date: Mon, 8 Jul 2019 13:00:44 +0200 Subject: [PATCH] Rename of types and errors. --- README.md | 10 +++-- bool_expression_test.go | 2 +- delete_statement.go | 6 +-- delete_statement_test.go | 4 +- execution/execution.go | 26 +++++------ expression.go | 14 +++--- expression_old.go | 51 --------------------- expression_old_test.go | 76 ------------------------------- expression_table.go | 2 +- expression_test.go | 2 +- func_expression.go | 2 +- generator/postgres/templates.go | 4 +- insert_statement.go | 6 +-- insert_statement_test.go | 4 +- lock_statement.go | 4 +- operators.go | 6 +-- order_by_clause.go | 2 +- select_statement.go | 6 +-- select_statement_test.go | 2 +- set_statement.go | 8 ++-- set_statement_test.go | 2 +- table.go | 10 ++--- table_test.go | 4 +- tests/scan_test.go | 20 ++++----- tests/select_test.go | 6 +-- update_statement.go | 8 ++-- update_statement_test.go | 4 +- utils.go | 8 ++-- wiki/Expressions.md | 79 ++++++++++++++++++++++----------- wiki/Model-data.md | 2 +- 30 files changed, 142 insertions(+), 238 deletions(-) delete mode 100644 expression_old.go delete mode 100644 expression_old_test.go diff --git a/README.md b/README.md index faa41f4..e98a549 100644 --- a/README.md +++ b/README.md @@ -247,7 +247,7 @@ jsonText, _ := json.MarshalIndent(dest, "", "\t") fmt.Println(string(jsonText)) ``` -```json +```js [ { "ActorID": 1, @@ -319,7 +319,8 @@ fmt.Println(string(jsonText)) } ] }, - ...(125 more items) + //...(125 more items) +] ``` What if we also want to have list of films per category and actors per category, where films are longer than 180 minutes, film language is 'English' @@ -340,7 +341,7 @@ handleError(err)
Click to see dest2 json -```json +```js [ { "CategoryID": 8, @@ -423,7 +424,8 @@ handleError(err) } ] }, - ... + //... +] ```
diff --git a/bool_expression_test.go b/bool_expression_test.go index 804e204..dd05e94 100644 --- a/bool_expression_test.go +++ b/bool_expression_test.go @@ -5,7 +5,7 @@ import ( ) func TestBoolExpressionEQ(t *testing.T) { - assertClauseSerializeErr(t, table1ColBool.EQ(nil), "nil rhs") + assertClauseSerializeErr(t, table1ColBool.EQ(nil), "jet: nil rhs") assertClauseSerialize(t, table1ColBool.EQ(table2ColBool), "(table1.col_bool = table2.col_bool)") assertClauseSerialize(t, table1ColBool.EQ(Bool(true)), "(table1.col_bool = $1)", true) } diff --git a/delete_statement.go b/delete_statement.go index feefefc..c328953 100644 --- a/delete_statement.go +++ b/delete_statement.go @@ -39,13 +39,13 @@ func (d *deleteStatementImpl) RETURNING(projections ...projection) DeleteStateme func (d *deleteStatementImpl) serializeImpl(out *sqlBuilder) error { if d == nil { - return errors.New("delete statement is nil") + return errors.New("jet: delete statement is nil") } out.newLine() out.writeString("DELETE FROM") if d.table == nil { - return errors.New("nil tableName") + return errors.New("jet: nil tableName") } if err := d.table.serialize(delete_statement, out); err != nil { @@ -53,7 +53,7 @@ func (d *deleteStatementImpl) serializeImpl(out *sqlBuilder) error { } if d.where == nil { - return errors.New("deleting without a WHERE clause") + return errors.New("jet: deleting without a WHERE clause") } if err := out.writeWhere(delete_statement, d.where); err != nil { diff --git a/delete_statement_test.go b/delete_statement_test.go index c9f724e..6de033a 100644 --- a/delete_statement_test.go +++ b/delete_statement_test.go @@ -5,8 +5,8 @@ import ( ) func TestDeleteUnconditionally(t *testing.T) { - assertStatementErr(t, table1.DELETE(), `deleting without a WHERE clause`) - assertStatementErr(t, table1.DELETE().WHERE(nil), `deleting without a WHERE clause`) + assertStatementErr(t, table1.DELETE(), `jet: deleting without a WHERE clause`) + assertStatementErr(t, table1.DELETE().WHERE(nil), `jet: deleting without a WHERE clause`) } func TestDeleteWithWhere(t *testing.T) { diff --git a/execution/execution.go b/execution/execution.go index 751bb86..05b4325 100644 --- a/execution/execution.go +++ b/execution/execution.go @@ -17,12 +17,12 @@ import ( func Query(db DB, context context.Context, query string, args []interface{}, destinationPtr interface{}) error { if destinationPtr == nil { - return errors.New("Destination is nil. ") + return errors.New("jet: Destination is nil.") } destinationPtrType := reflect.TypeOf(destinationPtr) if destinationPtrType.Kind() != reflect.Ptr { - return errors.New("Destination has to be a pointer to slice or pointer to struct. ") + return errors.New("jet: Destination has to be a pointer to slice or pointer to struct") } if destinationPtrType.Elem().Kind() == reflect.Slice { @@ -51,22 +51,22 @@ func Query(db DB, context context.Context, query string, args []interface{}, des } return nil } else { - return errors.New("Unsupported destination type. ") + return errors.New("jet: unsupported destination type") } } func queryToSlice(db DB, ctx context.Context, query string, args []interface{}, slicePtr interface{}) error { if db == nil { - return errors.New("db is nil") + return errors.New("jet: db is nil") } if slicePtr == nil { - return errors.New("Destination is nil. ") + return errors.New("jet: Destination is nil. ") } destinationType := reflect.TypeOf(slicePtr) if destinationType.Kind() != reflect.Ptr && destinationType.Elem().Kind() != reflect.Slice { - return errors.New("Destination has to be a pointer to slice. ") + return errors.New("jet: Destination has to be a pointer to slice. ") } if ctx == nil { @@ -157,7 +157,7 @@ func mapRowToSlice(scanContext *scanContext, groupKey string, slicePtrValue refl } if sliceElemType.Kind() != reflect.Struct { - return false, errors.New("Unsupported dest type: " + structField.Name + " " + structField.Type.String()) + return false, errors.New("jet: Unsupported dest type: " + structField.Name + " " + structField.Type.String()) } structGroupKey := scanContext.getGroupKey(sliceElemType, structField) @@ -229,7 +229,7 @@ func appendElemToSlice(slicePtrValue reflect.Value, objPtrValue reflect.Value) e } if !newElemValue.Type().AssignableTo(sliceElemType) { - return fmt.Errorf("Scan: can't append %s to %s slice ", newElemValue.Type().String(), sliceValue.Type().String()) + return fmt.Errorf("jet: can't append %s to %s slice ", newElemValue.Type().String(), sliceValue.Type().String()) } sliceValue.Set(reflect.Append(sliceValue, newElemValue)) @@ -247,7 +247,7 @@ func newElemPtrValueForSlice(slicePtrValue reflect.Value) reflect.Value { func mapRowToDestinationPtr(scanContext *scanContext, groupKey string, destPtrValue reflect.Value, structField *reflect.StructField) (updated bool, err error) { if destPtrValue.Kind() != reflect.Ptr { - return false, errors.New("Internal error. ") + return false, errors.New("jet: Internal error. ") } destValueKind := destPtrValue.Elem().Kind() @@ -257,7 +257,7 @@ func mapRowToDestinationPtr(scanContext *scanContext, groupKey string, destPtrVa } else if destValueKind == reflect.Slice { return mapRowToSlice(scanContext, groupKey, destPtrValue, structField) } else { - return false, errors.New("Unsupported dest type: " + structField.Name + " " + structField.Type.String()) + return false, errors.New("jet: Unsupported dest type: " + structField.Name + " " + structField.Type.String()) } } @@ -274,7 +274,7 @@ func mapRowToDestinationValue(scanContext *scanContext, groupKey string, dest re destPtrValue = dest } } else { - return false, errors.New("Internal error. ") + return false, errors.New("jet: Internal error. ") } updated, err = mapRowToDestinationPtr(scanContext, groupKey, destPtrValue, structField) @@ -337,7 +337,7 @@ func mapRowToStruct(scanContext *scanContext, groupKey string, structPtrValue re err = setReflectValue(reflect.ValueOf(cellValue), fieldValue) if err != nil { - err = fmt.Errorf("Scan: %s, at struct field: %s %s of type %s. ", err.Error(), field.Name, field.Type.String(), structType.String()) + err = fmt.Errorf("%s, at struct field: %s %s of type %s. ", err.Error(), field.Name, field.Type.String(), structType.String()) return } } @@ -456,7 +456,7 @@ func setReflectValue(source, destination reflect.Value) error { } if !sourceElem.Type().AssignableTo(destination.Type()) { - return errors.New("can't set " + sourceElem.Type().String() + " to " + destination.Type().String()) + return errors.New("jet: can't set " + sourceElem.Type().String() + " to " + destination.Type().String()) } destination.Set(sourceElem) diff --git a/expression.go b/expression.go index 2faea0f..4b63ca3 100644 --- a/expression.go +++ b/expression.go @@ -96,13 +96,13 @@ func newBinaryExpression(lhs, rhs Expression, operator string) binaryOpExpressio func (c *binaryOpExpression) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { if c == nil { - return errors.New("binary Expression is nil") + return errors.New("jet: binary Expression is nil") } if c.lhs == nil { - return errors.New("nil lhs") + return errors.New("jet: nil lhs") } if c.rhs == nil { - return errors.New("nil rhs") + return errors.New("jet: nil rhs") } wrap := !contains(options, noWrap) @@ -145,13 +145,13 @@ func newPrefixExpression(expression Expression, operator string) prefixOpExpress func (p *prefixOpExpression) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { if p == nil { - return errors.New("Prefix Expression is nil.") + return errors.New("jet: Prefix Expression is nil.") } out.writeString(p.operator + " ") if p.expression == nil { - return errors.New("nil prefix Expression.") + return errors.New("jet: nil prefix Expression.") } if err := p.expression.serialize(statement, out); err != nil { return err @@ -177,11 +177,11 @@ func newPostfixOpExpression(expression Expression, operator string) postfixOpExp func (p *postfixOpExpression) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { if p == nil { - return errors.New("Postifx operator Expression is nil.") + return errors.New("jet: Postifx operator Expression is nil.") } if p.expression == nil { - return errors.New("nil prefix Expression.") + return errors.New("jet: nil prefix Expression.") } if err := p.expression.serialize(statement, out); err != nil { return err diff --git a/expression_old.go b/expression_old.go deleted file mode 100644 index 7e8c19c..0000000 --- a/expression_old.go +++ /dev/null @@ -1,51 +0,0 @@ -package jet - -import ( - "strconv" - "time" -) - -type intervalExpression struct { - expressionInterfaceImpl - duration time.Duration -} - -const intervalSep = ":" - -func (c *intervalExpression) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { - out.writeString("INTERVAL '") - - duration := c.duration - - if duration < 0 { - duration = -duration - out.writeString("-") - } - - hours := duration / time.Hour - minutes := (duration % time.Hour) / time.Minute - sec := (duration % time.Minute) / time.Second - msec := (duration % time.Second) / time.Microsecond - - out.writeString(strconv.FormatInt(int64(hours), 10)) - out.writeString(intervalSep) - out.writeString(strconv.FormatInt(int64(minutes), 10)) - out.writeString(intervalSep) - out.writeString(strconv.FormatInt(int64(sec), 10)) - out.writeString(intervalSep) - out.writeString(strconv.FormatInt(int64(msec), 10)) - out.writeString("' HOUR_MICROSECOND") - - return nil -} - -//// Interval returns a representation of duration -//func Interval(duration time.Duration) expressions { -// intervalExp := &intervalExpression{ -// duration: duration, -// } -// -// intervalExp.expressionInterfaceImpl.parent = intervalExp -// -// return intervalExp -//} diff --git a/expression_old_test.go b/expression_old_test.go deleted file mode 100644 index bde087b..0000000 --- a/expression_old_test.go +++ /dev/null @@ -1,76 +0,0 @@ -// +build disabled - -package jet - -import ( - "bytes" - "time" - - gc "gopkg.in/check.v1" -) - -func (s *ExprSuite) TestInterval(c *gc.C) { - testTable := []struct { - interval time.Duration - expected string - expectedErr error - }{ - { - interval: 50 * time.Microsecond, - expected: "INTERVAL '0:0:0:50' HOUR_MICROSECOND", - }, - { - interval: -50 * time.Microsecond, - expected: "INTERVAL '-0:0:0:50' HOUR_MICROSECOND", - }, - { - interval: 50*time.Microsecond + 50*time.Second, - expected: "INTERVAL '0:0:50:50' HOUR_MICROSECOND", - }, - { - interval: 50*time.Microsecond + - 50*time.Second + - 50*time.Minute, - expected: "INTERVAL '0:50:50:50' HOUR_MICROSECOND", - }, - { - interval: 50*time.Microsecond + - 50*time.Second + - 50*time.Minute + - 50*time.Hour, - expected: "INTERVAL '50:50:50:50' HOUR_MICROSECOND", - }, - { - interval: 50 * time.Hour, - expected: "INTERVAL '50:0:0:0' HOUR_MICROSECOND", - }, - { - interval: 50*time.Hour + 50*time.Minute, - expected: "INTERVAL '50:50:0:0' HOUR_MICROSECOND", - }, - { - interval: 50*time.Hour + 50*time.Minute + 50*time.Second, - expected: "INTERVAL '50:50:50:0' HOUR_MICROSECOND", - }, - { - interval: 0, - expected: "INTERVAL '0:0:0:0' HOUR_MICROSECOND", - }, - { - interval: 50 * time.Nanosecond, - expected: "INTERVAL '0:0:0:0' HOUR_MICROSECOND", - }, - } - buf := &bytes.Buffer{} - - for i, tt := range testTable { - buf.Reset() - err := Interval(tt.interval).Serialize(buf) - c.Assert(err, gc.Equals, tt.expectedErr, - gc.Commentf("experiment #%d", i)) - if err == nil { - c.Assert(buf.String(), gc.Equals, tt.expected, - gc.Commentf("experiment #%d", i)) - } - } -} diff --git a/expression_table.go b/expression_table.go index 3e62d3f..e443660 100644 --- a/expression_table.go +++ b/expression_table.go @@ -46,7 +46,7 @@ func (e *expressionTableImpl) AllColumns() ProjectionList { func (e *expressionTableImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { if e == nil { - return errors.New("Expression table is nil. ") + return errors.New("jet: Expression table is nil. ") } err := e.expression.serialize(statement, out) diff --git a/expression_test.go b/expression_test.go index 9e24bf1..da0e033 100644 --- a/expression_test.go +++ b/expression_test.go @@ -7,7 +7,7 @@ import ( func TestExpressionIS_NULL(t *testing.T) { assertClauseSerialize(t, table2Col3.IS_NULL(), "table2.col3 IS NULL") assertClauseSerialize(t, table2Col3.ADD(table2Col3).IS_NULL(), "(table2.col3 + table2.col3) IS NULL") - assertClauseSerializeErr(t, table2Col3.ADD(nil), "nil rhs") + assertClauseSerializeErr(t, table2Col3.ADD(nil), "jet: nil rhs") } func TestExpressionIS_NOT_NULL(t *testing.T) { diff --git a/func_expression.go b/func_expression.go index d3264b1..447d249 100644 --- a/func_expression.go +++ b/func_expression.go @@ -27,7 +27,7 @@ func newFunc(name string, expressions []Expression, parent Expression) *funcExpr func (f *funcExpressionImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { if f == nil { - return errors.New("Function expressions is nil. ") + return errors.New("jet: Function expressions is nil. ") } addBrackets := !f.noBrackets || len(f.expressions) > 0 diff --git a/generator/postgres/templates.go b/generator/postgres/templates.go index c49e1fc..33fab25 100644 --- a/generator/postgres/templates.go +++ b/generator/postgres/templates.go @@ -103,7 +103,7 @@ const ( func (e *{{ToGoIdentifier $.Name}}) Scan(value interface{}) error { if v, ok := value.(string); !ok { - return errors.New("Invalid data for {{ToGoIdentifier $.Name}} enum") + return errors.New("jet: Invalid data for {{ToGoIdentifier $.Name}} enum") } else { switch string(v) { {{- range $index, $element := .Values}} @@ -111,7 +111,7 @@ func (e *{{ToGoIdentifier $.Name}}) Scan(value interface{}) error { *e = {{ToGoIdentifier $.Name}}_{{ToGoIdentifier $element}} {{- end}} default: - return errors.New("Inavlid data " + string(v) + "for {{ToGoIdentifier $.Name}} enum") + return errors.New("jet: Inavlid data " + string(v) + "for {{ToGoIdentifier $.Name}} enum") } return nil diff --git a/insert_statement.go b/insert_statement.go index fe23daf..1bb7d76 100644 --- a/insert_statement.go +++ b/insert_statement.go @@ -82,7 +82,7 @@ func (i *insertStatementImpl) Sql() (sql string, args []interface{}, err error) queryData.writeString("INSERT INTO") if isNil(i.table) { - return "", nil, errors.New("table is nil") + return "", nil, errors.New("jet: table is nil") } err = i.table.serialize(insert_statement, queryData) @@ -104,11 +104,11 @@ func (i *insertStatementImpl) Sql() (sql string, args []interface{}, err error) } if len(i.rows) == 0 && i.query == nil { - return "", nil, errors.New("no row values or query specified") + return "", nil, errors.New("jet: no row values or query specified") } if len(i.rows) > 0 && i.query != nil { - return "", nil, errors.New("only row values or query has to be specified") + return "", nil, errors.New("jet: only row values or query has to be specified") } if len(i.rows) > 0 { diff --git a/insert_statement_test.go b/insert_statement_test.go index 9e956d0..71bb398 100644 --- a/insert_statement_test.go +++ b/insert_statement_test.go @@ -7,8 +7,8 @@ import ( ) func TestInvalidInsert(t *testing.T) { - assertStatementErr(t, table1.INSERT(table1Col1), "no row values or query specified") - assertStatementErr(t, table1.INSERT(nil).VALUES(1), "nil column in columns list") + assertStatementErr(t, table1.INSERT(table1Col1), "jet: no row values or query specified") + assertStatementErr(t, table1.INSERT(nil).VALUES(1), "jet: nil column in columns list") } func TestInsertNilValue(t *testing.T) { diff --git a/lock_statement.go b/lock_statement.go index a5e9424..40aca9d 100644 --- a/lock_statement.go +++ b/lock_statement.go @@ -55,11 +55,11 @@ func (l *lockStatementImpl) DebugSql() (query string, err error) { func (l *lockStatementImpl) Sql() (query string, args []interface{}, err error) { if l == nil { - return "", nil, errors.New("nil Statement.") + return "", nil, errors.New("jet: nil Statement.") } if len(l.tables) == 0 { - return "", nil, errors.New("There is no table selected to be locked. ") + return "", nil, errors.New("jet: There is no table selected to be locked. ") } out := &sqlBuilder{} diff --git a/operators.go b/operators.go index c1b567c..9a3dcb3 100644 --- a/operators.go +++ b/operators.go @@ -102,7 +102,7 @@ func (c *caseOperatorImpl) ELSE(els Expression) CaseOperatorExpression { func (c *caseOperatorImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { if c == nil { - return errors.New("Case Expression is nil. ") + return errors.New("jet: Case Expression is nil. ") } out.writeString("(CASE") @@ -116,11 +116,11 @@ func (c *caseOperatorImpl) serialize(statement statementType, out *sqlBuilder, o } if len(c.when) == 0 || len(c.then) == 0 { - return errors.New("Invalid case Statement. There should be at least one when/then Expression pair. ") + return errors.New("jet: Invalid case Statement. There should be at least one when/then Expression pair. ") } if len(c.when) != len(c.then) { - return errors.New("When and then Expression count mismatch. ") + return errors.New("jet: When and then Expression count mismatch. ") } for i, when := range c.when { diff --git a/order_by_clause.go b/order_by_clause.go index 2184dae..51d9b3b 100644 --- a/order_by_clause.go +++ b/order_by_clause.go @@ -13,7 +13,7 @@ type orderByClauseImpl struct { func (o *orderByClauseImpl) serializeForOrderBy(statement statementType, out *sqlBuilder) error { if o.expression == nil { - return errors.New("nil orderBy by clause.") + return errors.New("jet: nil orderBy by clause.") } if err := o.expression.serializeForOrderBy(statement, out); err != nil { diff --git a/select_statement.go b/select_statement.go index 5207d19..cd39bdd 100644 --- a/select_statement.go +++ b/select_statement.go @@ -155,7 +155,7 @@ func (s *selectStatementImpl) projections() []projection { func (s *selectStatementImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { if s == nil { - return errors.New("Select expression is nil. ") + return errors.New("jet: Select expression is nil. ") } out.writeString("(") @@ -175,7 +175,7 @@ func (s *selectStatementImpl) serialize(statement statementType, out *sqlBuilder func (s *selectStatementImpl) serializeImpl(out *sqlBuilder) error { if s == nil { - return errors.New("Select expression is nil. ") + return errors.New("jet: Select expression is nil. ") } out.newLine() @@ -186,7 +186,7 @@ func (s *selectStatementImpl) serializeImpl(out *sqlBuilder) error { } if len(s.projectionList) == 0 { - return errors.New("no column selected for projection") + return errors.New("jet: no column selected for projection") } err := out.writeProjections(select_statement, s.projectionList) diff --git a/select_statement_test.go b/select_statement_test.go index f726376..50cfc00 100644 --- a/select_statement_test.go +++ b/select_statement_test.go @@ -3,7 +3,7 @@ package jet import "testing" func TestInvalidSelect(t *testing.T) { - assertStatementErr(t, SELECT(nil), "projection is nil") + assertStatementErr(t, SELECT(nil), "jet: projection is nil") } func TestSelectColumnList(t *testing.T) { diff --git a/set_statement.go b/set_statement.go index 0eea405..20c9bf4 100644 --- a/set_statement.go +++ b/set_statement.go @@ -71,7 +71,7 @@ func (s *setStatementImpl) projections() []projection { func (s *setStatementImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { if s == nil { - return errors.New("Set expression is nil. ") + return errors.New("jet: Set expression is nil. ") } wrap := s.orderBy != nil || s.limit >= 0 || s.offset >= 0 @@ -98,11 +98,11 @@ func (s *setStatementImpl) serialize(statement statementType, out *sqlBuilder, o func (s *setStatementImpl) serializeImpl(out *sqlBuilder) error { if s == nil { - return errors.New("Set expression is nil. ") + return errors.New("jet: Set expression is nil. ") } if len(s.selects) < 2 { - return errors.New("UNION Statement must have at least two SELECT statements.") + return errors.New("jet: UNION Statement must have at least two SELECT statements.") } out.newLine() @@ -121,7 +121,7 @@ func (s *setStatementImpl) serializeImpl(out *sqlBuilder) error { } if selectStmt == nil { - return errors.New("select statement is nil") + return errors.New("jet: select statement is nil") } err := selectStmt.serialize(set_statement, out) diff --git a/set_statement_test.go b/set_statement_test.go index 9741c14..8e9d3bb 100644 --- a/set_statement_test.go +++ b/set_statement_test.go @@ -37,7 +37,7 @@ func TestUnionNilSelect(t *testing.T) { SELECT(table1Col1). UNION(nil) - assertStatementErr(t, unionStmt, "select statement is nil") + assertStatementErr(t, unionStmt, "jet: select statement is nil") } func TestUnionThreeSelect1(t *testing.T) { diff --git a/table.go b/table.go index 7624a71..2a1b9fb 100644 --- a/table.go +++ b/table.go @@ -170,7 +170,7 @@ func (t *tableImpl) columns() []column { func (t *tableImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { if t == nil { - return errors.New("tableImpl is nil. ") + return errors.New("jet: tableImpl is nil. ") } out.writeIdentifier(t.schemaName) @@ -237,11 +237,11 @@ func (t *joinTable) columns() []column { func (t *joinTable) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) (err error) { if t == nil { - return errors.New("Join table is nil. ") + return errors.New("jet: Join table is nil. ") } if isNil(t.lhs) { - return errors.New("left hand side of join operation is nil table") + return errors.New("jet: left hand side of join operation is nil table") } if err = t.lhs.serialize(statement, out); err != nil { @@ -264,7 +264,7 @@ func (t *joinTable) serialize(statement statementType, out *sqlBuilder, options } if isNil(t.rhs) { - return errors.New("right hand side of join operation is nil table") + return errors.New("jet: right hand side of join operation is nil table") } if err = t.rhs.serialize(statement, out); err != nil { @@ -272,7 +272,7 @@ func (t *joinTable) serialize(statement statementType, out *sqlBuilder, options } if t.onCondition == nil && t.join_type != crossJoin { - return errors.New("join condition is nil") + return errors.New("jet: join condition is nil") } if t.onCondition != nil { diff --git a/table_test.go b/table_test.go index d22f39d..9a90da6 100644 --- a/table_test.go +++ b/table_test.go @@ -6,9 +6,9 @@ import ( func TestJoinNilInputs(t *testing.T) { assertClauseSerializeErr(t, table2.INNER_JOIN(nil, table1ColBool.EQ(table2ColBool)), - "right hand side of join operation is nil table") + "jet: right hand side of join operation is nil table") assertClauseSerializeErr(t, table2.INNER_JOIN(table1, nil), - "join condition is nil") + "jet: join condition is nil") } func TestINNER_JOIN(t *testing.T) { diff --git a/tests/scan_test.go b/tests/scan_test.go index 631c093..da78fe8 100644 --- a/tests/scan_test.go +++ b/tests/scan_test.go @@ -21,31 +21,31 @@ func TestScanToInvalidDestination(t *testing.T) { t.Run("nil dest", func(t *testing.T) { err := query.Query(db, nil) - assert.Error(t, err, "Destination is nil. ") + assert.Error(t, err, "jet: Destination is nil.") }) t.Run("struct dest", func(t *testing.T) { err := query.Query(db, struct{}{}) - assert.Error(t, err, "Destination has to be a pointer to slice or pointer to struct. ") + assert.Error(t, err, "jet: Destination has to be a pointer to slice or pointer to struct") }) t.Run("slice dest", func(t *testing.T) { err := query.Query(db, []struct{}{}) - assert.Error(t, err, "Destination has to be a pointer to slice or pointer to struct. ") + assert.Error(t, err, "jet: Destination has to be a pointer to slice or pointer to struct") }) t.Run("slice of pointers to pointer dest", func(t *testing.T) { err := query.Query(db, []**struct{}{}) - assert.Error(t, err, "Destination has to be a pointer to slice or pointer to struct. ") + assert.Error(t, err, "jet: Destination has to be a pointer to slice or pointer to struct") }) t.Run("map dest", func(t *testing.T) { err := query.Query(db, []map[string]string{}) - assert.Error(t, err, "Destination has to be a pointer to slice or pointer to struct. ") + assert.Error(t, err, "jet: Destination has to be a pointer to slice or pointer to struct") }) } @@ -129,7 +129,7 @@ func TestScanToStruct(t *testing.T) { err := query.Query(db, &dest) - assert.Error(t, err, "Unsupported dest type: Inventory **model.Inventory") + assert.Error(t, err, "jet: Unsupported dest type: Inventory **model.Inventory") }) t.Run("invalid dest 2", func(t *testing.T) { @@ -139,7 +139,7 @@ func TestScanToStruct(t *testing.T) { err := query.Query(db, &dest) - assert.Error(t, err, "Unsupported dest type: Inventory ***model.Inventory") + assert.Error(t, err, "jet: Unsupported dest type: Inventory ***model.Inventory") }) t.Run("custom struct", func(t *testing.T) { @@ -170,7 +170,7 @@ func TestScanToStruct(t *testing.T) { err := query.Query(db, &dest) - assert.Error(t, err, `Scan: can't set int32 to int, at struct field: InventoryID int of type tests.Inventory. `) + assert.Error(t, err, `jet: can't set int32 to int, at struct field: InventoryID int of type tests.Inventory. `) fmt.Println(err) }) @@ -431,7 +431,7 @@ func TestScanToSlice(t *testing.T) { var dest []int err := query.Query(db, &dest) - assert.Error(t, err, `Scan: can't append int32 to []int slice `) + assert.Error(t, err, `jet: can't append int32 to []int slice `) }) }) @@ -678,7 +678,7 @@ func TestScanToSlice(t *testing.T) { err := query.Query(db, &dest) - assert.Error(t, err, "Unsupported dest type: Cities []**struct { *model.City }") + assert.Error(t, err, "jet: Unsupported dest type: Cities []**struct { *model.City }") }) } diff --git a/tests/select_test.go b/tests/select_test.go index 5d2148f..3cafc03 100644 --- a/tests/select_test.go +++ b/tests/select_test.go @@ -861,14 +861,14 @@ FROM dvds.film WHERE film.rental_rate = ( SELECT MAX(film.rental_rate) FROM dvds.film - )::double precision + ) ORDER BY film.film_id ASC; ` - maxFilmRentalRate := CAST( + maxFilmRentalRate := FloatExp( Film. SELECT(MAXf(Film.RentalRate)), - ).AS_DOUBLE() + ) query := Film. SELECT(Film.AllColumns). diff --git a/update_statement.go b/update_statement.go index 3d1774a..1f342ca 100644 --- a/update_statement.go +++ b/update_statement.go @@ -62,7 +62,7 @@ func (u *updateStatementImpl) Sql() (sql string, args []interface{}, err error) out.writeString("UPDATE") if isNil(u.table) { - return "", nil, errors.New("table to update is nil") + return "", nil, errors.New("jet: table to update is nil") } if err = u.table.serialize(update_statement, out); err != nil { @@ -70,11 +70,11 @@ func (u *updateStatementImpl) Sql() (sql string, args []interface{}, err error) } if len(u.columns) == 0 { - return "", nil, errors.New("no columns selected") + return "", nil, errors.New("jet: no columns selected") } if len(u.row) == 0 { - return "", nil, errors.New("no values to updated") + return "", nil, errors.New("jet: no values to updated") } out.newLine() @@ -111,7 +111,7 @@ func (u *updateStatementImpl) Sql() (sql string, args []interface{}, err error) } if u.where == nil { - return "", nil, errors.New("WHERE clause not set") + return "", nil, errors.New("jet: WHERE clause not set") } if err = out.writeWhere(update_statement, u.where); err != nil { diff --git a/update_statement_test.go b/update_statement_test.go index ae5edf9..9b08675 100644 --- a/update_statement_test.go +++ b/update_statement_test.go @@ -71,6 +71,6 @@ RETURNING table1.col1 AS "table1.col1"; } func TestInvalidInputs(t *testing.T) { - assertStatementErr(t, table1.UPDATE(table1ColInt).SET(1, 2), "WHERE clause not set") - assertStatementErr(t, table1.UPDATE(nil).SET(1, 2), "nil column in columns list") + assertStatementErr(t, table1.UPDATE(table1ColInt).SET(1, 2), "jet: WHERE clause not set") + assertStatementErr(t, table1.UPDATE(nil).SET(1, 2), "jet: nil column in columns list") } diff --git a/utils.go b/utils.go index 725a9d2..b7c6299 100644 --- a/utils.go +++ b/utils.go @@ -32,7 +32,7 @@ func serializeGroupByClauseList(statement statementType, clauses []groupByClause } if c == nil { - return errors.New("nil clause.") + return errors.New("jet: nil clause.") } if err = c.serializeForGroupBy(statement, out); err != nil { @@ -51,7 +51,7 @@ func serializeClauseList(statement statementType, clauses []clause, out *sqlBuil } if c == nil { - return errors.New("nil clause.") + return errors.New("jet: nil clause.") } if err = c.serialize(statement, out); err != nil { @@ -87,7 +87,7 @@ func serializeProjectionList(statement statementType, projections []projection, } if col == nil { - return errors.New("projection is nil") + return errors.New("jet: projection is nil") } if err := col.serializeForProjection(statement, out); err != nil { @@ -105,7 +105,7 @@ func serializeColumnNames(columns []column, out *sqlBuilder) error { } if col == nil { - return errors.New("nil column in columns list") + return errors.New("jet: nil column in columns list") } out.writeString(col.Name()) diff --git a/wiki/Expressions.md b/wiki/Expressions.md index 2fe97b8..172110d 100644 --- a/wiki/Expressions.md +++ b/wiki/Expressions.md @@ -13,7 +13,7 @@ Jet sql builder supports following expression types: _This list might be extended with feature Jet releases._ -### Literal type +### Literal Types For every expression type there is a method to create one expression literal type . Literal type examples: @@ -32,7 +32,7 @@ jet.NULL jet.STAR (alias for *) ``` -### Column types +### Column Types Every sql builder table column belongs to one expression type. There are following column types: ``` jet.ColumnBool @@ -62,7 +62,7 @@ jet.Int(11).LIKE(jet.Float(22.2)) // integer expressions doesn't have LIKE ``` -## Comparision operators +## Comparision Operators Jet supports following comparison operators for all expression types: @@ -80,7 +80,7 @@ Jet supports following comparison operators for all expression types: *Left-hand side and right-hand side of operators have to be of the same type* -## Arithmetic operators +## Arithmetic Operators Following arithmetic operators are supported for integer and float expressions. If the first argument is float expression, second argument can be integer or float expression. @@ -96,7 +96,7 @@ If the first argument is integer expression second argument can only be integer | POW | jet.Float(10.01).POW(table.Film.Length) | 10.01 ^ film.length | -## Bit operators +## Bit Operators Following operators are only available on integer expressions: @@ -110,7 +110,7 @@ Following operators are only available on integer expressions: | BIT_SHIFT_RIGHT | jet.Int(11).BIT_SHIFT_RIGHT(table.Film.Length) | 11 >> film.length | -## Logical operators +## Logical Operators Following operators are only available on boolean expressions: @@ -124,7 +124,7 @@ Following operators are only available on boolean expressions: | IS_NOT_UNKNOWN | table.Staff.Active.IS_NOT_UNKNOWN() | staff.active IS NOT UNKNOWN | -## String operators +## String Operators Following operators are only available on string expressions: @@ -137,27 +137,56 @@ Following operators are only available on string expressions: | NOT_SIMILAR_TO | table.Film.Name.NOT_SIMILAR_TO(String("%Wind%")) | staff.active NOT SIMILAR TO %Wind% | -## SQL Cast operators +## SQL Cast Operators Cast operators allow expressions to be casted to some other database type. SQL builder expression type changes accordingly to database type. -| Method | Example | Generated sql | -| ------------------------------ | -------------------------------------------|---------------------------- | -| TO_BOOL | table.Film.Description.TO_BOOL() | film.description::boolean | -| TO_SMALLINT | table.Film.Description.TO_SMALLINT() | film.description::smallint | -| TO_INTEGER | table.Film.Description.TO_INTEGER() | film.description::integer | -| TO_BIGINT | table.Film.Description.TO_BIGINT() | film.description::bigint | -| TO_NUMERIC | table.Film.Description.TO_NUMERIC(10, 6) | film.description::numeric(10,6) | -| TO_REAL | table.Film.Description.TO_REAL() | film.description::real | -| TO_DOUBLE | table.Film.Description.TO_DOUBLE() | film.description::double | -| TO_TEXT | table.Film.Description.TO_TEXT() | film.description::text | -| TO_DATE | table.Film.Description.TO_DATE() | film.description::date | -| TO_TIME | table.Film.Description.TO_TIME() | film.description::time | -| TO_TIMEZ | table.Film.Description.TO_TIMEZ() | film.description::timez | -| TO_TIMESTAMP | table.Film.Description.TO_TIMESTAMP() | film.description::timestamp | -| TO_TIMESTAMPZ | table.Film.Description.TO_TIMESTAMPZ() | film.description::timestampz | +| Method | Example | Generated sql | +| ------------------------------ | ----------------------------------------------- | --------------------------------------------- | +| CAST(exp).AS_BOOL() | CAST(table.Film.Description).AS_BOOL() | film.description::boolean | +| CAST(exp).AS_SMALLINT() | CAST(table.Film.Description).AS_SMALLINT() | film.description::smallint | +| CAST(exp).AS_INTEGER() | CAST(table.Film.Description).AS_INTEGER() | film.description::integer | +| CAST(exp).AS_BIGINT() | CAST(table.Film.Description).AS_BIGINT() | film.description::bigint | +| CAST(exp).AS_NUMERIC() | CAST(table.Film.Description).AS_NUMERIC(10, 6) | film.description::numeric(10,6) | +| CAST(exp).AS_REAL() | CAST(table.Film.Description).AS_REAL() | film.description::real | +| CAST(exp).AS_DOUBLE() | CAST(table.Film.Description).AS_DOUBLE() | film.description::double | +| CAST(exp).AS_TEXT() | CAST(table.Film.Description).AS_TEXT() | film.description::text | +| CAST(exp).AS_DATE() | CAST(table.Film.Description).AS_DATE() | film.description::date | +| CAST(exp).AS_TIME() | CAST(table.Film.Description).AS_TIME() | film.description::time without time zone | +| CAST(exp).AS_TIMEZ() | CAST(table.Film.Description).AS_TIMEZ() | film.description::time with time zone | +| CAST(exp).AS_TIMESTAMP() | CAST(table.Film.Description).AS_TIMESTAMP() | film.description::timestamp without time zone | +| CAST(exp).AS_TIMESTAMPZ() | CAST(table.Film.Description).AS_TIMESTAMPZ() | film.description::timestamp with time zone | -## SQL builder cast +## SQL Builder Cast Wrapper -TODO: +For some expressions sql builder can't deduce expression type directly. For instance scalar sub-query: +``` + ( SELECT(MAXf(Film.RentalRate)). + FROM(Film) ).LT(Float(11.1)) +``` +This expression would not compile, because sub-query, although calculates one scalar float value, it is not a float expression. +To fix this sub-query can be cast to some float type, or just wrapped as float expression: +``` + FloatExp( SELECT(MAXf(Film.RentalRate)). + FROM(Film) ).LT(Float(11.1)) +``` +There are wrappers for all supported types: +``` + - BoolExp(exp) + - IntExp(exp) + - FloatExp(exp) + - StringExp(exp) + - DateExp(exp) + - TimeExp(exp) + - TimezExp(exp) + - TimestampExp(exp) + - TimestampzExp(exp) +``` +**Cast wrapper does NOT inject cast operator to generated SQL.** + +## RAW Operator +There is a RAW operator expression, that accepts raw sql as a string. It can be used for any unsupported functions, operators or expressions. +For example: + +```RAW("current_database()")``` _can be cast or wrapped, as needed._ diff --git a/wiki/Model-data.md b/wiki/Model-data.md index c20a650..8414a6d 100644 --- a/wiki/Model-data.md +++ b/wiki/Model-data.md @@ -113,7 +113,7 @@ const ( func (e *MpaaRating) Scan(value interface{}) error { if v, ok := value.(string); !ok { - return errors.New("Invalid data for MpaaRating enum") + return errors.New("jet: Invalid data for MpaaRating enum") } else { switch string(v) { case "G":