Rename of types and errors.
This commit is contained in:
parent
18bbf1b5fb
commit
63f2d04651
30 changed files with 142 additions and 238 deletions
10
README.md
10
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)
|
|||
<details>
|
||||
<summary>Click to see dest2 json</summary>
|
||||
|
||||
```json
|
||||
```js
|
||||
[
|
||||
{
|
||||
"CategoryID": 8,
|
||||
|
|
@ -423,7 +424,8 @@ handleError(err)
|
|||
}
|
||||
]
|
||||
},
|
||||
...
|
||||
//...
|
||||
]
|
||||
```
|
||||
</details>
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//}
|
||||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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{}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
10
table.go
10
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 {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 }")
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
8
utils.go
8
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())
|
||||
|
|
|
|||
|
|
@ -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._
|
||||
|
|
|
|||
|
|
@ -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":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue