Hello

Package contains package's variables, shared protected functions and initialisation part, which is executed when any public function attached to package is called. Every package has defined only one language. The reason for this is binary compatibility of package's variables. Private functions aren't SQL functions and it isn't possible to call them via SPI. Because PL/pgSQL can't call functions via different interface than SPI, PL/pgSQL won't support private functions. Package owner can attach any SQL funtions to package, even those written in different language, but only functions in same language as package can access package variables and protect functions. Package is similar to schema. Public package function can access package variables or private functions only if it has same language as package. Every function can be attached to just one package. Only owner can modify package (ALTER OR ATTACH functions).

Samples:

CREATE OR REPLACE PACKAGE foo_package
AS $$
DECLARE my_var integer;
BEGIN
 my_var := 0;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

CREATE OR REPLACE FUNCTION foo_package.counter() RETURNS integer
AS $$
BEGIN
 my_var := my_var + 1;
 RETURN foo_package.my_var; -- explicit namespace
END;
$$ LANGUAGE plpgsql IMMUTABLE;

SELECT foo_package.counter();

This proposal for package has minimal impact on current implementation of PL languages.

CREATE OR REPLACE PACKAGE xml_parser AS $$
 USE XML::LibXML;

 my $parser = XML::LibXML->new;
 my $schema_file = '/home/postgres/comm.xsd';
 my $schema = XML::LibXML::Schema->new(location => $schema_file);

sub get_data
{
        my ($root, $tag, $optional) = @_;
        my $aux = $root->getElementsByTag($tag);
        if (@aux eq 0)
        {
                elog(ERROR, "Missing value") if ! $optional;
                return undef;
        }
        return @aux[0]->getFirstChild->getData;
}
$$ LANGUAGE plperlu;

CREATE OR  REPLACE FUNCTION xml_parser.parse_document (
 IN body varchar,
 OUT name varchar,
 OUT document_type varchar)
AS $$
        my $body = $_[0];

        my $doc = $parser->parse_string($body);
        $schema->validate($doc);
        $root = $doc->getDocumentElement();
        return {
                name => $root->nodeName;
                document_type => get_data($root, 'type') };
$$ LANGUAGE plperlu;

- using different language, can access only public functions
CREATE OR REPLACE FUNCTION xml_parser.validate_all_doc(
 OUT _name varchar,
 OUT _state boolean) RETURNS SETOF RECORD
AS $$
DECLARE _body varchar;
BEGIN
 FOR _body, _name IN SELECT body, path FROM xml_repository LOOP
   BEGIN
     -- use implicit search_path containing package_name
     _state := true;
     PERFORM parse_document(_r.body);
   EXCEPTION WHEN OTHERS THEN
     _state := false;
   END;
   RETURN NEXT;
 END LOOP;
 RETURN;
END;
$$ LANGUAGE plpgsql VOLATILE;

SELECT xml_parser.validate_all_doc();

This system is simple and minimalistic and doesn't copy package system from ADA or Oracle which are more complicated and don't allow multiple PL.

Any comments are welcome

Regards
Pavel Stehule

p.s. I'll have free time on sept. and can work on it.

_________________________________________________________________
Emotikony a pozadi programu MSN Messenger ozivi vasi konverzaci. http://messenger.msn.cz/


---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?

              http://www.postgresql.org/docs/faq

Reply via email to