Package org.postgresql.pljava.model


package org.postgresql.pljava.model
Interfaces that model a useful subset of the PostgreSQL system catalogs and related PostgreSQL abstractions for convenient Java access.

CatalogObject and its subinterfaces

The bulk of this package consists of interfaces extending CatalogObject, corresponding to various database objects represented in the PostgreSQL system catalogs.

In many of the PostgreSQL catalog tables, each row is identified by an integer oid. When a row in a catalog table represents an object of some kind, the oid of that row (plus an identifier for which table it is defined in) will be enough to identify that object.

CatalogObject

In most of the catalog tables, reference to another object is by its bare oid; the containing table is understood. For example, the prorettype attribute of a row in pg_proc (the catalog of procedures and functions) is a bare oid, understood to identify a row in pg_type, namely, the data type that the function returns.

Such an oid standing alone, when the containing catalog is only implied in context, is represented in PL/Java by an instance of the root class CatalogObject itself. Such an object does not carry much information; it can be asked for its oid, and it can be combined with the oid of some catalog table to produce a CatalogObject.Addressed.

CatalogObject.Addressed

When the oid of a row in some catalog table is combined with an identifier for which catalog table, the result is the explicit address of an object. Because catalog tables themselves are defined by rows in one particular catalog table (pg_class), all that is needed to identify one is the oid of its defining row in pg_class. Therefore, a pair of numbers (classId, objectId) is a complete "object address" for most types of object in PostgreSQL. The classId identifies a catalog table (by its row in pg_class), and therefore what kind of object is intended, and the objectId identifies the specific row in that catalog table, and therefore the specific object.

Such an oid pair is represented in PL/Java by an instance of CatalogObject.Addressed—or, more likely, one of its specific subinterfaces in this package corresponding to the type of object. A function, for example, may be identified by a RegProcedure instance (classId identifies the pg_proc table, objectId is the row for the function), and its return type by a RegType instance (classId identifies the pg_type table, and objectId the row defining the data type).

CatalogObject.Component

The only current exception in PostgreSQL to the two-oids-identify-an-object rule is for attributes (columns of tables or components of composite types), which are identified by three numbers, the classId and objectId of the parent object, plus a third number subId for the component's position in the parent. Attribute, therefore, is that rare subinterface that also implements CatalogObject.Component.

For the most part, that detail should be of no consequence to a user of this package, who will probably only ever obtain Attribute instances from a TupleDescriptor.

CatalogObject instances are singletons

Object instances in this catalog model are lazily-populated singletons that exist upon being mentioned, and thereafter reliably identify the same (classId,objectId) in the PostgreSQL catalogs. (Whether that (classId,objectId) continues to identify the "same" thing in PostgreSQL can be affected by data-definition commands being issued in the same or some other session.) An instance is born lightweight, with only its identifying triple of numbers. Its methods that further expose properties of the addressed object (including whether any such object even exists) do not obtain that information from the PostgreSQL system caches until requested, and may then cache it in Java until signaled by PostgreSQL that some catalog change has invalidated it.

CharsetEncoding

While not strictly a catalog object (PostgreSQL's supported encodings are a hard-coded set, not represented in the catalogs), they are exposed by CharsetEncoding instances that otherwise behave much like the modeled catalog objects, and are returned by the encoding() methods on Database and RegCollation. The one in use on the server (an often-needed value) is exposed by the SERVER_ENCODING static.

Lifespan subinterfaces

Some PL/Java objects correspond to certain native structures in PostgreSQL and therefore must not be used beyond the native structures' lifespan. Lifespan abstractly models any object in PostgreSQL that can be used to define, and detect the end of, a native-object lifespan. Two interfaces in this package that extend it and model specific PostgreSQL objects with that ability are MemoryContext and ResourceOwner.

TupleTableSlot, TupleDescriptor, and Adapter

TupleTableSlot in PostgreSQL is a flexible abstraction that can present several variant forms of native tuples to be manipulated with a common API. Modeled on that, TupleTableSlot is further abstracted, and can present a uniform API in PL/Java even to tuple-like things—anything with a sequence of typed, possibly named values—that might not be in the form of PostgreSQL native tuples.

The key to the order, types, and names of the components of a tuple is its TupleDescriptor, which in broad strokes is little more than a List of Attribute.

Given a tuple, and an Attribute that identifies its PostgreSQL data type, the job of accessing that value as some appropriate Java type falls to an Adapter, of which PL/Java provides a selection to cover common types, and there is a service-provider interface allowing independent development of others.

PL/Java supplies simple adapters when a Java primitive or some existing standard Java class is clearly the appropriate mapping for a PostgreSQL type. Other than that (and excepting the model classes in this package), PL/Java avoids defining new Java classes to represent other PostgreSQL types. Such classes may already have been developed for an application, or may be found in existing Java driver libraries for PostgreSQL, such as PGJDBC or PGJDBC-NG. It would be unhelpful for PL/Java to offer another such, independent and incompatible, set.

Instead, for PostgreSQL types that might not have an obvious, appropriate mapping to a standard Java type, or that might have more than one plausible mapping, PL/Java provides a set of functional interfaces in the package org.postgresql.pljava.adt. An Adapter (encapsulating internal details of a data type) can then expose the content in a documented, semantically clear form, to a simple application-supplied functional interface implementation or lambda that will produce a result of whatever Java type the application may already wish to use.

Author:
Chapman Flack