Skip to content

Commit

Permalink
Classpath set(PostgreSQL libdir),dynamic loading of JDBC Drivers done
Browse files Browse the repository at this point in the history
  • Loading branch information
atris committed Jul 5, 2012
1 parent 97119d8 commit 4f297cb
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 22 deletions.
Binary file removed JDBCClasses/JDBCUtils.class
Binary file not shown.
33 changes: 33 additions & 0 deletions JDBCDriverLoader.java
@@ -0,0 +1,33 @@
/*-------------------------------------------------------------------------
*
* foreign-data wrapper for JDBC
*
* Copyright (c) 2012, PostgreSQL Global Development Group
*
* This software is released under the PostgreSQL Licence
*
* Author: Atri Sharma <atri.jiit@gmail.com>
*
* IDENTIFICATION
* jdbc_fdw/JDBCDriverLoader.java
*
*-------------------------------------------------------------------------
*/

import java.io.*;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.MalformedURLException;

public class JDBCDriverLoader extends URLClassLoader{
public
JDBCDriverLoader(URL[] path)
{
super (path);
}
public void
addPath(String path) throws MalformedURLException
{
addURL (new URL (path));
}
}
39 changes: 34 additions & 5 deletions JDBCClasses/JDBCUtils.java → JDBCUtils.java
@@ -1,18 +1,42 @@
/*-------------------------------------------------------------------------
*
* foreign-data wrapper for JDBC
*
* Copyright (c) 2012, PostgreSQL Global Development Group
*
* This software is released under the PostgreSQL Licence
*
* Author: Atri Sharma <atri.jiit@gmail.com>
*
* IDENTIFICATION
* jdbc_fdw/JDBCUtils.java
*
*-------------------------------------------------------------------------
*/

import java.sql.*;
import java.text.*;
import java.io.*;
public class JDBCUtils {
import java.net.URL;
import java.net.URLClassLoader;
import java.net.MalformedURLException;
import java.util.*;
public class JDBCUtils{
private ResultSet rs;
private Connection conn;
private int NumberOfColumns;
private int NumberOfRows;
private Statement sql;
private String[] Iterate;
public void
private JDBCDriverLoader JDBC_Driver_Loader;
public void
Initialize(String[] ar1) throws IOException
{
DatabaseMetaData dbmd;
ResultSetMetaData r1;
Properties JDBCProperties;
Class JDBCDriverClass;
Driver JDBCDriver;
String url = ar1[2];
String userName = ar1[3];
String password = ar1[4];
Expand All @@ -22,9 +46,15 @@ public class JDBCUtils {

try
{
Class.forName(ar1[1]);
conn = DriverManager.getConnection(url, userName, password);
JDBC_Driver_Loader = new JDBCDriverLoader(new URL[]{new URL("jar:file://"+ar1[6]+"!/")});
JDBCDriverClass = JDBC_Driver_Loader.loadClass(ar1[1]);
JDBCDriver = (Driver)JDBCDriverClass.newInstance();
JDBCProperties = new Properties();
JDBCProperties.put("user", userName);
JDBCProperties.put("password", password);

conn = JDBCDriver.connect(url, JDBCProperties);

dbmd = conn.getMetaData();
System.out.println("Connection to "+dbmd.getDatabaseProductName()+" "+dbmd.getDatabaseProductVersion()+" successful.\n");

Expand Down Expand Up @@ -102,7 +132,6 @@ public class JDBCUtils {
sql.cancel();
rs.close();
conn.close();

}catch(Exception a)
{
a.printStackTrace();
Expand Down
18 changes: 17 additions & 1 deletion Makefile
Expand Up @@ -23,8 +23,23 @@ REGRESS = jdbc_fdw

JDBC_CONFIG = jdbc_config

SHLIB_LINK= -ljvm
SHLIB_LINK = -ljvm

TRGTS = JAVAFILES

JAVA_SOURCES = \
JDBCUtils.java \
JDBCDriverLoader.java \

PG_CPPFLAGS=-D'PKG_LIB_DIR=$(pkglibdir)'

JFLAGS = -d $(pkglibdir)

all:$(TRGTS)

JAVAFILES:
javac $(JFLAGS) $(JAVA_SOURCES)

ifdef USE_PGXS
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
Expand All @@ -36,3 +51,4 @@ include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif


2 changes: 0 additions & 2 deletions README
@@ -1,5 +1,3 @@
IMPORTANT:Please note that,at the moment,for using jdbc_fdw,the user will have to manually set the classpaths:first,to JDBCUtils.class and second,to the JDBC driver which is being used for connecting and fetching data from the foreign database.

Installing
----------

Expand Down
74 changes: 60 additions & 14 deletions jdbc_fdw.c
Expand Up @@ -40,6 +40,11 @@
#include "storage/ipc.h"
#include "jni.h"

#define Str(arg) #arg
#define StrValue(arg) Str(arg)
#define STR_PKGLIBDIR StrValue(PKG_LIB_DIR)


PG_MODULE_MAGIC;

static JNIEnv *env;
Expand Down Expand Up @@ -68,6 +73,7 @@ static struct jdbcFdwOption valid_options[] =
{ "drivername", ForeignServerRelationId },
{ "url", ForeignServerRelationId },
{ "querytimeout", ForeignServerRelationId },
{ "jarfilename", ForeignServerRelationId },
{ "username", UserMappingRelationId },
{ "password", UserMappingRelationId },
{ "query", ForeignTableRelationId },
Expand Down Expand Up @@ -111,7 +117,7 @@ static void jdbcEndForeignScan(ForeignScanState *node);
* Helper functions
*/
static bool jdbcIsValidOption(const char *option, Oid context);
static void jdbcGetOptions(Oid foreigntableid, char **drivername, char **url, int *querytimeout, char **username, char **password, char **query, char **table);
static void jdbcGetOptions(Oid foreigntableid, char **drivername, char **url, int *querytimeout, char **jarfilename, char **username, char **password, char **query, char **table);
/*
* Uses a String object's content to create an instance of C String
*/
Expand Down Expand Up @@ -179,15 +185,16 @@ JVMInitialization()
JavaVMOption options[1];
#ifndef JNI_VERSION_1_2
JDK1_1InitArgs vm_args;
char classpath[1024];
#endif
static bool FunctionCallCheck=false; /* This flag safeguards against multiple calls of JVMInitialization().*/

char strpkglibdir[]=STR_PKGLIBDIR;
char classpath[1024];

if(FunctionCallCheck==false)
{
#ifdef JNI_VERSION_1_2
options[0].optionString =
"-Djava.class.path=" "/home/gitc/postgresql-9.1.3/contrib/jdbc_fdw/JDBCClasses:/home/gitc/Downloads/sqlite-jdbc-3.7.2.jar";
snprintf(classpath,strlen(strpkglibdir)+19,"-Djava.class.path=%s",strpkglibdir);
options[0].optionString = classpath;
vm_args.version = 0x00010002;
vm_args.options = options;
vm_args.nOptions = 1;
Expand Down Expand Up @@ -299,6 +306,7 @@ jdbc_fdw_validator(PG_FUNCTION_ARGS)
char *svr_password = NULL;
char *svr_query = NULL;
char *svr_table = NULL;
char *svr_jarfilename = NULL;
int svr_querytimeout = 0;
ListCell *cell;

Expand Down Expand Up @@ -362,6 +370,15 @@ jdbc_fdw_validator(PG_FUNCTION_ARGS)

svr_querytimeout = atoi(defGetString(def));
}
if (strcmp(def->defname, "jarfilename") == 0)
{
if (svr_jarfilename)
ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options: jarfilename (%s)", defGetString(def))
));

svr_jarfilename = defGetString(def);
}
if (strcmp(def->defname, "username") == 0)
{
if (svr_username)
Expand Down Expand Up @@ -439,7 +456,7 @@ jdbcIsValidOption(const char *option, Oid context)
* Fetch the options for a jdbc_fdw foreign table.
*/
static void
jdbcGetOptions(Oid foreigntableid, char **drivername, char **url, int *querytimeout, char **username, char **password, char **query, char **table)
jdbcGetOptions(Oid foreigntableid, char **drivername, char **url, int *querytimeout, char **jarfilename, char **username, char **password, char **query, char **table)
{
ForeignTable *f_table;
ForeignServer *f_server;
Expand Down Expand Up @@ -479,6 +496,11 @@ jdbcGetOptions(Oid foreigntableid, char **drivername, char **url, int *querytime
*querytimeout = atoi(defGetString(def));
}

if (strcmp(def->defname, "jarfilename") == 0)
{
*jarfilename = defGetString(def);
}

if (strcmp(def->defname, "password") == 0)
{
*password = defGetString(def);
Expand Down Expand Up @@ -516,6 +538,11 @@ jdbcGetOptions(Oid foreigntableid, char **drivername, char **url, int *querytime
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("URL must be specified")
));
if(!*jarfilename)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("JAR file name must be specified")
));
}

/*
Expand All @@ -533,16 +560,19 @@ jdbcPlanForeignScan(Oid foreigntableid, PlannerInfo *root, RelOptInfo *baserel)
char *svr_query = NULL;
char *svr_table = NULL;
char *svr_url = NULL;
char *svr_jarfilename = NULL;
int svr_querytimeout;
char *query;

fdwplan = makeNode(FdwPlan);

JVMInitialization();

SIGINTInterruptCheckProcess();

/* Fetch options */
jdbcGetOptions(foreigntableid, &svr_drivername, &svr_url, &svr_querytimeout, &svr_username, &svr_password, &svr_query, &svr_table);
jdbcGetOptions(foreigntableid, &svr_drivername, &svr_url, &svr_querytimeout, &svr_jarfilename, &svr_username, &svr_password, &svr_query, &svr_table);


/* Build the query */
if (svr_query)
Expand Down Expand Up @@ -576,10 +606,11 @@ jdbcExplainForeignScan(ForeignScanState *node, ExplainState *es)
char *svr_password = NULL;
char *svr_query = NULL;
char *svr_table = NULL;
char *svr_jarfilename = NULL;
int svr_querytimeout;

/* Fetch options */
jdbcGetOptions(RelationGetRelid(node->ss.ss_currentRelation), &svr_drivername, &svr_url, &svr_querytimeout, &svr_username, &svr_password, &svr_query, &svr_table);
jdbcGetOptions(RelationGetRelid(node->ss.ss_currentRelation), &svr_drivername, &svr_url, &svr_querytimeout, &svr_jarfilename, &svr_username, &svr_password, &svr_query, &svr_table);
SIGINTInterruptCheckProcess();
}

Expand All @@ -596,22 +627,25 @@ jdbcBeginForeignScan(ForeignScanState *node, int eflags)
char *svr_password = NULL;
char *svr_query = NULL;
char *svr_table = NULL;
int svr_querytimeout;
char *svr_jarfilename = NULL;
int svr_querytimeout = 0;
jdbcFdwExecutionState *festate;
char *query;
jclass JDBCUtilsClass;
jclass JavaString;
jstring StringArray[6];
jstring StringArray[7];
jmethodID id_initialize;
jobjectArray arg_array;
int counter = 0;
jfieldID id_numberofcolumns;
char *querytimeoutstr = NULL;
char jar_classpath[1024];
char strpkglibdir[] = STR_PKGLIBDIR;

SIGINTInterruptCheckProcess();

/* Fetch options */
jdbcGetOptions(RelationGetRelid(node->ss.ss_currentRelation), &svr_drivername, &svr_url, &svr_querytimeout, &svr_username, &svr_password, &svr_query, &svr_table);
jdbcGetOptions(RelationGetRelid(node->ss.ss_currentRelation), &svr_drivername, &svr_url, &svr_querytimeout, &svr_jarfilename, &svr_username, &svr_password, &svr_query, &svr_table);

/* Build the query */
if (svr_query){
Expand Down Expand Up @@ -653,25 +687,37 @@ jdbcBeginForeignScan(ForeignScanState *node, int eflags)
querytimeoutstr=(char*)palloc(sizeof(int));

snprintf(querytimeoutstr,sizeof(int),"%d",svr_querytimeout);
snprintf(jar_classpath,(strlen(strpkglibdir)+strlen(svr_jarfilename)+2),"%s/%s",strpkglibdir,svr_jarfilename);

if(svr_username == NULL)
{
svr_username = "";
}

if(svr_password == NULL)
{
svr_password = "";
}

StringArray[0] = (*env)->NewStringUTF(env, (festate->query));
StringArray[1] = (*env)->NewStringUTF(env, svr_drivername);
StringArray[2] = (*env)->NewStringUTF(env, svr_url);
StringArray[3] = (*env)->NewStringUTF(env, svr_username);
StringArray[4] = (*env)->NewStringUTF(env, svr_password);
StringArray[5] = (*env)->NewStringUTF(env, querytimeoutstr);
StringArray[6] = (*env)->NewStringUTF(env, jar_classpath);

JavaString= (*env)->FindClass(env, "java/lang/String");

arg_array = (*env)->NewObjectArray(env, 6, JavaString, StringArray[0]);
arg_array = (*env)->NewObjectArray(env, 7, JavaString, StringArray[0]);
if (arg_array == NULL)
{
elog(ERROR,"arg_array is NULL");
}

for(counter=1;counter<6;counter++)
for(counter=1;counter<7;counter++)
{
(*env)->SetObjectArrayElement(env,arg_array,counter,StringArray[counter]);
(*env)->SetObjectArrayElement(env,arg_array,counter,StringArray[counter]);
}

java_call=(*env)->AllocObject(env,JDBCUtilsClass);
Expand Down

0 comments on commit 4f297cb

Please sign in to comment.