@@ -14,8 +14,25 @@ enum Builtins {
1414 static let pos = Function ( . var( 0 ) , returning: . var( 0 ) )
1515 static let between = Function ( . var( 0 ) , . var( 0 ) , . var( 0 ) , returning: . integer)
1616 static let arithmetic = Function ( . var( 0 ) , . var( 0 ) , returning: . var( 0 ) )
17- static let divide = Function ( . var( 0 ) , . var( 0 ) , returning: . var( 0 ) ) { _, _, _ in
18- fatalError ( " check for integer division " )
17+ static let divide = Function ( . var( 0 ) , . var( 0 ) , returning: . var( 0 ) ) { types, exprs, location, diagnostics in
18+ func isInt( _ type: Type , expr: ExpressionSyntax ) -> Bool {
19+ if type. root == . integer || type. root == . int { return true }
20+ if case let . numeric( _, isInt) = expr. literal? . kind { return isInt }
21+ return false
22+ }
23+
24+ // If both sides are integers than the output will always be an integer
25+ // and not be floating point so emit a warning.
26+ guard types. count == 2 ,
27+ exprs. count == 2 ,
28+ isInt ( types [ 0 ] , expr: exprs [ 0 ] ) ,
29+ isInt ( types [ 1 ] , expr: exprs [ 1 ] ) else { return }
30+
31+ diagnostics. add ( . init(
32+ " Integer division, result will not be floating point. 'CAST' or add '.0' " ,
33+ level: . warning,
34+ at: location
35+ ) )
1936 }
2037 static let comparison = Function ( . var( 0 ) , . var( 0 ) , returning: . integer)
2138 static let `in` = Function ( . var( 0 ) , . row( . unknown( . var( 0 ) ) ) , returning: . integer)
@@ -87,7 +104,23 @@ enum Builtins {
87104 // Datetime
88105 " unixepoch " : Function ( returning: . integer) ,
89106 " julianday " : Function ( returning: . real) ,
90- " strftime " : strftime,
107+ " strftime " : Function (
108+ . text,
109+ returning: . text,
110+ variadic: true
111+ ) { _, args, location, diagnostics in
112+ guard args. count == 2 ,
113+ case let . string( first) = args [ 0 ] . literal? . kind,
114+ case let . string( second) = args [ 1 ] . literal? . kind,
115+ first == " %s " ,
116+ second == " now " else { return }
117+
118+ diagnostics. add ( . init(
119+ " Function returns the seconds as TEXT, not an INTEGER. Use unixepoch() instead " ,
120+ level: . warning,
121+ at: location
122+ ) )
123+ } ,
91124 " date " : Function ( . text, returning: . text, variadic: true ) ,
92125 " time " : Function ( . text, returning: . text, variadic: true ) ,
93126 " datetime " : Function ( . text, returning: . text, variadic: true ) ,
@@ -96,35 +129,15 @@ enum Builtins {
96129 // Aggregate Functions
97130 " avg " : Function ( . var( . integer( 0 ) ) , returning: . var( . integer( 0 ) ) ) ,
98131 " count " : Function ( . var( 0 ) , returning: . integer) ,
99- " group_concat " : groupConcat,
132+ " group_concat " : Function (
133+ . text,
134+ returning: . text,
135+ overloads: [ Function . Overload ( . text, . text, returning: . text) ]
136+ ) ,
100137 " string_agg " : Function ( . text, . text, returning: . text) ,
101138 // 'max' and 'min' are added through the scalar functions and can be reused.
102139 // In the future we may need to separate these if we store them separately
103140 " sum " : Function ( . var( . integer( 0 ) ) , returning: . var( . integer( 0 ) ) ) ,
104141 " total " : Function ( . var( . integer( 0 ) ) , returning: . var( . integer( 0 ) ) ) ,
105142 ]
106-
107- static let groupConcat = Function (
108- . text,
109- returning: . text,
110- overloads: [ Function . Overload ( . text, returning: . text) ]
111- )
112-
113- static let strftime = Function (
114- . text,
115- returning: . text,
116- variadic: true
117- ) { args, location, diagnostics in
118- guard args. count == 2 ,
119- case let . string( first) = args [ 0 ] . literal? . kind,
120- case let . string( second) = args [ 1 ] . literal? . kind,
121- first == " %s " ,
122- second == " now " else { return }
123-
124- diagnostics. add ( . init(
125- " Function returns the seconds as TEXT, not an INTEGER. Use unixepoch() instead " ,
126- level: . warning,
127- at: location
128- ) )
129- }
130143}
0 commit comments