Skip to content

Commit b58113a

Browse files
committed
enable arithmetics on Id/Id64
1 parent 5c4cb30 commit b58113a

File tree

4 files changed

+180
-27
lines changed

4 files changed

+180
-27
lines changed

src/tink/sql/Types.hx

+49-7
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,19 @@ abstract Id<T>(Int) to Int {
6161
@:op(A>=B) static function lte<T>(a:Id<T>, b:Id<T>):Bool;
6262
@:op(A==B) static function eq<T>(a:Id<T>, b:Id<T>):Bool;
6363
@:op(A!=B) static function neq<T>(a:Id<T>, b:Id<T>):Bool;
64-
64+
@:op(A+B) static function plus<T>(a:Id<T>, b:Int):Id<T>;
65+
@:op(A++) inline function postfixInc<T>():Id<T> {
66+
return this++;
67+
}
68+
@:op(++A) inline function prefixInc<T>():Id<T> {
69+
return ++this;
70+
}
71+
@:op(A--) inline function postfixDec<T>():Id<T> {
72+
return this--;
73+
}
74+
@:op(--A) inline function prefixDec<T>():Id<T> {
75+
return --this;
76+
}
6577
}
6678

6779
abstract Id64<T>(Int64) to Int64 {
@@ -78,11 +90,41 @@ abstract Id64<T>(Int64) to Int64 {
7890
@:to public function toExpr():Expr<Id64<T>>
7991
return tink.sql.Expr.ExprData.EValue(new Id64(this), cast VInt64);
8092

81-
@:op(A>B) static function gt<T>(a:Id64<T>, b:Id64<T>):Bool;
82-
@:op(A<B) static function lt<T>(a:Id64<T>, b:Id64<T>):Bool;
83-
@:op(A>=B) static function gte<T>(a:Id64<T>, b:Id64<T>):Bool;
84-
@:op(A>=B) static function lte<T>(a:Id64<T>, b:Id64<T>):Bool;
85-
@:op(A==B) static function eq<T>(a:Id64<T>, b:Id64<T>):Bool;
86-
@:op(A!=B) static function neq<T>(a:Id64<T>, b:Id64<T>):Bool;
93+
@:op(A>B) inline static function gt<T>(a:Id64<T>, b:Id64<T>):Bool {
94+
return (a:Int64) > (b:Int64);
95+
}
96+
@:op(A<B) inline static function lt<T>(a:Id64<T>, b:Id64<T>):Bool {
97+
return (a:Int64) < (b:Int64);
98+
}
99+
@:op(A>=B) inline static function gte<T>(a:Id64<T>, b:Id64<T>):Bool {
100+
return (a:Int64) >= (b:Int64);
101+
}
102+
@:op(A>=B) inline static function lte<T>(a:Id64<T>, b:Id64<T>):Bool {
103+
return (a:Int64) <= (b:Int64);
104+
}
105+
@:op(A==B) inline static function eq<T>(a:Id64<T>, b:Id64<T>):Bool {
106+
return (a:Int64) == (b:Int64);
107+
}
108+
@:op(A!=B) static function neq<T>(a:Id64<T>, b:Id64<T>):Bool {
109+
return (a:Int64) != (b:Int64);
110+
}
111+
@:op(A+B) static function plus<T>(a:Id64<T>, b:Int64):Id64<T> {
112+
return (a:Int64) + b;
113+
}
114+
@:op(A-B) static function minus<T>(a:Id64<T>, b:Int64):Id64<T> {
115+
return (a:Int64) - b;
116+
}
117+
@:op(A++) inline function postfixInc<T>():Id64<T> {
118+
return this++;
119+
}
120+
@:op(++A) inline function prefixInc<T>():Id64<T> {
121+
return ++this;
122+
}
123+
@:op(A--) inline function postfixDec<T>():Id64<T> {
124+
return this--;
125+
}
126+
@:op(--A) inline function prefixDec<T>():Id64<T> {
127+
return --this;
128+
}
87129

88130
}

src/tink/sql/macros/Targets.hx

+19-20
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,31 @@ package tink.sql.macros;
33
import haxe.macro.Expr;
44
import haxe.macro.Context;
55
import haxe.macro.Type;
6+
67
using tink.MacroApi;
78

89
class Targets {
9-
1010
static public function from(db:Expr, targetE:Expr, cnx:Expr) {
1111
return switch targetE.expr {
1212
case EObjectDecl([target]):
1313
var name = target.field;
1414
switch Context.typeof(macro @:privateAccess ${target.expr}.asSelected()) {
15-
case TInst(_, [fields, filter, result, db]):
15+
case TInst(_, [fields, filter, result, db]):
1616
var fields = [];
1717
var fieldsComplex = ComplexType.TAnonymous(fields);
1818
var resultComplex = result.toComplex();
1919
var aliasFields = [];
2020
switch haxe.macro.Context.followWithAbstracts(result) {
2121
case TAnonymous(_.get().fields => originalFields):
22-
for (field in originalFields) {
22+
for (field in originalFields) {
2323
var fComplex = field.type.toComplex();
2424
fields.push({
2525
pos: field.pos,
2626
name: field.name,
27-
kind: FProp('default', 'never', macro : tink.sql.Expr.Field<$fComplex, $resultComplex>)
27+
kind: FProp('default', 'never', macro :tink.sql.Expr.Field<$fComplex, $resultComplex>)
2828
});
2929
aliasFields.push({
30-
field: field.name,
30+
field: field.name,
3131
expr: macro new tink.sql.Expr.Field($v{name}, $v{field.name}, ${typeToExprOfExprType(field.type)}),
3232
});
3333
}
@@ -36,37 +36,36 @@ class Targets {
3636
var aliasFieldsE = EObjectDecl(aliasFields).at(target.expr.pos);
3737
var f:Function = {
3838
expr: macro return null,
39-
ret: macro : tink.sql.Expr.Condition,
40-
args: [{
41-
name: name,
42-
type: fieldsComplex
43-
}],
39+
ret: macro :tink.sql.Expr.Condition,
40+
args: [
41+
{
42+
name: name,
43+
type: fieldsComplex
44+
}
45+
],
4446
}
4547
var filterType = f.asExpr().typeof().sure().toComplex({direct: true});
4648
var blank = target.expr.pos.makeBlankType();
4749
macro @:pos(target.expr.pos) {
4850
var query = ${target.expr};
49-
var fields = (cast $aliasFieldsE: $fieldsComplex);
50-
@:privateAccess new tink.sql.Dataset.Selectable(
51-
$cnx,
52-
fields,
53-
(TQuery($v{name}, query.toQuery()): tink.sql.Target<$resultComplex, $blank>),
54-
function (filter:$filterType) return filter(fields)
55-
);
51+
var fields = (cast $aliasFieldsE : $fieldsComplex);
52+
@:privateAccess new tink.sql.Dataset.Selectable($cnx, fields,
53+
(TQuery($v{name}, query.toQuery()) : tink.sql.Target<$resultComplex, $blank>),
54+
function(filter:$filterType) return filter(fields));
5655
}
5756
default: target.expr.reject('Dataset expected');
5857
}
5958
default: targetE.reject('Object declaration with a single property expected');
6059
}
6160
}
62-
61+
6362
static function typeToExprOfExprType(type:Type):ExprOf<tink.sql.Expr.ExprType<Dynamic>> {
6463
return switch type.getID() {
6564
case 'String': macro VString;
6665
case 'Bool': macro VBool;
6766
case 'Float': macro VFloat;
6867
case 'Int' | 'tink.sql.Id': macro VInt;
69-
case 'haxe.Int64': macro VInt64;
68+
case 'haxe.Int64' | 'tink.sql.Id64': macro VInt64;
7069
case 'haxe.io.Bytes': macro VBytes;
7170
case 'Date': macro VDate;
7271
case 'tink.s2d.Point': macro VGeometry(Point);
@@ -83,4 +82,4 @@ class Targets {
8382
case _: throw 'Cannot convert $type to ExprType';
8483
}
8584
}
86-
}
85+
}

tests/IdTest.hx

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package;
2+
3+
import Db;
4+
import tink.sql.Types;
5+
import haxe.Int64;
6+
using tink.CoreApi;
7+
8+
@:asserts
9+
class IdTest {
10+
public function new():Void {}
11+
12+
public function arithmetics() {
13+
final id:Id<User> = 123;
14+
asserts.assert(id == 123);
15+
asserts.assert(id + 1 == 124);
16+
asserts.assert(id - 1 == 122);
17+
return asserts.done();
18+
}
19+
public function arithmetics64() {
20+
final id:Id64<User> = Int64.ofInt(123);
21+
asserts.assert(id == Int64.ofInt(123));
22+
asserts.assert(id + 1 == Int64.ofInt(124));
23+
asserts.assert(id - 1 == Int64.ofInt(122));
24+
return asserts.done();
25+
}
26+
27+
public function addAssign() {
28+
final id:Id<User> = 123;
29+
asserts.assert(id == 123);
30+
asserts.assert((id += 1) == 124);
31+
return asserts.done();
32+
}
33+
public function addAssign64() {
34+
final id:Id64<User> = Int64.ofInt(123);
35+
asserts.assert(id == Int64.ofInt(123));
36+
asserts.assert((id += 1) == Int64.ofInt(124));
37+
return asserts.done();
38+
}
39+
public function minusAssign() {
40+
final id:Id<User> = 123;
41+
asserts.assert(id == 123);
42+
asserts.assert((id -= 1) == 122);
43+
return asserts.done();
44+
}
45+
public function minusAssign64() {
46+
final id:Id64<User> = Int64.ofInt(123);
47+
asserts.assert(id == Int64.ofInt(123));
48+
asserts.assert((id -= 1) == Int64.ofInt(122));
49+
return asserts.done();
50+
}
51+
52+
public function postfixInc() {
53+
final id:Id<User> = 123;
54+
asserts.assert(id == 123);
55+
asserts.assert(id++ == 123);
56+
asserts.assert(id == 124);
57+
return asserts.done();
58+
}
59+
public function postfixInc64() {
60+
final id:Id64<User> = Int64.ofInt(123);
61+
asserts.assert(id == Int64.ofInt(123));
62+
asserts.assert(id++ == Int64.ofInt(123));
63+
asserts.assert(id == Int64.ofInt(124));
64+
return asserts.done();
65+
}
66+
public function postfixDec() {
67+
final id:Id<User> = 123;
68+
asserts.assert(id == 123);
69+
asserts.assert(id-- == 123);
70+
asserts.assert(id == 122);
71+
return asserts.done();
72+
}
73+
public function postfixDec64() {
74+
final id:Id64<User> = Int64.ofInt(123);
75+
asserts.assert(id == Int64.ofInt(123));
76+
asserts.assert(id-- == Int64.ofInt(123));
77+
asserts.assert(id == Int64.ofInt(122));
78+
return asserts.done();
79+
}
80+
public function prefixInc() {
81+
final id:Id<User> = 123;
82+
asserts.assert(id == 123);
83+
asserts.assert(++id == 124);
84+
asserts.assert(id == 124);
85+
return asserts.done();
86+
}
87+
public function prefixInc64() {
88+
final id:Id64<User> = Int64.ofInt(123);
89+
asserts.assert(id == Int64.ofInt(123));
90+
asserts.assert(++id == Int64.ofInt(124));
91+
asserts.assert(id == Int64.ofInt(124));
92+
return asserts.done();
93+
}
94+
public function prefixDec() {
95+
final id:Id<User> = 123;
96+
asserts.assert(id == 123);
97+
asserts.assert(--id == 122);
98+
asserts.assert(id == 122);
99+
return asserts.done();
100+
}
101+
public function prefixDec64() {
102+
final id:Id64<User> = Int64.ofInt(123);
103+
asserts.assert(id == Int64.ofInt(123));
104+
asserts.assert(--id == Int64.ofInt(122));
105+
asserts.assert(id == Int64.ofInt(122));
106+
return asserts.done();
107+
}
108+
}

tests/Run.hx

+4
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class Run extends TestWithDb {
6868
Promise.reject(Error.asError(err));
6969
}, max10Seconds)
7070
.next(_ -> Runner.run(TestBatch.make([
71+
new IdTest(),
7172
new TypeTest(mysql, dbMysql),
7273
new SelectTest(mysql, dbMysql),
7374
new FormatTest(mysql, dbMysql),
@@ -104,6 +105,7 @@ class Run extends TestWithDb {
104105
final dbPostgres = new Db(env('POSTGRES_DB', 'test'), postgres);
105106
return Promise.retry(()->loadFixture(dbPostgres, 'init_postgresql'), max10Seconds)
106107
.next(_ -> Runner.run(TestBatch.make([
108+
new IdTest(),
107109
new TypeTest(postgres, dbPostgres),
108110
new SelectTest(postgres, dbPostgres),
109111
new FormatTest(postgres, dbPostgres),
@@ -135,6 +137,7 @@ class Run extends TestWithDb {
135137
final db = new Db(env('COCKROACH_DATABASE', 'test'), cockroachdb);
136138
return Promise.retry(()->loadFixture(db, 'init_cockroachdb'), max10Seconds)
137139
.next(_ -> Runner.run(TestBatch.make([
140+
new IdTest(),
138141
new TypeTest(cockroachdb, db),
139142
new SelectTest(cockroachdb, db),
140143
new FormatTest(cockroachdb, db),
@@ -162,6 +165,7 @@ class Run extends TestWithDb {
162165

163166
return loadFixture(dbSqlite, 'init_sqlite')
164167
.next(_ -> Runner.run(TestBatch.make([
168+
new IdTest(),
165169
new TypeTest(sqlite, dbSqlite),
166170
new JsonTest(sqlite, dbSqlite),
167171
new DateTest(sqlite, dbSqlite),

0 commit comments

Comments
 (0)