Version 11 of Playing ISBL

Updated 2011-04-04 12:51:56 by jbr

JBR - 2011-04-02

I first read about ISBL and PRTV[L1 ](pdf) in early 2008 and it has been running about my thoughts ever since. This is mostly because I find SQL to be unintuitive and difficult to understand. I rather like something more algebraic.

I didn't want to write a complete database engine so here is a package that is a thin layer translating ISBL to sqlite. The main ISBL operators are available. Some features are a little different (delayed evaluation as views). The type system of "Domains" is absent. As with the original ISBL system the database update is problematic but I have provided a nice insert and delete with "+=" and "-=". I'll add update if I get some inspiration.

Here are the pieces:

Some examples to test it:

 lappend auto_path /home/john/lib

 ::tcl::tm::path add .

 package require isbl 1

 isbl create db data.db

 proc ? { 1 2 } { if { $1 ne [string trim $2] } { error "Huh? $1 ne $2" } }


 # Table construction
 #
 db eval { T  = % 1->x, 2->y }                          ; # make some tables from tuples
 db eval { T  = % 1->x, 4->y }                          ; # Assignment deletes old data!
 db eval { K  = % 1->x, 5->l }

 db eval { T += % 5->x, 9->y }                          ; # Insert
 db eval { T += % 7->x, 9->y }                          ; # Insert
 db eval { T -= % 7->x }                                ; # Delete


 db eval { X := T % x }                                 ; # isbl reference by name (sql view)
 ? [db eval X] { 1 5 }

 # Relational Operators
 #
 ? [db eval { T }]              { 1 4 5 9 }             ; # A single table

 db eval { T += % 5->x, 9->y }                          ; # Insert this again - It should replace
 db eval { T += % 5->x, 9->y }                          ; # Insert this again - It should replace

 ? [db eval { T }]              { 1 4 5 9 }             ; # Better not have changed

 ? [db eval { T % x }]          { 1 5 }                 ; # Project
 ? [db eval { (T + K) % x }]    { 1 5 }                 ; # Union
 ? [db eval { T % x . K % x }]  { 1 }                   ; # Intersect
 ? [db eval { T % x - K % x }]  { 5 }                   ; # Difference
 ? [db eval { T * K }]          { 1 4 5 }               ; # Join
 ? [db eval { T : x == 1 }]     { 1 4 }                 ; # Select

 ? [db eval { T * K % l -> x, x -> f }] { 5 9 1 }       ; # Column mapping w/as
 ? [db eval { T * K % l as x, x as f }] { 5 9 1 }       ; # Column mapping w/->


 # Special forms
 #
 db function int          mod2 { x } { expr { int($x) % 2 } }
 db function { real int } func { x } { list [expr $x*2] 2 }

 ? [db eval { T : mod2(x) }]       { 1 4 5 9 }  ; # Select from function return value
 ? [db eval { T % func(x | a,b) }] { 2 2 10 2 } ; # Project for function w/ tuple return


 # Project and remove columns.
 #
 ? [db eval { T % * !x }]          { 4 9 }
 ? [db eval { T %   !x }]          { 4 9 }
 ? [db eval { T % y  * }]          { 4 1 9 5 }

A Makefile to wrap it all up:

 PT=/home/john/src/tcllib-1.13/modules/pt/pt

 VERSION = 1.0

 isbl : main.tcl isbl-$(VERSION).tm
        sdx wrap isbl -runtime `which tclkit8.6`
        make test

 isbl-$(VERSION).tm : unsource isbl.tcl isbl-parser.tcl isbl-actions.tcl
        unsource isbl.tcl > isbl-$(VERSION).tm

 isbl-actions.tcl : parser-actions isbl-parser.peg isbl-actions.act
        parser-actions isbl-parser.peg isbl-actions.act > isbl-actions.tcl

 isbl-parser.tcl : isbl-parser.peg
        $(PT) generate snit -class isbl-parser -name isbl-parser isbl-parser.tcl peg isbl-parser.
        sed -e s/PACKAGE/isbl-parser/ < isbl-parser.tcl > tmp
        sed -e s/^return//            < tmp > isbl-parser.tcl
        rm tmp

arjen - 2011-04-04 03:09:11

Have you looked at TclRAL? That is a complete relational algebra package

jbr - There was now real imperative to writing the Playing ISBL package other than to explore Parser Tools, sqlite, modules, starpack, and to create an infix relational expression syntax. TclRAL is excellent. It has a complete set of prefix operators (tcl commands), but it has no backend.