@@ -29,300 +29,6 @@ import (
2929 "github.com/dolthub/go-mysql-server/sql/types"
3030)
3131
32- // NewAddDate returns a new function expression, or an error if one couldn't be created. The ADDDATE
33- // function is a synonym for DATE_ADD, with the one exception that if the second argument is NOT an
34- // explicitly declared interval, then the value is used and the interval period is assumed to be DAY.
35- // In either case, this function will actually return a *DateAdd struct.
36- func NewAddDate (args ... sql.Expression ) (sql.Expression , error ) {
37- if len (args ) != 2 {
38- return nil , sql .ErrInvalidArgumentNumber .New ("ADDDATE" , 2 , len (args ))
39- }
40-
41- // If the interval is explicitly specified, then we simply pass it all to DateSub
42- i , ok := args [1 ].(* expression.Interval )
43- if ok {
44- return & DateAdd {args [0 ], i }, nil
45- }
46-
47- // Otherwise, the interval period is assumed to be DAY
48- i = expression .NewInterval (args [1 ], "DAY" )
49- return & DateAdd {args [0 ], i }, nil
50- }
51-
52- // DateAdd adds an interval to a date.
53- type DateAdd struct {
54- Date sql.Expression
55- Interval * expression.Interval
56- }
57-
58- var _ sql.FunctionExpression = (* DateAdd )(nil )
59- var _ sql.CollationCoercible = (* DateAdd )(nil )
60-
61- // NewDateAdd creates a new date add function.
62- func NewDateAdd (args ... sql.Expression ) (sql.Expression , error ) {
63- if len (args ) != 2 {
64- return nil , sql .ErrInvalidArgumentNumber .New ("DATE_ADD" , 2 , len (args ))
65- }
66-
67- i , ok := args [1 ].(* expression.Interval )
68- if ! ok {
69- return nil , fmt .Errorf ("DATE_ADD expects an interval as second parameter" )
70- }
71-
72- return & DateAdd {args [0 ], i }, nil
73- }
74-
75- // FunctionName implements sql.FunctionExpression
76- func (d * DateAdd ) FunctionName () string {
77- return "date_add"
78- }
79-
80- // Description implements sql.FunctionExpression
81- func (d * DateAdd ) Description () string {
82- return "adds the interval to the given date."
83- }
84-
85- // Children implements the sql.Expression interface.
86- func (d * DateAdd ) Children () []sql.Expression {
87- return []sql.Expression {d .Date , d .Interval }
88- }
89-
90- // Resolved implements the sql.Expression interface.
91- func (d * DateAdd ) Resolved () bool {
92- return d .Date .Resolved () && d .Interval .Resolved ()
93- }
94-
95- // IsNullable implements the sql.Expression interface.
96- func (d * DateAdd ) IsNullable () bool {
97- return true
98- }
99-
100- // Type implements the sql.Expression interface.
101- func (d * DateAdd ) Type () sql.Type {
102- sqlType := dateOffsetType (d .Date , d .Interval )
103- return sqlType
104- }
105-
106- // CollationCoercibility implements the interface sql.CollationCoercible.
107- func (* DateAdd ) CollationCoercibility (ctx * sql.Context ) (collation sql.CollationID , coercibility byte ) {
108- return ctx .GetCollation (), 4
109- }
110-
111- // WithChildren implements the Expression interface.
112- func (d * DateAdd ) WithChildren (children ... sql.Expression ) (sql.Expression , error ) {
113- return NewDateAdd (children ... )
114- }
115-
116- // Eval implements the sql.Expression interface.
117- func (d * DateAdd ) Eval (ctx * sql.Context , row sql.Row ) (interface {}, error ) {
118- date , err := d .Date .Eval (ctx , row )
119- if err != nil {
120- return nil , err
121- }
122-
123- if date == nil {
124- return nil , nil
125- }
126-
127- delta , err := d .Interval .EvalDelta (ctx , row )
128- if err != nil {
129- return nil , err
130- }
131-
132- if delta == nil {
133- return nil , nil
134- }
135-
136- var dateVal interface {}
137- dateVal , _ , err = types .DatetimeMaxPrecision .Convert (ctx , date )
138- if err != nil {
139- ctx .Warn (1292 , err .Error ())
140- return nil , nil
141- }
142-
143- // return appropriate type
144- res := types .ValidateTime (delta .Add (dateVal .(time.Time )))
145- if res == nil {
146- return nil , nil
147- }
148-
149- resType := d .Type ()
150- if types .IsText (resType ) {
151- // If the input is a properly formatted date/datetime string, the output should also be a string
152- if dateStr , isStr := date .(string ); isStr {
153- if res .(time.Time ).Nanosecond () > 0 {
154- return res .(time.Time ).Format (sql .DatetimeLayoutNoTrim ), nil
155- }
156- if isHmsInterval (d .Interval ) {
157- return res .(time.Time ).Format (sql .TimestampDatetimeLayout ), nil
158- }
159- for _ , layout := range types .DateOnlyLayouts {
160- if _ , pErr := time .Parse (layout , dateStr ); pErr != nil {
161- continue
162- }
163- return res .(time.Time ).Format (sql .DateLayout ), nil
164- }
165- }
166- }
167-
168- ret , _ , err := resType .Convert (ctx , res )
169- if err != nil {
170- return nil , err
171- }
172- return ret , nil
173- }
174-
175- func (d * DateAdd ) String () string {
176- return fmt .Sprintf ("%s(%s,%s)" , d .FunctionName (), d .Date , d .Interval )
177- }
178-
179- // NewSubDate returns a new function expression, or an error if one couldn't be created. The SUBDATE
180- // function is a synonym for DATE_SUB, with the one exception that if the second argument is NOT an
181- // explicitly declared interval, then the value is used and the interval period is assumed to be DAY.
182- // In either case, this function will actually return a *DateSub struct.
183- func NewSubDate (args ... sql.Expression ) (sql.Expression , error ) {
184- if len (args ) != 2 {
185- return nil , sql .ErrInvalidArgumentNumber .New ("SUBDATE" , 2 , len (args ))
186- }
187-
188- // If the interval is explicitly specified, then we simply pass it all to DateSub
189- i , ok := args [1 ].(* expression.Interval )
190- if ok {
191- return & DateSub {args [0 ], i }, nil
192- }
193-
194- // Otherwise, the interval period is assumed to be DAY
195- i = expression .NewInterval (args [1 ], "DAY" )
196- return & DateSub {args [0 ], i }, nil
197- }
198-
199- // DateSub subtracts an interval from a date.
200- type DateSub struct {
201- Date sql.Expression
202- Interval * expression.Interval
203- }
204-
205- var _ sql.FunctionExpression = (* DateSub )(nil )
206- var _ sql.CollationCoercible = (* DateSub )(nil )
207-
208- // NewDateSub creates a new date add function.
209- func NewDateSub (args ... sql.Expression ) (sql.Expression , error ) {
210- if len (args ) != 2 {
211- return nil , sql .ErrInvalidArgumentNumber .New ("DATE_SUB" , 2 , len (args ))
212- }
213-
214- i , ok := args [1 ].(* expression.Interval )
215- if ! ok {
216- return nil , fmt .Errorf ("DATE_SUB expects an interval as second parameter" )
217- }
218-
219- return & DateSub {args [0 ], i }, nil
220- }
221-
222- // FunctionName implements sql.FunctionExpression
223- func (d * DateSub ) FunctionName () string {
224- return "date_sub"
225- }
226-
227- // Description implements sql.FunctionExpression
228- func (d * DateSub ) Description () string {
229- return "subtracts the interval from the given date."
230- }
231-
232- // Children implements the sql.Expression interface.
233- func (d * DateSub ) Children () []sql.Expression {
234- return []sql.Expression {d .Date , d .Interval }
235- }
236-
237- // Resolved implements the sql.Expression interface.
238- func (d * DateSub ) Resolved () bool {
239- return d .Date .Resolved () && d .Interval .Resolved ()
240- }
241-
242- // IsNullable implements the sql.Expression interface.
243- func (d * DateSub ) IsNullable () bool {
244- return true
245- }
246-
247- // Type implements the sql.Expression interface.
248- func (d * DateSub ) Type () sql.Type {
249- sqlType := dateOffsetType (d .Date , d .Interval )
250- return sqlType
251- }
252-
253- // CollationCoercibility implements the interface sql.CollationCoercible.
254- func (* DateSub ) CollationCoercibility (ctx * sql.Context ) (collation sql.CollationID , coercibility byte ) {
255- return ctx .GetCollation (), 4
256- }
257-
258- // WithChildren implements the Expression interface.
259- func (d * DateSub ) WithChildren (children ... sql.Expression ) (sql.Expression , error ) {
260- return NewDateSub (children ... )
261- }
262-
263- // Eval implements the sql.Expression interface.
264- func (d * DateSub ) Eval (ctx * sql.Context , row sql.Row ) (interface {}, error ) {
265- date , err := d .Date .Eval (ctx , row )
266- if err != nil {
267- return nil , err
268- }
269-
270- if date == nil {
271- return nil , nil
272- }
273-
274- delta , err := d .Interval .EvalDelta (ctx , row )
275- if err != nil {
276- return nil , err
277- }
278-
279- if delta == nil {
280- return nil , nil
281- }
282-
283- var dateVal interface {}
284- dateVal , _ , err = types .DatetimeMaxPrecision .Convert (ctx , date )
285- if err != nil {
286- ctx .Warn (1292 , err .Error ())
287- return nil , nil
288- }
289-
290- // return appropriate type
291- res := types .ValidateTime (delta .Sub (dateVal .(time.Time )))
292- if res == nil {
293- return nil , nil
294- }
295-
296- resType := d .Type ()
297- if types .IsText (resType ) {
298- // If the input is a properly formatted date/datetime string, the output should also be a string
299- if dateStr , isStr := date .(string ); isStr {
300- if res .(time.Time ).Nanosecond () > 0 {
301- return res .(time.Time ).Format (sql .DatetimeLayoutNoTrim ), nil
302- }
303- if isHmsInterval (d .Interval ) {
304- return res .(time.Time ).Format (sql .TimestampDatetimeLayout ), nil
305- }
306- for _ , layout := range types .DateOnlyLayouts {
307- if _ , pErr := time .Parse (layout , dateStr ); pErr != nil {
308- continue
309- }
310- return res .(time.Time ).Format (sql .DateLayout ), nil
311- }
312- }
313- }
314-
315- ret , _ , err := resType .Convert (ctx , res )
316- if err != nil {
317- return nil , err
318- }
319- return ret , nil
320- }
321-
322- func (d * DateSub ) String () string {
323- return fmt .Sprintf ("%s(%s,%s)" , d .FunctionName (), d .Date , d .Interval )
324- }
325-
32632// DatetimeConversion is a shorthand function for CONVERT(expr, DATETIME)
32733type DatetimeConversion struct {
32834 Date sql.Expression
0 commit comments