--panics:on
, --experimental:strictFuncs
.let
and const
.system.nim
, everything done via template
/macro
, strutils
is not imported, future-proof your code.--
Human readable comments, multi-line comments produce multi-line SQL comments, requires Stropping.COMMENT
, Postgres-only.UNION
, UNION ALL
.INTERSECT
, INTERSECT ALL
.EXCEPT
, EXCEPT ALL
, requires Stropping.CASE
with multiple WHEN
and 1 ELSE
with correct indentation, requires Stropping.INNER JOIN
, LEFT JOIN
, RIGHT JOIN
, FULL JOIN
.OFFSET
.LIMIT
.FROM
, requires Stropping.WHERE
, WHERE NOT
, WHERE EXISTS
, WHERE NOT EXISTS
.ORDER BY
.SELECT
, SELECT *
, SELECT DISTINCT
.SELECT TOP
, SELECT MIN
, SELECT MAX
, SELECT AVG
, SELECT SUM
, SELECT COUNT
.SELECT trim(lower( ))
for strings, SELECT round( )
for floats, useful shortcuts.DELETE FROM
.LIKE
, NOT LIKE
.BETWEEN
, NOT BETWEEN
.HAVING
.INSERT INTO
.IS NULL
, IS NOT NULL
.UPDATE
, SET
.VALUES
.DROP TABLE IF EXISTS
.CREATE TABLE IF NOT EXISTS
.Not supported:
TRUNCATE
, because is the same as DELETE FROM
without a WHERE
.WHERE IN
, WHERE NOT IN
, because is the same as JOIN
, but JOIN
is a lot faster.Nim StdLib API | Gatabase ORM API |
---|---|
tryExec |
tryExec |
exec |
exec |
getRow |
getRow |
getAllRows |
getAllRows |
getValue |
getValue |
tryInsertID |
tryInsertID |
insertID |
insertID |
execAffectedRows |
execAffectedRows |
Output | Gatabase ORM API |
---|---|
bool |
tryExec |
Row |
getRow |
seq[Row] |
getAllRows |
int64 |
tryInsertID |
int64 |
insertID |
int64 |
execAffectedRows |
SqlQuery |
sqls |
any |
getValue |
exec |
getValue
can return any specific arbitrary concrete type, depending on the arguments used (Optional).-- SQL Comments are supported, but stripped when build for Release. This is SQL.
`--` "SQL Comments are supported, but stripped when build for Release. This is Nim."
SELECT *
FROM sometable
select '*'
`from` "sometable"
SELECT somecolumn
FROM sometable
select "somecolumn"
`from` "sometable"
SELECT DISTINCT somecolumn
selectdistinct "somecolumn"
SELECT MIN(somecolumn)
selectmin "somecolumn"
SELECT MAX(somecolumn)
selectmax "somecolumn"
SELECT COUNT(somecolumn)
selectcount "somecolumn"
SELECT AVG(somecolumn)
selectavg "somecolumn"
SELECT SUM(somecolumn)
selectsum "somecolumn"
SELECT trim(lower(somestringcolumn))
selecttrim "somestringcolumn"
SELECT round(somefloatcolumn, 2)
selectround2 "somefloatcolumn"
SELECT round(somefloatcolumn, 4)
selectround4 "somefloatcolumn"
SELECT round(somefloatcolumn, 6)
selectround6 "somefloatcolumn"
SELECT TOP 5 *
selecttop 5
SELECT somecolumn
FROM sometable
WHERE power > 9000
select "somecolumn"
`from` "sometable"
where "power > 9000"
OFFSET 9
LIMIT 42
offset 9
limit 42
INSERT INTO person
VALUES (42, 'Nikola Tesla', true, 'nikola.tesla@nim-lang.org', 9.6)
insertinto "person"
values 5
Example:
insertinto "person"
values 5
INSERT INTO person
VALUES ( ?, ?, ?, ?, ? )
varargs
directly using stdlib, Gatabase does not format values ever.values 5
generates VALUES ( ?, ?, ?, ?, ? )
.UPDATE person
SET name = 'Nikola Tesla', mail = 'nikola.tesla@nim-lang.org'
update "person"
set ["name", "mail"]
Example:
update "person"
set ["name", "mail"]
UPDATE person
SET name = ?, mail = ?
varargs
directly using stdlib, Gatabase does not format values ever.set ["key", "other", "another"]
generates SET key = ?, other = ?, another = ?
.DELETE debts
delete "debts"
ORDER BY ASC
orderby "asc"
ORDER BY DESC
orderby "desc"
CASE
WHEN foo > 10 THEN 9
WHEN bar < 42 THEN 5
ELSE 0
END
`case` {
"foo > 10": "9",
"bar < 42": "5",
"else": "0"
}
COMMENT ON TABLE myTable IS 'This is an SQL COMMENT on a TABLE'
commentontable {"myTable": "This is an SQL COMMENT on a TABLE"}
COMMENT ON COLUMN myColumn IS 'This is an SQL COMMENT on a COLUMN'
commentoncolumn {"myColumn": "This is an SQL COMMENT on a COLUMN"}
COMMENT ON DATABASE myDatabase IS 'This is an SQL COMMENT on a DATABASE'
commentondatabase {"myDatabase": "This is an SQL COMMENT on a DATABASE"}
GROUP BY country
groupby "country"
FULL JOIN tablename
fulljoin "tablename"
INNER JOIN tablename
innerjoin "tablename"
LEFT JOIN tablename
leftjoin "tablename"
RIGHT JOIN tablename
rightjoin "tablename"
HAVING beer > 5
having "beer > 5"
UNION ALL
union true
UNION
union false
INTERSECT ALL
intersect true
INTERSECT
intersect false
EXCEPT ALL
`except` true
EXCEPT
`except` false
IS NULL
isnull true
IS NOT NULL
isnull false
DROP TABLE IF EXISTS tablename
dropTable "tablename"
dropTable
is part of Gatabase Sugar (Optional).CREATE TABLE IF NOT EXISTS kitten(
id INTEGER PRIMARY KEY,
age INTEGER NOT NULL DEFAULT 1,
sex VARCHAR(1) NOT NULL DEFAULT 'f',
name TEXT NOT NULL DEFAULT 'fluffy',
rank REAL NOT NULL DEFAULT 3.14,
);
let myTable = createTable "kitten": [
"age" := 1,
"sex" := 'f',
"name" := "fluffy",
"rank" := 3.14,
]
No default values:
CREATE TABLE IF NOT EXISTS kitten(
id INTEGER PRIMARY KEY,
age INTEGER,
sex VARCHAR(1),
name TEXT,
rank REAL,
);
let myTable = createTable "kitten": [
"age" := int,
"sex" := char,
"name" := string,
"rank" := float,
]
More examples:
CREATE TABLE IF NOT EXISTS kitten(
id INTEGER PRIMARY KEY,
age INTEGER NOT NULL DEFAULT 1,
sex VARCHAR(1),
);
let myTable = createTable "kitten": [
"age" := 1,
"sex" := char,
]
And more examples: https://github.com/juancarlospaco/nim-gatabase/blob/master/examples/database_fields_example.nim#L1
createTable
is part of Gatabase Sugar (Optional).'*'
*
.'?'
?
.Gatabase wont like Obfuscation, its code is easy to read and similar to Pretty-Printed SQL. nimpretty
friendly. Very KISS.
Compiles Ok:
let variable = sqls:
select '*'
`from` "clients"
groupby "country"
orderby AscNullsLast
Fails to Compile:
let variable = sqls: select('*') from("clients") groupby("country") orderby(AscNullsLast)
let variable = sqls: '*'.select() "clients".from() "country".groupby() AscNullsLast.orderby()
let variable = sqls: select '*' from "clients" groupby "country" orderby AscNullsLast
let variable = sqls:select'*' from"clients" groupby"country" orderby AscNullsLast
This helps on big projects where each developer tries to use a different code style.
Nim has template
is like a literal copy&paste of code in-place with no performance cost,that allows you to create your own custom ORM function callbacks on-the-fly,like the ones used on scripting languages.
template getMemes(): string =
result = [].getValue:
select "url"
`from` "memes"
limit 1
Then you do getMemes()
when you need it
From this MyClass.meta.Session.query(Memes).all().filter().first()
to this getMemes()
.
Remember on Python2 you had like print "value"
?, on Nim you can do the same for any function,then we made functions to mimic basic standard SQL, like select "value"
and it worked,its Type-Safe and valid Nim code, you have an ORM that gives you the freedom and power,this allows to support interesting features, like CASE
, UNION
, INTERSECT
, COMMENT
, etc.
When you get used to template
it requires a lot less code to do the same than SQLAlchemy.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine, MetaData, Table
from sqlalchemy import Column, Integer, String, Boolean, Float
engine = create_engine("sqlite:///:memory:", echo=False)
engine.execute("""
create table if not exists person(
id integer primary key,
name varchar(9) not null unique,
active bool not null default true,
rank float not null default 0.0
); """
)
meta = MetaData()
persons = Table(
"person", meta,
Column("id", Integer, primary_key = True),
Column("name", String, nullable = False, unique = True),
Column("active", Boolean, nullable = False, default = True),
Column("rank", Float, nullable = False, default = 0.0),
)
conn = engine.connect()
ins = persons.insert()
ins = persons.insert().values(id = 42, name = "Pepe", active = True, rank = 9.6)
result = conn.execute(ins)
persons_query = persons.select()
result = conn.execute(persons_query)
row = result.fetchone()
print(row)
import db_sqlite, gatabase
let db = open(":memory:", "", "", "")
db.exec(sql"""
create table if not exists person(
id integer primary key,
name varchar(9) not null unique,
active bool not null default true,
rank float not null default 0.0
); """)
exec [42, "Pepe", true, 9.6]:
insertinto "person"
values 4
let row = [].getRow:
select '*'
`from` "person"
echo row
It will perform a SQL Syntax checking at compile-time. Examples here Fail intentionally as expected:
exec []:
where "failure"
Fails to compile as expected, with a friendly error:
gatabase.nim(48, 16) Warning: WHERE without SELECT nor INSERT nor UPDATE nor DELETE.
Typical error of making a DELETE FROM
without WHERE
that deletes all your data:
exec []:
delete "users"
Compiles but prints a friendly warning:
gatabase.nim(207, 57) Warning: DELETE FROM without WHERE.
Typical bad practice of using SELECT *
everywhere:
exec []:
select '*'
Compiles but prints a friendly warning:
gatabase.nim(20, 50) Warning: SELECT * is bad practice.
Non-SQL wont compile, even if its valid Nim:
sqls:
discard
sqls:
echo "This is not SQL, wont compile"
$ nimble test
[Suite] Gatabase ORM Tests
[OK] let INSERT INTO
[OK] let SELECT ... FROM ... WHERE
[OK] let SELECT ... (comment) ... FROM ... COMMENT
[OK] let SELECT ... FROM ... LIMIT ... OFFSET
[OK] let INSERT INTO
[OK] let UNION ALL ... ORBER BY ... IS NOT NULL
[OK] let SELECT DISTINCT ... FROM ... WHERE
[OK] let INSERT INTO
[OK] const SELECT ... FROM ... WHERE
[OK] const SELECT ... (comment) ... FROM ... COMMENT
[OK] const SELECT ... FROM ... LIMIT ... OFFSET
[OK] const INSERT INTO
[OK] const UNION ALL ... ORBER BY ... IS NOT NULL
[OK] const INTERSECT ALL
[OK] const EXCEPT ALL
[OK] const SELECT DISTINCT ... FROM ... WHERE
[OK] var CASE
[OK] var SELECT MAX .. WHERE EXISTS ... OFFSET ... LIMIT ... ORDER BY
[OK] SELECT TRIM
[OK] SELECT ROUND
[OK] var DELETE FROM WHERE
":memory:"
with a "person"
table. +20 Tests.Object-relational mapping in computer science is a programming technique for convertingdata between incompatible type systems using object-oriented programming languages.
Feel free to contribute to Wikipedia.
Yes.
No.
No.
No.
No.
It does NOT make Parameter substitution internally, its delegated to standard library.
Yes.
Yes.
We try to keep as similar as possible, but SQLite is very limited.
Nimrod(已改名为 Nim)是一种静态类型的编译系统编程语言。它结合了 Python、Ada和Modula等成熟语言的成功理念。 高效的 Nim生成不依赖于虚拟机的本机无依赖可执行文件,这些可执行文件很小并且允许重新分配。 Nim编译器和生成的可执行文件支持所有主要平台,例如Windows,Linux,BSD和macOS。 在C ++和Rust的启发下,Nim的内存管理是确定性的,并且可以使用
nim-asciitables simple terminal ascii tables for nim DEPRECATION project is deprecated in favor for nim-terminaltables How to use asciitables has a very simple api setHeaders to set column names addRo
nim-terminaltables terminal tables for nim API API docs available hereterminaltables has a very small API newUnicodeTable uses unicodeStyle newAsciiTable uses asciiStyle Table style is configurable us
Dashing is a library to quickly create terminal-based dashboards in Nim. Dashing provides high-level components: vertical and horizontal charts, gauges, log panes, text windows and screen splitting. I
allographer An asynchronous query builder library inspired by Laravel/PHP and Orator/Python for Nim Easy to access Rdb Query Builder import asyncdispatchimport allographer/connectionimport allographer
libssh2.nim Nim wrapper for libssh2 For document please refer to libssh2 website Requirements In order to use this wrapper, libssh2 must installed on your system: Mac OSX:$ port install libssh2 Ubuntu