[libgda] JDBC provider: make it possible to use connection parameters similar to other providers
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda] JDBC provider: make it possible to use connection parameters similar to other providers
- Date: Fri, 3 May 2013 20:07:12 +0000 (UTC)
commit 613179a2b3857e57d3c3866a4446a19873857cfe
Author: Vivien Malerba <malerba gnome-db org>
Date: Fri May 3 22:05:26 2013 +0200
JDBC provider: make it possible to use connection parameters similar to other providers
like HOST, DB_NAME, ...
doc/C/limitations.xml | 15 +--
doc/C/prov-notes.xml | 48 +++++++
providers/jdbc/.gitignore | 1 +
providers/jdbc/Makefile.am | 16 ++-
providers/jdbc/gda-jdbc-provider.c | 136 +++++++++++++++++++-
providers/jdbc/jdbc-mappings.xml | 12 ++
providers/jdbc/jdbc.gresource.xml | 6 +
...osoft.sqlserver.jdbc.SQLServerDriver_dsn.xml.in | 9 ++
providers/jdbc/jdbc_specs_dsn.xml.in | 2 +-
providers/jdbc/libmain.c | 10 +-
10 files changed, 226 insertions(+), 29 deletions(-)
---
diff --git a/doc/C/limitations.xml b/doc/C/limitations.xml
index 4989aa1..e755576 100644
--- a/doc/C/limitations.xml
+++ b/doc/C/limitations.xml
@@ -202,22 +202,9 @@
needs to load the Java Virtual Machine (JVM) runtime first).
</para>
- <sect2><title>JDBC drivers' location</title>
- <para>
- JDBC drivers (".jar" files) are searched for in the following locations:
- <orderedlist>
- <listitem><para>in each directory or JAR file in the <envar>CLASSPATH</envar> environment variable
- (if set)</para></listitem>
- <listitem><para>in the <filename>$HOME/.local/share/libgda/config</filename> directory (or
- <filename class="directory">$HOME/.libgda</filename> if if exists and
- <filename>$HOME/.local/share/libgda/config</filename> does not)</para></listitem>
- </orderedlist>
- </para>
- </sect2>
-
<sect2><title>Last inserted row's values</title>
<para>
- TODO.
+ Not yet supported.
</para>
</sect2>
diff --git a/doc/C/prov-notes.xml b/doc/C/prov-notes.xml
index a897a7f..1018796 100644
--- a/doc/C/prov-notes.xml
+++ b/doc/C/prov-notes.xml
@@ -346,5 +346,53 @@ DETACH DATABASE plaintext; </programlisting>
</sect2>
</sect1>
+ <sect1 id="provider_notes_jdbc">
+ <title>For JDBC</title>
+ <sect2>
+ <title>How it works</title>
+ <para>
+ JDBC (Java Database Connectivity) is a Java-based technology to access databases, not unlike ODBC.
+ The JDBC provider runs a Java Virtual Machine in which the installed JDBC drivers are loaded.
Connections
+ are established and used through the JDBC driver, making an extensive use of the JNI (Java Native
Interface)
+ technology.
+ </para>
+ <para>
+ Any JDBC driver can be used, though only some of them have actually been tested. Some specializations
+ have been made to adapt to some corner cases in the way some JDBC drivers are written or some
specificities
+ of some database engines.
+ </para>
+ <para>
+ Note that the JDBC drivers are not provided by Libgda and must be obtained and installed separately.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>JDBC drivers' location</title>
+ <para>
+ JDBC drivers (".jar" files) are searched for in the following locations:
+ <orderedlist>
+ <listitem><para>in each directory or JAR file in the <envar>CLASSPATH</envar> environment variable
+ (if set)</para></listitem>
+ <listitem><para>in the <filename>$HOME/.local/share/libgda/config</filename> directory (or
+ <filename class="directory">$HOME/.libgda</filename> if if exists and
+ <filename>$HOME/.local/share/libgda/config</filename> does not)</para></listitem>
+ </orderedlist>
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>Connection parameters</title>
+ <para>
+ To connect to a database, the expected connection parameters are the ones required by the JDBC driver
being
+ used, which varies from driver to driver (for more information, refer to each driver's
documentation). Thus
+ &Libgda; expects only one argument named "URL" which it passes (without any modification) to the JDBC
driver.
+ </para>
+ <para>
+ However, for some widely used servers (such as SqlServer), Libgda also accepts some parameters like
+ for other database providers (like DB_NAME, HOST, ...). In this case one can either provide these
parameters
+ or provide the URL parameter (like for any JDBC provider) to specify a connection to open.
+ </para>
+ </sect2>
+ </sect1>
</chapter>
diff --git a/providers/jdbc/.gitignore b/providers/jdbc/.gitignore
index 2d0d7ec..7be24f6 100644
--- a/providers/jdbc/.gitignore
+++ b/providers/jdbc/.gitignore
@@ -3,3 +3,4 @@
gda-list-jdbc-providers-5.*
gda-jdbc-test
Gda*.h
+jdbc-resources.[ch]
\ No newline at end of file
diff --git a/providers/jdbc/Makefile.am b/providers/jdbc/Makefile.am
index 1a95f73..45f5871 100644
--- a/providers/jdbc/Makefile.am
+++ b/providers/jdbc/Makefile.am
@@ -29,10 +29,9 @@ jni_sources = \
jni_headers = $(jni_sources:.c=.h)
jni_classes = $(jni_sources:.c=.class)
-$(libgda_jdbc_la_OBJECTS): $(jni_headers)
+resources = jdbc-resources.h jdbc-resources.c
-aaa:
- echo $(path_jni_sources)
+$(libgda_jdbc_la_OBJECTS): $(jni_headers) $(resources)
libgda_jdbc_la_SOURCES = \
gda-jdbc-blob-op.c \
@@ -55,8 +54,8 @@ libgda_jdbc_la_SOURCES = \
jni-wrapper.h \
jni-wrapper.c \
$(jni_sources) \
- $(jni_headers)
-
+ $(jni_headers) \
+ $(resources)
libgda_jdbc_la_LDFLAGS = -export-dynamic -module -avoid-version $(NO_UNDEFINED)
$(LIBTOOL_PROV_EXPORT_OPTIONS)
libgda_jdbc_la_LIBADD = \
@@ -71,6 +70,10 @@ if PLATFORM_WIN32
libgda_jdbc_la_LDFLAGS += -Wl,--kill-at
endif
+jdbc-resources.h jdbc-resources.c: $(srcdir)/jdbc.gresource.xml Makefile $(shell $(GLIB_COMPILE_RESOURCES)
--sourcedir=$(srcdir) --generate-dependencies $(srcdir)/jdbc.gresource.xml)
+ $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --generate --c-name _jdbc
--manual-register $<
+
+CLEANFILES = $(resources)
$(jni_headers): $(jdbcprov_classes)
$(JAVAH) -classpath . -d $(builddir) -force `basename $@ | sed -e 's/\.h$$//'`
@@ -101,7 +104,8 @@ clean-local:
xmldir = $(datadir)/libgda-5.0
xml_in_files = \
jdbc_specs_dsn.xml.in \
- jdbc_specs_create_table.xml.in
+ jdbc_specs_create_table.xml.in \
+ jdbc_specs_com.microsoft.sqlserver.jdbc.SQLServerDriver_dsn.xml.in
@INTLTOOL_XML_RULE@
diff --git a/providers/jdbc/gda-jdbc-provider.c b/providers/jdbc/gda-jdbc-provider.c
index 1ae5360..8875f7d 100644
--- a/providers/jdbc/gda-jdbc-provider.c
+++ b/providers/jdbc/gda-jdbc-provider.c
@@ -40,6 +40,7 @@
#include "gda-jdbc-util.h"
#include "jni-wrapper.h"
#include "jni-globals.h"
+#include "jdbc-resources.h"
#define _GDA_PSTMT(x) ((GdaPStmt*)(x))
@@ -336,6 +337,121 @@ gda_jdbc_provider_get_version (G_GNUC_UNUSED GdaServerProvider *provider)
return PACKAGE_VERSION;
}
+/*
+ * make_url_from_params:
+ *
+ * Creates the URL to pass to the JDBC driver to open a connection. It uses the
+ * jdbc_mappings.xml file
+ *
+ * Returns: a new string, or %NULL if not enough information found to create the connection URL
+ */
+static gchar *
+make_url_from_params (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaQuarkList *params, G_GNUC_UNUSED GdaQuarkList *auth)
+{
+ GBytes *data;
+ const gchar *xmlstr;
+ gsize data_size = 0;
+ _jdbc_register_resource ();
+ data = g_resources_lookup_data ("/jdbc/jdbc-mappings.xml", G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
+ g_assert (data);
+ xmlstr = g_bytes_get_data (data, &data_size);
+
+ xmlDocPtr doc;
+ doc = xmlParseMemory (xmlstr, data_size);
+ g_bytes_unref (data);
+ _jdbc_unregister_resource ();
+
+ if (!doc)
+ return NULL;
+
+ xmlNodePtr root, node;
+ GString *url = NULL;
+ root = xmlDocGetRootElement (doc);
+ if (strcmp ((gchar*) root->name, "jdbc-mappings"))
+ goto out;
+
+ for (node = root->children; node; node = node->next) {
+ if (strcmp ((gchar *) node->name, "driver"))
+ continue;
+ xmlChar *prop;
+ prop = xmlGetProp (node, BAD_CAST "name");
+ if (!prop)
+ continue;
+ if (!strcmp ((gchar*) prop, gda_server_provider_get_name (provider))) {
+ xmlFree (prop);
+ break;
+ }
+ xmlFree (prop);
+ }
+ if (!node)
+ goto out;
+
+ url = g_string_new ("");
+ for (node = node->children; node; node = node->next) {
+ if (!strcmp ((gchar *) node->name, "prefix")) {
+ xmlChar *contents;
+ contents = xmlNodeGetContent (node);
+ if (contents && *contents)
+ g_string_append (url, (gchar*) contents);
+ }
+ else if (!strcmp ((gchar *) node->name, "part")) {
+ xmlChar *prop;
+ const gchar *cvarvalue = NULL;
+ gchar *varvalue = NULL;
+ gboolean opt = FALSE;
+ prop = xmlGetProp (node, BAD_CAST "variable");
+ if (prop) {
+ cvarvalue = gda_quark_list_find (params, (gchar*) prop);
+ xmlFree (prop);
+ }
+ prop = xmlGetProp (node, BAD_CAST "optional");
+ if (prop) {
+ if ((*prop == 't') || (*prop == 'T'))
+ opt = TRUE;
+ xmlFree (prop);
+ }
+
+ prop = xmlGetProp (node, BAD_CAST "if");
+ if (prop) {
+ if (!strcmp ((gchar*) prop, "CncReadOnly")) {
+ if (gda_connection_get_options (cnc) &
GDA_CONNECTION_OPTIONS_READ_ONLY) {
+ xmlFree (prop);
+ prop = xmlGetProp (node, BAD_CAST "value");
+ if (prop)
+ varvalue = g_strdup ((gchar*) prop);
+ }
+ }
+ if (prop)
+ xmlFree (prop);
+ }
+
+ if (cvarvalue || varvalue) {
+ prop = xmlGetProp (node, BAD_CAST "prefix");
+ if (prop) {
+ g_string_append (url, (gchar*) prop);
+ xmlFree (prop);
+ }
+ g_string_append (url, varvalue ? varvalue : cvarvalue);
+ g_free (varvalue);
+ }
+ else if (!varvalue && !cvarvalue && !opt) {
+ /* missing parameter */
+ g_string_free (url, TRUE);
+ url = NULL;
+ goto out;
+ }
+ }
+ }
+
+ out:
+ xmlFreeDoc (doc);
+ if (url)
+ return g_string_free (url, FALSE);
+ else
+ return NULL;
+}
+
/*
* Open connection request
*
@@ -365,12 +481,17 @@ gda_jdbc_provider_open_connection (GdaServerProvider *provider, GdaConnection *c
}
/* Check for connection parameters */
- const gchar *url;
- url = gda_quark_list_find (params, "URL");
+ gchar *url;
+ url = make_url_from_params (provider, cnc, params, auth);
if (!url) {
- gda_connection_add_event_string (cnc,
- _("The connection string must contain the URL value"));
- return FALSE;
+ const gchar *cstr;
+ cstr = gda_quark_list_find (params, "URL");
+ if (!cstr) {
+ gda_connection_add_event_string (cnc,
+ _("The connection string must contain the URL
value"));
+ return FALSE;
+ }
+ url = g_strdup (cstr);
}
/* Check for username / password */
@@ -397,10 +518,14 @@ gda_jdbc_provider_open_connection (GdaServerProvider *provider, GdaConnection *c
error && error->message ? error->message : _("No detail"));
if (error)
g_error_free (error);
+ g_free (url);
return FALSE;
}
jstr = (*env)->NewStringUTF (env, url);
+ /*g_print ("URL = [%s] USERNAME = [%s] PASSWORD = [%s]\n", url, username, password);*/
+ g_free (url);
+ url = NULL;
if (username)
jstr1 = (*env)->NewStringUTF (env, username);
else
@@ -409,6 +534,7 @@ gda_jdbc_provider_open_connection (GdaServerProvider *provider, GdaConnection *c
jstr2 = (*env)->NewStringUTF (env, password);
else
jstr2 = NULL;
+
obj_value = jni_wrapper_method_call (env, GdaJProvider__openConnection,
jprov->jprov_obj, &error_code, &sql_state, &error,
jstr, jstr1, jstr2);
diff --git a/providers/jdbc/jdbc-mappings.xml b/providers/jdbc/jdbc-mappings.xml
new file mode 100644
index 0000000..0cf60cd
--- /dev/null
+++ b/providers/jdbc/jdbc-mappings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<jdbc-mappings>
+ <driver name="com.microsoft.sqlserver.jdbc.SQLServerDriver">
+ <prefix>jdbc:sqlserver://</prefix>
+ <part variable="HOST" optional="true"/>
+ <part variable="INSTANCE" optional="true" prefix="/"/>
+ <part variable="PORT" optional="true" prefix=":"/>
+ <!-- properties, see http://msdn.microsoft.com/en-us/library/ms378988.aspx -->
+ <part variable="DB_NAME" optional="true" prefix=";database="/>
+ <part variable="applicationIntent" optional="true" prefix=";applicationIntent=" value="ReadOnly"
if="CncReadOnly"/>
+ </driver>
+</jdbc-mappings>
diff --git a/providers/jdbc/jdbc.gresource.xml b/providers/jdbc/jdbc.gresource.xml
new file mode 100644
index 0000000..511f0a7
--- /dev/null
+++ b/providers/jdbc/jdbc.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/jdbc">
+ <file compressed="true">jdbc-mappings.xml</file>
+ </gresource>
+</gresources>
diff --git a/providers/jdbc/jdbc_specs_com.microsoft.sqlserver.jdbc.SQLServerDriver_dsn.xml.in
b/providers/jdbc/jdbc_specs_com.microsoft.sqlserver.jdbc.SQLServerDriver_dsn.xml.in
new file mode 100644
index 0000000..8a2d1ed
--- /dev/null
+++ b/providers/jdbc/jdbc_specs_com.microsoft.sqlserver.jdbc.SQLServerDriver_dsn.xml.in
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<data-set-spec>
+ <parameters>
+ <parameter id="DB_NAME" _name="Database name" _descr="The name of a database to connect to"
gdatype="gchararray"/>
+ <parameter id="INSTANCE" _name="Instance" _descr="The instance to connect to, if not specified, a
connection to the default instance is made" gdatype="gchararray"/>
+ <parameter id="HOST" _name="Database server" _descr="Host on which the database server is running or
leave this field empty" gdatype="gchararray"/>
+ <parameter id="PORT" _name="Port" _descr="Database server port, 1433 by default" gdatype="gint"/>
+ </parameters>
+</data-set-spec>
diff --git a/providers/jdbc/jdbc_specs_dsn.xml.in b/providers/jdbc/jdbc_specs_dsn.xml.in
index fdcd4c8..2fb267c 100644
--- a/providers/jdbc/jdbc_specs_dsn.xml.in
+++ b/providers/jdbc/jdbc_specs_dsn.xml.in
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<data-set-spec>
<parameters>
- <parameter id="URL" _name="Connection URL" _descr="" gdatype="gchararray" nullok="FALSE"/>
+ <parameter id="URL" _name="Connection URL" _descr="Connection string required by the JDBC driver, refer
to the used JDBC driver for its contents and format" gdatype="gchararray" nullok="FALSE"/>
</parameters>
</data-set-spec>
diff --git a/providers/jdbc/libmain.c b/providers/jdbc/libmain.c
index f333a7e..cef2c0b 100644
--- a/providers/jdbc/libmain.c
+++ b/providers/jdbc/libmain.c
@@ -295,12 +295,16 @@ plugin_get_sub_description (const gchar *name)
}
EXPORT gchar *
-plugin_get_sub_dsn_spec (G_GNUC_UNUSED const gchar *name)
+plugin_get_sub_dsn_spec (const gchar *name)
{
- gchar *ret, *dir;
+ gchar *ret, *dir, *tmp;
dir = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, NULL);
- ret = gda_server_provider_load_file_contents (module_path, dir, "jdbc_specs_dsn.xml");
+ tmp = g_strdup_printf ("jdbc_specs_%s_dsn.xml", name);
+ ret = gda_server_provider_load_file_contents (module_path, dir, tmp);
+ g_free (tmp);
+ if (!ret)
+ ret = gda_server_provider_load_file_contents (module_path, dir, "jdbc_specs_dsn.xml");
g_free (dir);
return ret;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]