pljava-1.4.3/ 0000755 0000145 0000012 00000000000 11634451404 012123 5 ustar johann staff pljava-1.4.3/Makefile 0000644 0000145 0000012 00000007464 11634451404 013576 0 ustar johann staff #-------------------------------------------------------------------------
# Copyright (c) 2004, 2005, 2006 TADA AB - Taby Sweden
# Distributed under the terms shown in the file COPYRIGHT
# found in the root folder of this project or at
# http://eng.tada.se/osprojects/COPYRIGHT.html
#
# @author Thomas Hallgren
#
# Top level Makefile for PLJava
#
# To compile a PLJava for PostgreSQL 8.x the makefile system will utilize
# the PostgreSQL pgxs system. The only prerequisite for such a compile is
# that a PostgreSQL 8.x is installed on the system and that the PATH is set
# so that the binaries of this installed can be executed.
#
# The following options are recognized (aside from normal options like
# CFLAGS etc.)
#
# PGSQLDIR= Java™ is a registered trademark of Sun Microsystems, Inc. in the United States and other countries. A source tarball and four of binary builds can be found in the download area.
Two for Windows and two for i386 based Linux. Although all
pre-compiled binaries must run using a standard JVM, the PL/Java can also be
compiled and linked using GNU GCJ. PL/Java has no pre-compiled binaries for GCJ but the make system
contain what's needed to make the build easy. Please note that all use of GCJ should be regarded as experimental. Due to limitations in
the
implementation of java.security in some versions of GCJ the PL/Java trusted
language implementation is, in fact, not trusted. At present this applies
regardless of what GCJ version since the code is conditionally compiled. Get the binary distribution of PL/Java for your platform. Unzip it into a directory
of your own choice. Get the PostgreSQL environment up and running. You will need to modify the
Note that on the win32 platform you need to use a semicolon as a
path separator and double backslashes (since backslash is the escape character in
the postgresql.conf file) as directory separators. In order to see the logging from the tests add the following: Add the following entry:PL/Java, 1.2.x
Prerequisites
Postmaster configuration
postgresql.conf
file. In order to find the PL/Java shared object, you can do one of two things. Either
you install the shared object in a directory already searched by the postmaster
(such as the data directory) or you tell the postmaster where to find it using the
dynamic_library_path
. I.e. you have a setting similar to this:dynamic_library_path = '$libdir:<pljava installation>'
log_min_messages
= info
custom_variable_classes = 'pljava'
System classpath
Normally, all Java code is loaded into the database using the install_jar/replace_jar
SQL functions. Most of PL/Java (those functions included) is however implemented in Java.
Unless you use GCJ, where this Java code is compiled and linked with the pljava shared
object module, this hen and egg problem needs to be resolved using the system classpath.
Add the following entry to the
postgresql.conf
file:
pljava.classpath = <pljava installation>/pljava.jar
Unless you use GCJ, the postmaster must be made aware of the location of the shared objects used by the Java Runtime Environment (JRE). Please note that this applies to the postmaster, i.e. the backend process, and not to the client. The client will not need these settings.
Setting the LD_LIBRARY_PATH
environment will work on most Linux/Unix platforms:
export LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/i386:$JAVA_HOME/jre/lib/i386/client
.
Apparently, on some Linux platforms you will also need to include $JAVA_HOME/jre/lib/i386/native_threads.
An alternative to use LD_LIBRARY_PATH
is to edit the /etc/ld.so.conf
file and then use /sbin/ldconfig on some Linux/Unix systems.
On some platforms there will be a conflict between the libzip.so included in the JRE and the libz.so used by PostgreSQL (the JRE libzip.so includes a libz.so). The symptom is an InternalError in the java.util.zip.Inflater.init when an attempt is made to load the first class. You can verify the version of libzip.so using the following command:
strings libzip.so | fgrep Copyright
The problem can be resolved in one of the following ways depending on your needs and ability to recompile:
--without-zlib
, recompile and reinstall.
This will effetively disable all compression support in PostgreSQL.A standard install on a Windows box would be to add the following
entries to you PATH
environment:
set PATH=%PATH%;%JAVA_HOME%\jre\bin;%JAVA_HOME%\jre\bin\client
You are now ready to start the postmaster.
PL/Java adds a schema named SQLJ to the database (the naming is from the proposed
SQL standard for Java backend mapping) and adds a couple of tables and functions
to that schema. The deployment can be done in one of two ways. The simplest way
is probably to just execute the file install.sql
as a super user (the
uninstall.sql
will remove the PL/Java installation). PL/Java also comes with
deploy program that lets you install, reinstall, or uninstall PL/Java. This
program will assert that you indeed are a super user and then execute the
correct commands using jdbc. In
order to run this program, you must see to that the PostgreSQL jdbc driver package
postgresql.jar
and the deploy.jar
file is in your
CLASSPATH
, then run:
java org.postgresql.pljava.deploy.DeployerThis will result in a list of options. Typically you would use something like:
java org.postgresql.pljava.deploy.Deployer -install
That's all there's to it. You are now ready to start using the PL/Java system.
The tests are divided into two jar files. One is the client part found in the test.jar
. It contains some methods that executes
SQL statements and prints the output (all contained there can of course also be
executed from psql or any other client). The other is the examples.jar
which contains the sample code that runs in the backend. The latter must be installed
in the database in order to function. An easy way to do this is to use psql and
issue the command:
SELECT sqlj.install_jar('file:///some/directory/examples.jar', 'samples', true);
Please note that the deployment descriptor stored in examples.jar will attempt
to create the schema javatest
so the user that executes the sqlj.install_jar
must have permission to do that. If this command succeeds, everything is working correctly. You may get a couple
of errors here though.
org.postgresql.pljava.
<something>
cannot be found. CLASSPATH
seen by the postmaster
is incorrect so that the pljava.jar is not found.dynamic_library_path
in the postgresql.conf
file is incorrect.Once loaded, you must also set the classpath used by the PL/Java runtime. This
classpath is set per schema (namespace). A schema that lacks a classpath will default
to the classpath that has been set for the public schema. The tests will use the
schema javatest
. To define the classpath for this schema, simply use
psql and issue the command:
SELECT sqlj.set_classpath('javatest', 'samples');
The first argument is the name of the schema, the second is a colon separated list of jar names. The names must reflect jars that are installed in the system.
NOTE: If you don't use schemas, you must still issue the set_classpath command to assign a correct classpath to the 'public' schema. This can only be done by a super user.
Now, you should be able to run the tests:
java org.postgresql.pljava.test.Tester
Building should be very stright forward:
Java™ is a registered trademark of Sun Microsystems, Inc. in the United States and other countries.
When writing the PL/Java, mapping the JVM into the same process-space as the PostgreSQL backend code, some concerns have been raised regarding multiple threads, exception handling, and memory management. Here is a brief text explaining how these issues where resolved.
Java is inherently multi threaded. The PostgreSQL backend is not. There’s nothing stopping a developer from utilizing multiple Threads class in the Java code. Finalizers that call out to the backend might have been spawned from a background Garbage Collection thread. Several third party Java-packages that are likely to be used make use of multiple threads. How can this model coexist with the PostgreSQL backend in the same process without creating havoc?
The solution is simple. PL/Java defines a special object called the
Backend.THREADLOCK
. When PL/Java is initialized, the backend will immediately
grab this objects monitor (i.e. it will synchronize on this object). When the
backend calls a Java function, the monitor is released and then
immediately regained when the call returns. All calls from Java out to backend
code are synchronized on the same lock. This ensures that only one thread at a
time can call the backend from Java, and only at a time when the backend is
awaiting the
return of a Java function call.
Java makes frequent use of try/catch/finally blocks. PostgreSQL sometimes use an exception mechanism that calls longjmp to transfer control to a known state. Such a jump would normally effectively bypass the JVM. Prior to PostgreSQL version 8.0, the error was propagated before the actual jump and then discarded, thus there was no way to catch and handle the error.
The backend now allows errors to be caught using the macros
PG_TRY/PG_CATCH/PG_END_TRY
and in the catch block, the error can be
examined using the ErrorData
structure.
PL/Java implements a java.sql.SQLException
subclass called
org.postgresql.pljava.ServerException
. The ErrorData can be retrieved and
examined from that exception. A catch handler is allowed to issue a rollback to
a savepoint. After a successful rollback, execution can continue.
Primitive types will be passed by value always. This includes the String type (this is a must since Java uses double byte characters). Complex types are however often wrapped in Java objects and passed by reference. I.e, a Java object will contain a pointer to a palloc’ed or stack allocated memory and use native JNI calls to extract and manipulate data. Such data will become “stale” once a call has ended. Further attempts to access such data will at best give very unpredictable results but more likely cause a memory fault and a crash.
The PL/Java contains code that ensures that stale pointers are cleared when the MemoryContext or stack where they where allocated goes out of scope. The Java wrapper objects might live on but any attempt to use them will result in a “stale native handle” exception.