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.