https://github.com/haxetink/tink_sql
SQL embedded into Haxe
https://github.com/haxetink/tink_sql
database haxe sql tink
Last synced: 2 months ago
JSON representation
SQL embedded into Haxe
- Host: GitHub
- URL: https://github.com/haxetink/tink_sql
- Owner: haxetink
- License: mit
- Created: 2013-09-03T13:26:06.000Z (over 12 years ago)
- Default Branch: master
- Last Pushed: 2025-12-22T20:31:49.000Z (3 months ago)
- Last Synced: 2025-12-24T09:49:47.334Z (3 months ago)
- Topics: database, haxe, sql, tink
- Language: Haxe
- Homepage:
- Size: 896 KB
- Stars: 56
- Watchers: 9
- Forks: 18
- Open Issues: 43
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://github.com/haxetink/tink_sql/actions)
[](https://gitter.im/haxetink/public)
# Tinkerbell SQL
This library embeds SQL right into the Haxe language. Think LINQ (not the syntax sugar, but the framework).
**Breaking Change (2021-09-16)**
[Transaction](#transactions) is now supported with a minor breaking change.
Migration guide: https://github.com/haxetink/tink_sql/pull/130#issuecomment-822971910
## Motivation
Most developers tend to dislike SQL, at least for a significant part of their career. A symptom of that are ever-repeating attempts to hide the database layer behind ORMs, with very limited success.
Relational databases are however a very powerful concept, that was pioneered over 40 years ago.
Tink SQL has been built to embrace using SQL for your database interactions, but in a type safe way that fits with the Haxe ecosystem.
## Defining your schema
Define a database like so:
```haxe
import tink.sql.Types;
typedef User = {
var id:Id;
var name:VarChar<255>;
@:unique var email:VarChar<255>;
var password:VarChar<255>;
}
typedef Post = {
var id:Id;
var author:Id;
var title:LongText;
var url:VarChar<255>;
}
typedef Tag = {
var id:Id;
var name:VarChar<20>;
var desc:Null;
}
typedef PostTags = {
var post:Id;
var tag:Id;
}
@:tables(User, Post, Tag, PostTags)
class Db extends tink.sql.Database {}
```
## Redefining table names
```haxe
class Db extends tink.sql.Database {
@:table("blog_users") var user:User;
@:table("blog_posts") var post:Post;
@:table("news_tags") var tag:Tag;
@:table("post_tags") var postTags:PostTags;
}
```
## Connecting to the database
```haxe
import tink.sql.drivers.MySql;
var driver = new tink.sql.drivers.MySql({
user: 'user',
password: 'pass'
});
var db = new Db('db_name', driver);
```
## Tables API
- Table setup
- `db.User.create(): Promise;`
- `db.User.drop(): Promise;`
- `db.User.truncate(): Promise;`
- Selecting
- `db.User.count(): Promise;`
- `db.User.all(limit, orderBy): Promise>;`
- `db.User.first(orderBy): Promise;`
- `db.User.where(filter)`
- `db.User.select(f:Fields->Selection)`
- Example, select name of user: `db.User.select({name: User.name}).where(User.id == 1).first()`
- Writing
- `db.User.insertOne(row: User): Promise>;`
- `db.User.insertMany(rows: Array): Promise>;`
- `db.User.update(f:Fields->Update, options:{ where: Filter, ?max:Int }): Promise<{rowsAffected: Int}>;`
- Example, rename all users called 'Dave' to 'Donald': `db.User.update(function (u) return [u.name.set('Donald')], { where: function (u) return u.name == 'Dave' } );`
- `db.User.delete(options:{ where: Filter, ?max:Int }): Promise<{rowsAffected: Int}>;`
- Advanced Selecting
- `db.User.as(alias);`
- `db.User.join(db.User).on(id == copiedFrom).all();`
- `db.User.leftJoin(db.User);`
- `db.User.rightJoin(db.User);`
- `db.User.stream(limit, orderBy): tink.streams.RealStream;`
... to be continued ...
## Transactions
```haxe
// transaction with a commit
db.transaction(trx -> {
trx.User.insertOne(...).next(id -> Commit(id)); // user is inserted
});
// transaction with explicit rollback
db.transaction(trx -> {
trx.User.insertOne(...).next(_ -> Rollback); // user insert is rolled back
});
// transaction with implicit rollback upon error
db.transaction(trx -> {
trx.User.insertOne(...).next(_ -> new Error('Aborted')); // user insert is rolled back
});
```