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.


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"

enter categories here