Oratcl is an extension for Tcl that provides access to Oracle, the relational database management system from Oracle, Inc. With Oratcl, a Tcl program can retrieve (select) data from the database server, insert new rows, update or delete existing rows. Oratcl can also access advanced Oracle features, such as reading or writing long data and execute PL/SQL procedures on the database server. Oratcl is compatible with Oracle Server Version 6 and Version 7. Oracle's OCI ("Oracle Call Interface") libraries are required to build Oratcl. Oratcl was written using the Sybtcl extension as a model, thus Oratcl shares many similarities with Sybtcl.
While there is nothing that Oratcl can do that can't be accomplished with C and OCI or Pro*C (Oracle's embedded SQL preprocessor), Oratcl promotes creative uses and rapid development due to Tcl's environment. Interactive applications can be developed quickly using Tcl/Tk. Database administration procedures such as site specific backup/restore that are often cobbled together with Shell, Awk, and SQL*Plus (Oracle's command line SQL processor) can be written in a single language. Other uses of Oratcl reported by users include: an Oracle sever database administration tool; email gateway address translation; ad-hoc user report generation.
Oratcl adds several new commands to Tcl. All Oratcl commands are prefixed with "ora" to differentiate Oratcl commands from other Tcl commands. Oratcl also adds a global array variable, $oramsg, that provides the Tcl program with information about the execution of various Oratcl commands. Various indexes in the oramsg array are set with information about the success or failure of Oratcl commands. The oramsg array can be accessed anytime after an Oratcl command.
Here is a short example of Oratcl using the sample tables shipped with the Oracle product. In this example, we will connect to the Oracle server and select rows from the "emp" table:
tclsh> oralogon scott/tiger
oratcl0
tclsh> oraopen oratcl0
oratcl0.0
tclsh> orasql oratcl0.0 "select empno, ename from emp"
0
tclsh> orafetch oratcl0.0
7379 SMITH
tclsh> orafetch oratcl0.0
7499 Allen
tclsh> oralogoff oratcl0
Basic Oratcl Commands
Oracle allows connection to database server either on a local host via pipes, or over a network connection with Oracle's SQL*Net. Oracle client programs, such as Oratcl, communicate using a protocol (provided by OCI) to the server; the server in turn performs the database access and returns the results to the client. In order for a Oratcl to access the database, you must connect to the database server with a user id and password. Oralogon is the command in Oratcl to make the connection.
oralogon connect-str
Oralogon requires a single parameter, the Oracle connect string. Oracle allows a connect string to take several forms:
(null string) - Oracle will use the operating system id as a userid, if the server has been administered to use this facility. A single '/' may also be used.
name/password - a userid name and password, separated by a '/'
name/password@server - a userid name and password, attaching to an Oracle server named server on the local host.
name/password@n:host:server - a userid and password, attaching via network type n (typically 'T', for TCP/IP), on host host, to an Oracle server named server.
name/password@serveralias - a userid name and password, attaching to an Oracle server named serveralias that is defined in /etc/sqlnet or a user's .sqlnet file.
If a server is not specified on a connect string, the server name is take from the user's environment variable ORACLE_SID. Upon a successful connection, oralogon returns a connection "handle" in the form of a string. A connection handle is similar in purpose to a file descriptor or the value returned by the Tcl open command. The Oratcl connection handle is used with other Oratcl commands that operate at a connection level. Several connections to the same or different Oracle servers can be open at the same time, each connection uses a separate handle. Oratcl handle strings are in the format "oratcl0", the numeric suffix incrementing for each new handle opened. Normally, the handle would be saved into some Tcl variable for later access:
set handle [oralogon $idpasswd]
If you plan to use the same handle for the life of your program, be sure to specify the variable as global before using the variable in a Tcl procedure, and in all other procedures where you will be using Oratcl commands. In the case of several simultaneous connections, you would save each handle into separate variables:
global localserver remoteserver
set localserver [oralogon ${userid}/${password}]
set remoteserver [oralogon ${remoteid}/${remotepw}@${server}]
If a connection cannot be made to the Oracle server, either because of an invalid user id/password combination, server unavailable, etc., oralogon will cause a Tcl error to be raised. Information on why a connection cannot be made is available in $oramsg(errortxt). In the rest of this chapter, $handle will be used to signify a valid connection from oralogon.
Oracle further requires that one or more cursors be used to perform SQL queries and retrieve rows. Cursors are opened over a logon connection; a single logon connection can support multiple cursors. The Oratcl command oraopen opens an Oracle cursor:
tclsh> set handle [oralogon $idpasswd]
oratcl0
tclsh> set query_cursor [oraopen $handle]
oratcl0.0
tclsh> set update_cursor [oraopen $handle]
oratcl0.1
In the rest of this chapter, $cursor will be used to signify a valid cursor opened with oraopen.
Oratcl cursors and connection handles should normally be closed when the database connection is no longer needed, just as you would normally close an open file descriptor. Oratcl provides the oraclose and oralogoff commands to close a cursor or connection handle, respectively.
oraclose $query_cursor
oraclose $update_cursor
oralogoff $handle
Oraclose ensures that the cursor to the Oracle server is cleanly terminated. Each Oratcl cursor and connection handle occupy slots in an internal data structure. Properly closing a cursor or logon handle frees its corresponding slot, allowing the slot to be available for another new connection or cursor. Alternatively, oralogoff will also close all open cursors that have been opened on a handle at one time, in addition to terminating the logon connection.
So far, we've demonstrated connecting to a Oracle server, accessing databases in the server, and disconnecting. Now it's time for some real action. Oratcl provides two commands that do most of the data manipulation: orasql and orafetch.
Orasql is the command that sends a single SQL statement to the Oracle server for execution. Any valid Oracle SQL statement can be sent using orasql:
* Data manipulation commands: select, insert, update, delete.
* Data definition commands: create, alter, drop, grant, etc.
* Oracle transaction control commands: commit, rollback, savepoint, etc.
* Oracle session control commands: set role, alter session.
orasql $cursor $sql-statement
Orasql passes the SQL statement in its entirety to the Oracle server, aside from normal Tcl variable and command substitution. It's very convenient to use Tcl's variable substitution to construct an SQL command:
puts "search for what name?"
gets stdin searchname
orasql $cursor "select * from emp where \
ename like '${searchname}'"
Orasql will cause a Tcl error to be raised if the Oracle server rejects the SQL statement, either for improper syntax or if the SQL statement references tables or column names that do not exist. It's prudent to enclose any orasql command that may have user input inside of Tcl's catch. Additionally, where limited external input is used to construct an SQL statement as in the example above, it may be necessary to pre-process the input. If the user were to enter:
O'Reilly
in response to the prompt, the resulting SQL statement would become invalid because the single quote after the "O" would specify the end of the literal string, leaving "Reilly'" as an invalid SQL statement. In such a case you might want consider the SQL quoting and wild-card characters ("%","_) when building an SQL statement with string literals. To quote the quote character in SQL, you specify two quote characters. Regsub is handy to ensure that a literal string is properly quoted:
regsub -all ' $searchname '' searchname
Assuming a valid SQL statement was sent to the server, orasql will return "0" if the SQL executed properly. Should a Tcl error be raised because of an invalid SQL statement, $oramsg(rc) will contain the Oracle error number, and $oramsg(errortxt) will contain the description of the error.
When SQL is executed, the server holds any data rows generated by the query until requested by the program. To retrieve data rows from the server as the result of a SQL statement, Oratcl provides the orafetch command.
orafetch $cursor ?tcl-statements?
Orafetch retrieves the next row available, and returns the results in the form of a Tcl list. List elements correspond to the columns selected in the same order as specified in a "select" statement. The columns returned can then easily be picked apart with standard Tcl list oriented commands, lindex, lrange, etc.
orasql $cursor "select * from emp"
set row [orafetch $cursor]
puts "number of columns: [llength $row]"
puts "first column is: [lindex $row 0]"
Orafetch converts all SQL datatypes to printable strings, in keeping with the Tcl model that all data are strings. This is not normally a problem for rows returned in Oratcl, except the Oracle datatypes raw or long raw, in which the hexadecimal representation is returned.
Each execution of orafetch will return the next row from the current set. In addition to returning rows, orafetch sets the variable $oramsg(rc) to a status indicating what was returned. Typical values include:
* 0 - a row was returned
* 1403 - end of rows reached
In the case of executing an SQL "select" statement, each row returned would be further processed in some fashion. For example, to print a list of employee names and hire dates from the "emp" database:
puts [format "%-15.15s %s" "Employee" "Hire date"]
orasql $cursor "select ename, hiredate from emp"
set row [orafetch $cursor]
while {$oramsg(rc) == 0} {
puts [format "%-15.15s %s" \
[lindex $row 0] [lindex $row 1]]
set row [orafetch $cursor]
}
Since it is very common programming construct to retrieve and process all the rows from a query, orafetch can accept an optional argument that is a block of Tcl statements to be executed for each row returned in a result set. Orafetch internally takes care of the "while" loop, retrieving rows and checking for the end-of-rows condition. The example above can be rewritten as:
puts [format "%-15.15s %s" "Employee" "Hire date"]
orasql $cursor "select ename, hirehdate from emp"
orafetch $cursor { puts [format "%-15.15s %s" @1 @2] }
Columns from each row are specified using a special substitution notation, prefixed with "@". @1 refers to the first column, @2 refers to the second column, and so on. @0 is the entire row as a Tcl list, just as orafetch would normally return. There is no limit to the number of times a column may be specified, or the number of Tcl statements executed in the block.
There are a few extra rules to remember when using the tcl-statements option. First, don't try to reference a column beyond the number of columns that are returned. Second, columns are substituted into the tcl-statements in a way to ensure that the tcl-statements after substituting the column data are still valid Tcl commands, e.g., a proper Tcl list. Since the data returned in the column may contain Tcl quoting characters, the entire substitution maybe enclosed with Tcl quoting, with adjacent spaces inserted. If you need to format the columns for printing, use the Tcl format command as in the example above, or assign the column values into Tcl variables with the set command. Last, if any commands in the tcl-statements block fail, orafetch will raise a Tcl error.
The Tcl commands break and continue may be used in the tcl-statements block the same way they are used in while or for. Break will cause the orafetch command to return. Any further rows remaining in the query can be retrieved with a subsequent orafetch command. Continue will cause any remaining Tcl commands to be skipped and continue processing with the next row. The following example counts authors names that begin with "A" through "L", printing only the first 5:
orasql $cursor "select ename from emp order by ename"
set num_rows 0
orafetch $cursor {
incr num_rows
if {[string compare @1 M] == 1} { break }
if {$num_rows > 5} { continue }
puts @0
}
puts "number employees with names beginning A-L: $num_rows"
Beside retrieving data from the Oracle server, Oratcl also can retrieve information about the names of columns returned, their datatypes, and lengths. Oracols returns a Tcl list of the names of the columns returned by orafetch.
oracols $cursor
Oracols can be used after a orasql or orafetch command. The names of the columns returned are in the same order as the data values returned by orafetch. The names are the actual column names as defined in the tables from which the columns are retrieved, or any column alias name that may have been coded as part of the "select" statement.
tclsh> orasql $cursor {
select ename "Last Name", hiredate, sal from emp
where empno=7499
}
0
tclsh> orafetch $cursor
ALLEN 20-FEB-81 1600
tclsh> oracols $cursor
{Last Name} HIREDATE SAL
tclsh>
Beside getting column names, oracols also sets the column datatypes and lengths in the
oramsg global array. $oramsg(coltypes) is a Tcl list of the datatypes corresponding to the columns, $oramsg(collengths) is a Tcl list of the column lengths. Datatype values can be any of Oracle's datatypes (char, varchar2, number, long, rowid, date, raw, long_raw, mslabel, raw_mlslabel, unknown.) For "char" datatypes, the length returned is the maximum length defined in the table, not the column lengths of the last row retrieved. Additionally, number datatypes have elements in $oramsg(colprecs) and $oramsg(colscales), Tcl lists of the precision and scale. Non-numeric types have null elements within the precision and scale lists.
tclsh> orasql $cursor {select from empno, ename, hiredate, sal
from emp}
REG_ROW
tclsh> oracols $cursor
EMPNO ENAME HIREDATE SAL
tclsh> puts $oramsg(coltypes)
number varchar2 date number
tclsh> puts $oramsg(collengths)
40 10 75 40
tclsh> puts $oramsg(colprecs)
4 {} {} 7
tclsh> puts $oramsg(colscales)
0 {} {} 2
Sometimes it is desirable to stop processing rows before all rows have been retrieved. Oratcl provides the oracancel command for such a case.
oracancel $cursor
Oracancel informs the server that pending rows from the last orasql command are to be discarded. Orasql always performs an implicit oracancel before each execution of SQL; oracancel may be used explicitly at any time.
Oratcl also provides transactional level commands that operate on a connection handle basis. In normal Oracle processing, uncommitted changes to a database are only visible to the user making the changes; all other users of the database are unaware of changes until those changes are committed to the database.
Oracommit will cause Oracle to commit all changes to the database, making those changes visible to other users. All cursors that have been opened through the same logon connection are committed:
orasql $cursor {insert into dept
values (99, 'DEVELOPMENT', 'DENVER') }
oracommit $handle
Oraroll will cause Oracle to roll back all changes to the database, reverting any changes since the last commit. As with oracommit, all cursors that have been opened through the same logon connection are committed:
tclsh> orasql $cursor { select loc from dept where deptno=10 }
tclsh> orafetch $cursor
{NEW YORK}
tclsh> orasql $cursor { update dept set loc='DENVER'
where deptno=10 }
tclsh> orasql $cursor { select loc from dept where deptno=10 }
tclsh> orafetch $cursor
DENVER
tclsh> oraroll $handle
tclsh> orasql $cursor { select loc from dept where deptno=10 }
tclsh> orafetch $cursor
{NEW YORK}
In a transaction oriented program, it is often desirable that changes be committed immediately. Oratcl allows changes to be committed automatically on each SQL statement by using the oraautocom command:
oraautocom $handle on
When auto commit is turned on, each change to the database through orasql (insert, update, delete) is committed immediately. The default value for oraautocom is "off". If auto commit is enabled with oraautocom, it can later be disable by specifying "off" as the parameter for oraautocom.
Advanced Oratcl Commands
Oracle includes several advanced features in its database server product. PL/SQL is a procedural language that can be executed on the Oracle database server. PL/SQL procedures are often used for transactional processing, where an entire group of SQL statements are treated as an atomic unit. PL/SQL procedures can be executed as a block of statements sent to the server or stored in the database for later execution (stored procedures). Changes made to the database in a PL/SQL procedure can be treated as a unit, committed or rolled back as a group, in case any one SQL statement does not execute successfully. PL/SQL procedures can take arguments and return values.
Oratcl supports the use of PL/SQL procedures through the oraplexec command.
oraplexec $cursor pl-block ?:varname1 value1 :varname2 value2 ....?
Oraplexec requires an open cursor and a string that contains a block of PL/SQL code. The pl-block is an anonymous block of PL/SQL code (anonymous is Oracle terminology for PL/SQL code that is not stored in the database or otherwised named.) Optionally, oraplexec can bind PL/SQL variables denoted with a preceding colon (:) to Tcl values. As many :varname value pairs are required on the oraplexec command as coded in the PL/SQL block.
Assume the following PL/SQL procedure has been created in the Oracle database, which will compute and return the total amount of monthly pay based on job classification:
create procedure total_monthly_job_pay
(job_type in varchar2,
tot_sal out number)
as
tot_fixed number;
tot_var number;
begin
select sum(sal) into tot_fixed
from emp
where job = job_type;
select decode(sum(comm),NULL,0,sum(comm)) into tot_var
from emp
where job =job_type;
tot_sal := tot_fixed + tot_var;
end;
The oraplexec command to execute the procedure would be:
oraplexec $cursor {
begin
total_monthly_job_pay (:type, :total);
end;
} :type SALESMAN :total 0
In this example, the pl-block string is an anonymous block that takes two bind variables, and calls the stored procedure. The :type variable in the block is assigned the value "SALESMAN" , and is received as job_type by the stored procedure. Even though tot_sal is an output only variable in the procedure, oraplexec requires a value ("0") be associated with the bind variable :total.
Oraplexec will return all bind variables after execution of the PL/SQL block, with values that have been returned by the procedure. The return values are also buffered as a single data row, so that orafetch will also return the values.
tclsh> orafetch $cursor
SALESMAN 7800
Another advanced feature of Oracle supported by Oratcl is the storage and retrieval of long or long raw data columns. Long and long raw datatypes are similar, each datatype holding up to 2 gigabytes. Long datatypes usually imply printable text, whereas long raw datatypes are completely arbitrary. Sounds, graphics, and MPEG streams are examples of data that can be store in long raw columns. Because long and long raw datatypes may contain binary zeros (thus unable to be represented as a Tcl string), Oratcl provides commands to read and write long data to and from files.
orawritelong $cursor rowid table column filename
orareadlong $cursor rowid table column filename
Orawritelong is the Oratcl command to write a file into a long or long raw data column. Orawritelong requires the row be identified by the Oracle rowid as well as the table and column names. The rowid can be determined by issuing a "select", returning the Oracle rowid pseudo column.
orasql $cursor {select rowid from emppix where empno=7499}
set rowid [orafetch $cursor]
orawritelong $cursor $rowid emppix photo image.gif
Orawritelong returns the number of bytes written to the column. (Note - "emppix" is not a sample table shipped with Oracle. Assume it has been created with empno number(4,0), photo long raw.)
Orareadlong is the compliment of orawritelong: it retrieves the long data from the database and writes the contents into a file. Like orawritelong, the row must be identified by an Oracle rowid. Long columns can be retrieved by orafetch, just as ordinary columns, but there are a few problems with this approach. First, long raw columns are converted to a printable hexadecimal notation, which may require another conversion step to reconstruct the actual data values. Second, the column would be stored as an ordinary Tcl variable, with the risk that not enough memory could be allocated to hold the value. Orareadlong eliminates these problems by retrieving the data in smaller chunks, and writes the data directly to an operating system file.
orasql $cursor {select rowid from emppix where empno=7499}
set rowid [orafetch $cursor]
orawritelong $cursor $rowid emppix photo image.gif
Oracle Version 6 limits the maximum length of a long column to 65,536 bytes. Oracle Version 7 limits the maximum length to 2,147,483,647 bytes.
Server Information and Feedback
Besides the Oracle specific commands that are added to Tcl by Oratcl, a global array is maintained and used by Oratcl for information from the server, and to control various aspects of Oratcl. Oramsg is the name of the array, and it should always referenced as global before accessing it in any Tcl procedure. We've already touched lightly on some of the elements in $oramsg. Now we will examine each element in detail. The first to be discussed are the elements that can be set by the Oratcl user and affects Oratcl processing.
$oramsg(nullvalue)
Nullvalue controls how Oratcl represents columns containing NULL when retrieved with orafetch. The default value for $oramsg(nullvalue) is "default" which converts numeric datatypes to "0" and all other datatypes to a null string "". For example, you might want to set nullvalue to an unlikely string to differentiate a NULL from a column that consists of whitespace characters.
tclsh> set oramsg(nullvalue) <null>
tclsh> orasql $cursor {select literal string',NULL from dual}
REG_ROW
tclsh> orafetch $cursor
{literal string} <null>
$oramsg(maxlong)
Maxlong limits the amount of long or long raw data that is retrieved from the server for orafetch. The default limit is 32768 bytes; maxlong can be set to the maximum allowed by Oracle, 2147483647. Any change to maxlong becomes effective on the next execution of orasql.
The remainder of the elements in $oramsg are informational only. Oratcl resets the informational elements on every Oratcl command. Any element not explicitly set by a particular Oratcl command is set to a null string.
$oramsg(handle)
Since the oramsg array is shared among all open connections, this element reports the
handle or cursor of the last Oratcl command executed.
$oramsg(rc)
Rc has been has already been mentioned for both orasql and orafetch. The rc value is the return code from the OCI library function calls. Here's a quick review of the some common values:
* 0 - Function completely without error.
* 900-999 - Invalid SQL statement, missing keywords, invalid column names, etc.
* 1000-1099 - Logon denied, insufficient privileges, etc.
* 1400-1499 - SQL execution errors.
* 1403 - End of rows reached on orafetch.
* 1406 - A long column retrieved by orafetch was truncated.
Oracle has an exhaustive set of return codes. See the Oracle Error Messages and Codes manual for detailed information.
$oramsg(errortxt)
Errortxt is a descriptive message associated with an rc code. The descripition that Oracle provides is usually one line per error. For more information of a failure, check the Oracle Errors Messages and Codes manual.
$oramsg(collengths)
Collengths is a Tcl list of column lengths that correspond to the column names that are returned by oracols. The column lengths are either the internal size for numeric datatypes, or the maximum length that character datatypes are defined in the database.
$oramsg(coltypes)
Coltypes is a Tcl list of column datatypes that correspond to the column names that are returned by oracols. As with collengths, coltypes is only set after oracols has been executed.
$oramsg(colprecs)
Colprecs is a Tcl list of the precision of numeric columns that correspond to the column names that are returned by oracols. For non-numeric columns, the list element is a null string. Due to a limitation in the OCI library for Oracle Version 6, zeros are returned.
$oramsg(colscales)
Colscales is a Tcl list of the scale of numeric columns that correspond to the column names that are returned by oracols. For non-numeric columns, the list element is a null string. Due to a limitation in the OCI library for Oracle Version 6, zeros are returned.
$oramsg(sqlfunc)
Sqlfunc is a numeric code of the last SQL command performed. Codes for common SQL commands are:
* 3 - insert
* 4 - select
* 5 - update
* 9 - delete
A complete list of SQL command types are documented in the Oracle Call Interface manual
$oramsg(ocifunc)
Ocifunc is a numeric code of the last OCI function performed. A complete list of function types are in the Oracle Call Interface manual.
$oramsg(rows)
Rows is the number of rows affected by an insert, update, or delete SQL command, or the cumulative number of rows fetched by orafetch.
Handling Errors
Oratcl commands will raise a Tcl error condition when a Oratcl command is invalid or when the Oracle server reports an error in an SQL statement. Oratcl was designed with this conservative error handling approach so that inadvertent operations to a database would be reported.
The Tcl interpreter normally halts script processing when a Tcl error is raised. The Tcl command catch allows errors to be trapped and error handling code to be executed. For example, the oralogon command will normal raise a Tcl error when either a Oracle userid or password is invalid, or when the Oracle server is unavailable. Catching the error allows the script to continue, and information about the error to be extracted from the $oramsg array:
if [catch {oralogon ${userid}/${passwd} } handle] {
puts "cannot access server, reason: $oramsg(errortxt)"
exit
}
In addition to raising an error on invalid or improperly formed SQL statements, orasql will also raise a Tcl error if the Oracle server reports a logical error. Logical errors include attempting to insert a duplicate row into a table that has unique indexes, or perhaps a PL/SQL procedure or referential integrity trigger executing a Oracle "raise application error" statement.
Wosql - an X11 SQL Processor
Oratcl combined with the power of Tcl/Tk provides a basis for developing powerful database applications and tools. One common tool, usually provided by database vendors is a general SQL processor, passing SQL statements to the server and printing rows that are returned. Oracle provides `SQL*Plus', a command line SQL processor. Wosql is a descendent of Sybtcl's Wisqlite. Wosql is written to use commands from Extended Tcl (TclX), so its interpreter needs Tcl, Tk, TclX, and Oratcl.
Wosql is similar to other X11 applications in that it provides a menu bar, scrolling edit and result panes, and various popup windows.
Figure Oratcl-1: Wosql signon window
After starting wosql, the server signon window appears to collect the Oracle user id, password, and server to which it should connect. The server entry is pre-populated with the default (ORACLE_SID environment variable); pressing the "server" button will list all servers from the /etc/oratab, /etc/sqlnet, and the user's personal .sqlnet files. Pressing "Sign on" will attempt to connect the the Oracle server.
Figure Oratcl-2: Wosql main window
SQL statements are entered into the top pane (a Tk edit widget); pressing the "Execute" button will send the SQL off to the server, and results will be printed in the lower pane (a Tk listbox.) Menu bar items provide additional functionality.
File
The File menu controls the SQL edit pane. "New" clears the SQL edit and Results windows for a new query. "Open" prompts for a file containing SQL statements through a file selection dialog window. "Save" and "Save as" save the SQL edit window into the current file name, or prompts for a new file name. "Quit" will disconnect from the server and exit Wisqlite.
Results
The Results menu controls the Results window. "Append results" or "Clear results" selects whether the Results window should be cleared on each new SQL execution or appended to the end of the list. "Save as" allows the Results window to be saved to a file, overwriting any previous contents. "Print" sends the Results window to the printer (via the Unix "lp" command.) "Font" changes the font size of the Results window.
Options
The Options menu controls several Wosql processing options as well as starting specialized dialogs. "Autocommit" allows toggling of the auto commit feature. "Commit Now" issues an immediate commit of changes. "Rollback Now" rolls back any changes since the last commit. "Write Long Col..." and "Read Long Col..." opens a dialog box to write or read a file into a LONG datatype column. "Procedure Exec..." opens a dialog box in which to enter bind variables and their values for PL/SQL execution. "Set Null Value..." opens a dialog box to set the default format for representing NULL values. "default" causes the default null value behavior as described for $oramsg(nullvalue). Any other string can be entered.
DB Objects
The Objects menu provides for data dictionary access into the current database. Tables, views, indexes, PL/SQL procedures, and triggers can be listed, and detailed information on each can be retrieved. For example, when displaying a list of tables, clicking "Ok" or double clicking on a table will list the columns and their datatypes in that table; for a PL/SQL procedure or trigger, the text of the procedure is listed. It's also possible to display several objects at the same time, as each object is displayed in it's own window.
Execute
Execute causes the SQL statements in the edit window to be sent to the server, and results printed. While Wosql is retrieving rows, the Execute button becomes "Cancel"; pressing it will halt retrieval of additional rows. The SQL edit windows has a few keyboard bindings worth mentioning. "Control-Return" and "Shift-Return" are bound to the Execute/Cancel button, so a user doesn't have to move a hand from the keyboard to start the query. Also, a buffer of 10 previous commands can be accessed by holding
"Control" or "Shift" and pressing either the Up or Down arrow keys. E.g., "Shift-Down" will access the most recent command. Also worth noting is the SQL text doesn't require a terminating `;' as 'SQL*Plus' requires. The "#" character at the beginning of a line also indicates a comment, rather than the C-like delimiters "/* ... */".
Help
The last menu item is Help. It's admittedly rather sparse on information.
Other Oratcl applications - IUD Maker
IUD Maker is an application generator. It builds an Oratcl script that performs selection, insert, update, and delete operations on rows of a single table. IUD Maker prompts for database logon userid and password, then requests that a table be selected from a list of all tables available to the user.
Figure Oratcl-3: IUD Maker
After selecting a table, IUD Maker presents a list of all the columns in the target table with their datatypes. Highlighting a column and pressing "Add to Search" will cause that column to be used for searching and browsing in the target application. "Add to Detail" makes the selected column appear in the detail listing. "Add all columns to Detail" populates the detail list with all columns in the table. Pressing "Generate" will build an IUD application named by writing a file named owner.tablename.iud.
The IUD table application can then be started. It too prompts for Oracle logon information. On a successful signon, the IUD application is started.
Figure Oratcl-4: IUD application
At the top of the applicaton window, search criteria can be entered for the browse columns (ones that were chosen as search columns in IUD Maker.) Pressing "Search" will retrieve rows that match the search criteria. Rows will be retrieved and columns formatted in the browse window to line up with the search fields. If all search fields are empty the browse list will contain all rows from the table. Numeric column search fields may include a relational operator (such as ">"); character column search fields always append "%" to the end of any search string and perform a "like" column match.
After rows are retrieved, double clicking on a row retrieves all the detail columns for the row and populates the detail fields in the bottom half of the window. Values can be changed, and the row updated by pressing "Update". "Delete" will delete a selected row. "Insert" will insert a new row with data currently held in the detail fields. Pressing "Clear Fields" will clear all search and detail fields. Any SQL errors, such as trying to insert rows with duplicate primary keys, are reported at the bottom status message.
Building Oratcl
Oratcl builds "out of the box" for most environments. Oratcl is distributed as a compressed (GNU gzip) tar file. A configure shell script built with GNU Autoconf is used to build the initial Makefile. Although not required for building Oratcl, Extended Tcl is highly recommended. Wosql requires commands from TclX. Configure will search for Tcl, Tk, and TclX (Extended Tcl) source directories in sibling directories from where Oratcl was un-tarred.
The other requirement for the configure script is finding the Oracle home directory, since Oratcl needs the Oracle OCI libraires to link executables. Configure looks in the directory defined by the ORACLE_HOME environment variable. The resulting Makefile will build a Tcl command line interpreter and a Tcl/Tk Wish interpreter, each with or without TclX. The Makefile target "all" will compile oratcl.c, build a library that contains the Oratcl commands in addition to the required Oracle OCI objects, then build the two interpreters, leaving the executables in the distribution directory. The target "install" will copy the executables to the installation bin directory, and the Oratcl man page to the installation man directory. If Oratcl was built with TclX, the target "install-wosql" will configure Wosql with the proper #!interpreter line and copy Wosql to the installation bin directory.
The "README" file contains notes on a particular release of Oratcl, which Tcl/Tk versions that are required, tested configurations, and general information. The file "INSTALL" contains detailed information on building Oratcl, including configure options recognized. Both README and INSTALL should be perused prior to building Oratcl. The file "CHANGES" is a history of features added and bugs fixed in Oratcl. The subdirectory "samples" contains additional sample Oratcl scripts.
Oratcl can be found at ftp.aud.alcatel.com in the directory /tcl/extensions/oratcl-2.3.tar.gz. Newer versions will be named the same, except for incrementing the major or minor version numbers. Current Usenet discussion of Oratcl takes place in comp.lang.tcl or comp.database.oracle. I can be reached at tpoindex@nyx.cs.du.edu.