#define DX_PT_EOM "Qwerty: Over." #define DX_PT_EOT "Qwerty: Over and out." #define DX_PT_MSGLIST "Qwerty: Say MSGLIST." #define DX_PT_HELP "Qwerty: Say HELP." #define DX_PT_PROGRAM "Qwerty: Say PROGRAM." #define DX_PT_VERSION "Qwerty: Say VERSION." #define DX_PT_NOTICE "Qwerty: Say NOTICE."
Note/Example | Command/Code |
---|---|
Example Program Object scripts and programs are included in the Daylight distribution. | <--- Some entries may be omitted ---> % ls ${DY_ROOT}/bin/*talk clogptalk cmrtalk dayproptalk merlinsmartstalk % ls ${DY_ROOT}/contrib/src/oracle/*talk* clogptalk.sh echotalk.sh % ls ${DY_ROOT}/contrib/src/oracle/mdl/*talk* mol2smitalk mol2smitalk.sh smi2moltalk smi2moltalk.sh % ls ${DY_ROOT}/contrib/src/c/progob add_clogp clogpaccess echotalk fingertalk merlinbintalk pipetalker shelltalk stringtalker verbosetalk |
A Program Object directory should be created at ${ORACLE_BASE}/progob and owned by the Oracle user. | % su - oracle % mkdir ${ORACLE_BASE}/progob |
Program Object scripts may be copied in from the Daylight installation directories. | % cp ${DY_ROOT}/contrib/src/oracle/clogptalk.sh ${ORACLE_BASE}/progob |
To prevent access to unauthorized Oracle privileges, the program object directory and files should't be group or world writable. | % chmod -R 700 ${ORACLE_BASE}/progob |
Note/Example | Command/Code |
---|---|
Program Objects are defined in the c$dcischem.progob dictionary table. | SQL> desc progob Name Null? Type -------------------------- -------- ----------------- NAME VARCHAR2(60) PATH VARCHAR2(4000) ARGS VARCHAR2(4000) |
A new Program Object is added by defining a symbolic name ('clogp'), an absolute path to the shell wrapper ('/oracle/progob/clogptalk.sh') and the initial (whitespace delimited) arguments (NULL). | SQL> insert into progob values ('clogp', '/oracle/progob/clogptalk.sh', NULL); SQL> select * from progob; NAME --------------------------------------------- PATH -------------------------------------------------- ARGS -------------------------------------------------- clogp /oracle/progob/clogptalk.sh |
Note/Example | Command/Code |
---|---|
Since Oracle executes the program object with an empty environment, all required variables must be defined in a shell wrapper before calling the program object. | % cat /oracle/progob/clogptalk.sh #!/bin/sh DY_ROOT=/usr/local/daylight/v481 export DY_ROOT DY_LICENSEDATA=/usr/local/daylight/dy_license.dat export DY_LICENSEDATA LD_LIBRARY_PATH=/usr/lib:${DY_ROOT}/lib export LD_LIBRARY_PATH ${DY_ROOT}/bin/clogptalk |
The Program Object setup can be verified by running it from the command line with an empty environment. | % /usr/bin/env -i /oracle/progob/clogptalk.sh Qwerty: Over. Qwerty: Say VERSION. Qwerty: Over. 4.82 Qwerty: Over. CCO Qwerty: Over. CCO -0.235 0 LogPstar: -0.31 Qwerty: Over. |
Note/Example | Command/Code |
---|---|
Since program objects may return data types which contain several lines of data (VARCHAR2 or CLOB), most require a PL/SQL wrapper function to convert to line-oriented data and to parse returned results. | <--- Excerpt from ${DY_ROOT}/contrib/src/oracle/contrib_create.sql ---> SQL> create function fclogp (sosdata in varchar2) return number as v1 varchar2(4000); rc number; off1 number; off2 number; begin v1 := c$dcischem.ddpackage.fprogob('clogp', sosdata); off1 := instr(v1, ' ', 1, 1); off2 := instr(v1, ' ', 1, 2); rc := to_number(substr(v1, off1, off2 - off1)); return rc; end; / |
Note/Example | Command/Code |
---|---|
PipeTalk compatibility has been written directly into several supported binary "talk" executables. | % ${DY_ROOT}/bin/clogptalk Qwerty: Over. Qwerty: Say MSGLIST. Qwerty: Over. Qwerty: Say HELP. Qwerty: Say PROGRAM. Qwerty: Say VERSION. Qwerty: Say MSGLIST. Qwerty: Say NOTICE. Qwerty: Say ERRORTEXT. Qwerty: Say FRAGDB. Qwerty: Set TABLEOUTPUT. Qwerty: Set TABLE0. Qwerty: Set TABLE1. Qwerty: Set TABLE2. Qwerty: Set TABLE3. Qwerty: Set NOTABLEOUTPUT. Qwerty: Set TDT. Qwerty: Set INTEGERERRORS. Qwerty: Set ENGLISHERRORS. Qwerty: Over. |
A shell wrapper can parse PipeTalk messages and respond with the appropriate action. | <--- Some lines are omitted ---> % cat ${DY_ROOT}/contrib/src/oracle/echotalk.sh #!/bin/sh echo "echotalk.sh version 1.0" echo "Qwerty: Over." while { read line;} do if [ "$line" = "Qwerty: Over and out." ] ; then exit fi while { read junk;} do if [ "$junk" = "Qwerty: Over." ] ; then break fi done case "$line" in "Qwerty: Say HELP.") echo "echotalk.sh - echos it's input";; "Qwerty: Say PROGRAM.") echo "echotalk.sh";; "Qwerty: Say VERSION.") echo "Version 1.0.";; *) echo "Args: '$*' Current line is: '$line'";; esac echo "Qwerty: Over." done exit |
PipeTalk compatibility can be added into C programs as described in the Program Object section of the Toolkit Programmers Guide | #include <stdio.h> #include <string.h> #include "dt_smiles.h" #include "dt_progob.h" int main(int argc, char *argv[]) { dt_Handle mol; int lencan; char *out_string, line[1000]; printf(DX_PT_EOM"\n"); while (gets(line)) { if (0 == memcmp(DX_PT_EOT, line, strlen(line))) { return 0; } else if (0 == memcmp(DX_PT_HELP, line, strlen(line))) { out_string = "Enter only valid SMILES."; } else if (0 == memcmp(DX_PT_PROGRAM, line, strlen(line))) { out_string = "cansmitalk."; } else if (0 == memcmp(DX_PT_VERSION, line, strlen(line))) { out_string = "1.0"; } else if (0 == memcmp(DX_PT_EOM, line, strlen(line))) { printf("%.*s\n", strlen(out_string), out_string); printf(DX_PT_EOM"\n"); } else { mol = dt_smilin(strlen(line), line); out_string = dt_cansmiles(&lencan, mol, 0); dt_dealloc(mol); } } } |
Contributed libraries can make it easier to implement Program Objects. | <--- Comment lines are omitted ---> % cat more ${DY_ROOT}/contrib/src/c/progob/echotalk.c #include "dt_smiles.h" #include "dt_progob.h" #include "du_pipeio.h" static dt_Handle copysos(dt_Handle sosin) { dt_Handle sob, sosout = dt_alloc_seq(); dt_reset(sosin); while (NULL_OB != (sob = dt_next(sosin))) dt_append(sosout, dt_copy(sob)); dt_reset(sosout); return sosout; } static dt_Handle mytalk(dt_Handle msgin) { return (NULL_OB == msgin ? NULL_OB : copysos(msgin)); } main() { du_pipe_loop(NULL_OB, mytalk); } |
Note/Example | Command/Code |
---|---|
Program Objects may be executed using the fprogob function using the symbolic name as the first argument and the message as the second argument. | SQL> select ddpackage.fprogob('clogp', 'c1ccccc1') from dual; DDPACKAGE.FPROGOB('CLOGP','C1CCCCC1') ----------------------------------------------- c1ccccc1 2.142 0 LogPstar: 2.13 |
If a PL/SQL wrapper function has been created, it may be executed with the message as the only argument. | SQL> select fclogp('c1ccccc1') from dual; FCLOGP('C1CCCCC1') ------------------ 2.142 |
Program Objects can be used in conjunction with triggers to automatically generate derived column values. | SQL> create or replace trigger add_logp before insert or update on example_table for each row begin :new.clogp := fclogp(:new.usmiles); end; / |