I'm seeking a method to port Oracle's pl/sql wrappers which manipulate ACS 4.0 objects.
Here's overview of a solution that sort of works:
- PL/Tcl was used
- I decided to 'pack' all input arguments into single TEXT string, and let Tcl unwind it with 'array set'
- the idea is to have one PL/Tcl function per package which accepts just two arguments: method ('new', 'delete', ...) and packed input parameters as second arg (as stated above). This way we should avoid namespace pollution. Oh, and the return value is of type TEXT, into which id's returned from constructors can be safely coerced, while we can simply ignore return values from destructors. Here's how it can be invoked:
SELECT pltcl_acs_attribute('create', '
object_type "''apm_package''"
attribute_name "''package_blah''"
datatype "''string''"
pretty_name "''Package Blah''"
pretty_plural "''Package Blahs''"
');
... resulting in:
NOTICE: INSERT INTO acs_attributes
(attribute_id, min_n_values, pretty_name, datatype,
attribute_name,
object_type, storage, max_n_values, sort_order, static_p,
pretty_plural)
VALUES
(17, 1, 'Package Blah', 'string', 'package_blah', 'apm_package',
'type_specific', 1, 1, 'f', 'Package Blahs')
pltcl_acs_attribute
---------------------
17
(1 row)
Here's the actual code:
(here
is the link to relevant part of classic ACS 4.0 data model)
CREATE FUNCTION pltcl_acs_attribute(text, text)
RETURNS text
AS '
switch -- $1 {
create {
array set pl_args $2
if {![info exists pl_args(min_n_values)]} {
set pl_args(min_n_values) 1
}
if {![info exists pl_args(max_n_values)]} {
set pl_args(max_n_values) 1
}
if {![info exists pl_args(storage)]} {
set pl_args(storage) ''type_specific''
}
if {![info exists pl_args(static_p)]} {
set pl_args(static_p) ''f''
}
if {![info exists pl_args(sort_order)]} {
spi_exec "
SELECT COALESCE(MAX(sort_order), 1) AS v_sort_order
FROM acs_attributes
WHERE object_type = $pl_args(object_type)
and attribute_name = $pl_args(attribute_name)"
set pl_args(sort_order) $v_sort_order
}
spi_exec "SELECT NEXTVAL(''acs_attribute_id_seq'') AS
v_attribute_id"
set pl_args(attribute_id) $v_attribute_id
set target_list [list]
set values_list [list]
foreach key [array names pl_args] {
lappend target_list $key
lappend values_list $pl_args($key)
}
set sql "INSERT INTO acs_attributes
([join $target_list ", "])
VALUES
([join $values_list ", "])"
elog NOTICE $sql
spi_exec $sql
return $v_attribute_id
}
default {
# maybe throw exception here?
return ""
}
}
'
LANGUAGE 'pltcl';
Problems:
- Constructing 'packed' argument is major pain in the ass. Just look at the number of single and double-quotes.
- Again, the way the input arguments are 'packed' is huge security hole (SQL-wise). [quote ...] should be used carefully, because we might still want to pass NULL here and there.
- Tcl code should be smarter about required arguments.
- Tcl code should be smarter about defaults.
Request notifications