With this release you can call functions and triggers in Java. At present
the implementation uses a very simple classloader
mechanism (the CLASSPATH must be set prior to starting postmaster) and there's
no
1. Wrap the Relation/TupleDesc/Tuple code in the interfaces ResultSet and ResultSetMetaData (java.sql package) and change so that complex types and sets are passed as ResultSet.
2. Far better packaging, more generic makefile, and more elaborated instructions on how to build.
3. Implement java.sql interfaces on top of SPI functions (SPI_prepare, SPI_cursor_open, etc.).
4. Enable the SQLJ schema with functions like INSTALL_JAR, REPLACE_JAR, REMOVE_JAR, and ALTER_JAVA_PATH (this is according to SQL-2003 standard).
5. Documentation, both API and User Guide.
6.
If possible, add transaction
Further steps aimed to bring the PL/Java more closely to the standard will be dependent on some additions to the Postgres SQL parser. User Defined Java types in particular needs to be addressed. The ability to write "EXTERNAL NAME '...'" instead of just "AS '...'" in CREATE FUNCTION is another issue. There's more...
See to that you have Java 1.4 installed on your machine.
This project has been written using Linux 9.0 on an Intel box and Eclipse 3.0 with CDT 2.0. The pljava CVS contains the some Eclipse specific files. They are there for convenience only and there’s absolutely no requirement to use Eclipse (nor of course to use Linux and Intel). You must at least have Ant (look at the apache.org website) in order to build the Java stuff and to generate the JNI headers.
Install the source of postgresql-7.4. Place it adjacent to the org.postgresql.pljava directory (the makefiles uses ../postgresql-7.4 to get to the Postgres source).
In order to run the test code you will also need the Postgres JDBC driver.
Once everything compile, you must do the following:
-
The postgresql.conf dynamic_library_path variable must be set so that
postmaster can find the libpljava.so file.
-
The CLASSPATH environment variable seen by
postmaster must point to the pljava.jar and the examples.jar (the latter only required for the samples and
test of course). This is a temporary kludge (see road map).
- The LD_LIBRARY_PATH environment variable must be set so that the loader finds the shared libraries used by the JVM. A standard install on an Intel Linux box will need LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/i386:$JAVA_HOME/jre/lib/i386/client.
Once the postmaster is running with the above configuration, you should be
able to run the test code found in org.postgresql.pljava.test.Tester.
It contains some rudimentary tests for primitive parameter passing and the
client side of a Java version of a couple of triggers originally from the
postgres source distribution (under contrib/spi).
Look at the code first. It’s not very scientific.
The makefiles of this project should be improved (need better way to find the postgres include files for instance). Help and ideas in this area are greatly appreciated.
On a Linux 9 system, there is a jni.h file that
apparently is bundled with the GNU compiler. The GNU jni.h
file has no
Java and JNI will use the following naming scheme when finding the shared library on a Unix box:
Prepend the name with “lib” and then append “.so”. Find the resulting file using the LD_LIBRARY_PATH.
On a Windows box it does like this:
Append “.dll” (nothing is prepended) and then use PATH to find the resulting file.
Postgres have a scheme of its own. Apparently it doesn’t prepend the “lib” on a Unix box and it uses the Dynamic_library_path instead of the LD_LIBRARY_PATH/PATH to find the module. Unfortunately, the Dynamic_library_path is not seen by the loader so if a module needs to load other dynamic libraries it will fail unless LD_LIBRARY_PATH/PATH is set correctly.
At present, I merge the Dynamic_library_path and the LD_LIBRARY_PATH and use the result in the JVM. That seems to work fine (the JVM will attempt to load the shared library too and unless it finds the already loaded one, it will fail). I think that it would be great if PostgreSQL could do the merge and set the correct LD_LIBRARY_PATH/PATH in the environment used by the forked backend processes. That way, the system loader would function correctly and PostgreSQL would not need any specific code to handle module loading.
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 and the TriggerData structure are however passed by reference. In essence, a Java object will contain a pointer to a palloc’ed memory and use native JNI calls to extract and manipulate data. Such data will become “stale” once a call has ended and code is present to ensure that such pointers are cleared. Any attempt to access instances of the following classes after the called where they where obtain has ended will yield a “closed native handle” exception:
org.postgresql.pljava.Relation
org.postgresql.pljava.TriggerData
org.postgresql.pljava.Tuple
org.postgresql.pljava.TupleDesc
You will most likely find more issues.