This commit is contained in:
2025-12-01 20:53:20 +01:00
parent 88680f1954
commit 690af291b5
185 changed files with 466 additions and 849 deletions

View File

@@ -1,51 +1,10 @@
# module orm
## Contents
- [Constants](#Constants)
- [new_query](#new_query)
- [orm_select_gen](#orm_select_gen)
- [orm_stmt_gen](#orm_stmt_gen)
- [orm_table_gen](#orm_table_gen)
- [Connection](#Connection)
- [Primitive](#Primitive)
- [QueryBuilder[T]](#QueryBuilder[T])
- [reset](#reset)
- [where](#where)
- [or_where](#or_where)
- [order](#order)
- [limit](#limit)
- [offset](#offset)
- [select](#select)
- [set](#set)
- [query](#query)
- [count](#count)
- [insert](#insert)
- [insert_many](#insert_many)
- [update](#update)
- [delete](#delete)
- [create](#create)
- [drop](#drop)
- [last_id](#last_id)
- [MathOperationKind](#MathOperationKind)
- [OperationKind](#OperationKind)
- [OrderType](#OrderType)
- [SQLDialect](#SQLDialect)
- [StmtKind](#StmtKind)
- [InfixType](#InfixType)
- [Null](#Null)
- [QueryBuilder](#QueryBuilder)
- [QueryData](#QueryData)
- [SelectConfig](#SelectConfig)
- [Table](#Table)
- [TableField](#TableField)
## Constants
```v
const num64 = [typeof[i64]().idx, typeof[u64]().idx]
```
[[Return to contents]](#Contents)
```v
const nums = [
@@ -59,7 +18,7 @@ const nums = [
]
```
[[Return to contents]](#Contents)
```v
const float = [
@@ -68,31 +27,31 @@ const float = [
]
```
[[Return to contents]](#Contents)
```v
const type_string = typeof[string]().idx
```
[[Return to contents]](#Contents)
```v
const serial = -1
```
[[Return to contents]](#Contents)
```v
const time_ = -2
```
[[Return to contents]](#Contents)
```v
const enum_ = -3
```
[[Return to contents]](#Contents)
```v
const type_idx = {
@@ -111,19 +70,19 @@ const type_idx = {
}
```
[[Return to contents]](#Contents)
```v
const string_max_len = 2048
```
[[Return to contents]](#Contents)
```v
const null_primitive = Primitive(Null{})
```
[[Return to contents]](#Contents)
## new_query
```v
@@ -132,7 +91,7 @@ fn new_query[T](conn Connection) &QueryBuilder[T]
new_query create a new query object for struct `T`
[[Return to contents]](#Contents)
## orm_select_gen
```v
@@ -141,7 +100,7 @@ fn orm_select_gen(cfg SelectConfig, q string, num bool, qm string, start_pos int
Generates an sql select stmt, from universal parameter orm - See SelectConfig q, num, qm, start_pos - see orm_stmt_gen where - See QueryData
[[Return to contents]](#Contents)
## orm_stmt_gen
```v
@@ -151,7 +110,7 @@ fn orm_stmt_gen(sql_dialect SQLDialect, table Table, q string, kind StmtKind, nu
Generates an sql stmt, from universal parameter q - The quotes character, which can be different in every type, so it's variable num - Stmt uses nums at prepared statements (? or ?1) qm - Character for prepared statement (qm for question mark, as in sqlite) start_pos - When num is true, it's the start position of the counter
[[Return to contents]](#Contents)
## orm_table_gen
```v
@@ -161,7 +120,7 @@ fn orm_table_gen(sql_dialect SQLDialect, table Table, q string, defaults bool, d
Generates an sql table stmt, from universal parameter table - Table struct q - see orm_stmt_gen defaults - enables default values in stmt def_unique_len - sets default unique length for texts fields - See TableField sql_from_v - Function which maps type indices to sql type names alternative - Needed for msdb
[[Return to contents]](#Contents)
## Connection
```v
@@ -181,7 +140,7 @@ Interfaces gets called from the backend and can be implemented Since the orm sup
Every function without last_id() returns an optional, which returns an error if present last_id returns the last inserted id of the db
[[Return to contents]](#Contents)
## Primitive
```v
@@ -203,7 +162,7 @@ type Primitive = InfixType
| []Primitive
```
[[Return to contents]](#Contents)
## QueryBuilder[T]
## reset
@@ -213,7 +172,7 @@ fn (qb_ &QueryBuilder[T]) reset() &QueryBuilder[T]
reset reset a query object, but keep the connection and table name
[[Return to contents]](#Contents)
## where
```v
@@ -222,7 +181,7 @@ fn (qb_ &QueryBuilder[T]) where(condition string, params ...Primitive) !&QueryBu
where create a `where` clause, it will `AND` with previous `where` clause. valid token in the `condition` include: `field's names`, `operator`, `(`, `)`, `?`, `AND`, `OR`, `||`, `&&`, valid `operator` incldue: `=`, `!=`, `<>`, `>=`, `<=`, `>`, `<`, `LIKE`, `ILIKE`, `IS NULL`, `IS NOT NULL`, `IN`, `NOT IN` example: `where('(a > ? AND b <= ?) OR (c <> ? AND (x = ? OR y = ?))', a, b, c, x, y)`
[[Return to contents]](#Contents)
## or_where
```v
@@ -231,7 +190,7 @@ fn (qb_ &QueryBuilder[T]) or_where(condition string, params ...Primitive) !&Quer
or_where create a `where` clause, it will `OR` with previous `where` clause.
[[Return to contents]](#Contents)
## order
```v
@@ -240,7 +199,7 @@ fn (qb_ &QueryBuilder[T]) order(order_type OrderType, field string) !&QueryBuild
order create a `order` clause
[[Return to contents]](#Contents)
## limit
```v
@@ -249,7 +208,7 @@ fn (qb_ &QueryBuilder[T]) limit(limit int) !&QueryBuilder[T]
limit create a `limit` clause
[[Return to contents]](#Contents)
## offset
```v
@@ -258,7 +217,7 @@ fn (qb_ &QueryBuilder[T]) offset(offset int) !&QueryBuilder[T]
offset create a `offset` clause
[[Return to contents]](#Contents)
## select
```v
@@ -267,7 +226,7 @@ fn (qb_ &QueryBuilder[T]) select(fields ...string) !&QueryBuilder[T]
select create a `select` clause
[[Return to contents]](#Contents)
## set
```v
@@ -276,7 +235,7 @@ fn (qb_ &QueryBuilder[T]) set(assign string, values ...Primitive) !&QueryBuilder
set create a `set` clause for `update`
[[Return to contents]](#Contents)
## query
```v
@@ -285,7 +244,7 @@ fn (qb_ &QueryBuilder[T]) query() ![]T
query start a query and return result in struct `T`
[[Return to contents]](#Contents)
## count
```v
@@ -294,7 +253,7 @@ fn (qb_ &QueryBuilder[T]) count() !int
count start a count query and return result
[[Return to contents]](#Contents)
## insert
```v
@@ -303,7 +262,7 @@ fn (qb_ &QueryBuilder[T]) insert[T](value T) !&QueryBuilder[T]
insert insert a record into the database
[[Return to contents]](#Contents)
## insert_many
```v
@@ -312,7 +271,7 @@ fn (qb_ &QueryBuilder[T]) insert_many[T](values []T) !&QueryBuilder[T]
insert_many insert records into the database
[[Return to contents]](#Contents)
## update
```v
@@ -321,7 +280,7 @@ fn (qb_ &QueryBuilder[T]) update() !&QueryBuilder[T]
update update record(s) in the database
[[Return to contents]](#Contents)
## delete
```v
@@ -330,7 +289,7 @@ fn (qb_ &QueryBuilder[T]) delete() !&QueryBuilder[T]
delete delete record(s) in the database
[[Return to contents]](#Contents)
## create
```v
@@ -339,7 +298,7 @@ fn (qb_ &QueryBuilder[T]) create() !&QueryBuilder[T]
create create a table
[[Return to contents]](#Contents)
## drop
```v
@@ -348,7 +307,7 @@ fn (qb_ &QueryBuilder[T]) drop() !&QueryBuilder[T]
drop drop a table
[[Return to contents]](#Contents)
## last_id
```v
@@ -357,7 +316,7 @@ fn (qb_ &QueryBuilder[T]) last_id() int
last_id returns the last inserted id of the db
[[Return to contents]](#Contents)
## MathOperationKind
```v
@@ -369,7 +328,7 @@ enum MathOperationKind {
}
```
[[Return to contents]](#Contents)
## OperationKind
```v
@@ -389,7 +348,7 @@ enum OperationKind {
}
```
[[Return to contents]](#Contents)
## OrderType
```v
@@ -399,7 +358,7 @@ enum OrderType {
}
```
[[Return to contents]](#Contents)
## SQLDialect
```v
@@ -411,7 +370,7 @@ enum SQLDialect {
}
```
[[Return to contents]](#Contents)
## StmtKind
```v
@@ -422,7 +381,7 @@ enum StmtKind {
}
```
[[Return to contents]](#Contents)
## InfixType
```v
@@ -434,14 +393,14 @@ pub:
}
```
[[Return to contents]](#Contents)
## Null
```v
struct Null {}
```
[[Return to contents]](#Contents)
## QueryBuilder
```v
@@ -456,7 +415,7 @@ pub mut:
}
```
[[Return to contents]](#Contents)
## QueryData
```v
@@ -474,7 +433,7 @@ pub mut:
Examples for QueryData in SQL: abc == 3 && b == 'test' => fields[abc, b]; data[3, 'test']; types[index of int, index of string]; kinds[.eq, .eq]; is_and[true]; Every field, data, type & kind of operation in the expr share the same index in the arrays is_and defines how they're addicted to each other either and or or parentheses defines which fields will be inside () auto_fields are indexes of fields where db should generate a value when absent in an insert
[[Return to contents]](#Contents)
## SelectConfig
```v
@@ -496,7 +455,7 @@ pub mut:
table - Table struct is_count - Either the data will be returned or an integer with the count has_where - Select all or use a where expr has_order - Order the results order - Name of the column which will be ordered order_type - Type of order (asc, desc) has_limit - Limits the output data primary - Name of the primary field has_offset - Add an offset to the result fields - Fields to select types - Types to select
[[Return to contents]](#Contents)
## Table
```v
@@ -507,7 +466,7 @@ pub mut:
}
```
[[Return to contents]](#Contents)
## TableField
```v
@@ -521,7 +480,3 @@ pub mut:
is_arr bool
}
```
[[Return to contents]](#Contents)
#### Powered by vdoc. Generated on: 2 Sep 2025 07:19:37

View File

@@ -0,0 +1,282 @@
# V ORM — Developer Cheat Sheet
*Fast reference for Struct Mapping, CRUD, Attributes, Query Builder, and Usage Patterns*
---
## 1. What V ORM Is
* Built-in ORM for **SQLite**, **MySQL**, **PostgreSQL**
* Unified V-syntax; no SQL string building
* Automatic query sanitization
* Compile-time type & field checks
* Structs map directly to tables
---
## 2. Define Models (Struct ↔ Table)
### Basic Example
```v
struct User {
id int @[primary; sql: serial]
name string
email string @[unique]
}
```
### Nullable Fields
```v
age ?int // allows NULL
```
---
## 3. Struct Attributes
### Table-level
| Attribute | Meaning |
| ---------------------------- | ------------------------- |
| `@[table: 'custom_name']` | Override table name |
| `@[comment: '...']` | Table comment |
| `@[index: 'field1, field2']` | Creates multi-field index |
---
## 4. Field Attributes
| Attribute | Description |
| ------------------------------------------------ | ---------------------------- |
| `@[primary]` | Primary key |
| `@[unique]` | UNIQUE constraint |
| `@[unique: 'group']` | Composite unique group |
| `@[skip]` / `@[sql: '-']` | Ignore field |
| `@[sql: serial]` | Auto-increment key |
| `@[sql: 'col_name']` | Rename column |
| `@[sql_type: 'BIGINT']` | Force SQL type |
| `@[default: 'CURRENT_TIMESTAMP']` | Raw SQL default |
| `@[fkey: 'field']` | Foreign key on a child array |
| `@[references]`, `@[references: 'table(field)']` | FK relationship |
| `@[index]` | Index on field |
| `@[comment: '...']` | Column comment |
### Example
```v
struct Post {
id int @[primary; sql: serial]
title string
body string
author_id int @[references: 'users(id)']
}
```
---
## 5. ORM SQL Block (Primary API)
### Create Table
```v
sql db {
create table User
}!
```
### Drop Table
```v
sql db {
drop table User
}!
```
### Insert
```v
id := sql db {
insert new_user into User
}!
```
### Select
```v
users := sql db {
select from User where age > 18 && name != 'Tom'
order by id desc
limit 10
}!
```
### Update
```v
sql db {
update User set name = 'Alice' where id == 1
}!
```
### Delete
```v
sql db {
delete from User where id > 100
}!
```
---
## 6. Relationships
### One-to-Many
```v
struct Parent {
id int @[primary; sql: serial]
children []Child @[fkey: 'parent_id']
}
struct Child {
id int @[primary; sql: serial]
parent_id int
}
```
---
## 7. Notes on `time.Time`
* Stored as integer timestamps
* SQL defaults like `NOW()` / `CURRENT_TIMESTAMP` **dont work** for `time.Time` with V ORM defaults
* Use `@[default: 'CURRENT_TIMESTAMP']` only with custom SQL types
---
## 8. Query Builder API (Dynamic Queries)
### Create Builder
```v
mut qb := orm.new_query[User](db)
```
### Create Table
```v
qb.create()!
```
### Insert Many
```v
qb.insert_many(users)!
```
### Select
```v
results := qb
.select('id, name')!
.where('age > ?', 18)!
.order('id DESC')!
.limit(20)!
.query()!
```
### Update
```v
qb
.set('name = ?', 'NewName')!
.where('id = ?', 1)!
.update()!
```
### Delete
```v
qb.where('created_at IS NULL')!.delete()!
```
### Complex WHERE
```v
qb.where(
'(salary > ? AND age < ?) OR (role LIKE ?)',
3000, 40, '%engineer%'
)!
```
---
## 9. Connecting to Databases
### SQLite
```v
import db.sqlite
db := sqlite.connect('db.sqlite')!
```
### MySQL
```v
import db.mysql
db := mysql.connect(host: 'localhost', user: 'root', password: '', dbname: 'test')!
```
### PostgreSQL
```v
import db.pg
db := pg.connect(conn_str)!
```
---
## 10. Full Example (Complete CRUD)
```v
import db.sqlite
struct Customer {
id int @[primary; sql: serial]
name string
email string @[unique]
}
fn main() {
db := sqlite.connect('customers.db')!
sql db { create table Customer }!
new_c := Customer{name: 'Alice', email: 'alice@x.com'}
id := sql db { insert new_c into Customer }!
println(id)
list := sql db { select from Customer where name == 'Alice' }!
println(list)
sql db { update Customer set name = 'Alicia' where id == id }!
sql db { delete from Customer where id == id }!
}
```
---
## 11. Best Practices
* Always use `sql db { ... }` for static queries
* Use QueryBuilder for dynamic conditions
* Prefer `sql: serial` for primary keys
* Explicitly define foreign keys
* Use `?T` for nullable fields
* Keep struct names identical to table names unless overridden