Playing ISBL

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 no 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. As a preprocessor for SQL it may be useful in simplifying existing code (or not). TclRAL is excellent. It has a complete set of prefix operators (tcl commands), but it has no backend.