Oracall
Go package for calling Oracle PL/SQL stored procedures through OCI
Install / Use
/learn @tgulacsi/OracallREADME
OraCall
OraCall is a package for calling Oracle stored procedures with gRPC. As OCI does not allow using PL/SQL record types, this causes some difficulty.
Getting Started
Prerequisities
Of course you'll need a working Oracle environment. For instructions, see godror.
As OraCall uses gRPC for the interface, you'll need protoc, the
Protocol Buffers
code generator and a Go code generator,
such as protoc-gen-gofast.
But these two is downloaded by go generate.
Installing
go get github.com/tgulacsi/oracall
go generate github.com/tgulacsi/oracall # this will download protoc and protoc-gen-gofast
Then you can use it:
oracall -db-out ./pkg/db -pb-out ./pkg/pb -connect 'user/passw@sid' 'MY_PKG.%'
This will generate
my_pkg_functions.gowith the calling machinery,my_pkg.protowith the Protocol Buffers messages and RPC service definitions,- and call
protoco-gen-gofastwithmy_pkg.proto, which will generatemy_pkg.pb.gowith the Protocol Buffers (un)marshal code.
How does it work?
1. read stored procedures' definitions from the database
First, it reads the functions, procedures' names and their arguments' types from the given database with the following query:
SELECT object_id, subprogram_id, package_name, object_name,
data_level, sequence, argument_name, in_out,
data_type, data_precision, data_scale, character_set_name,
pls_type, char_length, type_owner, type_name, type_subname, type_link
FROM user_arguments
ORDER BY object_id, subprogram_id, SEQUENCE;
So the argument's type must be readable in user_arguments!
For a SYS_REFCURSOR (returning a cursor, a query's result set in Oracle parlance),
you have to specialize the type for the returned columns -- see below.
2. generate calling machinery
3. generate .proto file
4. call protoc-gen-gofast
5. profit!
Restrictions
Supported types:
- PL/SQL simple types
- PL/SQL record types (defined at stored package level)
- PL/SQL associative arrays, but just "INDEX BY BINARY_INTEGER" and this arrays must be one of the previously supported types (but not arrays!) 'Cause of OCI restrictions, these arrays must be indexed from 1.
- cursors.
Tweaks
If you have a package with mixed content, you can force oracall to ignore them either by
- specify command-line flag:
-private pkg.func_to_be_ignored,pkg2.other_private - or add a comment:
--oracall:private func_to_be_ignoredto the package header.
The latter can be used to implement two other hacks:
- rename a function (if you have a non-oracall-compliant and a replacement, and have to keep both): `--oracall:rename non_compliant => compliant
- replace a function's innards with another function getting and receiving xml as CLOB:
--oracall:replace non_compliant_complex => xml_replacementand this will create thenon_compliant_complexfunction's call type in the protobuf file (so this will look like the original complex function), but will call thexml_replacementfunction with the protobuf serialized to XML, and deserialized from the returned XML.
REF_CURSOR
For example for
FUNCTION ret_cur(p_id IN INTEGER) RETURN SYS_REFCURSOR IS
v_cur SYS_REFCURSOR;
BEGIN
OPEN v_cur FOR
SELECT state, amount FROM table;
RETURN v_cur;
END;
You'll have to define the type in the package HEAD:
TYPE state_amount_rec_typ IS RECORD (state table.state%TYPE, amount table.amount%TYPE);
TYPE state_amount_cur_typ IS REF CURSOR RETURN state_amount_rec_typ;
Then only change the type in the BODY:
FUNCTION ret_cur(p_id IN INTEGER) RETURN state_amount_cur_typ IS
v_cur state_amount_cur_typ;
BEGIN
OPEN v_cur FOR
SELECT state, amount FROM table;
RETURN v_cur;
END;
TL;DR; oracall needs "strongly typed" REF CURSOR - see http://www.dba-oracle.com/plsql/t_plsql_cursor_variables.htm for example!
Examples
Minimal
Minimal is a minimal example using OraCall: a simple main package which connects to the database and calls the function specified on the command line. Args are specified using JSON.
This must be compiled with your oracall output - such as
oracall <one.csv >examples/minimal/generated_functions.go \
&& go fmt ./examples/minimal/ \
&& go build ./examples/minimal/ \
&& ./minimal DB_web.sendpreoffer_31101
This calls oracall with one.csv as stdin, and redirects its output to examples/minimal/generated_functions.go. Then formats the output (good for safety check, too) after this it builds the "minimal" binary (into the current dir). If all this was successful, than calls the resulting binary to call the specified function.
Related Skills
feishu-drive
352.0k|
things-mac
352.0kManage Things 3 via the `things` CLI on macOS (add/update projects+todos via URL scheme; read/search/list from the local Things database)
clawhub
352.0kUse the ClawHub CLI to search, install, update, and publish agent skills from clawhub.com
postkit
PostgreSQL-native identity, configuration, metering, and job queues. SQL functions that work with any language or driver
