Mumps with POstgreSQL on Ubuntu
(Similar instructions apply to Cygwin)

Oct 21, 2008


  1. Be sure to install the PostgreSQL development libraries. The development libraries are listed separately under a name like: postgresql-server-dev-8.3

  2. Add your userid to the 'postgres' group. This user id must not be 'root'. This step is required in order to set locks. On the main screen, go to System | Administration | Users and Groups. Click 'Manage Groups.' Locate the 'postgres' group and click it. Click 'Properties' then put a check mark next to your userid. This makes you a member of the postgress group. Click 'Ok' etc. Logout/in in order for this change to take effect.

  3. Add to PostgreSQL the user 'www-data' (this is Apache) and make it a privileged user. Use the PostgreSQL 'createuser' command.

  4. If you are going to use PostgreSQL only to store the Mumps globals (that is, not access any other PostgreSQL databbases) you need to create a data base for mumps. If you are using Mumps along with existing PostgreSQL databases, do not do this step. Mumps will use the existing database you connect to to store its globals, if any.

    createdb mumps

  5. Build the Mumps interpreter/compiler. Download the most recent distribution from http://www.cs.uni.edu/~okane/source/MUMPS-MDH/. Be certain that the gcc/g++ compiler and libraries are installed as well as the PCRE libraries.

    Un-tar/compress it with a command like (use latest version number):

    tar xvzf mumpscompiler-11.5.src.tar.gz

    Descend into the mumpsc directory and type:

    1. For Mumps globals stored in PostgreSQL database and PostgreSQL database access:
      configure prefix=/usr --with-pgdb=/usr/include/postgresql
      
      or, for Cygwin
      
      configure prefix=/usr --with-pgdb=/usr/include
      make
      make install
      
    2. If you want to use the native btree data base but still have access to the PostgreSQL data base, use the following configure commands:
      for Ubuntu:
      
      configure prefix=/usr --with-pgsql=/usr/include/postgresql
      make
      make install
      
      for Cygwin:
      
      configure prefix=/usr --with-pgsql=/usr/include
      
      Note the 'pgsql' rather than 'pgdb'. The 'pgsql' enables the SQL command in Mumps/II to accesss PostgreSQL but places global arrays in the native data base. The 'pgdb' option enables SQL command access and places the global arrays in the PostgreSQL data base in a database table named mumps.

    3. For native btree based Mumps globals (fastest) but no Postgresql access:
      configure prefix=/usr
      make
      make install
      

    Note: the configure command may need to be prefixed by ./ and you may see warning messages, this is normal. If you are using 64 bit Ubuntu, add the --with-cpu64 option to the configure lines.

  6. If you are using PostgreSQL to store the global arrays but you will not access any other PostgreSQL databases, you need a database for the globals to reside in. By default PostgreSQL database name is set to mumps.' You can change it with the --with-dbname= configure parameter:
    configure prefix=/usr --with-pgdb=/usr/include --with-dbname=fluffy
    
    The dbname is where Mumps will store its global arrays.

    If you will be connecting to an existing PostgreSQL database, ignore this. Any Mumps globals you create will be places in a table in the database you connect to named 'mumps.'

  7. When running through the CGI-BIN interface, be sure the files and directories are not owned by root. Make them owned by Apache (www-data) and in the Apache group (www-data).

  8. If you run Apache and PostgreSQL on the same machine, you may do so with no further modifications.

    If you want to run scripts on a different machine than the one running PostgreSQL, you need to enable TCP/IP connections to PostgreSQL.

    To accept TCP/IP connections, you must start postmaster with the -i option and the connecting clients' IP numbers should be in the file pg_hba.conf found in the PostgreSQL data directory.

    Note: to enable a group of IP numbers, your IPV4 address should look like:

    host    all         all         134.161.0.0/16          trust
    
    Where the high order 16 bits must match (134.161) but the remainng 16 bits can be any value. The above would enable any machine on the UNI campus. Alternatively, passwords can be used. See the PostgreSQL documentation.

    To test a connection, try something like:

    psql -h tuatha.cs.uni.edu -d medical
    
    where the '-h' option specifies the remote host to connect to.

  9. Basic Mumps SQL commands:

    1. sql/d connect-string

      where 'connect-string' is either text or &~exp~ such that 'exp' evaluates to a string of text.

      The string is the information needed to connect to the PostgreSQL server. At a minimum, it should include the name of the database being connected to:

      dbname=medical

      Other options include the host, host address, user, password, etc. See http://www.postgresql.org/docs/8.3/static/libpq-connect.html for a complete list (this is the documentation of the C function PQconnectdb() used to connect to the database but has all the possible options listed). Options you don't include default. For a local server, you probably only need the dbname= parameter and be sure that (1) you are running as a known PostgreSQL user and (2) that you have read/write privs in the directory you are running in.

      Examples:

      sql/d dbname=medical
      
      sql/d host=abc.def.xyz.edu dbname=medical
      
      sql/d hostaddr=123.321.432.321 dbname=medical
      
      sql/d user=joe password=abc123 dbname=medical host=abc.def.xyz.edu
      
      set x="dbname=medical"
      sql/d &~x~
      

    2. sql/c

      Disconnect from the database. No parameters, no other commands on the line.

    3. sql/f

      Clear and prepare a mumps database table in PstgreSQL. This removes any previous mumps database table from PostgreSQL and defines a new one. Do this the first time you try to store Mumps global arrays in PostgreSQL. Subsequently, do this only if you want to delete the mumps global array database and start over.

      Theis command (no other line options, no other commands on the same line) creates a table named mumps in the current database. Thus, you must be connected with a server and a database before you execute it. Mumps will place its global arrays in this table. The mumps database has eleven columns the first of which is named 'gbl' and the subsequent ones are named a1, a2, ... a10. It may be queried by SELECT statements but this is probably not desireable.

    4. sql string

      Where 'string' can be text or &~exp~ where 'exp' evaluates to a string. Passes a command to the PostgreSQL server. $test will be true (1) if no error is reported. $zsql will contain any messages or 'ok' if there were none. Do not use this command for SELECT queries.

    5. sql/o=fileExp string

      where 'fileExp' must evaluate to a valid filename in which will be stored the results of the command and 'string' may be a text string or &~exp~ where 'exp' evaluates to valid SQL command text. The tuple output of the command will be stored in the file with TAB characters delimiting the values of the columns.

    6. sql/t=table,size

      The sql/t=table,size command is used to switch to a different PostgreSQL table for Mumps global array access.. This command only applies if PostgreSQL is being used as the backend storage facility for the global arrays. Both table and size must be valid Mumps/II expressions. 'table' is the name of the PostgreSQL table which will be used for global array references and size gives the number of columns, exclusive of the global array name column (always column one).

      Normally, global array access go to the table named 'mumps' which has eleven columns named 'gbl', 'a1', 'a2', ... 'a10'. Theses are all text columns. Each successive column is a level lower in the Mumps global array tree. Many later columns are NULL.

      If you create a table (see example below) and you name the columns appropriately (some prefix subset of the ones above), you can access the table with Mumps global array references.

  10. A test script:
    #!/usr/bin/mumps html Content-type: text/html &!&! html <html><body bgcolor=silver><font size=+1> set x="host=tuatha.cs.uni.edu dbname=medical" # Open the connection. # The &~exp~ causes the result of 'exp' to be inserted into the line sql/d &~x~ # $test will be 1 and $zsql will be 'ok' if it worked if $test html Connection to database open <br> else do . html Connection to database failed </body></html> . halt # Flush/delete/create a mumps table in the database. sql/f if $test html Mumps tables initialized <br> else html Mumps table initialization failed <br> # prepare a query and run it. Output will go to xxx.file # where 'xxx' is the process id of this program set x="select * from ptname;" html Sending query: &~x~ <br> sql/o="/tmp/"_$job_".file" &~x~ set ptname=$zsqlCols // gets column names TAB separated if $test html Query successfully processed <p> else do . html Query failed. Message=&~$zsql~ <br></body></html> . halt # Open the file or results and process same. open 1:"/tmp/"_$job_".file,old" if '$test do . html Results file error<br></body></html> . halt # Each line consists of columns separated by TAB characters # $char(9) is a TAB. sepearte the lines. ptname is: html <table border><tr> for i=1:1:6 do . html <td> &~$piece(ptname,$char(9),i)~ </td> html </tr> for do . use 1 // unit 1 to be used for I/O . read line . if '$test break . use 5 // unit 5 now used for I/O . html <tr> . for i=1:1 do .. set col=$piece(line,$char(9),i) .. if col="" break .. html <td> &~col~ </td> . html </tr> use 5 html </table> html </body> html </html> shell/g rm &~"/tmp/"_$job_".file"~ halt
    The results:


    Another example using direct global array / PostgreSQL table access:

    name.mps #!/usr/bin/mumps html Content-type: text/html &!&! html <html><body bgcolor=silver><font size=+1> set x="host=tuatha.cs.uni.edu dbname=medical" # Open the connection. # The &~exp~ causes the result of 'exp' to be inserted into the line sql/d &~x~ # $test will be 1 and $zsql will be 'ok' if it worked if $test html Connection to database open <br> else do . html Connection to database failed </body></html> . halt # Flush/delete/create a mumps table in the database. sql/f if $test html Mumps tables initialized <br> else html Mumps table initialization failed <br> set cmd="create temp view names (gbl,a1,a2,a3) as select " set cmd=cmd_"text 'names', ptid, namefirst, namelast from ptname;" sql &~cmd~ sql/t="names",3 html <hr> for ptid="":$order(^names(ptid)):"" do . for first="":$order(^names(ptid,first)):"" do .. for last="":$order(^names(ptid,first,last)):"" do ... write ptid," ",first," ",last,"<br>" html <hr></body></html> halt


    More examples with three Mumps programs. Note: in this example one Mumps program invokes another. When this happens, the symbol table, all open files, and other environment variables are shared.

    name.mps #!/usr/bin/mumps # this module assumes that the connection is open # prepare a query and run it. Output will go to xxx.file # where 'xxx' is the process id of this program set x="select * from ptname where ptid='"_ptid_"';" sql/o="/tmp/"_$job_".file" &~x~ set cols=$zsqlCols if '$test do . html Query failed. <br></body></html> . halt # Open the file or results and process same. do ^rsltprint.mps rsltprint.mps #!/usr/bin/mumps # this module assumes that the results file exists open 1:"/tmp/"_$job_".file,old" if '$test do . html Results file error<br></body></html> . halt # Each line consists of columns separated by TAB characters # $char(9) is a TAB. separate the lines. html <table border=1><tr> for i=1:1 do . set x=$piece(cols,$char(9),i) . if x="" break . html <td> &~x~ </td> html </tr><hr> for do . use 1 // unit 1 to be used for I/O . read line . if '$test break . use 5 // unit 5 now used for I/O . html <tr> . for i=1:1 do .. set col=$piece(line,$char(9),i) .. if col="" break .. html <td> &~col~ </td> . html </tr> use 5 html </table> html </body> html </html> close 1 # delete the file shell/g rm &~"/tmp/"_$job_".file"~ labrpt.mps #!/usr/bin/mumps html Content-type: text/html &!&! html <html><body bgcolor=silver><font size=+1><center> set x="user=okane host=tuatha.cs.uni.edu dbname=medical" # Open the connection. # The &~exp~ causes the result of 'exp' to be inserted into the line sql/d &~x~ # $test will be 1 and $zsql will be 'ok' if it worked if '$test do . html Connection to database failed </body></html> . halt if '$data(ptid) do . html Error: no value specified for Patient ID (ptid). . html </body></html> # call a mumps routine to print the name of person ptid do ^name.mps # prepare a query and run it. Output will go to xxx.file # where 'xxx' is the process id of this program set x="select * from labs where ptid='"_ptid_"';" sql/o="/tmp/"_$job_".file" &~x~ set cols=$zsqlCols if '$test do . html Query failed. Message=&~$zsql~ <br></body></html> . halt # print results do ^rsltprint.mps html </center></body> html </html> halt labs.html <html> <body> <font size=+2> Worst General Hospital Lab Reports <p> <hr> <form method=get action="cgi-bin/labrpt.mps"> Enter Patient Id: <input type=text name=ptid value="" size=10> &nbsp; &nbsp; &nbsp; <input type=submit value="Display Labs"> </form> </body> </html>