Skip to content
This repository was archived by the owner on Feb 21, 2024. It is now read-only.

Commit bc07fb4

Browse files
authored
SQL3 Test Coverage: complete coerceValue coverage (#2343)
* complete coereceVal test coverage * sql between test * optimized between operator * basic operator test
1 parent dd90838 commit bc07fb4

8 files changed

Lines changed: 287 additions & 28 deletions

File tree

sql3/planner/expression.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ func coerceValue(sourceType parser.ExprDataType, targetType parser.ExprDataType,
9191
}
9292
if tm, err := time.ParseInLocation(time.RFC3339Nano, val, time.UTC); err == nil {
9393
return tm, nil
94-
} else if tm, err := time.ParseInLocation(time.RFC3339, val, time.UTC); err == nil {
95-
return tm, nil
9694
} else if tm, err := time.ParseInLocation("2006-01-02", val, time.UTC); err == nil {
9795
return tm, nil
9896
} else {
@@ -2983,8 +2981,6 @@ func wildCardToRegexp(pattern string) string {
29832981
func timestampFromString(s string) (time.Time, error) {
29842982
if tm, err := time.ParseInLocation(time.RFC3339Nano, s, time.UTC); err == nil {
29852983
return tm, nil
2986-
} else if tm, err := time.ParseInLocation(time.RFC3339, s, time.UTC); err == nil {
2987-
return tm, nil
29882984
} else if tm, err := time.ParseInLocation("2006-01-02", s, time.UTC); err == nil {
29892985
return tm, nil
29902986
}

sql3/planner/expression_it_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@ import (
1010
)
1111

1212
func TestExpressions(t *testing.T) {
13-
1413
t.Run("StringerTest", func(t *testing.T) {
15-
1614
uop := newUnaryOpPlanExpression(parser.PLUS, newIntLiteralPlanExpression(10), parser.NewDataTypeInt())
1715
assert.Equal(t, uop.String(), "+10")
1816

17+
uop1 := newUnaryOpPlanExpression(parser.PLUS, newIntLiteralPlanExpression(10), parser.NewDataTypeID())
18+
assert.Equal(t, uop1.String(), "+10")
19+
20+
uop2 := newUnaryOpPlanExpression(parser.MINUS, newIntLiteralPlanExpression(10), parser.NewDataTypeID())
21+
assert.Equal(t, uop2.String(), "-10")
22+
1923
bop := newBinOpPlanExpression(newIntLiteralPlanExpression(10), parser.PLUS, newIntLiteralPlanExpression(20), parser.NewDataTypeInt())
2024
assert.Equal(t, bop.String(), "10+20")
2125

@@ -78,7 +82,5 @@ func TestExpressions(t *testing.T) {
7882

7983
tplop := newExprTupleLiteralPlanExpression([]types.PlanExpression{newStringLiteralPlanExpression("foo"), newStringLiteralPlanExpression("bar")}, parser.NewDataTypeString())
8084
assert.Equal(t, tplop.String(), "{'foo', 'bar'}")
81-
8285
})
83-
8486
}

sql3/planner/expression_test.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
// Copyright 2022 Molecula Corp. All rights reserved.
2+
3+
package planner
4+
5+
import (
6+
"math"
7+
"reflect"
8+
"testing"
9+
"time"
10+
11+
"github.com/featurebasedb/featurebase/v3/pql"
12+
"github.com/featurebasedb/featurebase/v3/sql3/parser"
13+
)
14+
15+
func Test_coerceValue(t *testing.T) {
16+
type args struct {
17+
sourceType parser.ExprDataType
18+
targetType parser.ExprDataType
19+
value interface{}
20+
atPos parser.Pos
21+
}
22+
tests := []struct {
23+
name string
24+
args args
25+
want interface{}
26+
wantErr bool
27+
}{
28+
{
29+
name: "int-int",
30+
args: args{sourceType: &parser.DataTypeInt{}, targetType: &parser.DataTypeInt{}, value: 1, atPos: parser.Pos{}},
31+
want: 1,
32+
wantErr: false,
33+
}, {
34+
name: "int-id",
35+
args: args{sourceType: &parser.DataTypeInt{}, targetType: &parser.DataTypeID{}, value: int64(42), atPos: parser.Pos{}},
36+
want: int64(42),
37+
wantErr: false,
38+
}, {
39+
name: "int-decimal",
40+
args: args{sourceType: &parser.DataTypeInt{}, targetType: &parser.DataTypeDecimal{Scale: 2}, value: int64(1), atPos: parser.Pos{}},
41+
want: pql.NewDecimal(int64(math.Pow(10, float64(2))), 2),
42+
wantErr: false,
43+
}, {
44+
name: "int-timestamp",
45+
args: args{sourceType: &parser.DataTypeInt{}, targetType: &parser.DataTypeTimestamp{}, value: int64(1679499982), atPos: parser.Pos{}},
46+
want: time.Unix(1679499982, 0).UTC(),
47+
wantErr: false,
48+
}, {
49+
name: "ID-int",
50+
args: args{sourceType: &parser.DataTypeID{}, targetType: &parser.DataTypeInt{}, value: int64(42), atPos: parser.Pos{}},
51+
want: int64(42),
52+
wantErr: false,
53+
}, {
54+
name: "ID-decimal",
55+
args: args{sourceType: &parser.DataTypeID{}, targetType: &parser.DataTypeDecimal{Scale: 2}, value: int64(1), atPos: parser.Pos{}},
56+
want: pql.NewDecimal(int64(math.Pow(10, float64(2))), 2),
57+
wantErr: false,
58+
}, {
59+
name: "ID-timestamp",
60+
args: args{sourceType: &parser.DataTypeID{}, targetType: &parser.DataTypeTimestamp{}, value: int64(1679499982), atPos: parser.Pos{}},
61+
want: time.Unix(1679499982, 0).UTC(),
62+
wantErr: false,
63+
}, {
64+
name: "ID-ID",
65+
args: args{sourceType: &parser.DataTypeID{}, targetType: &parser.DataTypeID{}, value: 0, atPos: parser.Pos{}},
66+
want: 0,
67+
wantErr: false,
68+
}, {
69+
name: "decimal-decimal",
70+
args: args{sourceType: &parser.DataTypeDecimal{}, targetType: &parser.DataTypeDecimal{}, value: 0, atPos: parser.Pos{}},
71+
want: 0,
72+
wantErr: false,
73+
}, {
74+
name: "string-string",
75+
args: args{sourceType: &parser.DataTypeString{}, targetType: &parser.DataTypeString{}, value: "hello", atPos: parser.Pos{}},
76+
want: "hello",
77+
wantErr: false,
78+
}, {
79+
name: "string-timestamp",
80+
args: args{sourceType: &parser.DataTypeString{}, targetType: &parser.DataTypeTimestamp{}, value: "2022-03-24", atPos: parser.Pos{}},
81+
want: func() time.Time { tm, _ := time.ParseInLocation("2006-01-02", "2022-03-24", time.UTC); return tm }(),
82+
wantErr: false,
83+
}, {
84+
name: "timestamp-timestamp",
85+
args: args{sourceType: &parser.DataTypeTimestamp{}, targetType: &parser.DataTypeTimestamp{}, value: 0, atPos: parser.Pos{}},
86+
want: 0,
87+
wantErr: false,
88+
}, {
89+
name: "idset-idset",
90+
args: args{sourceType: &parser.DataTypeIDSet{}, targetType: &parser.DataTypeIDSet{}, value: 0, atPos: parser.Pos{}},
91+
want: 0,
92+
wantErr: false,
93+
}, {
94+
name: "idset-quantum",
95+
args: args{sourceType: &parser.DataTypeIDSet{}, targetType: &parser.DataTypeIDSetQuantum{}, value: 10, atPos: parser.Pos{}},
96+
want: []interface{}{nil, 10},
97+
wantErr: false,
98+
}, {
99+
name: "stringset-idset",
100+
args: args{sourceType: &parser.DataTypeStringSet{}, targetType: &parser.DataTypeStringSet{}, value: 0, atPos: parser.Pos{}},
101+
want: 0,
102+
wantErr: false,
103+
}, {
104+
name: "stringset-quantum",
105+
args: args{sourceType: &parser.DataTypeStringSet{}, targetType: &parser.DataTypeStringSetQuantum{}, value: "YMD", atPos: parser.Pos{}},
106+
want: []interface{}{nil, "YMD"},
107+
wantErr: false,
108+
}, {
109+
name: "tuple-stringsetquantum",
110+
args: args{sourceType: &parser.DataTypeTuple{}, targetType: &parser.DataTypeStringSetQuantum{}, value: 0, atPos: parser.Pos{}},
111+
want: 0,
112+
wantErr: false,
113+
}, {
114+
name: "tuple-idsetquantum",
115+
args: args{sourceType: &parser.DataTypeTuple{}, targetType: &parser.DataTypeIDSetQuantum{}, value: 0, atPos: parser.Pos{}},
116+
want: 0,
117+
wantErr: false,
118+
},
119+
}
120+
for _, tt := range tests {
121+
t.Run(tt.name, func(t *testing.T) {
122+
got, err := coerceValue(tt.args.sourceType, tt.args.targetType, tt.args.value, tt.args.atPos)
123+
if (err != nil) != tt.wantErr {
124+
t.Errorf("coerceValue() error = %v, wantErr %v", err, tt.wantErr)
125+
return
126+
}
127+
if !reflect.DeepEqual(got, tt.want) {
128+
t.Errorf("coerceValue() = %v, want %v", got, tt.want)
129+
}
130+
})
131+
}
132+
}

sql3/planner/expressionpql.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,33 @@ func (p *ExecutionPlanner) generatePQLCallFromExpr(ctx context.Context, expr typ
232232
call.Children = append(call.Children, rc)
233233
}
234234
return call, nil
235-
235+
case *betweenOpPlanExpression:
236+
lhs, ok := expr.lhs.(*qualifiedRefPlanExpression)
237+
if !ok {
238+
return nil, sql3.NewErrInternalf("expected expression type: planner.qualifiedRefPlanExpression got:%T", expr.lhs)
239+
}
240+
rexp, ok := expr.rhs.(*rangePlanExpression)
241+
if !ok {
242+
return nil, sql3.NewErrInternalf("expected expression type: planner.rangePlanExpression got:%T", expr.rhs)
243+
}
244+
lower, err := planExprToValue(rexp.lhs)
245+
if err != nil {
246+
return nil, err
247+
}
248+
upper, err := planExprToValue(rexp.rhs)
249+
if err != nil {
250+
return nil, err
251+
}
252+
call := &pql.Call{
253+
Name: "Row",
254+
Args: map[string]interface{}{
255+
lhs.columnName: &pql.Condition{
256+
Op: pql.BETWEEN,
257+
Value: []interface{}{lower, upper},
258+
},
259+
},
260+
}
261+
return call, nil
236262
default:
237263
return nil, sql3.NewErrInternalf("unexpected expression type: %T", expr)
238264
}

sql3/planner/opinsert.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,10 @@ func (i *insertRowIter) Next(ctx context.Context) (types.Row, error) {
197197
default:
198198
// If we get to here, it's likey that the id type is unsupported
199199
// and will cause an error in batch.Add(). So there's no need to
200-
// return an error here in this default.
200+
// return an error here in this default. The only route here
201+
// would be if a primary key had a type other than intLiteralPlanExpression
202+
// or stringLiteralPlanExpression
203+
201204
row.ID = eval
202205
}
203206
}
@@ -390,8 +393,8 @@ func (i *insertRowIter) Next(ctx context.Context) (types.Row, error) {
390393
return nil, errors.Wrapf(err, "converting timestamp to int64: %s", v)
391394
}
392395
row.Values[posVals[idx]] = i64
393-
//integers passed as input for Timestamp fields will be treated as time represented in number of seconds since epoch defined for the field
394-
//for timestamp fields created using SQL epoch will be defaulted to unix epoch
396+
// integers passed as input for Timestamp fields will be treated as time represented in number of seconds since epoch defined for the field
397+
// for timestamp fields created using SQL epoch will be defaulted to unix epoch
395398
case int64:
396399
// Convert the input seconds to target timeunit defined for the Timestamp field
397400
// Add Base, which is the base epoch for Timestamp fields, to the input before saving

sql3/test/defs/defs.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var TableTests []TableTest = []TableTest{
2424
selectTests,
2525
selectKeyedTests,
2626
selectHavingTests,
27+
selectBetweenTests,
2728
filterPredicates,
2829
filterPredicatesIdKey,
2930
filterPredicatesId,
@@ -140,7 +141,7 @@ var TableTests []TableTest = []TableTest{
140141
binOpExprWithStringSetString,
141142
binOpExprWithStringSetStringSet,
142143

143-
//cast tests
144+
// cast tests
144145
castIntLiteral,
145146
castInt,
146147

@@ -152,41 +153,41 @@ var TableTests []TableTest = []TableTest{
152153
castStringSet,
153154
castTimestamp,
154155

155-
//like tests
156+
// like tests
156157
likeTests,
157158
notLikeTests,
158159

159-
//null tests
160+
// null tests
160161
nullTests,
161162
notNullTests,
162163

163-
//null filter tests
164+
// null filter tests
164165
nullFilterTests,
165166

166-
//between tests
167+
// between tests
167168
betweenTests,
168169
notBetweenTests,
169170

170-
//in tests
171+
// in tests
171172
inTests,
172173
notInTests,
173174

174-
//aggregate tests
175+
// aggregate tests
175176
countTests,
176177
countDistinctTests,
177178
sumTests,
178179
avgTests,
179180
percentileTests,
180181
minmaxTests,
181182

182-
//groupby tests
183+
// groupby tests
183184
groupByTests,
184185

185-
//create table tests
186+
// create table tests
186187
createTable,
187188
alterTable,
188189

189-
//joins
190+
// joins
190191
joinTestsUsers,
191192
joinTestsOrders,
192193
joinTests,
@@ -195,7 +196,7 @@ var TableTests []TableTest = []TableTest{
195196
bulkInsertTable,
196197
bulkInsert,
197198

198-
//bool (batch logic)
199+
// bool (batch logic)
199200
boolTests,
200201

201202
// time quantums

0 commit comments

Comments
 (0)