tpersist

Difference between version 2 and 5 - Previous - Next
Database Persistence Layer for TCL

Contact: neophytos (at) gmail (dot) com

https://github.com/jerily/tpersist%|%tpersist git repo%|%

This module was generated with help from AI.


****Releases****

* 2026-10-31 https://github.com/jerily/tpersist/releases/tag/v0.1.0%|%tpersist-v0.1.0%|% (Initial release of tpersist, a Tcl SQL toolkit inspired by SQLAlchemy Core.)

----
****Examples****
***Examples***


Here are some examples with optional [TclOO] API:

======    package require tpersist::oo
    namespace import ::tpersist::db_*
    set database [::tpersist::oo::Database new -database :memory:]
try {
    $database create_table [db_define_table users {
        id {type integer primary_key 1 auto_increment 1}
        name {type text}
        age {type integer}
    }]
    set insert [$database insert users]
    $database transaction {
        foreach {name age} {Alice 30 Bob 17 Carol 42} {
            $insert values [dict create name $name age $age]
            $insert execute
        }
    }

    # set everyone [$database select users -columns {name age}]
    set everyone [$database select users -expr {name, age}]
    set adults [$everyone fork]
    # $adults where [db_ge [db_col age] [db_value 18 -type integer]]
    $adults where -expr {age >= 18}
    # $adults order_by [db_desc [db_col age]]
    $adults order_by -expr {age DESC}
    $adults limit 10
    puts "Adults: [$adults all]"
    puts "Everyone: [$everyone all]"

    # Interoperate with procedural code using the same statement dictionary.
    puts "SQL: [dict get [db_compile [$adults statement]] sql]"
    puts "Params: [dict get [db_compile [$adults statement]] params]"} finally {
    # Also destroys its queries and disconnects the TDBC connection.
    $database destroy}

# Adults: {name Carol age 42} {name Alice age 30}
# Everyone: {name Alice age 30} {name Bob age 17} {name Carol age 42}
# SQL: SELECT "name", "age" FROM "users" WHERE ("age" >= :p1) ORDER BY "age" DESC LIMIT :p2
# Params: p1 18 p2 10

======
****Transactions****

======
package require tpersist::oo
namespace import ::tpersist::db_*

set database [::tpersist::oo::Database new -database :memory:]
try {
    $database create_table [db_define_table accounts {name {type text primary_key 1} balance {type integer not_null 1}}]
    set insert [$database insert accounts]
    $database transaction {
        $insert values {name Alice balance 100}
        $insert execute
        $insert values {name Bob balance 20}
        $insert execute
    }
    $database transaction {
        set alice [$database update accounts]
        # $alice where [db_eq [db_col name] [db_value Alice]]
        $alice where -expr {name = 'Alice'}
        set bob [$database update accounts]
        # $bob where [db_eq [db_col name] [db_value Bob]]
        $bob where -expr {name = 'Bob'}
        $alice values {balance 90}
        $alice execute
        $bob values {balance 30}
        $bob execute

        # This nested scope has its own savepoint. Its failure does not undo
        # the successful transfer in the surrounding transaction.
        if {[catch {$database transaction {
            # Rollback affects database rows, not mutable query objects.
            set adjustment [$alice fork]
            $adjustment values {balance 0}
            $adjustment execute
            error "Rejected optional adjustment"
        }} message]} { puts $message }
    }
    set accounts [$database select accounts]
    # $accounts order_by name
    $accounts order_by -expr {name}
    puts "After transfer: [$accounts all]"
    $database commit

    # Explicit savepoints use the procedural API with a borrowed connection.
    set connection [$database connection]
    $database begin
    db_savepoint $connection experiment
    set remove [$database delete accounts]
    $remove execute
    db_rollback_to $connection experiment
    db_release $connection experiment
    $database commit
    puts "After undo: [$accounts all]"
} finally {
    # Also destroys its queries and disconnects the TDBC connection.
    $database destroy
}

======