2026-01-25 01:47:47 +00:00
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title > dataset - Wren-CLI Manual</ title >
< link rel = "stylesheet" href = "../css/style.css" >
</ head >
< body >
< button class = "mobile-menu-toggle" > Menu</ button >
< div class = "container" >
< aside class = "sidebar" >
< div class = "sidebar-header" >
< h1 >< a href = "../index.html" > Wren-CLI</ a ></ h1 >
< div class = "version" > v0.4.0</ div >
</ div >
< nav class = "sidebar-nav" >
< div class = "section" >
< span class = "section-title" > Getting Started</ span >
< ul >
< li >< a href = "../getting-started/index.html" > Overview</ a ></ li >
< li >< a href = "../getting-started/installation.html" > Installation</ a ></ li >
< li >< a href = "../getting-started/first-script.html" > First Script</ a ></ li >
< li >< a href = "../getting-started/repl.html" > Using the REPL</ a ></ li >
</ ul >
</ div >
< div class = "section" >
< span class = "section-title" > Language</ span >
< ul >
< li >< a href = "../language/index.html" > Syntax Overview</ a ></ li >
< li >< a href = "../language/classes.html" > Classes</ a ></ li >
< li >< a href = "../language/methods.html" > Methods</ a ></ li >
< li >< a href = "../language/control-flow.html" > Control Flow</ a ></ li >
< li >< a href = "../language/fibers.html" > Fibers</ a ></ li >
< li >< a href = "../language/modules.html" > Modules</ a ></ li >
</ ul >
</ div >
< div class = "section" >
< span class = "section-title" > API Reference</ span >
< ul >
< li >< a href = "index.html" > Overview</ a ></ li >
2026-01-25 03:58:39 +00:00
< li >< a href = "string.html" > String</ a ></ li >
< li >< a href = "number.html" > Num</ a ></ li >
2026-01-25 01:47:47 +00:00
< li >< a href = "http.html" > http</ a ></ li >
< li >< a href = "websocket.html" > websocket</ a ></ li >
< li >< a href = "tls.html" > tls</ a ></ li >
< li >< a href = "net.html" > net</ a ></ li >
< li >< a href = "dns.html" > dns</ a ></ li >
< li >< a href = "json.html" > json</ a ></ li >
< li >< a href = "base64.html" > base64</ a ></ li >
< li >< a href = "regex.html" > regex</ a ></ li >
< li >< a href = "jinja.html" > jinja</ a ></ li >
< li >< a href = "crypto.html" > crypto</ a ></ li >
< li >< a href = "os.html" > os</ a ></ li >
< li >< a href = "env.html" > env</ a ></ li >
< li >< a href = "signal.html" > signal</ a ></ li >
< li >< a href = "subprocess.html" > subprocess</ a ></ li >
< li >< a href = "sqlite.html" > sqlite</ a ></ li >
< li >< a href = "datetime.html" > datetime</ a ></ li >
< li >< a href = "timer.html" > timer</ a ></ li >
< li >< a href = "io.html" > io</ a ></ li >
2026-01-25 03:58:39 +00:00
< li >< a href = "pathlib.html" > pathlib</ a ></ li >
2026-01-25 01:47:47 +00:00
< li >< a href = "scheduler.html" > scheduler</ a ></ li >
< li >< a href = "math.html" > math</ a ></ li >
< li >< a href = "uuid.html" > uuid</ a ></ li >
< li >< a href = "html.html" > html</ a ></ li >
< li >< a href = "argparse.html" > argparse</ a ></ li >
< li >< a href = "wdantic.html" > wdantic</ a ></ li >
< li >< a href = "dataset.html" class = "active" > dataset</ a ></ li >
< li >< a href = "markdown.html" > markdown</ a ></ li >
< li >< a href = "web.html" > web</ a ></ li >
</ ul >
</ div >
< div class = "section" >
< span class = "section-title" > Tutorials</ span >
< ul >
< li >< a href = "../tutorials/index.html" > Tutorial List</ a ></ li >
</ ul >
</ div >
< div class = "section" >
< span class = "section-title" > How-To Guides</ span >
< ul >
< li >< a href = "../howto/index.html" > How-To List</ a ></ li >
</ ul >
</ div >
</ nav >
</ aside >
< main class = "content" >
< nav class = "breadcrumb" >
< a href = "../index.html" > Home</ a >
< span class = "separator" > /</ span >
< a href = "index.html" > API Reference</ a >
< span class = "separator" > /</ span >
< span > dataset</ span >
</ nav >
< article >
< h1 > dataset</ h1 >
< p > The < code > dataset</ code > module provides a simple ORM-like interface for SQLite databases with automatic schema management. Tables and columns are created automatically as you insert data.</ p >
< pre >< code > import "dataset" for Dataset, Table</ code ></ pre >
< h2 > Dataset Class</ h2 >
< div class = "class-header" >
< h3 > Dataset</ h3 >
< p > Database connection and table access</ p >
</ div >
< h3 > Constructors</ h3 >
< div class = "method-signature" >
< span class = "method-name" > Dataset.open</ span > (< span class = "param" > path</ span > ) → < span class = "type" > Dataset</ span >
</ div >
< p > Opens or creates a SQLite database file.</ p >
< ul class = "param-list" >
< li >< span class = "param-name" > path</ span > < span class = "param-type" > (String)</ span > - Path to the database file</ li >
</ ul >
< pre >< code > var db = Dataset.open("data.db")</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > Dataset.memory</ span > () → < span class = "type" > Dataset</ span >
</ div >
< p > Creates an in-memory database (data is lost when closed).</ p >
< pre >< code > var db = Dataset.memory()</ code ></ pre >
< h3 > Properties</ h3 >
< div class = "method-signature" >
< span class = "method-name" > db</ span > → < span class = "type" > Database</ span >
</ div >
< p > Access to the underlying SQLite database for raw queries.</ p >
< div class = "method-signature" >
< span class = "method-name" > tables</ span > → < span class = "type" > List</ span >
</ div >
< p > List of table names in the database.</ p >
< h3 > Subscript Access</ h3 >
< div class = "method-signature" >
< span class = "method-name" > [tableName]</ span > → < span class = "type" > Table</ span >
</ div >
< p > Gets a table by name. Creates the table if it does not exist on first insert.</ p >
< pre >< code > var users = db["users"]</ code ></ pre >
< h3 > Instance Methods</ h3 >
< div class = "method-signature" >
< span class = "method-name" > close</ span > ()
</ div >
< p > Closes the database connection.</ p >
< h2 > Table Class</ h2 >
< div class = "class-header" >
< h3 > Table</ h3 >
< p > CRUD operations on a database table</ p >
</ div >
< h3 > Properties</ h3 >
< div class = "method-signature" >
< span class = "method-name" > name</ span > → < span class = "type" > String</ span >
</ div >
< p > The table name.</ p >
< div class = "method-signature" >
< span class = "method-name" > columns</ span > → < span class = "type" > Map</ span >
</ div >
< p > Map of column names to SQL types.</ p >
< h3 > Instance Methods</ h3 >
< div class = "method-signature" >
< span class = "method-name" > insert</ span > (< span class = "param" > record</ span > ) → < span class = "type" > Map</ span >
</ div >
< p > Inserts a record and returns it with generated < code > uid</ code > and < code > created_at</ code > .</ p >
< ul class = "param-list" >
< li >< span class = "param-name" > record</ span > < span class = "param-type" > (Map)</ span > - Data to insert</ li >
< li >< span class = "returns" > Returns:</ span > Inserted record with uid and created_at</ li >
</ ul >
< pre >< code > var user = db["users"].insert({
"name": "Alice",
"email": "alice@example.com"
})
System.print(user["uid"]) // auto-generated UUID</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > update</ span > (< span class = "param" > record</ span > ) → < span class = "type" > Num</ span >
</ div >
< p > Updates a record by uid. Returns number of rows affected.</ p >
< ul class = "param-list" >
< li >< span class = "param-name" > record</ span > < span class = "param-type" > (Map)</ span > - Must contain < code > uid</ code > and fields to update</ li >
</ ul >
< pre >< code > db["users"].update({
"uid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Alice Smith"
})</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > delete</ span > (< span class = "param" > uid</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Soft deletes a record (sets < code > deleted_at</ code > timestamp). Returns true if record was deleted.</ p >
< pre >< code > db["users"].delete("550e8400-e29b-41d4-a716-446655440000")</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > hardDelete</ span > (< span class = "param" > uid</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Permanently deletes a record from the database.</ p >
< div class = "method-signature" >
< span class = "method-name" > find</ span > (< span class = "param" > conditions</ span > ) → < span class = "type" > List</ span >
</ div >
< p > Finds records matching conditions. Returns list of records (excludes soft-deleted).</ p >
< pre >< code > var admins = db["users"].find({"role": "admin"})</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > findOne</ span > (< span class = "param" > conditions</ span > ) → < span class = "type" > Map|null</ span >
</ div >
< p > Finds first record matching conditions or null.</ p >
< pre >< code > var user = db["users"].findOne({"email": "alice@example.com"})</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > all</ span > () → < span class = "type" > List</ span >
</ div >
< p > Returns all non-deleted records.</ p >
< div class = "method-signature" >
< span class = "method-name" > count</ span > () → < span class = "type" > Num</ span >
</ div >
< p > Returns count of non-deleted records.</ p >
< h2 > Query Operators</ h2 >
< p > Use suffixes in condition keys for comparison operators:</ p >
< table >
< tr >
< th > Suffix</ th >
< th > SQL Operator</ th >
< th > Example</ th >
</ tr >
< tr >
< td >< code > __gt</ code ></ td >
< td > > </ td >
< td >< code > {"age__gt": 18}</ code ></ td >
</ tr >
< tr >
< td >< code > __lt</ code ></ td >
< td > < </ td >
< td >< code > {"price__lt": 100}</ code ></ td >
</ tr >
< tr >
< td >< code > __gte</ code ></ td >
< td > > =</ td >
< td >< code > {"score__gte": 90}</ code ></ td >
</ tr >
< tr >
< td >< code > __lte</ code ></ td >
< td > < =</ td >
< td >< code > {"score__lte": 100}</ code ></ td >
</ tr >
< tr >
< td >< code > __ne</ code ></ td >
< td > !=</ td >
< td >< code > {"status__ne": "deleted"}</ code ></ td >
</ tr >
< tr >
< td >< code > __like</ code ></ td >
< td > LIKE</ td >
< td >< code > {"name__like": "A\%"}</ code ></ td >
</ tr >
< tr >
< td >< code > __in</ code ></ td >
< td > IN</ td >
< td >< code > {"status__in": ["active", "pending"]}</ code ></ td >
</ tr >
< tr >
< td >< code > __null</ code ></ td >
< td > IS NULL / IS NOT NULL</ td >
< td >< code > {"deleted_at__null": true}</ code ></ td >
</ tr >
</ table >
< h2 > Automatic Features</ h2 >
< h3 > Auto-Generated Fields</ h3 >
< ul >
< li >< code > uid</ code > - UUID v4 primary key (auto-generated if not provided)</ li >
< li >< code > created_at</ code > - ISO timestamp (auto-generated on insert)</ li >
< li >< code > deleted_at</ code > - ISO timestamp (set by soft delete)</ li >
</ ul >
< h3 > Auto Schema</ h3 >
< ul >
< li > Tables are created automatically on first insert</ li >
< li > Columns are added automatically when new fields appear</ li >
< li > Type inference: Num → INTEGER/REAL, Bool → INTEGER, Map/List → TEXT (JSON)</ li >
</ ul >
< h3 > JSON Serialization</ h3 >
< p > Maps and Lists are automatically serialized to JSON when stored and deserialized when retrieved.</ p >
< h2 > Examples</ h2 >
< h3 > Basic CRUD</ h3 >
< pre >< code > import "dataset" for Dataset
var db = Dataset.open("app.db")
var users = db["users"]
var user = users.insert({
"name": "Alice",
"email": "alice@example.com",
"settings": {"theme": "dark", "notifications": true}
})
System.print("Created user: %(user["uid"])")
users.update({
"uid": user["uid"],
"name": "Alice Smith"
})
var found = users.findOne({"email": "alice@example.com"})
System.print("Found: %(found["name"])")
users.delete(user["uid"])
db.close()</ code ></ pre >
< h3 > Querying with Operators</ h3 >
< pre >< code > import "dataset" for Dataset
var db = Dataset.open("products.db")
var products = db["products"]
var expensive = products.find({"price__gt": 100})
var cheap = products.find({"price__lte": 10})
var search = products.find({"name__like": "\%phone\%"})
var featured = products.find({
"category__in": ["electronics", "gadgets"],
"stock__gt": 0
})
db.close()</ code ></ pre >
< h3 > Working with JSON Data</ h3 >
< pre >< code > import "dataset" for Dataset
var db = Dataset.memory()
db["posts"].insert({
"title": "First Post",
"tags": ["wren", "programming", "tutorial"],
"metadata": {
"author": "Alice",
"views": 100,
"featured": true
}
})
var post = db["posts"].findOne({"title": "First Post"})
System.print(post["tags"]) // ["wren", "programming", "tutorial"]
System.print(post["metadata"]) // {"author": "Alice", ...}</ code ></ pre >
< div class = "admonition note" >
< div class = "admonition-title" > Note</ div >
< p > Soft delete is the default behavior. Records are not permanently removed but marked with a < code > deleted_at</ code > timestamp. Use < code > hardDelete()</ code > for permanent removal. All query methods automatically exclude soft-deleted records.</ p >
</ div >
< div class = "admonition warning" >
< div class = "admonition-title" > Warning</ div >
< p > The < code > uid</ code > field is the primary key. Do not use < code > id</ code > as a field name. If you provide a < code > uid</ code > during insert, it will be used instead of auto-generating one.</ p >
</ div >
</ article >
< footer class = "page-footer" >
< a href = "wdantic.html" class = "prev" > wdantic</ a >
< a href = "markdown.html" class = "next" > markdown</ a >
</ footer >
</ main >
</ div >
< script src = "../js/main.js" ></ script >
</ body >
</ html >