We take two tcl access scripts, presuming presence of Maxima and PostgreSQL on a system or in the latter case on some system in the network:

 proc domaxima { {m} } {
    set t "display2d:false;\n$m;"
    # return [string range [exec maxima << $t | tail -2  ] 6 end-7]
    return [string range [exec maxima -q << $t ] 32 end-7]
    #return [exec maxima --real-quiet << $t ]
 }

 proc dosql {s} {
  global db
   if {[catch {pg_exec $db $s} reply]} {
      puts "sql error : $reply,[pg_result $reply -error]"
      return "Error"
   }
   if {[pg_result $reply -status] == "PGRES_COMMAND_OK"} {
      return {}
   }
   if {[pg_result $reply -status] != "PGRES_TUPLES_OK"} {
      puts "sql error: [pg_result $reply -error]"
      return "Error"
   }
   return [pg_result $reply -llist]
 #   pg_result $reply -clear
   return 
 }

 # You could use another with similar results, it appears:
 package require pgintcl
 # connect to your sql server:
 set db [pg_connect -conninfo [list host = 192.168.0.1 user = zxy dbname = somedb password = 0x987654]]

 # Now create a table for formulas
 dosql "create table formula (f varchar(256))"

Now we can try to make a nice database with formulas:

 dosql "insert into formula values ([pg_quote "x^2"])"
 dosql "insert into formula values ([pg_quote "x^3"])"

But we can also use maxima to help us, for instance the optimizer will reorder terms and at request also simplify so we can keep formulas unique for instance:

 dosql "insert into formula values ([pg_quote [domaxima "x^4"]])"
 dosql "insert into formula values ([pg_quote [domaxima "x^3"]])"

Now lets look at the nice lil' list of math work:

 foreach i [dosql "select distinct f from formula"] {puts |$i}
  |x^2
  |x^3
  |x^4

A more interesting example, a list of repeated derivatives of a products of two functions, a well known formula for case 1:

 dosql "create table derivatives (ref varchar(64), f varchar(10000), df varchar(10000))"
 set i 1; set fo "q(x)*r(x)"; 
 dosql "insert into derivatives values ( [pg_quote "prod$i"], [pg_quote [domaxima $fo]], [pg_quote [domaxima "diff($fo)"]] )"
 incr i; 
 set fo "diff($fo)";
 dosql "insert into derivatives values ( [pg_quote "prod$i"], [pg_quote [domaxima $fo]], [pg_quote [domaxima "diff($fo)"]] )"
 incr i; 
 set fo "diff($fo)";
 dosql "insert into derivatives values ( [pg_quote "prod$i"], [pg_quote [domaxima $fo]], [pg_quote [domaxima "diff($fo)"]] )"
 incr i; 
 set fo "diff($fo)";
 dosql "insert into derivatives values ( [pg_quote "prod$i"], [pg_quote [domaxima $fo]], [pg_quote [domaxima "diff($fo)"]] )"

Of course that could be easily put in a loop, but it's to prove the principle. Now:

 % foreach i [dosql "select * from derivatives"] {puts $i}
 prod1 q(x)*r(x) (q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))*del(x)
 prod2 (q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))*del(x) {((q(x)*'diff(r(x),x,2)+2*'diff(q(x),x,1)*'diff(r(x),x,1)
                            +r(x)*'diff(q(x),x,2))
       *del(x)
       +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))*'diff(del(x),x,1))
       *del(x)}
 prod3 {((q(x)*'diff(r(x),x,2)+2*'diff(q(x),x,1)*'diff(r(x),x,1)
                            +r(x)*'diff(q(x),x,2))
       *del(x)
       +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))*'diff(del(x),x,1))
       *del(x)} {(((q(x)*'diff(r(x),x,3)+3*'diff(q(x),x,1)*'diff(r(x),x,2)
                             +3*'diff(q(x),x,2)*'diff(r(x),x,1)
                             +r(x)*'diff(q(x),x,3))
       *del(x)
       +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))*'diff(del(x),x,2)
       +2*(q(x)*'diff(r(x),x,2)+2*'diff(q(x),x,1)*'diff(r(x),x,1)
                               +r(x)*'diff(q(x),x,2))*'diff(del(x),x,1))
       *del(x)
       +'diff(del(x),x,1)*((q(x)*'diff(r(x),x,2)
                          +2*'diff(q(x),x,1)*'diff(r(x),x,1)
                          +r(x)*'diff(q(x),x,2))
                          *del(x)
                          +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))
                           *'diff(del(x),x,1)))
       *del(x)}
 prod4 {(((q(x)*'diff(r(x),x,3)+3*'diff(q(x),x,1)*'diff(r(x),x,2)
                             +3*'diff(q(x),x,2)*'diff(r(x),x,1)
                             +r(x)*'diff(q(x),x,3))
       *del(x)
       +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))*'diff(del(x),x,2)
       +2*(q(x)*'diff(r(x),x,2)+2*'diff(q(x),x,1)*'diff(r(x),x,1)
                               +r(x)*'diff(q(x),x,2))*'diff(del(x),x,1))
       *del(x)
       +'diff(del(x),x,1)*((q(x)*'diff(r(x),x,2)
                          +2*'diff(q(x),x,1)*'diff(r(x),x,1)
                          +r(x)*'diff(q(x),x,2))
                          *del(x)
                          +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))
                           *'diff(del(x),x,1)))
       *del(x)} {((((q(x)*'diff(r(x),x,4)+4*'diff(q(x),x,1)*'diff(r(x),x,3)
                              +6*'diff(q(x),x,2)*'diff(r(x),x,2)
                              +4*'diff(q(x),x,3)*'diff(r(x),x,1)
                              +r(x)*'diff(q(x),x,4))
       *del(x)
       +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))*'diff(del(x),x,3)
       +3*(q(x)*'diff(r(x),x,2)+2*'diff(q(x),x,1)*'diff(r(x),x,1)
                               +r(x)*'diff(q(x),x,2))*'diff(del(x),x,2)
       +3*(q(x)*'diff(r(x),x,3)+3*'diff(q(x),x,1)*'diff(r(x),x,2)
                               +3*'diff(q(x),x,2)*'diff(r(x),x,1)
                               +r(x)*'diff(q(x),x,3))*'diff(del(x),x,1))
       *del(x)
       +2*'diff(del(x),x,1)
         *((q(x)*'diff(r(x),x,3)+3*'diff(q(x),x,1)*'diff(r(x),x,2)
                                +3*'diff(q(x),x,2)*'diff(r(x),x,1)
                                +r(x)*'diff(q(x),x,3))
          *del(x)
          +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))*'diff(del(x),x,2)
          +2*(q(x)*'diff(r(x),x,2)+2*'diff(q(x),x,1)*'diff(r(x),x,1)
                                  +r(x)*'diff(q(x),x,2))*'diff(del(x),x,1))
       +'diff(del(x),x,2)*((q(x)*'diff(r(x),x,2)
                          +2*'diff(q(x),x,1)*'diff(r(x),x,1)
                          +r(x)*'diff(q(x),x,2))
                          *del(x)
                          +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))
                           *'diff(del(x),x,1)))
       *del(x)
       +'diff(del(x),x,1)*(((q(x)*'diff(r(x),x,3)
                          +3*'diff(q(x),x,1)*'diff(r(x),x,2)
                          +3*'diff(q(x),x,2)*'diff(r(x),x,1)
                          +r(x)*'diff(q(x),x,3))
                          *del(x)
                          +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))
                           *'diff(del(x),x,2)
                          +2*(q(x)*'diff(r(x),x,2)
                             +2*'diff(q(x),x,1)*'diff(r(x),x,1)
                             +r(x)*'diff(q(x),x,2))*'diff(del(x),x,1))
                          *del(x)
                          +'diff(del(x),x,1)
                           *((q(x)*'diff(r(x),x,2)
                            +2*'diff(q(x),x,1)*'diff(r(x),x,1)
                            +r(x)*'diff(q(x),x,2))
                            *del(x)
                            +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))
                             *'diff(del(x),x,1))))
       *del(x)}

More intelligently we can now look up in our little database what the general form is of a certain derivative of a product of functions, and what the original was from that derivative (the integral except for a constant), for instance:

 (Tcl) 69 % dosql "select ref, f from derivatives where df = [pg_quote "(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))*del(x)"]"
 {prod1 q(x)*r(x)}

Or case 4:

 dosql "select ref from derivatives where df = [pg_quote [domaxima "((((q(x)*'diff(r(x),x,4)+4*'diff(q(x),x,1)*'diff(r(x),x,3)
                              +6*'diff(q(x),x,2)*'diff(r(x),x,2)
                              +4*'diff(q(x),x,3)*'diff(r(x),x,1)
                              +r(x)*'diff(q(x),x,4))
       *del(x)
       +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))*'diff(del(x),x,3)
       +3*(q(x)*'diff(r(x),x,2)+2*'diff(q(x),x,1)*'diff(r(x),x,1)
                               +r(x)*'diff(q(x),x,2))*'diff(del(x),x,2)
       +3*(q(x)*'diff(r(x),x,3)+3*'diff(q(x),x,1)*'diff(r(x),x,2)
                               +3*'diff(q(x),x,2)*'diff(r(x),x,1)
                               +r(x)*'diff(q(x),x,3))*'diff(del(x),x,1))
       *del(x)
       +2*'diff(del(x),x,1)
         *((q(x)*'diff(r(x),x,3)+3*'diff(q(x),x,1)*'diff(r(x),x,2)
                                +3*'diff(q(x),x,2)*'diff(r(x),x,1)
                                +r(x)*'diff(q(x),x,3))
          *del(x)
          +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))*'diff(del(x),x,2)
          +2*(q(x)*'diff(r(x),x,2)+2*'diff(q(x),x,1)*'diff(r(x),x,1)
                                  +r(x)*'diff(q(x),x,2))*'diff(del(x),x,1))
       +'diff(del(x),x,2)*((q(x)*'diff(r(x),x,2)
                          +2*'diff(q(x),x,1)*'diff(r(x),x,1)
                          +r(x)*'diff(q(x),x,2))
                          *del(x)
                          +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))
                           *'diff(del(x),x,1)))
       *del(x)
       +'diff(del(x),x,1)*(((q(x)*'diff(r(x),x,3)
                          +3*'diff(q(x),x,1)*'diff(r(x),x,2)
                          +3*'diff(q(x),x,2)*'diff(r(x),x,1)
                          +r(x)*'diff(q(x),x,3))
                          *del(x)
                          +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))
                           *'diff(del(x),x,2)
                          +2*(q(x)*'diff(r(x),x,2)
                             +2*'diff(q(x),x,1)*'diff(r(x),x,1)
                             +r(x)*'diff(q(x),x,2))*'diff(del(x),x,1))
                          *del(x)
                          +'diff(del(x),x,1)
                           *((q(x)*'diff(r(x),x,2)
                            +2*'diff(q(x),x,1)*'diff(r(x),x,1)
                            +r(x)*'diff(q(x),x,2))
                            *del(x)
                            +(q(x)*'diff(r(x),x,1)+r(x)*'diff(q(x),x,1))
                             *'diff(del(x),x,1))))
       *del(x)"]]"
 prod4

It finds the correct f for df, with the help of an additional 'domaxima' it doesn't matter what the formatting of the text of the formula is. Try for yourself.

Another dual application script tryout for the scientifically oriented which in the longer run could prove useful: a set of integral (Fourier - type) transformed functions in the database.

 # create a new table
 dosql "create table transform (f text, h text, d text)"
 # try it out
 dosql "insert into transform values (1, 1/s)"
 #or better (and a unique definition of the table could be good,too):
 dosql "insert into transform values ([pg_quote 1], [pg_quote 1/s])"

This should do the same, but compute the transformation automatically:

  domaxima "laplace(1, t, s)"
 1/s

Correct. Let's populate a nice LaPlace tranform table letting the tranforms be computed automatically (the description remains NULL for the moment):

 foreach fo "t^2 t^3 t^4 t^5 t^6  sin(2*%pi*f*t)  sin(2*%pi*f*t)+(1/2)*sin(2*2*%pi*f*t)  " {
    dosql "insert into transform values ([pg_quote $fo], [pg_quote [domaxima "laplace($fo, t, s)"]] )"
 }

 dosql "select h from transform where f like [pg_quote "t^%"]"

 dosql "select h from transform where f = [pg_quote "sin(2*%pi*f*t)+(1/2)*sin(2*2*%pi*f*t)"]"

I've made a ~/.maxima/maxima-init.mac file with

 assume (n>0);

check with (from the tcl console)

 domaxima facts()

to get certain transforms to work with parameter n, which otherwise would call for an interactive entry which hangs the maxima procedure. Of course those defines then hold for all maxima invokations, so beware. A change to the simple maxima wrapper proc isn't needed, the output remain the same. In case you make that precaution, t^n can be added to the above list, which gives a gamma function as result.

Because we have these facilities now handily available at tcl (console) level, we can also pick La Place transformed formulas from the database (the SQL table) and perform an automatic inverse transform with Maxima, and we should get the same as the original t-function!

 domaxima "ilt([dosql "select h from transform where f like [pg_quote "t^6"]"],s,t)"

That works, if you want exercise, you could make a loop of this over all formulas. Of course, which is a mathematical exercise, there are issues with the integrals involved, so some assumptions must be made.

The result in postgres:

http://82.171.148.176/Wiki/scrprocsql4.png


To remember manipulations easier adn centrally, I've made a history table which can contain all succesfully executed sql commands with timestamp on the sql server:

 proc dosql { {s} } {
  global db
   if {[catch {pg_exec $db $s} reply]} {
      puts "sql error : $reply,[pg_result $reply -error]"
      return "Error"
   }
   if {[pg_result $reply -status] == "PGRES_COMMAND_OK"} {
      catch {pg_exec $db "insert into history values (DEFAULT, [pg_quote $s] , 'now' , NULL)"}
      return {}
   }
   if {[pg_result $reply -status] != "PGRES_TUPLES_OK"} {
      puts "sql error: [pg_result $reply -error]"
      return "Error"
   }
   set res [pg_result $reply -llist]
   catch {pg_exec $db "insert into history values (DEFAULT, [pg_quote $s] , 'now' , NULL)"}
   return $res
 # we only put non-errors in the history
 #   pg_result $reply -clear
   return
 } 

 # once only:
 dosql "create table history (i serial, l text, date timestamp , comment text)"

Now we can for instance

 dosql "select date,l from history"

Or

 set im [dosql "select max(i) from history "]
 puts " last entry #: $im"
 78
 % foreach i [dosql "select i,date,l from history where i > $im order by i asc"] {puts $i}
 76 {2009-04-24 03:48:27.118317} {select l from history where i > 66 order by i asc}
 77 {2009-04-24 03:49:15.686698} {select i,date,l from history where i > 66 order by i asc}
 78 {2009-04-24 03:49:36.509501} {select i,date,l from history where i > 75 order by i asc}

Short:

 dosql "select i,date,l from history order by i desc limit 3"

handy with wildcard:

 dosql "select l from history where l like 'create%' "

enter categories here