[libgda] Set up new oracle provider structure
- From: Vivien Malerba <vivien src gnome org>
- To: svn-commits-list gnome org
- Subject: [libgda] Set up new oracle provider structure
- Date: Thu, 23 Apr 2009 14:57:17 -0400 (EDT)
commit e07be9c86404d8ccdf507b1a507914e58f6b05b0
Author: Vivien Malerba <malerba gnome-db org>
Date: Mon Apr 20 23:12:01 2009 +0200
Set up new oracle provider structure
---
ChangeLog | 6 +
configure.in | 17 +-
providers/Makefile.am | 4 +-
providers/oracle/Makefile.am | 69 +-
providers/oracle/gda-oracle-blob-op.c | 244 +--
providers/oracle/gda-oracle-blob-op.h | 16 +-
providers/oracle/gda-oracle-ddl.c | 191 +-
providers/oracle/gda-oracle-ddl.h | 28 +-
providers/oracle/gda-oracle-meta.c | 488 ++++
providers/oracle/gda-oracle-meta.h | 197 ++
providers/oracle/gda-oracle-parser.c | 84 +
providers/oracle/gda-oracle-parser.h | 59 +
providers/oracle/gda-oracle-provider.c | 2908 +++++++--------------
providers/oracle/gda-oracle-provider.h | 49 +-
providers/oracle/gda-oracle-pstmt.c | 96 +
providers/oracle/gda-oracle-pstmt.h | 57 +
providers/oracle/gda-oracle-recordset.c | 843 ++-----
providers/oracle/gda-oracle-recordset.h | 39 +-
providers/oracle/gda-oracle.h | 74 +-
providers/oracle/gen_def.c | 188 ++
providers/oracle/libmain.c | 35 +-
providers/oracle/oracle_specs_create_table.xml.in | 26 +
providers/oracle/oracle_specs_dsn.xml.in | 2 +-
providers/oracle/parser.y | 1008 +++++++
providers/oracle/utils.c | 550 ----
25 files changed, 3778 insertions(+), 3500 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 58157e2..cbb3804 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2009-04-20 Vivien Malerba <malerba gnome-db org>
+
+ * configure.in:
+ * providers/Makefile.am:
+ * providers/oracle/*: set up new oracle provider structure
+
2009-04-19 Vivien Malerba <malerba gnome-db org>
* libgda-report/RML/trml2html/Makefile.am:
diff --git a/configure.in b/configure.in
index ba138b2..8e38710 100644
--- a/configure.in
+++ b/configure.in
@@ -858,7 +858,7 @@ fi
dnl test for ORACLE
try_oracle=true
AC_ARG_WITH(oracle,
-[ --with-oracle=<directory> use ORACLE backend in <directoty>],[
+[ --with-oracle=<directory> use ORACLE backend in <directory>],[
if test $withval = no
then
try_oracle=false
@@ -878,7 +878,16 @@ then
then
AC_MSG_RESULT(found ORACLE in $d)
oracledir=$d
+ oraclelibdir=$lib
break
+ else
+ if test -f $d/lib/libclntsh.so
+ then
+ AC_MSG_RESULT(found ORACLE in $d)
+ oracledir=$d
+ oraclelibdir="lib"
+ break
+ fi
fi
done
if test x$oracledir = x
@@ -887,7 +896,7 @@ then
else
AC_DEFINE(HAVE_ORACLE, 1, [Have ORACLE])
ORACLE_CFLAGS=" -I$oracledir/include/oracle/client -I$oracledir/rdbms/demo -I${ORACLE_HOME}/rdbms/public -I${ORACLE_HOME}/plsql/public -I$oracledir/network/public"
- ORACLE_LIBS="-L$oracledir/lib -lm -ldl -lclntsh"
+ ORACLE_LIBS="-L$oracledir/$oraclelibdir -lm -ldl -lclntsh"
fi
fi
@@ -1493,6 +1502,8 @@ providers/mdb/Makefile
providers/mdb/libgda-mdb-4.0.pc
providers/mysql/Makefile
providers/mysql/libgda-mysql-4.0.pc
+providers/oracle/Makefile
+providers/oracle/libgda-oracle-4.0.pc
providers/postgres/Makefile
providers/postgres/libgda-postgres-4.0.pc
providers/sqlite/Makefile
@@ -1544,7 +1555,7 @@ echo " MDB (MS Access) = `if test x$mdbdir != x; then echo yes; else echo n
echo " MySQL = `if test x$mysqldir != x; then echo yes; else echo no; fi`"
dnl echo " mSQL = `if test x$msqldir != x; then echo yes; else echo no; fi`"
dnl echo " ODBC = `if test x$odbcdir != x; then echo yes; else echo no; fi`"
-dnl echo " Oracle = `if test x$oracledir != x; then echo yes; else echo no; fi`"
+echo " Oracle = `if test x$oracledir != x; then echo yes; else echo no; fi`"
echo " PostgreSQL = `if test x$postgresdir != x; then echo yes; else echo no; fi`"
echo " SQLite = yes `if test x$have_sqlite = xyes; then echo '(from system installation)'; else echo '(embedded)'; fi`"
dnl echo " Sybase = `if test x$sybasedir != x; then echo yes; else echo no; fi`"
diff --git a/providers/Makefile.am b/providers/Makefile.am
index 2244c69..cf5c18f 100644
--- a/providers/Makefile.am
+++ b/providers/Makefile.am
@@ -61,13 +61,13 @@ SUBDIRS = \
$(GDA_MDB_SERVER) \
$(GDA_POSTGRES_SERVER) \
$(GDA_MYSQL_SERVER) \
- $(GDA_JAVA_SERVER)
+ $(GDA_JAVA_SERVER) \
+ $(GDA_ORACLE_SERVER)
# $(GDA_FREETDS_SERVER) \
# $(GDA_IBMDB2_SERVER) \
# $(GDA_FIREBIRD_SERVER) \
# $(GDA_MSQL_SERVER) \
# $(GDA_ODBC_SERVER) \
-# $(GDA_ORACLE_SERVER) \
# $(GDA_SYBASE_SERVER) \
# $(GDA_XBASE_SERVER) \
# $(GDA_LDAP_SERVER)
diff --git a/providers/oracle/Makefile.am b/providers/oracle/Makefile.am
index b2b4f63..f419a9e 100644
--- a/providers/oracle/Makefile.am
+++ b/providers/oracle/Makefile.am
@@ -1,66 +1,67 @@
-# GDA Oracle provider
-# Copyright (C) 1998 - 2007 The GNOME Foundation
-#
-# AUTHORS:
-# Rodrigo Moya <rodrigo gnome-db org>
-# Vivien Malerba <malerba gnome-db org>
-# Bas Driessen <bas driessen xobas com>
-#
-# This Library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-#
-# This Library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this Library; see the file COPYING.LIB. If not,
-# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-
providerdir=$(libdir)/libgda-$(GDA_ABI_MAJOR_VERSION).$(GDA_ABI_MINOR_VERSION)/providers
provider_LTLIBRARIES = libgda-oracle.la
+#Rem: ORACLE_CFLAGS and ORACLE_LIBS are the compile and link flags necessary to use the
+# C API. It is specific to the API and should be computed in the configure.in script.
+
AM_CPPFLAGS = \
-I$(top_srcdir) \
-I$(top_srcdir)/libgda \
-I$(top_builddir) \
$(LIBGDA_CFLAGS) \
- $(ORACLE_CFLAGS)
+ $(ORACLE_CFLAGS)
+
+# parser generation
+parser.c parser.h: parser.y $(top_builddir)/libgda/sql-parser/lemon$(EXEEXT_FOR_BUILD)
+ - $(top_builddir)/libgda/sql-parser/lemon$(EXEEXT_FOR_BUILD) -q -d $(srcdir)/parser.y $(top_srcdir)/libgda/sql-parser/lempar.c
+
+gen_def$(EXEEXT_FOR_BUILD): gen_def.c
+ $(CC_FOR_BUILD) -o gen_def$(EXEEXT_FOR_BUILD) -DIMPOSED_HEADER=\""$(top_srcdir)/libgda/sql-parser/token_types.h"\" $(srcdir)/gen_def.c
+
+oracle_token_types.h: gen_def$(EXEEXT_FOR_BUILD) parser.h
+ ./gen_def$(EXEEXT_FOR_BUILD) > oracle_token_types.h
+
+$(OBJECTS) $(libgda_oracle_la_OBJECTS): oracle_token_types.h
libgda_oracle_la_SOURCES = \
gda-oracle-blob-op.c \
gda-oracle-blob-op.h \
gda-oracle-ddl.c \
gda-oracle-ddl.h \
+ gda-oracle-parser.c \
+ gda-oracle-parser.h \
gda-oracle-provider.c \
gda-oracle-provider.h \
+ gda-oracle-pstmt.h \
+ gda-oracle-pstmt.c \
+ gda-oracle-meta.c \
+ gda-oracle-meta.h \
gda-oracle-recordset.c \
gda-oracle-recordset.h \
gda-oracle.h \
libmain.c \
- utils.c
-libgda_oracle_la_LDFLAGS = -export-dynamic -module -avoid-version $(NO_UNDEFINED)
+ parser.h \
+ parser.c \
+ oracle_token_types.h
+
+libgda_oracle_la_LDFLAGS = -export-dynamic -module -avoid-version $(NO_UNDEFINED) $(LIBTOOL_PROV_EXPORT_OPTIONS)
libgda_oracle_la_LIBADD = \
$(top_builddir)/libgda/libgda-4.0.la \
- $(LIBGDA_LIBS) \
- $(ORACLE_LIBS)
+ $(LIBGDA_LIBS) $(ORACLE_LIBS)
xmldir = $(datadir)/libgda-4.0
-xml_in_files = oracle_specs_dsn.xml.in \
- oracle_specs_drop_table.xml.in \
- oracle_specs_drop_index.xml.in
+xml_in_files = \
+ oracle_specs_dsn.xml.in \
+ oracle_specs_create_table.xml.in
@INTLTOOL_XML_RULE@
-xml_DATA = $(xml_in_files:.xml.in=.xml)
+xml_DATA = $(xml_in_files:.xml.in=.xml)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libgda-oracle-4.0.pc
-EXTRA_DIST = $(xml_in_files) libgda-oracle-4.0.pc.in
+EXTRA_DIST = $(xml_in_files) libgda-oracle-4.0.pc.in parser.y gen_def.c
DISTCLEANFILES = $(xml_DATA)
+
+CLEANFILES = parser.h parser.c parser.out oracle_token_types.h gen_def$(EXEEXT_FOR_BUILD)
diff --git a/providers/oracle/gda-oracle-blob-op.c b/providers/oracle/gda-oracle-blob-op.c
index 85478cb..04dc562 100644
--- a/providers/oracle/gda-oracle-blob-op.c
+++ b/providers/oracle/gda-oracle-blob-op.c
@@ -1,8 +1,8 @@
-/* GDA Postgres blob
- * Copyright (C) 2007 The GNOME Foundation
+/* GDA Oracle provider
+ * Copyright (C) 2008 The GNOME Foundation
*
* AUTHORS:
- * Vivien Malerba <malerba gnome-db org>
+ * TO_ADD: your name and email
*
* This Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
@@ -22,29 +22,23 @@
#include <glib/gi18n-lib.h>
#include <string.h>
+#include <libgda/libgda.h>
#include "gda-oracle.h"
#include "gda-oracle-blob-op.h"
-#ifdef PARENT_TYPE
-#undef PARENT_TYPE
-#endif
-
-#define PARENT_TYPE GDA_TYPE_BLOB_OP
-
struct _GdaOracleBlobOpPrivate {
GdaConnection *cnc;
- OCILobLocator *lobl;
+ /* TO_ADD: specific information describing a Blob in the C API */
};
static void gda_oracle_blob_op_class_init (GdaOracleBlobOpClass *klass);
static void gda_oracle_blob_op_init (GdaOracleBlobOp *blob,
- GdaOracleBlobOpClass *klass);
+ GdaOracleBlobOpClass *klass);
static void gda_oracle_blob_op_finalize (GObject *object);
static glong gda_oracle_blob_op_get_length (GdaBlobOp *op);
static glong gda_oracle_blob_op_read (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size);
static glong gda_oracle_blob_op_write (GdaBlobOp *op, GdaBlob *blob, glong offset);
-static gboolean gda_oracle_blob_op_write_all (GdaBlobOp *op, GdaBlob *blob);
static GObjectClass *parent_class = NULL;
@@ -57,6 +51,7 @@ gda_oracle_blob_op_get_type (void)
static GType type = 0;
if (G_UNLIKELY (type == 0)) {
+ static GStaticMutex registering = G_STATIC_MUTEX_INIT;
static const GTypeInfo info = {
sizeof (GdaOracleBlobOpClass),
(GBaseInitFunc) NULL,
@@ -68,7 +63,10 @@ gda_oracle_blob_op_get_type (void)
0,
(GInstanceInitFunc) gda_oracle_blob_op_init
};
- type = g_type_register_static (PARENT_TYPE, "GdaOracleBlobOp", &info, 0);
+ g_static_mutex_lock (®istering);
+ if (type == 0)
+ type = g_type_register_static (GDA_TYPE_BLOB_OP, "GdaOracleBlobOp", &info, 0);
+ g_static_mutex_unlock (®istering);
}
return type;
}
@@ -80,7 +78,9 @@ gda_oracle_blob_op_init (GdaOracleBlobOp *op,
g_return_if_fail (GDA_IS_ORACLE_BLOB_OP (op));
op->priv = g_new0 (GdaOracleBlobOpPrivate, 1);
- op->priv->lobl = NULL;
+
+ /* initialize specific structure */
+ TO_IMPLEMENT;
}
static void
@@ -95,204 +95,132 @@ gda_oracle_blob_op_class_init (GdaOracleBlobOpClass *klass)
blob_class->get_length = gda_oracle_blob_op_get_length;
blob_class->read = gda_oracle_blob_op_read;
blob_class->write = gda_oracle_blob_op_write;
- blob_class->write_all = gda_oracle_blob_op_write_all;
-}
-
-static GdaOracleConnectionData *
-get_conn_data (GdaConnection *cnc)
-{
- GdaOracleConnectionData *priv_data;
-
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data) {
- gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
- return NULL;
- }
-
- return priv_data;
}
static void
gda_oracle_blob_op_finalize (GObject * object)
{
- GdaOracleBlobOp *op = (GdaOracleBlobOp *) object;
+ GdaOracleBlobOp *bop = (GdaOracleBlobOp *) object;
- g_return_if_fail (GDA_IS_ORACLE_BLOB_OP (op));
+ g_return_if_fail (GDA_IS_ORACLE_BLOB_OP (bop));
- if (op->priv->lobl) {
- GdaOracleConnectionData *priv_data = get_conn_data (op->priv->cnc);
- g_assert (priv_data);
+ /* free specific information */
+ TO_IMPLEMENT;
- OCILobClose (priv_data->hservice, priv_data->herr, op->priv->lobl);
- }
- g_free (op->priv);
- op->priv = NULL;
+ g_free (bop->priv);
+ bop->priv = NULL;
parent_class->finalize (object);
}
GdaBlobOp *
-gda_oracle_blob_op_new (GdaConnection *cnc, OCILobLocator *lobloc)
+gda_oracle_blob_op_new (GdaConnection *cnc)
{
- GdaOracleBlobOp *blob;
+ GdaOracleBlobOp *bop;
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
- g_return_val_if_fail (lobloc, NULL);
- blob = g_object_new (GDA_TYPE_ORACLE_BLOB_OP, NULL);
- blob->priv->cnc = cnc;
- blob->priv->lobl = lobloc;
+ bop = g_object_new (GDA_TYPE_ORACLE_BLOB_OP, NULL);
+ bop->priv->cnc = cnc;
- return GDA_BLOB_OP (blob);
+ return GDA_BLOB_OP (bop);
}
-
/*
- * Virtual functions
+ * Get length request
*/
static glong
gda_oracle_blob_op_get_length (GdaBlobOp *op)
{
- GdaOracleBlobOp *oraop;
- ub4 loblen = 0;
+ GdaOracleBlobOp *bop;
g_return_val_if_fail (GDA_IS_ORACLE_BLOB_OP (op), -1);
- oraop = GDA_ORACLE_BLOB_OP (op);
- g_return_val_if_fail (oraop->priv, -1);
- g_return_val_if_fail (GDA_IS_CONNECTION (oraop->priv->cnc), -1);
-
- if (oraop->priv->lobl) {
- gint result;
- GdaConnectionEvent *error;
- GdaOracleConnectionData *priv_data = get_conn_data (oraop->priv->cnc);
- g_assert (priv_data);
-
- result = OCILobGetLength (priv_data->hservice, priv_data->herr, oraop->priv->lobl, &loblen);
- error = gda_oracle_check_result (result, oraop->priv->cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not get the length of LOB object"));
- if (!error)
- return loblen;
- }
+ bop = GDA_ORACLE_BLOB_OP (op);
+ g_return_val_if_fail (bop->priv, -1);
+ g_return_val_if_fail (GDA_IS_CONNECTION (bop->priv->cnc), -1);
+
+ TO_IMPLEMENT;
return -1;
}
+/*
+ * Blob read request
+ */
static glong
gda_oracle_blob_op_read (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size)
{
- GdaOracleBlobOp *oraop;
+ GdaOracleBlobOp *bop;
GdaBinary *bin;
g_return_val_if_fail (GDA_IS_ORACLE_BLOB_OP (op), -1);
- oraop = GDA_ORACLE_BLOB_OP (op);
- g_return_val_if_fail (oraop->priv, -1);
- g_return_val_if_fail (GDA_IS_CONNECTION (oraop->priv->cnc), -1);
+ bop = GDA_ORACLE_BLOB_OP (op);
+ g_return_val_if_fail (bop->priv, -1);
+ g_return_val_if_fail (GDA_IS_CONNECTION (bop->priv->cnc), -1);
+ if (offset >= G_MAXINT)
+ return -1;
g_return_val_if_fail (blob, -1);
bin = (GdaBinary *) blob;
- if (bin->data) {
+ if (bin->data)
g_free (bin->data);
- bin->data = NULL;
- bin->binary_length = 0;
- }
+ bin->data = g_new0 (guchar, size);
+ bin->binary_length = 0;
- if (oraop->priv->lobl) {
- sword result;
- ub4 nbbytes;
- GdaOracleConnectionData *priv_data = get_conn_data (oraop->priv->cnc);
- ub4 loblen = 0;
- ub1 *buf;
- g_assert (priv_data);
-
- result = OCILobGetLength (priv_data->hservice, priv_data->herr, oraop->priv->lobl, &loblen);
- if (gda_oracle_check_result (result, oraop->priv->cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not get the length of LOB object")))
- return -1;
-
- nbbytes = (size > loblen) ? loblen : size;
- buf = g_new (ub1, nbbytes);
- /*result = OCILobRead2 (priv_data->hservice, priv_data->herr, oraop->priv->lobl, &nbbytes, 0,
- offset + 1, (dvoid *) buf, nbbytes, OCI_ONE_PIECE,
- NULL, NULL, 0, SQLCS_IMPLICIT);*/
- result = OCILobRead (priv_data->hservice, priv_data->herr, oraop->priv->lobl, &nbbytes,
- offset + 1, (dvoid *) buf, nbbytes,
- NULL, NULL, 0, SQLCS_IMPLICIT);
- if (gda_oracle_check_result (result, oraop->priv->cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not read from LOB object"))) {
- g_free (buf);
- return -1;
- }
- bin->data = buf;
- bin->binary_length = nbbytes;
- return bin->binary_length;
- }
+ /* fetch blob data using C API into bin->data, and set bin->binary_length */
+ TO_IMPLEMENT;
- return -1;
+ return bin->binary_length;
}
+/*
+ * Blob write request
+ */
static glong
gda_oracle_blob_op_write (GdaBlobOp *op, GdaBlob *blob, glong offset)
{
- GdaOracleBlobOp *oraop;
+ GdaOracleBlobOp *bop;
GdaBinary *bin;
+ glong nbwritten = -1;
g_return_val_if_fail (GDA_IS_ORACLE_BLOB_OP (op), -1);
- oraop = GDA_ORACLE_BLOB_OP (op);
- g_return_val_if_fail (oraop->priv, -1);
- g_return_val_if_fail (GDA_IS_CONNECTION (oraop->priv->cnc), -1);
+ bop = GDA_ORACLE_BLOB_OP (op);
+ g_return_val_if_fail (bop->priv, -1);
+ g_return_val_if_fail (GDA_IS_CONNECTION (bop->priv->cnc), -1);
g_return_val_if_fail (blob, -1);
- bin = (GdaBinary *) blob;
-
- if (oraop->priv->lobl) {
- sword result;
- ub4 nbbytes;
- GdaOracleConnectionData *priv_data = get_conn_data (oraop->priv->cnc);
- g_assert (priv_data);
-
- nbbytes = bin->binary_length;
- result = OCILobWrite (priv_data->hservice, priv_data->herr, oraop->priv->lobl, &nbbytes, (ub4) offset + 1,
- (dvoid *) bin->data, bin->binary_length,
- OCI_ONE_PIECE, NULL, NULL, 0, SQLCS_IMPLICIT);
- if (gda_oracle_check_result (result, oraop->priv->cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not write to LOB object"))) {
- return -1;
+ if (blob->op && (blob->op != op)) {
+ /* use data through blob->op */
+ #define buf_size 16384
+ gint nread = 0;
+ GdaBlob *tmpblob = g_new0 (GdaBlob, 1);
+ tmpblob->op = blob->op;
+
+ nbwritten = 0;
+
+ for (nread = gda_blob_op_read (tmpblob->op, tmpblob, nbwritten, buf_size);
+ nread > 0;
+ nread = gda_blob_op_read (tmpblob->op, tmpblob, nbwritten, buf_size)) {
+ glong tmp_written;
+
+ tmp_written = -1; TO_IMPLEMENT;
+
+ if (tmp_written < 0) {
+ /* treat error */
+ gda_blob_free ((gpointer) tmpblob);
+ return -1;
+ }
+ nbwritten += tmp_written;
+ if (nread < buf_size)
+ /* nothing more to read */
+ break;
}
- return nbbytes;
+ gda_blob_free ((gpointer) tmpblob);
}
-
- return -1;
-}
-
-static gboolean
-gda_oracle_blob_op_write_all (GdaBlobOp *op, GdaBlob *blob)
-{
- GdaOracleBlobOp *oraop;
- GdaBinary *bin;
-
- g_return_val_if_fail (GDA_IS_ORACLE_BLOB_OP (op), FALSE);
- oraop = GDA_ORACLE_BLOB_OP (op);
- g_return_val_if_fail (oraop->priv, FALSE);
- g_return_val_if_fail (GDA_IS_CONNECTION (oraop->priv->cnc), FALSE);
- g_return_val_if_fail (blob, FALSE);
-
- bin = (GdaBinary *) blob;
- if (oraop->priv->lobl) {
- sword result;
- GdaOracleConnectionData *priv_data = get_conn_data (oraop->priv->cnc);
- g_assert (priv_data);
-
- if (gda_oracle_blob_op_write (op, blob, 0) != bin->binary_length)
- return FALSE;
- else {
- /* truncate lob at the end */
- result = OCILobTrim (priv_data->hservice, priv_data->herr, oraop->priv->lobl, bin->binary_length);
- if (gda_oracle_check_result (result, oraop->priv->cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not truncate LOB object")))
- return FALSE;
- else
- return TRUE;
- }
+ else {
+ /* write blob using bin->data and bin->binary_length */
+ bin = (GdaBinary *) blob;
+ nbwritten = -1; TO_IMPLEMENT;
}
- return FALSE;
+ return nbwritten;
}
diff --git a/providers/oracle/gda-oracle-blob-op.h b/providers/oracle/gda-oracle-blob-op.h
index 2ac37b9..a118316 100644
--- a/providers/oracle/gda-oracle-blob-op.h
+++ b/providers/oracle/gda-oracle-blob-op.h
@@ -1,8 +1,8 @@
-/* GDA DB Oracle Blob
- * Copyright (C) 2007 The GNOME Foundation
+/* GDA Oracle provider
+ * Copyright (C) 2008 The GNOME Foundation
*
* AUTHORS:
- * Vivien Malerba <malerba gnome-db org>
+ * TO_ADD: your name and email
*
* This Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
@@ -23,9 +23,7 @@
#ifndef __GDA_ORACLE_BLOB_OP_H__
#define __GDA_ORACLE_BLOB_OP_H__
-#include <libgda/gda-value.h>
#include <libgda/gda-blob-op.h>
-#include <oci.h>
G_BEGIN_DECLS
@@ -40,16 +38,18 @@ typedef struct _GdaOracleBlobOpClass GdaOracleBlobOpClass;
typedef struct _GdaOracleBlobOpPrivate GdaOracleBlobOpPrivate;
struct _GdaOracleBlobOp {
- GdaBlobOp parent;
+ GdaBlobOp parent;
GdaOracleBlobOpPrivate *priv;
};
struct _GdaOracleBlobOpClass {
- GdaBlobOpClass parent_class;
+ GdaBlobOpClass parent_class;
};
GType gda_oracle_blob_op_get_type (void) G_GNUC_CONST;
-GdaBlobOp *gda_oracle_blob_op_new (GdaConnection *cnc, OCILobLocator *lobloc);
+GdaBlobOp *gda_oracle_blob_op_new (GdaConnection *cnc);
+
+/* TO_ADD: more convenient API to create a GdaBlobOp with some specific information as argument */
G_END_DECLS
diff --git a/providers/oracle/gda-oracle-ddl.c b/providers/oracle/gda-oracle-ddl.c
index cf38335..28d559f 100644
--- a/providers/oracle/gda-oracle-ddl.c
+++ b/providers/oracle/gda-oracle-ddl.c
@@ -1,9 +1,8 @@
-/* GNOME DB Oracle Provider
- * Copyright (C) 2006 The GNOME Foundation
+/* GDA Oracle Provider
+ * Copyright (C) 2008 The GNOME Foundation
*
* AUTHORS:
- * Vivien Malerba <malerba gnome-db org>
- * Bas Driessen <bas driessen xobas com>
+ * TO_ADD: your name and email
*
* This Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
@@ -21,111 +20,125 @@
* Boston, MA 02111-1307, USA.
*/
-#include "gda-oracle-ddl.h"
#include <glib/gi18n-lib.h>
-#include <libgda/gda-data-handler.h>
-
-gchar *
-gda_oracle_render_CREATE_DB (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error)
-{
- return NULL;
-}
-
-gchar *
-gda_oracle_render_DROP_DB (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error)
-{
- return NULL;
-}
-
+#include <libgda/libgda.h>
+#include "gda-oracle-ddl.h"
gchar *
gda_oracle_render_CREATE_TABLE (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error)
-{
- return NULL;
-}
-
-gchar *
-gda_oracle_render_DROP_TABLE (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error)
+ GdaServerOperation *op, GError **error)
{
GString *string;
const GValue *value;
+ gboolean allok = TRUE;
+ gboolean hasfields = FALSE;
+ gint nrows;
+ gint i;
+ gboolean first;
+ GSList *pkfields = NULL; /* list of GValue* composing the pkey */
+ gint nbpkfields = 0;
gchar *sql = NULL;
- string = g_string_new ("DROP TABLE ");
+ /* CREATE TABLE */
+ string = g_string_new ("CREATE TABLE ");
- value = gda_server_operation_get_value_at (op, "/TABLE_DESC_P/TABLE_NAME");
+ value = gda_server_operation_get_value_at (op, "/TABLE_DEF_P/TABLE_NAME");
g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
g_string_append (string, g_value_get_string (value));
-
- value = gda_server_operation_get_value_at (op, "/TABLE_DESC_P/REFERENCED_ACTION");
- if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
- g_string_append_c (string, ' ');
- g_string_append (string, g_value_get_string (value));
+ g_string_append (string, " (");
+
+ /* FIELDS */
+ if (allok) {
+ GdaServerOperationNode *node;
+
+ node = gda_server_operation_get_node_info (op, "/FIELDS_A");
+ g_assert (node);
+
+ /* finding if there is a composed primary key */
+ nrows = gda_data_model_get_n_rows (node->model);
+ for (i = 0; i < nrows; i++) {
+ value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_PKEY/%d", i);
+ if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+ pkfields = g_slist_append (pkfields,
+ (GValue *) gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_NAME/%d", i));
+ }
+ nbpkfields = g_slist_length (pkfields);
+
+ /* manually defined fields */
+ first = TRUE;
+ for (i = 0; i < nrows; i++) {
+ hasfields = TRUE;
+ if (first)
+ first = FALSE;
+ else
+ g_string_append (string, ", ");
+
+ value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_NAME/%d", i);
+ g_string_append (string, g_value_get_string (value));
+ g_string_append_c (string, ' ');
+
+ value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_TYPE/%d", i);
+ g_string_append (string, g_value_get_string (value));
+
+ value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_DEFAULT/%d", i);
+ if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
+ const gchar *str = g_value_get_string (value);
+ if (str && *str) {
+ g_string_append (string, " DEFAULT ");
+ g_string_append (string, str);
+ }
+ }
+
+ value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_NNUL/%d", i);
+ if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+ g_string_append (string, " NOT NULL");
+
+ value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_UNIQUE/%d", i);
+ if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+ g_string_append (string, " UNIQUE");
+
+ if (nbpkfields == 1) {
+ value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_PKEY/%d", i);
+ if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+ g_string_append (string, " PRIMARY KEY");
+ }
+
+ value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_CHECK/%d", i);
+ if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
+ const gchar *str = g_value_get_string (value);
+ if (str && *str) {
+ g_string_append (string, " CHECK (");
+ g_string_append (string, str);
+ g_string_append_c (string, ')');
+ }
+ }
+ }
}
- sql = string->str;
- g_string_free (string, FALSE);
-
- return sql;
-}
-
-gchar *
-gda_oracle_render_RENAME_TABLE (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error)
-{
- return NULL;
-}
-
-
-gchar *
-gda_oracle_render_ADD_COLUMN (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error)
-{
- return NULL;
-}
-
-gchar *
-gda_oracle_render_DROP_COLUMN (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error)
-{
- return NULL;
-}
-
-
-gchar *
-gda_oracle_render_CREATE_INDEX (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error)
-{
- return NULL;
-}
-
-gchar *
-gda_oracle_render_DROP_INDEX (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error)
-{
- GString *string;
- const GValue *value;
- gchar *sql = NULL;
-
- string = g_string_new ("DROP INDEX ");
+ /* composed primary key */
+ if (nbpkfields > 1) {
+ GSList *list = pkfields;
+
+ g_string_append (string, ", PRIMARY KEY (");
+ while (list) {
+ if (list != pkfields)
+ g_string_append (string, ", ");
+ g_string_append (string, g_value_get_string ((GValue*) list->data));
+ list = list->next;
+ }
+ g_string_append_c (string, ')');
+ }
- value = gda_server_operation_get_value_at (op, "/INDEX_DESC_P/INDEX_NAME");
- g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
- g_string_append (string, g_value_get_string (value));
+ g_string_append (string, ")");
- value = gda_server_operation_get_value_at (op, "/INDEX_DESC_P/REFERENCED_ACTION");
- if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
- g_string_append_c (string, ' ');
- g_string_append (string, g_value_get_string (value));
+ if (!hasfields) {
+ allok = FALSE;
+ g_set_error (error, 0, 0, "%s", _("Table to create must have at least one row"));
}
+ g_slist_free (pkfields);
sql = string->str;
g_string_free (string, FALSE);
return sql;
}
-
diff --git a/providers/oracle/gda-oracle-ddl.h b/providers/oracle/gda-oracle-ddl.h
index 94af629..0f14318 100644
--- a/providers/oracle/gda-oracle-ddl.h
+++ b/providers/oracle/gda-oracle-ddl.h
@@ -1,9 +1,8 @@
-/* GDA Oracle Provider
- * Copyright (C) 2006 The GNOME Foundation
+/* GDA Oracle provider
+ * Copyright (C) 2008 The GNOME Foundation
*
* AUTHORS:
- * Vivien Malerba <malerba gnome-db org>
- * Bas Driessen <bas driessen xobas com>
+ * TO_ADD: your name and email
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -27,25 +26,8 @@
G_BEGIN_DECLS
-gchar *gda_oracle_render_CREATE_DB (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_DROP_DB (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_CREATE_TABLE (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_RENAME_TABLE (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_DROP_TABLE (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_ADD_COLUMN (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_DROP_COLUMN (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_CREATE_INDEX (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error);
-gchar *gda_oracle_render_DROP_INDEX (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error);
-
+gchar *gda_oracle_render_CREATE_TABLE (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaServerOperation *op, GError **error);
G_END_DECLS
#endif
diff --git a/providers/oracle/gda-oracle-meta.c b/providers/oracle/gda-oracle-meta.c
new file mode 100644
index 0000000..128cca6
--- /dev/null
+++ b/providers/oracle/gda-oracle-meta.c
@@ -0,0 +1,488 @@
+/* GDA oracle provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ * TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include "gda-oracle.h"
+#include "gda-oracle-meta.h"
+#include "gda-oracle-provider.h"
+#include <libgda/gda-meta-store.h>
+#include <libgda/sql-parser/gda-sql-parser.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/gda-server-provider-extra.h>
+#include <libgda/gda-connection-private.h>
+#include <libgda/gda-data-model-array.h>
+#include <libgda/gda-set.h>
+#include <libgda/gda-holder.h>
+
+/*
+ * predefined statements' IDs
+ */
+typedef enum {
+ I_STMT_1,
+} InternalStatementItem;
+
+
+/*
+ * predefined statements' SQL
+ */
+static gchar *internal_sql[] = {
+ "SQL for I_STMT_1"
+};
+
+/*
+ * global static values, and
+ * predefined statements' GdaStatement, all initialized in _gda_oracle_provider_meta_init()
+ */
+static GdaStatement **internal_stmt;
+static GdaSet *i_set;
+static GdaSqlParser *internal_parser = NULL;
+/* TO_ADD: other static values */
+
+
+/*
+ * Meta initialization
+ */
+void
+_gda_oracle_provider_meta_init (GdaServerProvider *provider)
+{
+ static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
+ InternalStatementItem i;
+
+ g_static_mutex_lock (&init_mutex);
+
+ internal_parser = gda_server_provider_internal_get_parser (provider);
+ internal_stmt = g_new0 (GdaStatement *, sizeof (internal_sql) / sizeof (gchar*));
+ for (i = I_STMT_1; i < sizeof (internal_sql) / sizeof (gchar*); i++) {
+ internal_stmt[i] = gda_sql_parser_parse_string (internal_parser, internal_sql[i], NULL, NULL);
+ if (!internal_stmt[i])
+ g_error ("Could not parse internal statement: %s\n", internal_sql[i]);
+ }
+
+ /* initialize static values here */
+ i_set = gda_set_new_inline (4, "cat", G_TYPE_STRING, "",
+ "name", G_TYPE_STRING, "",
+ "schema", G_TYPE_STRING, "",
+ "name2", G_TYPE_STRING, "");
+
+ g_static_mutex_unlock (&init_mutex);
+}
+
+gboolean
+_gda_oracle_meta__info (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ GdaDataModel *model;
+ gboolean retval;
+
+ TO_IMPLEMENT;
+ /* fill in @model, with something like:
+ * model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_1], NULL,
+ * error);
+ */
+ if (!model)
+ return FALSE;
+ retval = gda_meta_store_modify_with_context (store, context, model, error);
+ g_object_unref (model);
+
+ return retval;
+}
+
+gboolean
+_gda_oracle_meta__btypes (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__udt (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_udt (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *udt_catalog, const GValue *udt_schema)
+{
+ GdaDataModel *model;
+ gboolean retval = TRUE;
+
+ /* set internal holder's values from the arguments */
+ if (! gda_holder_set_value (gda_set_get_holder (i_set, "cat"), udt_catalog, error))
+ return FALSE;
+ if (! gda_holder_set_value (gda_set_get_holder (i_set, "schema"), udt_schema, error))
+ return FALSE;
+
+ TO_IMPLEMENT;
+ /* fill in @model, with something like:
+ * model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_UDT], i_set, error);
+ */
+ if (!model)
+ return FALSE;
+ retval = gda_meta_store_modify_with_context (store, context, model, error);
+ g_object_unref (model);
+
+ return retval;
+}
+
+
+gboolean
+_gda_oracle_meta__udt_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_udt_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__enums (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_enums (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+
+gboolean
+_gda_oracle_meta__domains (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_domains (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *domain_catalog, const GValue *domain_schema)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__constraints_dom (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_constraints_dom (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *domain_catalog, const GValue *domain_schema,
+ const GValue *domain_name)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__el_types (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_el_types (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *specific_name)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__collations (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_collations (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *collation_catalog, const GValue *collation_schema,
+ const GValue *collation_name_n)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__character_sets (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_character_sets (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *chset_catalog, const GValue *chset_schema,
+ const GValue *chset_name_n)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__schemata (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *catalog_name, const GValue *schema_name_n)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__tables_views (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name_n)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__view_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_view_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *view_catalog, const GValue *view_schema,
+ const GValue *view_name)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__constraints_tab (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_constraints_tab (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name, const GValue *constraint_name_n)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__constraints_ref (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_constraints_ref (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema, const GValue *table_name,
+ const GValue *constraint_name)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__key_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_key_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name, const GValue *constraint_name)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__check_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_check_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name, const GValue *constraint_name)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__triggers (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_triggers (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__routines (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_routines (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *routine_catalog, const GValue *routine_schema,
+ const GValue *routine_name_n)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__routine_col (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_routine_col (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *rout_catalog, const GValue *rout_schema,
+ const GValue *rout_name)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta__routine_par (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
+
+gboolean
+_gda_oracle_meta_routine_par (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *rout_catalog, const GValue *rout_schema,
+ const GValue *rout_name)
+{
+ TO_IMPLEMENT;
+ return TRUE;
+}
diff --git a/providers/oracle/gda-oracle-meta.h b/providers/oracle/gda-oracle-meta.h
new file mode 100644
index 0000000..0850505
--- /dev/null
+++ b/providers/oracle/gda-oracle-meta.h
@@ -0,0 +1,197 @@
+/* GDA oracle provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ * TO_ADD: your name and email
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GDA_ORACLE_META_H__
+#define __GDA_ORACLE_META_H__
+
+#include <libgda/gda-server-provider.h>
+
+G_BEGIN_DECLS
+
+void _gda_oracle_provider_meta_init (GdaServerProvider *provider);
+
+/* _information_schema_catalog_name */
+gboolean _gda_oracle_meta__info (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+
+/* _builtin_data_types */
+gboolean _gda_oracle_meta__btypes (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+
+/* _udt */
+gboolean _gda_oracle_meta__udt (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_udt (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *udt_catalog, const GValue *udt_schema);
+
+/* _udt_columns */
+gboolean _gda_oracle_meta__udt_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_udt_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name);
+
+/* _enums */
+gboolean _gda_oracle_meta__enums (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_enums (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name);
+
+/* _domains */
+gboolean _gda_oracle_meta__domains (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_domains (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *domain_catalog, const GValue *domain_schema);
+
+/* _domain_constraints */
+gboolean _gda_oracle_meta__constraints_dom (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_constraints_dom (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *domain_catalog, const GValue *domain_schema,
+ const GValue *domain_name);
+
+/* _element_types */
+gboolean _gda_oracle_meta__el_types (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_el_types (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *specific_name);
+
+/* _collations */
+gboolean _gda_oracle_meta__collations (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_collations (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *collation_catalog, const GValue *collation_schema,
+ const GValue *collation_name_n);
+
+/* _character_sets */
+gboolean _gda_oracle_meta__character_sets (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_character_sets (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *chset_catalog, const GValue *chset_schema,
+ const GValue *chset_name_n);
+
+/* _schemata */
+gboolean _gda_oracle_meta__schemata (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *catalog_name, const GValue *schema_name_n);
+
+/* _tables or _views */
+gboolean _gda_oracle_meta__tables_views (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name_n);
+
+/* _columns */
+gboolean _gda_oracle_meta__columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name);
+
+/* _view_column_usage */
+gboolean _gda_oracle_meta__view_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_view_cols (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *view_catalog, const GValue *view_schema,
+ const GValue *view_name);
+
+/* _table_constraints */
+gboolean _gda_oracle_meta__constraints_tab (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_constraints_tab (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name, const GValue *constraint_name_n);
+
+/* _referential_constraints */
+gboolean _gda_oracle_meta__constraints_ref (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_constraints_ref (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema, const GValue *table_name,
+ const GValue *constraint_name);
+
+/* _key_column_usage */
+gboolean _gda_oracle_meta__key_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_key_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name, const GValue *constraint_name);
+
+/* _check_column_usage */
+gboolean _gda_oracle_meta__check_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_check_columns (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name, const GValue *constraint_name);
+
+/* _triggers */
+gboolean _gda_oracle_meta__triggers (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_triggers (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name);
+
+/* _routines */
+gboolean _gda_oracle_meta__routines (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_routines (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *routine_catalog, const GValue *routine_schema,
+ const GValue *routine_name_n);
+
+/* _routine_columns */
+gboolean _gda_oracle_meta__routine_col (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_routine_col (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *rout_catalog, const GValue *rout_schema,
+ const GValue *rout_name);
+
+/* _parameters */
+gboolean _gda_oracle_meta__routine_par (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_oracle_meta_routine_par (GdaServerProvider *prov, GdaConnection *cnc,
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *rout_catalog, const GValue *rout_schema,
+ const GValue *rout_name);
+
+
+G_END_DECLS
+
+#endif
+
diff --git a/providers/oracle/gda-oracle-parser.c b/providers/oracle/gda-oracle-parser.c
new file mode 100644
index 0000000..0568732
--- /dev/null
+++ b/providers/oracle/gda-oracle-parser.c
@@ -0,0 +1,84 @@
+/* GDA Oracle provider
+ *
+ * Copyright (C) 2008 The GNOME Foundation
+ *
+ * AUTHORS:
+ * TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gda-oracle-parser.h"
+#include "oracle_token_types.h"
+#include <string.h>
+
+/*
+ * Main static functions
+ */
+static void gda_oracle_parser_class_init (GdaOracleParserClass *klass);
+static void gda_oracle_parser_init (GdaOracleParser *stmt);
+
+GType
+gda_oracle_parser_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+ static const GTypeInfo info = {
+ sizeof (GdaOracleParserClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gda_oracle_parser_class_init,
+ NULL,
+ NULL,
+ sizeof (GdaOracleParser),
+ 0,
+ (GInstanceInitFunc) gda_oracle_parser_init
+ };
+
+ g_static_mutex_lock (®istering);
+ if (type == 0)
+ type = g_type_register_static (GDA_TYPE_SQL_PARSER, "GdaOracleParser", &info, 0);
+ g_static_mutex_unlock (®istering);
+ }
+ return type;
+}
+
+/*
+ * The interface to the LEMON-generated parser
+ */
+void *gda_lemon_oracle_parserAlloc (void*(*)(size_t));
+void gda_lemon_oracle_parserFree (void*, void(*)(void*));
+void gda_lemon_oracle_parserTrace (void*, char *);
+void gda_lemon_oracle_parser (void*, int, GValue *, GdaSqlParserIface *);
+
+static void
+gda_oracle_parser_class_init (GdaOracleParserClass * klass)
+{
+ GdaSqlParserClass *pclass = GDA_SQL_PARSER_CLASS (klass);
+
+ pclass->parser_alloc = gda_lemon_oracle_parserAlloc;
+ pclass->parser_free = gda_lemon_oracle_parserFree;
+ pclass->parser_trace = gda_lemon_oracle_parserTrace;
+ pclass->parser_parse = gda_lemon_oracle_parser;
+ pclass->parser_tokens_trans = oracle_parser_tokens;
+}
+
+static void
+gda_oracle_parser_init (GdaOracleParser *parser)
+{
+}
diff --git a/providers/oracle/gda-oracle-parser.h b/providers/oracle/gda-oracle-parser.h
new file mode 100644
index 0000000..088bc49
--- /dev/null
+++ b/providers/oracle/gda-oracle-parser.h
@@ -0,0 +1,59 @@
+/* GDA Oracle provider
+ *
+ * Copyright (C) 2008 The GNOME Foundation
+ *
+ * AUTHORS:
+ * TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GDA_ORACLE_PARSER_H_
+#define __GDA_ORACLE_PARSER_H_
+
+#include <sql-parser/gda-sql-parser.h>
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_ORACLE_PARSER (gda_oracle_parser_get_type())
+#define GDA_ORACLE_PARSER(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_ORACLE_PARSER, GdaOracleParser))
+#define GDA_ORACLE_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST (klass, GDA_TYPE_ORACLE_PARSER, GdaOracleParserClass))
+#define GDA_IS_ORACLE_PARSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GDA_TYPE_ORACLE_PARSER))
+#define GDA_IS_ORACLE_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDA_TYPE_ORACLE_PARSER))
+
+typedef struct _GdaOracleParser GdaOracleParser;
+typedef struct _GdaOracleParserClass GdaOracleParserClass;
+typedef struct _GdaOracleParserPrivate GdaOracleParserPrivate;
+
+/* struct for the object's data */
+struct _GdaOracleParser
+{
+ GdaSqlParser object;
+ GdaOracleParserPrivate *priv;
+};
+
+/* struct for the object's class */
+struct _GdaOracleParserClass
+{
+ GdaSqlParserClass parent_class;
+};
+
+GType gda_oracle_parser_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif
diff --git a/providers/oracle/gda-oracle-provider.c b/providers/oracle/gda-oracle-provider.c
index a2cf04f..296dc1a 100644
--- a/providers/oracle/gda-oracle-provider.c
+++ b/providers/oracle/gda-oracle-provider.c
@@ -1,11 +1,8 @@
/* GDA Oracle provider
- * Copyright (C) 2000 - 2007 The GNOME Foundation.
+ * Copyright (C) 2008 The GNOME Foundation.
*
* AUTHORS:
- * Rodrigo Moya <rodrigo gnome-db org>
- * Tim Coleman <tim timcoleman com>
- * Vivien Malerba <malerba gnome-db org>
- * Bas Driessen <bas driessen xobas com>
+ * TO_ADD: your name and email
*
* This Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
@@ -23,182 +20,251 @@
* Boston, MA 02111-1307, USA.
*/
-#include <libgda/gda-row.h>
-#include <libgda/gda-query.h>
-#include <libgda/gda-parameter-list.h>
-#include <libgda/gda-parameter-util.h>
-#include <libgda/gda-data-model-array.h>
-#include <libgda/gda-data-model-private.h>
-#include <libgda/gda-server-provider-extra.h>
-#include <libgda/gda-renderer.h>
-#include <glib/gi18n-lib.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <errno.h>
#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+#include <libgda/libgda.h>
+#include <libgda/gda-data-model-private.h>
+#include <libgda/gda-server-provider-extra.h>
+#include <libgda/binreloc/gda-binreloc.h>
+#include <libgda/gda-statement-extra.h>
+#include <sql-parser/gda-sql-parser.h>
#include "gda-oracle.h"
#include "gda-oracle-provider.h"
#include "gda-oracle-recordset.h"
#include "gda-oracle-ddl.h"
-#include <libgda/gda-connection-private.h>
-
-#include <libgda/handlers/gda-handler-numerical.h>
-#include <libgda/handlers/gda-handler-bin.h>
-#include <libgda/handlers/gda-handler-boolean.h>
-#include <libgda/handlers/gda-handler-time.h>
-#include <libgda/handlers/gda-handler-string.h>
-#include <libgda/handlers/gda-handler-type.h>
-
-#include <libgda/sql-parser/gda-sql-parser.h>
-#include <libgda/sql-delimiter/gda-sql-delimiter.h>
-#include <libgda/binreloc/gda-binreloc.h>
-
-#define PARENT_TYPE GDA_TYPE_SERVER_PROVIDER
+#include "gda-oracle-meta.h"
+#define _GDA_PSTMT(x) ((GdaPStmt*)(x))
+/*
+ * GObject methods
+ */
static void gda_oracle_provider_class_init (GdaOracleProviderClass *klass);
static void gda_oracle_provider_init (GdaOracleProvider *provider,
- GdaOracleProviderClass *klass);
-static void gda_oracle_provider_finalize (GObject *object);
-
-static const gchar *gda_oracle_provider_get_version (GdaServerProvider *provider);
-static gboolean gda_oracle_provider_open_connection (GdaServerProvider *provider,
- GdaConnection *cnc,
- GdaQuarkList *params,
- const gchar *username,
- const gchar *password);
-static gboolean gda_oracle_provider_close_connection (GdaServerProvider *provider,
- GdaConnection *cnc);
-static const gchar *gda_oracle_provider_get_server_version (GdaServerProvider *provider,
- GdaConnection *cnc);
-static const gchar *gda_oracle_provider_get_database (GdaServerProvider *provider,
- GdaConnection *cnc);
-static gboolean gda_oracle_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperationType type, GdaParameterList *options);
+ GdaOracleProviderClass *klass);
+static GObjectClass *parent_class = NULL;
+
+/*
+ * GdaServerProvider's virtual methods
+ */
+/* connection management */
+static gboolean gda_oracle_provider_open_connection (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaQuarkList *params, GdaQuarkList *auth,
+ guint *task_id, GdaServerProviderAsyncCallback async_cb, gpointer cb_data);
+static gboolean gda_oracle_provider_close_connection (GdaServerProvider *provider, GdaConnection *cnc);
+static const gchar *gda_oracle_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc);
+static const gchar *gda_oracle_provider_get_database (GdaServerProvider *provider, GdaConnection *cnc);
+
+/* DDL operations */
+static gboolean gda_oracle_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaServerOperationType type, GdaSet *options);
static GdaServerOperation *gda_oracle_provider_create_operation (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperationType type,
- GdaParameterList *options, GError **error);
-static gchar *gda_oracle_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error);
-static gboolean gda_oracle_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error);
-static GList *gda_oracle_provider_execute_command (GdaServerProvider *provider,
- GdaConnection *cnc,
- GdaCommand *cmd,
- GdaParameterList *params);
-static GdaObject *gda_oracle_provider_execute_query (GdaServerProvider *provider,
- GdaConnection *cnc,
- GdaQuery *query,
- GdaParameterList *params);
-
-static gboolean gda_oracle_provider_begin_transaction (GdaServerProvider *provider,
- GdaConnection *cnc,
- const gchar *name, GdaTransactionIsolation level,
- GError **error);
-static gboolean gda_oracle_provider_commit_transaction (GdaServerProvider *provider,
- GdaConnection *cnc,
- const gchar *name, GError **error);
-static gboolean gda_oracle_provider_rollback_transaction (GdaServerProvider *provider,
- GdaConnection *cnc,
- const gchar *name, GError **error);
-static gboolean gda_oracle_provider_supports (GdaServerProvider *provider,
- GdaConnection *cnc,
- GdaConnectionFeature feature);
-
-static GdaServerProviderInfo *gda_oracle_provider_get_info (GdaServerProvider *provider,
- GdaConnection *cnc);
-
-static GdaDataHandler *gda_oracle_provider_get_data_handler (GdaServerProvider *provider,
- GdaConnection *cnc,
- GType g_type,
- const gchar *dbms_type);
-
-static GdaDataModel *gda_oracle_provider_get_schema (GdaServerProvider *provider,
- GdaConnection *cnc,
- GdaConnectionSchema schema,
- GdaParameterList *params);
-
-static const gchar* gda_oracle_provider_get_default_dbms_type (GdaServerProvider *provider,
- GdaConnection *cnc,
- GType type);
-
-static GdaSqlParser *gda_oracle_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc);
-
-static GList *process_sql_commands (GList *reclist, GdaConnection *cnc,
- const gchar *sql, GdaParameterList *params,
- GdaCommandOptions options, GArray *col_size_array);
+ GdaServerOperationType type,
+ GdaSet *options, GError **error);
+static gchar *gda_oracle_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaServerOperation *op, GError **error);
+
+static gboolean gda_oracle_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaServerOperation *op, guint *task_id,
+ GdaServerProviderAsyncCallback async_cb, gpointer cb_data,
+ GError **error);
+/* transactions */
+static gboolean gda_oracle_provider_begin_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+ const gchar *name, GdaTransactionIsolation level, GError **error);
+static gboolean gda_oracle_provider_commit_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+ const gchar *name, GError **error);
+static gboolean gda_oracle_provider_rollback_transaction (GdaServerProvider *provider, GdaConnection * cnc,
+ const gchar *name, GError **error);
+static gboolean gda_oracle_provider_add_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+ const gchar *name, GError **error);
+static gboolean gda_oracle_provider_rollback_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+ const gchar *name, GError **error);
+static gboolean gda_oracle_provider_delete_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+ const gchar *name, GError **error);
+
+/* information retreival */
+static const gchar *gda_oracle_provider_get_version (GdaServerProvider *provider);
+static gboolean gda_oracle_provider_supports_feature (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaConnectionFeature feature);
+
+static const gchar *gda_oracle_provider_get_name (GdaServerProvider *provider);
+
+static GdaDataHandler *gda_oracle_provider_get_data_handler (GdaServerProvider *provider, GdaConnection *cnc,
+ GType g_type, const gchar *dbms_type);
+
+static const gchar* gda_oracle_provider_get_default_dbms_type (GdaServerProvider *provider, GdaConnection *cnc,
+ GType type);
+/* statements */
+static GdaSqlParser *gda_oracle_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc);
+static gchar *gda_oracle_provider_statement_to_sql (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaStatement *stmt, GdaSet *params,
+ GdaStatementSqlFlag flags,
+ GSList **params_used, GError **error);
+static gboolean gda_oracle_provider_statement_prepare (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaStatement *stmt, GError **error);
+static GObject *gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaStatement *stmt, GdaSet *params,
+ GdaStatementModelUsage model_usage,
+ GType *col_types, GdaSet **last_inserted_row,
+ guint *task_id, GdaServerProviderExecCallback async_cb,
+ gpointer cb_data, GError **error);
+
+/* distributed transactions */
+static gboolean gda_oracle_provider_xa_start (GdaServerProvider *provider, GdaConnection *cnc,
+ const GdaXaTransactionId *xid, GError **error);
+
+static gboolean gda_oracle_provider_xa_end (GdaServerProvider *provider, GdaConnection *cnc,
+ const GdaXaTransactionId *xid, GError **error);
+static gboolean gda_oracle_provider_xa_prepare (GdaServerProvider *provider, GdaConnection *cnc,
+ const GdaXaTransactionId *xid, GError **error);
+
+static gboolean gda_oracle_provider_xa_commit (GdaServerProvider *provider, GdaConnection *cnc,
+ const GdaXaTransactionId *xid, GError **error);
+static gboolean gda_oracle_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc,
+ const GdaXaTransactionId *xid, GError **error);
+
+static GList *gda_oracle_provider_xa_recover (GdaServerProvider *provider, GdaConnection *cnc,
+ GError **error);
-static GObjectClass *parent_class = NULL;
+/*
+ * private connection data destroy
+ */
+static void gda_oracle_free_cnc_data (OracleConnectionData *cdata);
-typedef struct {
- gboolean primary_key;
- gboolean unique;
- gchar *references;
-} GdaOracleIndexData;
/*
- * GdaOracleProvider class implementation
+ * Prepared internal statements
+ * TO_ADD: any prepared statement to be used internally by the provider should be
+ * declared here, as constants and as SQL statements
*/
+static GdaStatement **internal_stmt;
+typedef enum {
+ INTERNAL_STMT1
+} InternalStatementItem;
+
+static gchar *internal_sql[] = {
+ "SQL for INTERNAL_STMT1"
+};
+
+/*
+ * GdaOracleProvider class implementation
+ */
static void
gda_oracle_provider_class_init (GdaOracleProviderClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdaServerProviderClass *provider_class = GDA_SERVER_PROVIDER_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
- object_class->finalize = gda_oracle_provider_finalize;
-
provider_class->get_version = gda_oracle_provider_get_version;
provider_class->get_server_version = gda_oracle_provider_get_server_version;
- provider_class->get_info = gda_oracle_provider_get_info;
- provider_class->supports_feature = gda_oracle_provider_supports;
- provider_class->get_schema = gda_oracle_provider_get_schema;
+ provider_class->get_name = gda_oracle_provider_get_name;
+ provider_class->supports_feature = gda_oracle_provider_supports_feature;
provider_class->get_data_handler = gda_oracle_provider_get_data_handler;
- provider_class->string_to_value = NULL;
provider_class->get_def_dbms_type = gda_oracle_provider_get_default_dbms_type;
- provider_class->create_connection = NULL;
provider_class->open_connection = gda_oracle_provider_open_connection;
provider_class->close_connection = gda_oracle_provider_close_connection;
provider_class->get_database = gda_oracle_provider_get_database;
- provider_class->change_database = NULL;
provider_class->supports_operation = gda_oracle_provider_supports_operation;
provider_class->create_operation = gda_oracle_provider_create_operation;
provider_class->render_operation = gda_oracle_provider_render_operation;
provider_class->perform_operation = gda_oracle_provider_perform_operation;
- provider_class->execute_command = gda_oracle_provider_execute_command;
- provider_class->execute_query = gda_oracle_provider_execute_query;
- provider_class->get_last_insert_id = NULL;
-
provider_class->begin_transaction = gda_oracle_provider_begin_transaction;
provider_class->commit_transaction = gda_oracle_provider_commit_transaction;
provider_class->rollback_transaction = gda_oracle_provider_rollback_transaction;
- provider_class->add_savepoint = NULL;
- provider_class->rollback_savepoint = NULL;
- provider_class->delete_savepoint = NULL;
+ provider_class->add_savepoint = gda_oracle_provider_add_savepoint;
+ provider_class->rollback_savepoint = gda_oracle_provider_rollback_savepoint;
+ provider_class->delete_savepoint = gda_oracle_provider_delete_savepoint;
provider_class->create_parser = gda_oracle_provider_create_parser;
- provider_class->statement_to_sql = NULL;
- provider_class->statement_prepare = NULL;
- provider_class->statement_execute = NULL;
-}
+ provider_class->statement_to_sql = gda_oracle_provider_statement_to_sql;
+ provider_class->statement_prepare = gda_oracle_provider_statement_prepare;
+ provider_class->statement_execute = gda_oracle_provider_statement_execute;
-static void
-gda_oracle_provider_init (GdaOracleProvider *myprv, GdaOracleProviderClass *klass)
-{
+ provider_class->is_busy = NULL;
+ provider_class->cancel = NULL;
+ provider_class->create_connection = NULL;
+
+ memset (&(provider_class->meta_funcs), 0, sizeof (GdaServerProviderMeta));
+ provider_class->meta_funcs._info = _gda_oracle_meta__info;
+ provider_class->meta_funcs._btypes = _gda_oracle_meta__btypes;
+ provider_class->meta_funcs._udt = _gda_oracle_meta__udt;
+ provider_class->meta_funcs.udt = _gda_oracle_meta_udt;
+ provider_class->meta_funcs._udt_cols = _gda_oracle_meta__udt_cols;
+ provider_class->meta_funcs.udt_cols = _gda_oracle_meta_udt_cols;
+ provider_class->meta_funcs._enums = _gda_oracle_meta__enums;
+ provider_class->meta_funcs.enums = _gda_oracle_meta_enums;
+ provider_class->meta_funcs._domains = _gda_oracle_meta__domains;
+ provider_class->meta_funcs.domains = _gda_oracle_meta_domains;
+ provider_class->meta_funcs._constraints_dom = _gda_oracle_meta__constraints_dom;
+ provider_class->meta_funcs.constraints_dom = _gda_oracle_meta_constraints_dom;
+ provider_class->meta_funcs._el_types = _gda_oracle_meta__el_types;
+ provider_class->meta_funcs.el_types = _gda_oracle_meta_el_types;
+ provider_class->meta_funcs._collations = _gda_oracle_meta__collations;
+ provider_class->meta_funcs.collations = _gda_oracle_meta_collations;
+ provider_class->meta_funcs._character_sets = _gda_oracle_meta__character_sets;
+ provider_class->meta_funcs.character_sets = _gda_oracle_meta_character_sets;
+ provider_class->meta_funcs._schemata = _gda_oracle_meta__schemata;
+ provider_class->meta_funcs.schemata = _gda_oracle_meta_schemata;
+ provider_class->meta_funcs._tables_views = _gda_oracle_meta__tables_views;
+ provider_class->meta_funcs.tables_views = _gda_oracle_meta_tables_views;
+ provider_class->meta_funcs._columns = _gda_oracle_meta__columns;
+ provider_class->meta_funcs.columns = _gda_oracle_meta_columns;
+ provider_class->meta_funcs._view_cols = _gda_oracle_meta__view_cols;
+ provider_class->meta_funcs.view_cols = _gda_oracle_meta_view_cols;
+ provider_class->meta_funcs._constraints_tab = _gda_oracle_meta__constraints_tab;
+ provider_class->meta_funcs.constraints_tab = _gda_oracle_meta_constraints_tab;
+ provider_class->meta_funcs._constraints_ref = _gda_oracle_meta__constraints_ref;
+ provider_class->meta_funcs.constraints_ref = _gda_oracle_meta_constraints_ref;
+ provider_class->meta_funcs._key_columns = _gda_oracle_meta__key_columns;
+ provider_class->meta_funcs.key_columns = _gda_oracle_meta_key_columns;
+ provider_class->meta_funcs._check_columns = _gda_oracle_meta__check_columns;
+ provider_class->meta_funcs.check_columns = _gda_oracle_meta_check_columns;
+ provider_class->meta_funcs._triggers = _gda_oracle_meta__triggers;
+ provider_class->meta_funcs.triggers = _gda_oracle_meta_triggers;
+ provider_class->meta_funcs._routines = _gda_oracle_meta__routines;
+ provider_class->meta_funcs.routines = _gda_oracle_meta_routines;
+ provider_class->meta_funcs._routine_col = _gda_oracle_meta__routine_col;
+ provider_class->meta_funcs.routine_col = _gda_oracle_meta_routine_col;
+ provider_class->meta_funcs._routine_par = _gda_oracle_meta__routine_par;
+ provider_class->meta_funcs.routine_par = _gda_oracle_meta_routine_par;
+
+ /* distributed transactions: if not supported, then provider_class->xa_funcs should be set to NULL */
+ provider_class->xa_funcs = g_new0 (GdaServerProviderXa, 1);
+ provider_class->xa_funcs->xa_start = gda_oracle_provider_xa_start;
+ provider_class->xa_funcs->xa_end = gda_oracle_provider_xa_end;
+ provider_class->xa_funcs->xa_prepare = gda_oracle_provider_xa_prepare;
+ provider_class->xa_funcs->xa_commit = gda_oracle_provider_xa_commit;
+ provider_class->xa_funcs->xa_rollback = gda_oracle_provider_xa_rollback;
+ provider_class->xa_funcs->xa_recover = gda_oracle_provider_xa_recover;
}
static void
-gda_oracle_provider_finalize (GObject *object)
+gda_oracle_provider_init (GdaOracleProvider *oracle_prv, GdaOracleProviderClass *klass)
{
- GdaOracleProvider *myprv = (GdaOracleProvider *) object;
+ InternalStatementItem i;
+ GdaSqlParser *parser;
+
+ parser = gda_server_provider_internal_get_parser ((GdaServerProvider*) oracle_prv);
+ internal_stmt = g_new0 (GdaStatement *, sizeof (internal_sql) / sizeof (gchar*));
+ for (i = INTERNAL_STMT1; i < sizeof (internal_sql) / sizeof (gchar*); i++) {
+ internal_stmt[i] = gda_sql_parser_parse_string (parser, internal_sql[i], NULL, NULL);
+ if (!internal_stmt[i])
+ g_error ("Could not parse internal statement: %s\n", internal_sql[i]);
+ }
- g_return_if_fail (GDA_IS_ORACLE_PROVIDER (myprv));
+ /* meta data init */
+ _gda_oracle_provider_meta_init ((GdaServerProvider*) oracle_prv);
- /* chain to parent class */
- parent_class->finalize (object);
+ /* TO_ADD: any other provider's init should be added here */
}
GType
@@ -207,6 +273,7 @@ gda_oracle_provider_get_type (void)
static GType type = 0;
if (G_UNLIKELY (type == 0)) {
+ static GStaticMutex registering = G_STATIC_MUTEX_INIT;
static GTypeInfo info = {
sizeof (GdaOracleProviderClass),
(GBaseInitFunc) NULL,
@@ -217,2018 +284,1051 @@ gda_oracle_provider_get_type (void)
0,
(GInstanceInitFunc) gda_oracle_provider_init
};
- type = g_type_register_static (PARENT_TYPE, "GdaOracleProvider", &info, 0);
+ g_static_mutex_lock (®istering);
+ if (type == 0)
+ type = g_type_register_static (GDA_TYPE_SERVER_PROVIDER, "GdaOracleProvider", &info, 0);
+ g_static_mutex_unlock (®istering);
}
return type;
}
-GdaServerProvider *
-gda_oracle_provider_new (void)
-{
- GdaOracleProvider *provider;
- provider = g_object_new (gda_oracle_provider_get_type (), NULL);
- return GDA_SERVER_PROVIDER (provider);
+/*
+ * Get provider name request
+ */
+static const gchar *
+gda_oracle_provider_get_name (GdaServerProvider *provider)
+{
+ return ORACLE_PROVIDER_NAME;
}
-/* get_version handler for the GdaOracleProvider class */
+/*
+ * Get provider's version, no need to change this
+ */
static const gchar *
gda_oracle_provider_get_version (GdaServerProvider *provider)
{
return PACKAGE_VERSION;
}
-/* open_connection handler for the GdaOracleProvider class */
+/*
+ * Open connection request
+ *
+ * In this function, the following _must_ be done:
+ * - check for the presence and validify of the parameters required to actually open a connection,
+ * using @params
+ * - open the real connection to the database using the parameters previously checked
+ * - create a OracleConnectionData structure and associate it to @cnc
+ *
+ * Returns: TRUE if no error occurred, or FALSE otherwise (and an ERROR gonnection event must be added to @cnc)
+ */
static gboolean
-gda_oracle_provider_open_connection (GdaServerProvider *provider,
- GdaConnection *cnc,
- GdaQuarkList *params,
- const gchar *username,
- const gchar *password)
+gda_oracle_provider_open_connection (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaQuarkList *params, GdaQuarkList *auth,
+ guint *task_id, GdaServerProviderAsyncCallback async_cb, gpointer cb_data)
{
- const gchar *tnsname;
- gint result;
-
- GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
- GdaOracleConnectionData *priv_data;
-
- g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), FALSE);
+ g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (provider), FALSE);
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
- /* check we have a TNS name to connect to */
-
- if ((tnsname = gda_quark_list_find (params, "TNSNAME")) == NULL) {
- gda_connection_add_event_string (cnc,
- _("No TNS name supplied"));
- return FALSE;
+ /* If asynchronous connection opening is not supported, then exit now */
+ if (async_cb) {
+ gda_connection_add_event_string (cnc, _("Provider does not support asynchronous connection open"));
+ return FALSE;
}
- priv_data = g_new0 (GdaOracleConnectionData, 1);
-
- /* initialize Oracle */
- result = OCIInitialize ((ub4) OCI_THREADED,
- (dvoid *) 0,
- (dvoid * (*)(dvoid *, size_t)) 0,
- (dvoid * (*)(dvoid *, dvoid *, size_t)) 0,
- (void (*)(dvoid *, dvoid *)) 0);
-
- if (result != OCI_SUCCESS) {
- gda_connection_add_event_string (cnc,
- _("Could not initialize Oracle"));
+ /* Check for connection parameters */
+ /* TO_ADD: your own connection parameters */
+ const gchar *db_name;
+ db_name = gda_quark_list_find (params, "DB_NAME");
+ if (!db_name) {
+ gda_connection_add_event_string (cnc,
+ _("The connection string must contain the DB_NAME values"));
return FALSE;
}
- /* initialize the Oracle environment */
- result = OCIEnvInit ((OCIEnv **) & priv_data->henv,
- (ub4) OCI_DEFAULT,
- (size_t) 0,
- (dvoid **) 0);
- if (result != OCI_SUCCESS) {
- gda_connection_add_event_string (cnc,
- _("Could not initialize the Oracle environment"));
- return FALSE;
- }
-
- /* create the service context */
- result = OCIHandleAlloc ((dvoid *) priv_data->henv,
- (dvoid **) &priv_data->hservice,
- (ub4) OCI_HTYPE_SVCCTX,
- (size_t) 0,
- (dvoid **) 0);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
- _("Could not allocate the Oracle service handle")))
- return FALSE;
-
- /* create the error handle */
- result = OCIHandleAlloc ((dvoid *) priv_data->henv,
- (dvoid **) &(priv_data->herr),
- (ub4) OCI_HTYPE_ERROR,
- (size_t) 0,
- (dvoid **) 0);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
- _("Could not allocate the Oracle error handle"))) {
- OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
- return FALSE;
- }
-
- /* we use the Multiple Sessions/Connections OCI paradigm for this server */
- result = OCIHandleAlloc ((dvoid *) priv_data->henv,
- (dvoid **) & priv_data->hserver,
- (ub4) OCI_HTYPE_SERVER,
- (size_t) 0,
- (dvoid **) 0);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
- _("Could not allocate the Oracle server handle"))) {
- OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
- OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
- return FALSE;
- }
+ /* open the real connection to the database */
+ /* TO_ADD: C API specific function calls;
+ * if it fails, add a connection event and return FALSE */
+ TO_IMPLEMENT;
- /* create the session handle */
- result = OCIHandleAlloc ((dvoid *) priv_data->henv,
- (dvoid **) &priv_data->hsession,
- (ub4) OCI_HTYPE_SESSION,
- (size_t) 0,
- (dvoid **) 0);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
- _("Could not allocate the Oracle session handle"))) {
- OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
- OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
- OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
- return FALSE;
- }
-
- /* if the username isn't provided, try to find it in the DSN */
-
- if (username == NULL || *username == '\0') {
- username = gda_quark_list_find (params, "USER");
- if (username == NULL)
- username="";
- }
+ /* Create a new instance of the provider specific data associated to a connection (OracleConnectionData),
+ * and set its contents */
+ OracleConnectionData *cdata;
+ cdata = g_new0 (OracleConnectionData, 1);
+ gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_oracle_free_cnc_data);
+ TO_IMPLEMENT; /* cdata->... = ... */
- /* if the password isn't provided, try to find it in the DSN */
- if (password == NULL || *password == '\0') {
- password = gda_quark_list_find (params, "PASSWORD");
- if (password == NULL)
- password="";
- }
-
- /* attach to Oracle server */
- result = OCIServerAttach (priv_data->hserver,
- priv_data->herr,
- (text *) tnsname,
- (ub4) strlen (tnsname),
- OCI_DEFAULT);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not attach to the Oracle server"))) {
- OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
- OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
- OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
- OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
- return FALSE;
- }
-
- /* set the server attribute in the service context */
- result = OCIAttrSet ((dvoid *) priv_data->hservice,
- (ub4) OCI_HTYPE_SVCCTX,
- (dvoid *) priv_data->hserver,
- (ub4) 0,
- (ub4) OCI_ATTR_SERVER,
- priv_data->herr);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not set the Oracle server attribute in the service context"))) {
- OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
- OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
- OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
- OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
- return FALSE;
- }
-
- /* set the username attribute */
- result = OCIAttrSet ((dvoid *) priv_data->hsession,
- (ub4) OCI_HTYPE_SESSION,
- (dvoid *) username,
- (ub4) strlen (username),
- (ub4) OCI_ATTR_USERNAME,
- priv_data->herr);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not set the Oracle username attribute"))) {
- OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
- OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
- OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
- OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
- return FALSE;
- }
-
- /* set the password attribute */
- result = OCIAttrSet ((dvoid *) priv_data->hsession,
- (ub4) OCI_HTYPE_SESSION,
- (dvoid *) password,
- (ub4) strlen (password),
- (ub4) OCI_ATTR_PASSWORD,
- priv_data->herr);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not set the Oracle password attribute"))) {
- OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
- OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
- OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
- OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
- return FALSE;
- }
-
- /* begin the session */
- result = OCISessionBegin (priv_data->hservice,
- priv_data->herr,
- priv_data->hsession,
- (ub4) OCI_CRED_RDBMS,
- (ub4) OCI_DEFAULT);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not begin the Oracle session"))) {
- OCIServerDetach (priv_data->hserver, priv_data->herr, OCI_DEFAULT);
- OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
- OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
- OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
- OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
- priv_data->hsession = NULL;
- return FALSE;
- }
-
- /* set the session attribute in the service context */
- result = OCIAttrSet ((dvoid *) priv_data->hservice,
- (ub4) OCI_HTYPE_SVCCTX,
- (dvoid *) priv_data->hsession,
- (ub4) 0,
- (ub4) OCI_ATTR_SESSION,
- priv_data->herr);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not set the Oracle session attribute in the service context"))) {
- OCIServerDetach (priv_data->hserver, priv_data->herr, OCI_DEFAULT);
- OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
- OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
- OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
- OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
- return FALSE;
- }
-
- priv_data->schema = g_ascii_strup (username, -1);
-
- /* attach the oracle connection data to the gda connection object */
- g_object_set_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE, priv_data);
-
- /* set sessions parameters */
- GList *reclist;
-
- reclist = process_sql_commands (NULL, cnc,
- "ALTER SESSION SET NLS_DATE_FORMAT = 'MM/DD/YYYY';"
- "ALTER SESSION SET NLS_NUMERIC_CHARACTERS = \". \";",
- NULL, GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
-
- g_list_foreach (reclist, (GFunc) g_object_unref, NULL);
- g_list_free (reclist);
+ /* Optionnally set some attributes for the newly opened connection (encoding to UTF-8 for example )*/
+ TO_IMPLEMENT;
return TRUE;
}
-/* close_connection handler for the GdaOracleProvider class */
+/*
+ * Close connection request
+ *
+ * In this function, the following _must_ be done:
+ * - Actually close the connection to the database using @cnc's associated OracleConnectionData structure
+ * - Free the OracleConnectionData structure and its contents
+ *
+ * Returns: TRUE if no error occurred, or FALSE otherwise (and an ERROR gonnection event must be added to @cnc)
+ */
static gboolean
gda_oracle_provider_close_connection (GdaServerProvider *provider, GdaConnection *cnc)
{
- GdaOracleConnectionData *priv_data;
- GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
- gint result;
+ OracleConnectionData *cdata;
- g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), FALSE);
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data)
- return FALSE;
-
- /* end the session */
- if ((result =
- OCISessionEnd (priv_data->hservice,
- priv_data->herr,
- priv_data->hsession,
- OCI_DEFAULT))) {
- gda_connection_add_event (cnc,
- gda_oracle_make_error (priv_data->herr, OCI_HTYPE_ERROR, __FILE__, __LINE__));
+ /* Close the connection using the C API */
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
return FALSE;
- }
+ TO_IMPLEMENT;
- /* free all of the handles */
- if (priv_data->hsession)
- OCIHandleFree ((dvoid *) priv_data->hsession, OCI_HTYPE_SESSION);
- if (priv_data->hservice)
- OCIHandleFree ((dvoid *) priv_data->hservice, OCI_HTYPE_SVCCTX);
- if (priv_data->hserver)
- OCIHandleFree ((dvoid *) priv_data->hserver, OCI_HTYPE_SERVER);
- if (priv_data->herr)
- OCIHandleFree ((dvoid *) priv_data->herr, OCI_HTYPE_ERROR);
- if (priv_data->henv)
- OCIHandleFree ((dvoid *) priv_data->henv, OCI_HTYPE_ENV);
- if (priv_data->schema)
- g_free(priv_data->schema);
-
- g_free (priv_data);
- g_object_set_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE, NULL);
+ /* Free the OracleConnectionData structure and its contents*/
+ gda_oracle_free_cnc_data (cdata);
+ gda_connection_internal_set_provider_data (cnc, NULL, NULL);
return TRUE;
}
-/* get_server_version handler for the GdaOracleProvider class */
-static const gchar *
-gda_oracle_provider_get_server_version (GdaServerProvider *provider,
- GdaConnection *cnc)
-{
- GdaOracleConnectionData *priv_data;
- static guchar version[512];
-
- if (cnc)
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
- else
- return NULL;
-
- /* Get the OracleConnectionData */
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data) {
- gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
- return NULL;
- }
-
- OCIServerVersion (priv_data->hservice, priv_data->herr, version, 255, OCI_HTYPE_SVCCTX);
-
- return (const gchar *) version;
-}
-
-/*
- * prepare_oracle_statement prepares the Oracle statement handle for use
- *
- * Its parameters are the connection object, a list of parameters to be bound,
- * and the SQL statement to be prepared.
- *
- * It's generally good style to name your parameters beginning with a colon (:)
- * i.e. :parameter_name. This will avoid confusion.
+/*
+ * Server version request
*
- * IMPORTANT: If you pass in a parameter in this list that isn't in the statement
- * it will still try to perform a bind anyway.
+ * Returns the server version as a string, which should be stored in @cnc's associated OracleConnectionData structure
*/
-static OCIStmt *
-prepare_oracle_statement (GdaConnection *cnc, GdaParameterList *params, gchar *sql)
+static const gchar *
+gda_oracle_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc)
{
- GdaOracleConnectionData *priv_data;
- OCIStmt *stmthp = (OCIStmt *) 0;
- gint result;
-
- /* Get the OracleConnectionData */
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data) {
- gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
- return NULL;
- }
+ OracleConnectionData *cdata;
- /* Allocate an oracle statement handle */
- result = OCIHandleAlloc ((dvoid *) priv_data->henv,
- (dvoid **) &stmthp,
- (ub4) OCI_HTYPE_STMT,
- (size_t) 0,
- (dvoid **) 0);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
- _("Could not allocate the Oracle statement handle")))
- return NULL;
-
- /* Prepare the statement */
- result = OCIStmtPrepare ((dvoid *) stmthp,
- (dvoid *) priv_data->herr,
- (text *) sql,
- (ub4) strlen(sql),
- (ub4) OCI_NTV_SYNTAX,
- (ub4) OCI_DEFAULT);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not prepare the Oracle statement"))) {
- OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
- return NULL;
- }
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
- /* Bind parameters */
- if (params != NULL) {
- /* loop through parameters and bind by name */
- GSList *parm_list = params->parameters;
-
- for (parm_list = params->parameters; parm_list; parm_list = parm_list->next) {
- gchar *parm_name = gda_parameter_get_alphanum_name (GDA_PARAMETER (parm_list->data));
- const GValue *gda_value = gda_parameter_get_value (GDA_PARAMETER (parm_list->data));
- GdaOracleValue *ora_value = gda_value_to_oracle_value (gda_value);
- OCIBind *bindpp = (OCIBind *) 0;
-
- result = OCIBindByName ((dvoid *) stmthp,
- (OCIBind **) &bindpp,
- (OCIError *) priv_data->herr,
- (text *) parm_name,
- (sb4) strlen (parm_name),
- (dvoid *) ora_value->value,
- (sb4) ora_value->defined_size,
- (ub2) ora_value->sql_type,
- (dvoid *) &ora_value->indicator,
- (ub2 *) 0,
- (ub2) 0,
- (ub4) 0,
- (ub4 *) 0,
- (ub4) OCI_DEFAULT);
- g_free (parm_name);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not bind the Oracle statement parameter"))) {
- OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
- return NULL;
- }
- }
- }
- return stmthp;
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
+ return FALSE;
+ TO_IMPLEMENT;
+ return NULL;
}
/*
- * executes @stmthp and returns a GdaDataModel or a GdaParameterList
+ * Get database request
*
- * WARNING: don't use stmthp afterwards.
+ * Returns the database name as a string, which should be stored in @cnc's associated OracleConnectionData structure
*/
-static GdaObject *
-process_oci_statement (OCIStmt *stmthp, const gchar *sql, GdaConnection *cnc, GArray *col_size_array)
-{
- GdaObject *retval = NULL;
- gint result;
- GdaOracleConnectionData *priv_data;
- GdaConnectionEvent *error = NULL;
- ub2 stmt_type;
-
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data) {
- gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
- return NULL;
- }
-
- result = OCIAttrGet (stmthp, OCI_HTYPE_STMT,
- (dvoid *) &stmt_type, NULL,
- OCI_ATTR_STMT_TYPE, priv_data->herr);
- error = gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not get the Oracle statement type"));
- if (!error) {
- ub4 prefetch = 200;
- result = OCIAttrSet (stmthp, OCI_HTYPE_STMT,
- &prefetch, 0,
- OCI_ATTR_PREFETCH_ROWS, priv_data->herr);
- error = gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not set the Oracle statement pre-fetch row count"));
- if (!error) {
- GdaConnectionEvent *event;
- event = gda_connection_event_new (GDA_CONNECTION_EVENT_COMMAND);
- gda_connection_event_set_description (event, sql);
- gda_connection_add_event (cnc, event);
-
- result = OCIStmtExecute (priv_data->hservice,
- stmthp,
- priv_data->herr,
- (ub4) ((stmt_type == OCI_STMT_SELECT) ? 0 : 1),
- (ub4) 0,
- (CONST OCISnapshot *) NULL,
- (OCISnapshot *) NULL,
- OCI_DEFAULT); /* not OCI_COMMIT_ON_SUCCESS because transactions are
- handled separately */
-
- error = gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not execute the Oracle statement"));
- }
- }
- gda_connection_internal_treat_sql (cnc, sql, error);
- if (error) {
- OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
- return NULL;
- }
-
- if (stmt_type != OCI_STMT_SELECT) {
- /* get the number of affected rows */
- int nrows;
-
- result = OCIAttrGet (stmthp, OCI_HTYPE_STMT,
- (dvoid *) &stmt_type, NULL,
- OCI_ATTR_SQLFNCODE, priv_data->herr);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not get the Oracle statement type"))) {
- OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
- return NULL;
- }
- result = OCIAttrGet (stmthp, OCI_HTYPE_STMT,
- (dvoid *) &nrows, NULL,
- OCI_ATTR_ROW_COUNT, priv_data->herr);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not get the number of affected rows"))) {
- OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
- return NULL;
- }
-
- retval = GDA_OBJECT (gda_parameter_list_new_inline (NULL, "IMPACTED_ROWS", G_TYPE_INT, nrows, NULL));
-
- /* handle the attached transaction */
- OCITrans *txnhp = NULL;
- result = OCIAttrGet ((dvoid *) priv_data->hservice,
- OCI_HTYPE_SVCCTX,
- (dvoid **) &txnhp,
- 0,
- OCI_ATTR_TRANS,
- priv_data->herr);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not get the attached transaction from the service context")))
- return NULL;
-
- if (!txnhp) {
- /* Commit local transaction (no global transaction) */
- result = OCITransCommit (priv_data->hservice, priv_data->herr, 0);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not execute the Oracle statement"))) {
- OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
- return NULL;
- }
- }
- /*else
- g_print ("Don't commit local transaction (there is a global transaction)\n");*/
- }
- else {
- GList *columns = NULL;
- ub4 ncolumns;
- ub4 i;
-
- /* get the number of columns in the result set */
- result = OCIAttrGet ((dvoid *) stmthp,
- (ub4) OCI_HTYPE_STMT,
- (dvoid *) &ncolumns,
- (ub4 *) 0,
- (ub4) OCI_ATTR_PARAM_COUNT,
- priv_data->herr);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not get the number of columns in the result set"))) {
- OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
- return NULL;
- }
-
- for (i = 0; i < ncolumns; i += 1) {
- text *pgchar_dummy = (text *) 0;
- ub4 col_name_len;
- OCIParam *pard = (OCIParam *) 0;
- gchar *name_buffer;
-
- result = OCIParamGet ((dvoid *) stmthp,
- OCI_HTYPE_STMT,
- priv_data->herr,
- (dvoid **) &pard,
- (ub4) i + 1);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not get the parameter descripter in the result set"))) {
- OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
- return NULL;
- }
-
- result = OCIAttrGet ((dvoid *) pard,
- (ub4) OCI_DTYPE_PARAM,
- (dvoid **) &pgchar_dummy,
- (ub4 *) &col_name_len,
- (ub4) OCI_ATTR_NAME,
- (OCIError *) priv_data->herr);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not get the column name in the result set"))) {
- OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
- return NULL;
- }
-
- name_buffer = g_malloc0 (col_name_len + 1);
- memcpy (name_buffer, pgchar_dummy, col_name_len);
- name_buffer[col_name_len] = '\0';
- columns = g_list_append (columns, name_buffer);
- }
-
- retval = GDA_OBJECT (gda_oracle_recordset_new (cnc, priv_data, stmthp,
- col_size_array));
- stmthp = NULL;
- GList *l;
- g_object_set (G_OBJECT (retval),
- "command_text", sql,
- "command_type", GDA_COMMAND_TYPE_SQL, NULL);
-
- for (i = 0, l = columns; l; l = l->next, i++) {
- gchar *col_name = (gchar *) l->data;
- gda_data_model_set_column_title ((GdaDataModel *) retval, i, col_name);
- }
-
- /*gda_data_model_dump (recset, stdout);*/
- g_list_free (columns);
- }
-
- return retval;
-}
-
-static GList *
-process_sql_commands (GList *reclist, GdaConnection *cnc,
- const gchar *sql, GdaParameterList *params,
- GdaCommandOptions options, GArray *col_size_array)
-{
- gchar **arr;
-
- /* parse SQL string, which can contain several commands, separated by ';' */
- arr = gda_delimiter_split_sql (sql);
- if (arr) {
- gint n;
-
- for (n = 0; arr[n]; n++) {
- GdaObject *obj;
- OCIStmt *stmthp;
-
- stmthp = prepare_oracle_statement (cnc, params, arr[n]);
- obj = process_oci_statement (stmthp, arr[n], cnc, col_size_array);
- reclist = g_list_append (reclist, obj);
- }
-
- g_strfreev (arr);
- }
-
- return reclist;
-}
-
-/* get_database handler for the GdaOracleProvider class */
static const gchar *
-gda_oracle_provider_get_database (GdaServerProvider *provider,
- GdaConnection *cnc)
+gda_oracle_provider_get_database (GdaServerProvider *provider, GdaConnection *cnc)
{
- GdaOracleConnectionData *priv_data;
- GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
+ OracleConnectionData *cdata;
- g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), NULL);
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data) {
- gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
- return FALSE;
- }
-
- /* don't know what to do here yet. */
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
+ return NULL;
+ TO_IMPLEMENT;
return NULL;
}
+/*
+ * Support operation request
+ *
+ * Tells what the implemented server operations are. To add support for an operation, the following steps are required:
+ * - create a oracle_specs_....xml.in file describing the required and optional parameters for the operation
+ * - add it to the Makefile.am
+ * - make this method return TRUE for the operation type
+ * - implement the gda_oracle_provider_render_operation() and gda_oracle_provider_perform_operation() methods
+ *
+ * In this example, the GDA_SERVER_OPERATION_CREATE_TABLE is implemented
+ */
static gboolean
gda_oracle_provider_supports_operation (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperationType type, GdaParameterList *options)
+ GdaServerOperationType type, GdaSet *options)
{
- switch (type) {
- case GDA_SERVER_OPERATION_CREATE_DB:
- case GDA_SERVER_OPERATION_DROP_DB:
-
- case GDA_SERVER_OPERATION_CREATE_TABLE:
- case GDA_SERVER_OPERATION_DROP_TABLE:
- case GDA_SERVER_OPERATION_RENAME_TABLE:
+ if (cnc) {
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+ }
- case GDA_SERVER_OPERATION_ADD_COLUMN:
- case GDA_SERVER_OPERATION_DROP_COLUMN:
+ switch (type) {
+ case GDA_SERVER_OPERATION_CREATE_DB:
+ case GDA_SERVER_OPERATION_DROP_DB:
+ return FALSE;
- case GDA_SERVER_OPERATION_CREATE_INDEX:
- case GDA_SERVER_OPERATION_DROP_INDEX:
+ case GDA_SERVER_OPERATION_CREATE_TABLE:
return TRUE;
- default:
- return FALSE;
- }
+ case GDA_SERVER_OPERATION_DROP_TABLE:
+ case GDA_SERVER_OPERATION_RENAME_TABLE:
+
+ case GDA_SERVER_OPERATION_ADD_COLUMN:
+
+ case GDA_SERVER_OPERATION_CREATE_INDEX:
+ case GDA_SERVER_OPERATION_DROP_INDEX:
+
+ case GDA_SERVER_OPERATION_CREATE_VIEW:
+ case GDA_SERVER_OPERATION_DROP_VIEW:
+ default:
+ return FALSE;
+ }
}
+
+/*
+ * Create operation request
+ *
+ * Creates a #GdaServerOperation. The following code is generic and should only be changed
+ * if some further initialization is required, or if operation's contents is dependant on @cnc
+ */
static GdaServerOperation *
gda_oracle_provider_create_operation (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperationType type,
- GdaParameterList *options, GError **error)
+ GdaServerOperationType type, GdaSet *options, GError **error)
{
- gchar *file;
- GdaServerOperation *op;
- gchar *str;
+ gchar *file;
+ GdaServerOperation *op;
+ gchar *str;
gchar *dir;
- file = g_utf8_strdown (gda_server_operation_op_type_to_string (type), -1);
- str = g_strdup_printf ("oracle_specs_%s.xml", file);
- g_free (file);
+ if (cnc) {
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+ }
+
+ file = g_utf8_strdown (gda_server_operation_op_type_to_string (type), -1);
+ str = g_strdup_printf ("oracle_specs_%s.xml", file);
+ g_free (file);
dir = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, NULL);
- file = gda_server_provider_find_file (provider, dir, str);
+ file = gda_server_provider_find_file (provider, dir, str);
g_free (dir);
- g_free (str);
- if (! file) {
- g_set_error (error, 0, 0, _("Missing spec. file '%s'"), file);
- return NULL;
- }
+ if (! file) {
+ g_set_error (error, 0, 0, _("Missing spec. file '%s'"), str);
+ g_free (str);
+ return NULL;
+ }
+ g_free (str);
- op = gda_server_operation_new (type, file);
- g_free (file);
+ op = gda_server_operation_new (type, file);
+ g_free (file);
- return op;
+ return op;
}
+/*
+ * Render operation request
+ */
static gchar *
-gda_oracle_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error)
+gda_oracle_provider_render_operation (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaServerOperation *op, GError **error)
{
- gchar *sql = NULL;
- gchar *file;
- gchar *str;
+ gchar *sql = NULL;
+ gchar *file;
+ gchar *str;
gchar *dir;
- file = g_utf8_strdown (gda_server_operation_op_type_to_string (gda_server_operation_get_op_type (op)), -1);
- str = g_strdup_printf ("oracle_specs_%s.xml", file);
- g_free (file);
-
+ if (cnc) {
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+ }
+
+ /* test @op's validity */
+ file = g_utf8_strdown (gda_server_operation_op_type_to_string (gda_server_operation_get_op_type (op)), -1);
+ str = g_strdup_printf ("oracle_specs_%s.xml", file);
+ g_free (file);
+
dir = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, NULL);
- file = gda_server_provider_find_file (provider, dir, str);
+ file = gda_server_provider_find_file (provider, dir, str);
g_free (dir);
- g_free (str);
- if (! file) {
- g_set_error (error, 0, 0, _("Missing spec. file '%s'"), file);
- return NULL;
- }
- if (!gda_server_operation_is_valid (op, file, error)) {
- g_free (file);
- return NULL;
- }
- g_free (file);
-
- switch (gda_server_operation_get_op_type (op)) {
- case GDA_SERVER_OPERATION_CREATE_DB:
- sql = gda_oracle_render_CREATE_DB (provider, cnc, op, error);
- break;
- case GDA_SERVER_OPERATION_DROP_DB:
- sql = gda_oracle_render_DROP_DB (provider, cnc, op, error);
- break;
- case GDA_SERVER_OPERATION_CREATE_TABLE:
- sql = gda_oracle_render_CREATE_TABLE (provider, cnc, op, error);
- break;
- case GDA_SERVER_OPERATION_DROP_TABLE:
- sql = gda_oracle_render_DROP_TABLE (provider, cnc, op, error);
- break;
- case GDA_SERVER_OPERATION_RENAME_TABLE:
- sql = gda_oracle_render_RENAME_TABLE (provider, cnc, op, error);
- break;
- case GDA_SERVER_OPERATION_ADD_COLUMN:
- sql = gda_oracle_render_ADD_COLUMN (provider, cnc, op, error);
- break;
- case GDA_SERVER_OPERATION_DROP_COLUMN:
- sql = gda_oracle_render_DROP_COLUMN (provider, cnc, op, error);
- break;
- case GDA_SERVER_OPERATION_CREATE_INDEX:
- sql = gda_oracle_render_CREATE_INDEX (provider, cnc, op, error);
- break;
- case GDA_SERVER_OPERATION_DROP_INDEX:
- sql = gda_oracle_render_DROP_INDEX (provider, cnc, op, error);
- break;
- default:
- g_assert_not_reached ();
- }
- return sql;
+ if (! file) {
+ g_set_error (error, 0, 0, _("Missing spec. file '%s'"), str);
+ g_free (str);
+ return NULL;
+ }
+ g_free (str);
+ if (!gda_server_operation_is_valid (op, file, error)) {
+ g_free (file);
+ return NULL;
+ }
+ g_free (file);
+
+ /* actual rendering */
+ switch (gda_server_operation_get_op_type (op)) {
+ case GDA_SERVER_OPERATION_CREATE_DB:
+ case GDA_SERVER_OPERATION_DROP_DB:
+ sql = NULL;
+ break;
+ case GDA_SERVER_OPERATION_CREATE_TABLE:
+ sql = gda_oracle_render_CREATE_TABLE (provider, cnc, op, error);
+ break;
+ case GDA_SERVER_OPERATION_DROP_TABLE:
+ case GDA_SERVER_OPERATION_RENAME_TABLE:
+ case GDA_SERVER_OPERATION_ADD_COLUMN:
+ case GDA_SERVER_OPERATION_CREATE_INDEX:
+ case GDA_SERVER_OPERATION_DROP_INDEX:
+ case GDA_SERVER_OPERATION_CREATE_VIEW:
+ case GDA_SERVER_OPERATION_DROP_VIEW:
+ sql = NULL;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ return sql;
}
+/*
+ * Perform operation request
+ */
static gboolean
-gda_oracle_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc,
- GdaServerOperation *op, GError **error)
+gda_oracle_provider_perform_operation (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaServerOperation *op, guint *task_id,
+ GdaServerProviderAsyncCallback async_cb, gpointer cb_data, GError **error)
{
- GdaServerOperationType optype;
+ GdaServerOperationType optype;
- optype = gda_server_operation_get_op_type (op);
- if (!cnc &&
- ((optype == GDA_SERVER_OPERATION_CREATE_DB) ||
- (optype == GDA_SERVER_OPERATION_DROP_DB))) {
+ /* If asynchronous connection opening is not supported, then exit now */
+ if (async_cb) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_METHOD_NON_IMPLEMENTED_ERROR,
+ "%s", _("Provider does not support asynchronous server operation"));
+ return FALSE;
+ }
- /* Not yet implemented */
- return FALSE;
+ if (cnc) {
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
}
- else {
+ optype = gda_server_operation_get_op_type (op);
+ switch (optype) {
+ case GDA_SERVER_OPERATION_CREATE_DB:
+ case GDA_SERVER_OPERATION_DROP_DB:
+ default:
/* use the SQL from the provider to perform the action */
- gchar *sql;
- GdaCommand *cmd;
-
- sql = gda_server_provider_render_operation (provider, cnc, op, error);
- if (!sql)
- return FALSE;
-
- cmd = gda_command_new (sql, GDA_COMMAND_TYPE_SQL, GDA_COMMAND_OPTION_STOP_ON_ERRORS);
- g_free (sql);
-
- if (gda_connection_execute_non_select_command (cnc, cmd, NULL, error) != -1) {
- gda_command_free (cmd);
- return TRUE;
- }
- else {
- gda_command_free (cmd);
- return FALSE;
- }
+ return gda_server_provider_perform_operation_default (provider, cnc, op, error);
}
}
-/* execute_command handler */
-static GList *
-gda_oracle_provider_execute_command (GdaServerProvider *provider,
- GdaConnection *cnc,
- GdaCommand *cmd,
- GdaParameterList *params)
+/*
+ * Begin transaction request
+ */
+static gboolean
+gda_oracle_provider_begin_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+ const gchar *name, GdaTransactionIsolation level,
+ GError **error)
{
- GList *reclist = NULL;
- gchar *str;
- GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
- GdaOracleConnectionData *priv_data;
+ OracleConnectionData *cdata;
- GdaCommandOptions options;
-
- g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), NULL);
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
- g_return_val_if_fail (cmd != NULL, NULL);
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data) {
- gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
return FALSE;
- }
-
- options = gda_command_get_options (cmd);
- switch (gda_command_get_command_type (cmd)) {
- case GDA_COMMAND_TYPE_SQL:
- reclist = process_sql_commands (reclist, cnc, gda_command_get_text (cmd), NULL, options, NULL);
- break;
- case GDA_COMMAND_TYPE_TABLE:
- str = g_strdup_printf ("SELECT * FROM %s", gda_command_get_text (cmd));
- reclist = process_sql_commands (reclist, cnc, str, NULL, options, NULL);
- g_free (str);
- break;
- default:
- break;
- }
+ TO_IMPLEMENT;
- return reclist;
+ return FALSE;
}
-static GdaObject *
-gda_oracle_provider_execute_query (GdaServerProvider *provider,
- GdaConnection *cnc,
- GdaQuery *query,
- GdaParameterList *params)
+/*
+ * Commit transaction request
+ */
+static gboolean
+gda_oracle_provider_commit_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+ const gchar *name, GError **error)
{
- GdaObject *retval = NULL;
- gchar *pseudo_sql;
- GError *error = NULL;
- GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
- GdaOracleConnectionData *priv_data;
- GSList *used_params = NULL;
-
- g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), NULL);
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
- g_return_val_if_fail (GDA_IS_QUERY (query), NULL);
+ OracleConnectionData *cdata;
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data) {
- gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
- return NULL;
- }
-
- pseudo_sql = gda_renderer_render_as_sql (GDA_RENDERER (query), params, &used_params,
- GDA_RENDERER_PARAMS_AS_COLON, &error);
- if (!pseudo_sql) {
- GdaConnectionEvent *event;
- event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
- gda_connection_event_set_description (event, error && error->message ?
- error->message : _("No detail"));
- g_error_free (error);
- gda_connection_add_event (cnc, event);
- return NULL;
- }
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
- OCIStmt *stmthp;
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
+ return FALSE;
- stmthp = prepare_oracle_statement (cnc, params, pseudo_sql);
- retval = process_oci_statement (stmthp, pseudo_sql, cnc, NULL);
- g_free (pseudo_sql);
+ TO_IMPLEMENT;
- return retval;
+ return FALSE;
}
-
-/* begin_transaction handler for the GdaOracleProvider class */
+/*
+ * Rollback transaction request
+ */
static gboolean
-gda_oracle_provider_begin_transaction (GdaServerProvider *provider,
- GdaConnection *cnc,
- const gchar *name, GdaTransactionIsolation level,
- GError **error)
+gda_oracle_provider_rollback_transaction (GdaServerProvider *provider, GdaConnection *cnc,
+ const gchar *name, GError **error)
{
- GdaOracleConnectionData *priv_data;
- GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
- gint result;
- OCITrans *txnhp;
+ OracleConnectionData *cdata;
- g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), FALSE);
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data) {
- gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
- return FALSE;
- }
-
- if (gda_connection_get_options (cnc) & GDA_CONNECTION_OPTIONS_READ_ONLY) {
- gda_connection_add_event_string (cnc, _("Transactions are not supported in read-only mode"));
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
return FALSE;
- }
- /* allocate the Oracle transaction handle */
- result = OCIHandleAlloc ((dvoid *) priv_data->henv,
- (dvoid **) &txnhp,
- (ub4) OCI_HTYPE_TRANS,
- (size_t) 0,
- (dvoid **) 0);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
- _("Could not allocate the Oracle transaction handle")))
- return FALSE;
+ TO_IMPLEMENT;
- /* set the transaction name if applicable */
- if (name) {
- result = OCIAttrSet ((dvoid *) txnhp,
- OCI_HTYPE_TRANS,
- (text *) name,
- strlen (name),
- OCI_ATTR_TRANS_NAME,
- priv_data->herr);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not set the Oracle transaction name"))) {
- OCIHandleFree ((dvoid *) txnhp, OCI_HTYPE_TRANS);
- return FALSE;
- }
- }
-
- /* attach the transaction to the service context */
- result = OCIAttrSet ((dvoid *) priv_data->hservice,
- OCI_HTYPE_SVCCTX,
- (dvoid *) txnhp,
- 0,
- OCI_ATTR_TRANS,
- priv_data->herr);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not attach the transaction to the service context"))) {
- OCIHandleFree ((dvoid *) txnhp, OCI_HTYPE_TRANS);
- return FALSE;
- }
-
- /* start the transaction */
- result = OCITransStart (priv_data->hservice,
- priv_data->herr,
- 60,
- OCI_TRANS_NEW);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not start the Oracle transaction"))) {
- OCIAttrSet ((dvoid *) priv_data->hservice,
- OCI_HTYPE_SVCCTX,
- (dvoid *) NULL,
- 0,
- OCI_ATTR_TRANS,
- priv_data->herr);
- OCIHandleFree ((dvoid *) txnhp, OCI_HTYPE_TRANS);
- return FALSE;
- }
-
- /* help the GdaConnection keep track of the transaction status */
- gda_connection_internal_transaction_started (cnc, NULL, name, GDA_TRANSACTION_ISOLATION_UNKNOWN);
-
- return TRUE;
+ return FALSE;
}
-/* commit_transaction handler for the GdaOracleProvider class */
+/*
+ * Add savepoint request
+ */
static gboolean
-gda_oracle_provider_commit_transaction (GdaServerProvider *provider,
- GdaConnection *cnc,
- const gchar *name, GError **error)
+gda_oracle_provider_add_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+ const gchar *name, GError **error)
{
- GdaOracleConnectionData *priv_data;
- GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
- gint result;
- OCITrans *txnhp = NULL;
+ OracleConnectionData *cdata;
- g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), FALSE);
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data) {
- gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
- return FALSE;
- }
-
- result = OCIAttrGet ((dvoid *) priv_data->hservice,
- OCI_HTYPE_SVCCTX,
- (dvoid **) &txnhp,
- 0,
- OCI_ATTR_TRANS,
- priv_data->herr);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not get the attached transaction from the service context")))
- return FALSE;
-
- if (gda_connection_get_options (cnc) & GDA_CONNECTION_OPTIONS_READ_ONLY) {
- gda_connection_add_event_string (cnc, _("Transactions are not supported in read-only mode"));
- return FALSE;
- }
-
- /* commit */
- result = OCITransCommit (priv_data->hservice,
- priv_data->herr,
- OCI_DEFAULT);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not commit the Oracle transaction")))
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
return FALSE;
- /* get rid of transaction handle */
- result = OCIAttrSet ((dvoid *) priv_data->hservice,
- OCI_HTYPE_SVCCTX,
- (dvoid *) NULL,
- 0,
- OCI_ATTR_TRANS,
- priv_data->herr);
- gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not de-attach the transaction to the service context"));
- if (txnhp)
- OCIHandleFree ((dvoid *) txnhp, OCI_HTYPE_TRANS);
-
- /* help the GdaConnection keep track of the transaction status */
- gda_connection_internal_transaction_committed (cnc, name);
-
- return TRUE;
+ TO_IMPLEMENT;
+ return FALSE;
}
-/* rollback_transaction handler for the GdaOracleProvider class */
+/*
+ * Rollback savepoint request
+ */
static gboolean
-gda_oracle_provider_rollback_transaction (GdaServerProvider *provider,
- GdaConnection *cnc,
- const gchar *name, GError **error)
+gda_oracle_provider_rollback_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+ const gchar *name, GError **error)
{
- GdaOracleConnectionData *priv_data;
- GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
- gint result;
- OCITrans *txnhp = NULL;
+ OracleConnectionData *cdata;
- g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), FALSE);
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data) {
- gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
return FALSE;
- }
- result = OCIAttrGet ((dvoid *) priv_data->hservice,
- OCI_HTYPE_SVCCTX,
- (dvoid **) &txnhp,
- 0,
- OCI_ATTR_TRANS,
- priv_data->herr);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not get the attached transaction from the service context")))
- return FALSE;
+ TO_IMPLEMENT;
- if (gda_connection_get_options (cnc) & GDA_CONNECTION_OPTIONS_READ_ONLY) {
- gda_connection_add_event_string (cnc, _("Transactions are not supported in read-only mode"));
- return FALSE;
- }
+ return FALSE;
+}
+
+/*
+ * Delete savepoint request
+ */
+static gboolean
+gda_oracle_provider_delete_savepoint (GdaServerProvider *provider, GdaConnection *cnc,
+ const gchar *name, GError **error)
+{
+ OracleConnectionData *cdata;
+
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
- /* attach the transaction to the service context */
- result = OCITransRollback (priv_data->hservice,
- priv_data->herr,
- OCI_DEFAULT);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not rollback the Oracle transaction")))
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
return FALSE;
- /* get rid of transaction handle */
- result = OCIAttrSet ((dvoid *) priv_data->hservice,
- OCI_HTYPE_SVCCTX,
- (dvoid *) NULL,
- 0,
- OCI_ATTR_TRANS,
- priv_data->herr);
- gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not de-attach the transaction to the service context"));
- if (txnhp)
- OCIHandleFree ((dvoid *) txnhp, OCI_HTYPE_TRANS);
-
- /* help the GdaConnection keep track of the transaction status */
- gda_connection_internal_transaction_rolledback (cnc, name);
+ TO_IMPLEMENT;
- return TRUE;
+ return FALSE;
}
-/* supports handler for the GdaOracleProvider class */
+/*
+ * Feature support request
+ */
static gboolean
-gda_oracle_provider_supports (GdaServerProvider *provider,
- GdaConnection *cnc,
- GdaConnectionFeature feature)
+gda_oracle_provider_supports_feature (GdaServerProvider *provider, GdaConnection *cnc, GdaConnectionFeature feature)
{
- GdaOracleProvider *ora_prv = (GdaOracleProvider *) provider;
-
- g_return_val_if_fail (GDA_IS_ORACLE_PROVIDER (ora_prv), FALSE);
+ if (cnc) {
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+ }
switch (feature) {
- case GDA_CONNECTION_FEATURE_AGGREGATES :
- case GDA_CONNECTION_FEATURE_INDEXES :
- case GDA_CONNECTION_FEATURE_PROCEDURES :
- case GDA_CONNECTION_FEATURE_SEQUENCES :
case GDA_CONNECTION_FEATURE_SQL :
- case GDA_CONNECTION_FEATURE_TRANSACTIONS :
- case GDA_CONNECTION_FEATURE_TRIGGERS :
- case GDA_CONNECTION_FEATURE_USERS :
- case GDA_CONNECTION_FEATURE_VIEWS :
- case GDA_CONNECTION_FEATURE_BLOBS :
return TRUE;
- default :
- break;
+ default:
+ return FALSE;
}
-
- return FALSE;
-}
-
-static GdaServerProviderInfo *
-gda_oracle_provider_get_info (GdaServerProvider *provider, GdaConnection *cnc)
-{
- static GdaServerProviderInfo info = {
- "Oracle",
- TRUE,
- TRUE,
- FALSE,
- TRUE,
- TRUE,
- TRUE
- };
-
- return &info;
}
-typedef struct
-{
- const gchar *name;
- const gchar *uid;
- const gchar *args;
-} gda_oracle_aggregate_t;
-
-static gda_oracle_aggregate_t aggregate_tab[] =
-{
- { "AVG", "SYS_AGG01", "NUMBER" },
- { "COLLECT", "SYS_AGG33", "-" },
- { "CORR", "SYS_AGG02", "NUMBER NUMBER" },
- { "COUNT", "SYS_AGG03", "-" },
- { "COVAR_POP", "SYS_AGG04", "NUMBER NUMBER" },
- { "COVAR_SAMP", "SYS_AGG05", "NUMBER NUMBER" },
- { "CUME_DIST", "SYS_AGG06", "NUMBER" },
- { "FIRST", "SYS_AGG35", "NUMBER" },
- { "DENSE_RANK", "SYS_AGG07", "NUMBER" },
- { "GROUP_ID", "SYS_AGG08", "" },
- { "GROUPING", "SYS_AGG09", "-" },
- { "GROUPING_ID", "SYS_AGG10", "-" },
- { "LAST", "SYS_AGG34", "NUMBER" },
- { "MAX", "SYS_AGG11", "NUMBER" },
- { "MIN", "SYS_AGG12", "NUMBER" },
- { "PERCENTILE_CONT", "SYS_AGG13", "NUMBER" },
- { "PERCENTILE_DISC", "SYS_AGG14", "NUMBER" },
- { "PERCENT_RANK", "SYS_AGG15", "NUMBER" },
- { "RANK", "SYS_AGG16", "NUMBER" },
- { "REGR_SLOPE", "SYS_AGG17", "NUMBER NUMBER" },
- { "REGR_INTERCEPT", "SYS_AGG18", "NUMBER NUMBER" },
- { "REGR_COUNT", "SYS_AGG19", "NUMBER NUMBER" },
- { "REGR_R2", "SYS_AGG20", "NUMBER NUMBER" },
- { "REGR_AVGX", "SYS_AGG21", "NUMBER NUMBER" },
- { "REGR_AVGY", "SYS_AGG22", "NUMBER NUMBER" },
- { "REGR_SXX", "SYS_AGG23", "NUMBER NUMBER" },
- { "REGR_SYY", "SYS_AGG24", "NUMBER NUMBER" },
- { "REGR_SXY", "SYS_AGG25", "NUMBER NUMBER" },
- { "STDDEV", "SYS_AGG26", "NUMBER" },
- { "STDDEV_POP", "SYS_AGG27", "NUMBER" },
- { "STDDEV_SAMP", "SYS_AGG28", "NUMBER" },
- { "SUM", "SYS_AGG29", "NUMBER" },
- { "VAR_POP", "SYS_AGG30", "NUMBER" },
- { "VAR_SAMP", "SYS_AGG31", "NUMBER" },
- { "VARIANCE", "SYS_AGG32", "NUMBER" }
-};
-static const gda_oracle_aggregate_t
-*aggregate_end = aggregate_tab + (sizeof(aggregate_tab)/sizeof(gda_oracle_aggregate_t));
-
-static GdaDataModel *
-get_oracle_aggregates (GdaConnection *cnc, GdaParameterList *params)
+/*
+ * Get data handler request
+ *
+ * This method allows one to obtain a pointer to a #GdaDataHandler object specific to @type or @dbms_type (@dbms_type
+ * must be considered only if @type is not a valid GType).
+ *
+ * A data handler allows one to convert a value between its different representations which are a human readable string,
+ * an SQL representation and a GValue.
+ *
+ * The recommended method is to create GdaDataHandler objects only when they are needed and to keep a reference to them
+ * for further usage, using the gda_server_provider_handler_declare() method.
+ *
+ * The implementation shown here does not define any specific data handler, but there should be some for at least
+ * binary and time related types.
+ */
+static GdaDataHandler *
+gda_oracle_provider_get_data_handler (GdaServerProvider *provider, GdaConnection *cnc,
+ GType type, const gchar *dbms_type)
{
- GdaOracleConnectionData *priv_data;
- GdaDataModelArray *recset;
- GdaParameter *par = NULL;
- gchar *uc_name = NULL;
- gda_oracle_aggregate_t *row;
-
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data) {
- gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
- return NULL;
+ GdaDataHandler *dh;
+ if (cnc) {
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
}
- /* create the recordset */
- recset = GDA_DATA_MODEL_ARRAY (gda_data_model_array_new
- (gda_server_provider_get_schema_nb_columns (GDA_CONNECTION_SCHEMA_AGGREGATES)));
- gda_server_provider_init_schema_model (GDA_DATA_MODEL (recset), GDA_CONNECTION_SCHEMA_AGGREGATES);
-
- if (params)
- par = gda_parameter_list_find_param (params, "name");
- if (par) {
- gchar *name;
- name = (gchar *) g_value_get_string ((GValue *) gda_parameter_get_value (par));
- uc_name = g_ascii_strup (name, -1);
- }
-
- for (row = aggregate_tab; row < aggregate_end; row++) {
- GList *list;
- GValue *tmpval;
-
- if (uc_name && strcmp (row->name, uc_name))
- continue;
-
- /* 1st the name */
- g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), row->name);
- list = g_list_append (NULL, tmpval);
- /* 2nd the unique id */
- g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), row->uid);
- list = g_list_append (list, tmpval);
- /* 3rd the owner */
- g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "SYS");
- list = g_list_append (list, tmpval);
- /* 4th the comments */
- list = g_list_append (list, gda_value_new_null ());
- /* 5th the return type */
- g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "NUMBER");
- list = g_list_append (list, tmpval);
- /* 6th the argument type */
- g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), row->args);
- list = g_list_append (list, tmpval);
- /* 7th the SQL definition */
- list = g_list_append (list, gda_value_new_null ());
-
- gda_data_model_append_values (GDA_DATA_MODEL (recset), list, NULL);
-
- g_list_foreach (list, (GFunc) gda_value_free, NULL);
- g_list_free (list);
+ if (type == G_TYPE_INVALID) {
+ TO_IMPLEMENT; /* use @dbms_type */
+ dh = NULL;
}
+ else if ((type == GDA_TYPE_BINARY) ||
+ (type == GDA_TYPE_BLOB)) {
+ TO_IMPLEMENT; /* define data handlers for these types */
+ dh = NULL;
+ }
+ else if ((type == GDA_TYPE_TIME) ||
+ (type == GDA_TYPE_TIMESTAMP) ||
+ (type == G_TYPE_DATE)) {
+ TO_IMPLEMENT; /* define data handlers for these types */
+ dh = NULL;
+ }
+ else
+ dh = gda_server_provider_get_data_handler_default (provider, cnc, type, dbms_type);
- g_free (uc_name);
- return GDA_DATA_MODEL (recset);
-}
-
-static GString *
-g_string_right_trim (GString * input)
-{
- gint i;
-
- for (i = input->len - 1; i >= 0; i -= 1)
- if (input->str[i] != ' ')
- return g_string_truncate (input, i+1);
-
- return g_string_truncate (input, 0);
+ return dh;
}
-static GHashTable *
-get_oracle_index_data (GdaConnection *cnc, const gchar *owner, const gchar *tblname)
+/*
+ * Get default DBMS type request
+ *
+ * This method returns the "preferred" DBMS type for GType
+ */
+static const gchar*
+gda_oracle_provider_get_default_dbms_type (GdaServerProvider *provider, GdaConnection *cnc, GType type)
{
- gchar *sql;
- GList *reclist;
- GdaDataModel *recset;
- GdaOracleIndexData *index_data;
- GdaParameter *param;
- GdaParameterList *query_params = gda_parameter_list_new (NULL);
- GString *references;
- gint nrows;
- GString *colname;
- GString *newcolname;
- GHashTable *h_table = g_hash_table_new (g_str_hash, g_str_equal);
- GValue *value;
- gint i;
-
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-
- sql = g_strdup ("SELECT c1.column_name column_name, "
- "con.constraint_type constraint_type, "
- "'' uniqueness, "
- "c2.table_name reference "
- "FROM all_cons_columns c1, all_cons_columns c2, all_constraints con "
- "WHERE con.constraint_name = c1.constraint_name "
- "AND con.constraint_type = 'R' "
- "AND con.constraint_type IS NOT NULL "
- "AND c1.table_name = upper (:TBLNAME) "
- "AND c1.owner = upper (:OWNER) "
- "AND con.r_constraint_name = c2.constraint_name "
- "UNION ALL "
- "SELECT c.column_name column_name, "
- "t.constraint_type constraint_type, "
- "substr (i.uniqueness, 1, 6) uniqueness, "
- "'' reference "
- "FROM all_indexes i, all_ind_columns c, all_constraints t "
- "WHERE i.table_name = upper (:TBLNAME) "
- "AND i.table_owner = upper (:OWNER) "
- "AND t.constraint_type != 'R' "
- "AND i.index_name = c.index_name "
- "AND i.index_name = t.constraint_name "
- "ORDER BY 1" );
-
- param = gda_parameter_new_string (":OWNER", owner);
- gda_parameter_list_add_param (query_params, param);
- g_object_unref (param);
-
- param = gda_parameter_new_string (":TBLNAME", tblname);
- gda_parameter_list_add_param (query_params, param);
- g_object_unref (param);
-
- reclist = process_sql_commands (NULL, cnc, sql,
- query_params, GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
- if (!reclist)
- return NULL;
-
- recset = GDA_DATA_MODEL (reclist->data);
- g_list_free (reclist);
-
- nrows = gda_data_model_get_n_rows (recset);
-
- if (nrows == 0) {
- g_object_unref(recset);
- return NULL;
+ if (cnc) {
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
}
- index_data = g_new0 (GdaOracleIndexData, 1);
- references = g_string_new ("");
-
- value = (GValue *)gda_data_model_get_value_at (recset, 0, 0);
- colname = g_string_right_trim (g_string_new (g_value_get_string (value)));
-
- for (i = 0; i < nrows; i += 1) {
- gchar *constraint_type = "";
-
- value = (GValue *)gda_data_model_get_value_at (recset, 1, i);
- if (!value)
- continue;
- if (gda_value_is_null (value))
- continue;
-
- constraint_type = g_strdup (g_value_get_string (value));
-
- if (!strcmp (constraint_type, "P"))
- index_data->primary_key = TRUE;
-
- value = (GValue *)gda_data_model_get_value_at (recset, 2, i);
- if (value)
- if (!gda_value_is_null (value))
- if (!strcmp (g_value_get_string (value), "UNIQUE"))
- index_data->unique = TRUE;
-
- if (!strcmp (constraint_type, "R")) {
- value = (GValue *)gda_data_model_get_value_at (recset, 3, i);
- if (value)
- if (!gda_value_is_null (value)) {
- if (references->len > 0)
- references = g_string_append (references, ", ");
- references = g_string_right_trim (g_string_append (references, g_value_get_string (value)));
- }
- }
+ TO_IMPLEMENT;
- if (i == nrows - 1) {
- index_data->references = g_strdup (references->str);
- g_hash_table_insert (h_table, colname->str, index_data);
- break;
- }
+ if ((type == G_TYPE_INT64) ||
+ (type == G_TYPE_INT) ||
+ (type == GDA_TYPE_SHORT) ||
+ (type == GDA_TYPE_USHORT) ||
+ (type == G_TYPE_CHAR) ||
+ (type == G_TYPE_UCHAR) ||
+ (type == G_TYPE_ULONG) ||
+ (type == G_TYPE_UINT) ||
+ (type == G_TYPE_UINT64))
+ return "integer";
- value = (GValue *)gda_data_model_get_value_at (recset, 0, i+1);
- newcolname = g_string_right_trim (g_string_new (g_value_get_string (value)));
+ if ((type == GDA_TYPE_BINARY) ||
+ (type == GDA_TYPE_BLOB))
+ return "blob";
- if (strcmp (colname->str, newcolname->str)) {
- index_data->references = g_strdup (references->str);
- g_hash_table_insert (h_table, colname->str, index_data);
+ if (type == G_TYPE_BOOLEAN)
+ return "boolean";
+
+ if ((type == G_TYPE_DATE) ||
+ (type == GDA_TYPE_GEOMETRIC_POINT) ||
+ (type == G_TYPE_OBJECT) ||
+ (type == GDA_TYPE_LIST) ||
+ (type == G_TYPE_STRING) ||
+ (type == GDA_TYPE_TIME) ||
+ (type == GDA_TYPE_TIMESTAMP) ||
+ (type == G_TYPE_INVALID) ||
+ (type == G_TYPE_GTYPE))
+ return "string";
+
+ if ((type == G_TYPE_DOUBLE) ||
+ (type == GDA_TYPE_NUMERIC) ||
+ (type == G_TYPE_FLOAT))
+ return "real";
+
+ if (type == GDA_TYPE_TIME)
+ return "time";
+ if (type == GDA_TYPE_TIMESTAMP)
+ return "timestamp";
+ if (type == G_TYPE_DATE)
+ return "date";
- index_data = g_new0 (GdaOracleIndexData, 1);
- index_data->unique = FALSE;
- index_data->primary_key = FALSE;
- index_data->references = g_strdup ("");
- references = g_string_new ("");
- colname = g_string_new (newcolname->str);
- }
- }
- g_object_unref(recset);
- return h_table;
+ return "text";
}
-
-
-static GdaDataModel *
-get_oracle_users (GdaConnection *cnc, GdaParameterList *params)
+/*
+ * Create parser request
+ *
+ * This method is responsible for creating a #GdaSqlParser object specific to the SQL dialect used
+ * by the database. See the PostgreSQL provider implementation for an example.
+ */
+static GdaSqlParser *
+gda_oracle_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc)
{
- GList *reclist;
- GdaDataModel *recset;
-
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-
- reclist = process_sql_commands (NULL, cnc, "SELECT USERNAME FROM USER_USERS",
- NULL, GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
-
- if (!reclist)
- return NULL;
-
- recset = GDA_DATA_MODEL (reclist->data);
- g_list_free (reclist);
-
- /* Set it here instead of the SQL query to allow i18n */
- if (recset)
- gda_server_provider_init_schema_model (recset, GDA_CONNECTION_SCHEMA_USERS);
-
- return recset;
+ TO_IMPLEMENT;
+ return NULL;
}
-static GdaDataModel *
-get_oracle_databases (GdaConnection *cnc, GdaParameterList *params)
+/*
+ * GdaStatement to SQL request
+ *
+ * This method renders a #GdaStatement into its SQL representation.
+ *
+ * The implementation show here simply calls gda_statement_to_sql_extended() but the rendering
+ * can be specialized to the database's SQL dialect, see the implementation of gda_statement_to_sql_extended()
+ * and SQLite's specialized rendering for more details
+ */
+static gchar *
+gda_oracle_provider_statement_to_sql (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaStatement *stmt, GdaSet *params, GdaStatementSqlFlag flags,
+ GSList **params_used, GError **error)
{
- GList *reclist;
- GdaDataModel *recset;
- gchar *sql = g_strdup ("SELECT TABLESPACE_NAME FROM USER_TABLESPACES");
-
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-
- reclist = process_sql_commands (NULL, cnc, sql, NULL,
- GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
+ g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
+ if (cnc) {
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
+ }
- g_free (sql);
+ return gda_statement_to_sql_extended (stmt, cnc, params, flags, params_used, error);
+}
- if (!reclist)
- return NULL;
+/*
+ * Statement prepare request
+ *
+ * This methods "converts" @stmt into a prepared statement. A prepared statement is a notion
+ * specific in its implementation details to the C API used here. If successfull, it must create
+ * a new #GdaOraclePStmt object and declare it to @cnc.
+ */
+static gboolean
+gda_oracle_provider_statement_prepare (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaStatement *stmt, GError **error)
+{
+ GdaOraclePStmt *ps;
+ gboolean retval = FALSE;
- recset = GDA_DATA_MODEL (reclist->data);
- g_list_free (reclist);
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+ g_return_val_if_fail (GDA_IS_STATEMENT (stmt), FALSE);
- /* Set it here instead of the SQL query to allow i18n */
- if (recset)
- gda_server_provider_init_schema_model (recset, GDA_CONNECTION_SCHEMA_DATABASES);
+ /* fetch prepares stmt if already done */
+ ps = (GdaOraclePStmt *) gda_connection_get_prepared_statement (cnc, stmt);
+ if (ps)
+ return TRUE;
- return recset;
+ /* render as SQL understood by the provider */
+ GdaSet *params = NULL;
+ gchar *sql;
+ GSList *used_params = NULL;
+ if (! gda_statement_get_parameters (stmt, ¶ms, error))
+ return FALSE;
+ sql = gda_oracle_provider_statement_to_sql (provider, cnc, stmt, params, GDA_STATEMENT_SQL_PARAMS_AS_UQMARK,
+ &used_params, error);
+ if (!sql)
+ goto out;
+
+ /* prepare @stmt using the C API, creates @ps */
+ TO_IMPLEMENT;
+
+ /* make a list of the parameter names used in the statement */
+ GSList *param_ids = NULL;
+ if (used_params) {
+ GSList *list;
+ for (list = used_params; list; list = list->next) {
+ const gchar *cid;
+ cid = gda_holder_get_id (GDA_HOLDER (list->data));
+ if (cid) {
+ param_ids = g_slist_append (param_ids, g_strdup (cid));
+ /*g_print ("PREPARATION: param ID: %s\n", cid);*/
+ }
+ else {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_PREPARE_STMT_ERROR,
+ "%s", _("Unnamed parameter is not allowed in prepared statements"));
+ g_slist_foreach (param_ids, (GFunc) g_free, NULL);
+ g_slist_free (param_ids);
+ goto out;
+ }
+ }
+ }
+
+ /* create a prepared statement object */
+ /*ps = gda_oracle_pstmt_new (...);*/
+ gda_pstmt_set_gda_statement (_GDA_PSTMT (ps), stmt);
+ _GDA_PSTMT (ps)->param_ids = param_ids;
+ _GDA_PSTMT (ps)->sql = sql;
+
+ gda_connection_add_prepared_statement (cnc, stmt, (GdaPStmt *) ps);
+ g_object_unref (ps);
+
+ retval = TRUE;
+
+ out:
+ if (used_params)
+ g_slist_free (used_params);
+ if (params)
+ g_object_unref (params);
+ return retval;
}
-static GdaDataModel *
-get_oracle_tables (GdaConnection *cnc, GdaParameterList *params)
+/*
+ * Execute statement request
+ *
+ * Executes a statement. This method should do the following:
+ * - try to prepare the statement if not yet done
+ * - optionnally reset the prepared statement
+ * - bind the variables's values (which are in @params)
+ * - add a connection event to log the execution
+ * - execute the prepared statement
+ *
+ * If @stmt is an INSERT statement and @last_inserted_row is not NULL then additional actions must be taken to return the
+ * actual inserted row
+ */
+static GObject *
+gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnection *cnc,
+ GdaStatement *stmt, GdaSet *params,
+ GdaStatementModelUsage model_usage,
+ GType *col_types, GdaSet **last_inserted_row,
+ guint *task_id,
+ GdaServerProviderExecCallback async_cb, gpointer cb_data, GError **error)
{
- GdaDataModel *recset;
- GdaParameter *par = NULL;
- gchar *upc_namespace = NULL;
- GList *reclist;
- gchar *sql;
- GdaOracleConnectionData *priv_data;
+ GdaOraclePStmt *ps;
+ OracleConnectionData *cdata;
+ gboolean allow_noparam;
+ gboolean empty_rs = FALSE; /* TRUE when @allow_noparam is TRUE and there is a problem with @params
+ => resulting data model will be empty (0 row) */
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data)
- return FALSE;
-
- if (params)
- par = gda_parameter_list_find_param (params, "namespace");
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
+ g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
- if (par) {
- const gchar *namespace;
- namespace = g_value_get_string ((GValue *) gda_parameter_get_value (par));
- upc_namespace = g_ascii_strup (namespace, -1);
+ /* If asynchronous connection opening is not supported, then exit now */
+ if (async_cb) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_METHOD_NON_IMPLEMENTED_ERROR,
+ "%s", _("Provider does not support asynchronous statement execution"));
+ return NULL;
}
- else
- upc_namespace = g_ascii_strup (priv_data->schema, -1);
- sql = g_strdup_printf ("SELECT t.table_name, t.owner, c.comments, NULL FROM ALL_TABLES t join ALL_TAB_COMMENTS c on (t.table_name=c.table_name AND t.owner=c.owner) WHERE t.OWNER='%s' ORDER BY TABLE_NAME",
- upc_namespace);
- g_free (upc_namespace);
-
- reclist = process_sql_commands (NULL, cnc, sql, NULL,
- GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
- g_free (sql);
-
- if (!reclist)
- return NULL;
+
+ allow_noparam = (model_usage & GDA_STATEMENT_MODEL_ALLOW_NOPARAM) &&
+ (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_SELECT);
- recset = GDA_DATA_MODEL (reclist->data);
- g_list_free (reclist);
+ if (last_inserted_row)
+ *last_inserted_row = NULL;
- /* Set it here instead of the SQL query to allow i18n */
- if (recset)
- gda_server_provider_init_schema_model (recset, GDA_CONNECTION_SCHEMA_TABLES);
+ /* Get private data */
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
+ return FALSE;
- return recset;
-}
-static GdaDataModel *
-get_oracle_views (GdaConnection *cnc, GdaParameterList *params)
-{
- GdaDataModel *recset;
- GdaParameter *par = NULL;
- gchar *upc_namespace = NULL;
- GList *reclist;
- gchar *sql;
- GdaOracleConnectionData *priv_data;
- GArray *col_size_array = NULL;
+ /* get/create new prepared statement */
+ ps = (GdaOraclePStmt *) gda_connection_get_prepared_statement (cnc, stmt);
+ if (!ps) {
+ if (!gda_oracle_provider_statement_prepare (provider, cnc, stmt, NULL)) {
+ /* this case can appear for example if some variables are used in places
+ * where the C API cannot allow them (for example if the variable is the table name
+ * in a SELECT statement). The action here is to get the actual SQL code for @stmt,
+ * and use that SQL instead of @stmt to create another GdaOraclePStmt object.
+ *
+ * Don't call gda_connection_add_prepared_statement() with this new prepared statement
+ * as it will be destroyed once used.
+ */
+ TO_IMPLEMENT;
+ return NULL;
+ }
+ else {
+ ps = (GdaOraclePStmt *) gda_connection_get_prepared_statement (cnc, stmt);
+ g_object_ref (ps);
+ }
+ }
+ else
+ g_object_ref (ps);
+ g_assert (ps);
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data)
- return FALSE;
+ /* optionnally reset the prepared statement if required by the API */
+ TO_IMPLEMENT;
- if (params)
- par = gda_parameter_list_find_param (params, "namespace");
+ /* bind statement's parameters */
+ GSList *list;
+ GdaConnectionEvent *event = NULL;
+ int i;
+ for (i = 1, list = _GDA_PSTMT (ps)->param_ids; list; list = list->next, i++) {
+ const gchar *pname = (gchar *) list->data;
+ GdaHolder *h;
+
+ /* find requested parameter */
+ if (!params) {
+ event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+ gda_connection_event_set_description (event, _("Missing parameter(s) to execute query"));
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR,
+ "%s", _("Missing parameter(s) to execute query"));
+ break;
+ }
- if (par) {
- const gchar *namespace;
- namespace = g_value_get_string ((GValue *) gda_parameter_get_value (par));
- upc_namespace = g_ascii_strup (namespace, -1);
- }
- else
- upc_namespace = g_ascii_strup (priv_data->schema, -1);
-
- /* get the max size of the "text" column */
- sql = g_strdup_printf ("SELECT max (v.text_length) FROM all_views v WHERE v.owner= '%s'",
- upc_namespace);
- reclist = process_sql_commands (NULL, cnc, sql, NULL, GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
- g_free (sql);
-
- if (reclist) {
- GdaDataModel *recset = (GdaDataModel *) reclist->data;
- if (GDA_IS_DATA_MODEL (recset)) {
- if (gda_data_model_get_n_rows (recset) == 1) {
- const GValue *val;
- val = gda_data_model_get_value_at (recset, 0, 0);
- if (val) {
- const GdaNumeric *num;
- ub2 size;
-
- num = gda_value_get_numeric (val);
- col_size_array = g_array_sized_new (FALSE, TRUE, sizeof (ub2), 4);
- size = atoi (num->number);
- g_array_set_size (col_size_array, 4);
- g_array_insert_vals (col_size_array, 3, &size, 1);
- }
+ h = gda_set_get_holder (params, pname);
+ if (!h) {
+ gchar *tmp = gda_alphanum_to_text (g_strdup (pname + 1));
+ if (tmp) {
+ h = gda_set_get_holder (params, tmp);
+ g_free (tmp);
}
}
- g_object_unref (recset);
- g_list_free (reclist);
- }
-
- /* real SQL */
- sql = g_strdup_printf ("SELECT v.view_name, v.owner, NULL, v.text FROM ALL_VIEWS v WHERE v.OWNER='%s' ORDER BY VIEW_NAME",
- upc_namespace);
- g_free (upc_namespace);
+ if (!h) {
+ if (! allow_noparam) {
+ gchar *str;
+ str = g_strdup_printf (_("Missing parameter '%s' to execute query"), pname);
+ event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+ gda_connection_event_set_description (event, str);
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, "%s", str);
+ g_free (str);
+ break;
+ }
+ else {
+ /* bind param to NULL */
+ TO_IMPLEMENT;
+ empty_rs = TRUE;
+ continue;
+ }
- reclist = process_sql_commands (NULL, cnc, sql, NULL,
- GDA_COMMAND_OPTION_STOP_ON_ERRORS, col_size_array);
- if (col_size_array)
- g_array_free (col_size_array, TRUE);
- g_free (sql);
+ }
+ if (!gda_holder_is_valid (h)) {
+ if (! allow_noparam) {
+ gchar *str;
+ str = g_strdup_printf (_("Parameter '%s' is invalid"), pname);
+ event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+ gda_connection_event_set_description (event, str);
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, "%s", str);
+ g_free (str);
+ break;
+ }
+ else {
+ /* bind param to NULL */
+ TO_IMPLEMENT;
+ empty_rs = TRUE;
+ continue;
+ }
+ }
- if (!reclist)
+ /* actual binding using the C API, for parameter at position @i */
+ const GValue *value = gda_holder_get_value (h);
+ TO_IMPLEMENT;
+ }
+
+ if (event) {
+ gda_connection_add_event (cnc, event);
+ g_object_unref (ps);
return NULL;
+ }
- recset = GDA_DATA_MODEL (reclist->data);
- g_list_free (reclist);
+ /* add a connection event for the execution */
+ event = gda_connection_event_new (GDA_CONNECTION_EVENT_COMMAND);
+ gda_connection_event_set_description (event, _GDA_PSTMT (ps)->sql);
+ gda_connection_add_event (cnc, event);
+
+ if (empty_rs) {
+ /* There are some missing parameters, so the SQL can't be executed but we still want
+ * to execute something to get the columns correctly. A possibility is to actually
+ * execute another SQL which is the code shown here.
+ *
+ * To adapt depending on the C API and its features */
+ GdaStatement *estmt;
+ gchar *esql;
+ estmt = gda_select_alter_select_for_empty (stmt, error);
+ if (!estmt) {
+ g_object_unref (ps);
+ return NULL;
+ }
+ esql = gda_statement_to_sql (estmt, NULL, error);
+ g_object_unref (estmt);
+ if (!esql) {
+ g_object_unref (ps);
+ return NULL;
+ }
- /* Set it here instead of the SQL query to allow i18n */
- if (recset)
- gda_server_provider_init_schema_model (recset, GDA_CONNECTION_SCHEMA_VIEWS);
+ /* Execute the 'esql' SQL code */
+ g_free (esql);
- return recset;
+ TO_IMPLEMENT;
+ }
+ else {
+ /* Execute the _GDA_PSTMT (ps)->sql SQL code */
+ TO_IMPLEMENT;
+ }
+
+ /* execute prepared statement using C API depending on its kind */
+ if (! g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "SELECT", 6) ||
+ ! g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "EXPLAIN", 7)) {
+ GObject *data_model;
+ GdaDataModelAccessFlags flags;
+
+ if (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS)
+ flags = GDA_DATA_MODEL_ACCESS_RANDOM;
+ else
+ flags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;
+
+ data_model = (GObject *) gda_oracle_recordset_new (cnc, ps, params, flags, col_types);
+ gda_connection_internal_statement_executed (cnc, stmt, params, NULL); /* required: help @cnc keep some stats */
+ g_object_unref (ps);
+ return data_model;
+ }
+ else {
+ GdaSet *set = NULL;
+
+ TO_IMPLEMENT;
+ /* Create a #GdaSet containing "IMPACTED_ROWS" */
+ /* Create GdaConnectionEvent notice with the type of command and impacted rows */
+
+ gda_connection_internal_statement_executed (cnc, stmt, params, event); /* required: help @cnc keep some stats */
+ g_object_unref (ps);
+ return (GObject*) set;
+ }
}
/*
- * get_oracle_objects
- *
- * This function gets the objects of the given schema type from the
- * database. This is done by quering against the USER_OBJECTS
- * table which the OBJECT_TYPE parameter set to the appropriate
- * value. This makes use of parameter binding, so it is a good
- * test to see if that is working for strings
- *
- * We effectively ignore the GdaParameterList we are given
- * because I don't want to rely on it being empty, and I can't
- * see any use for any user passed parameters at this point.
+ * starts a distributed transaction: put the XA transaction in the ACTIVE state
*/
-static GdaDataModel *
-get_oracle_objects (GdaConnection *cnc, GdaParameterList *params, GdaConnectionSchema schema, gint nargs, const gchar *title)
+static gboolean
+gda_oracle_provider_xa_start (GdaServerProvider *provider, GdaConnection *cnc,
+ const GdaXaTransactionId *xid, GError **error)
{
- GList *reclist;
- GdaDataModel *recset;
- gint cnt;
- GdaParameterList *query_params = gda_parameter_list_new (NULL);
- GdaParameter *param;
- GString *sql;
+ OracleConnectionData *cdata;
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+ g_return_val_if_fail (xid, FALSE);
- sql = g_string_new ("SELECT OBJECT_NAME");
- for (cnt = 1; cnt < nargs; cnt++)
- sql = g_string_append (sql, ", NULL");
-
- sql = g_string_append (sql, " FROM USER_OBJECTS WHERE OBJECT_TYPE=:OBJ_TYPE");
-
- /* add the object type parameter */
- switch (schema) {
- case GDA_CONNECTION_SCHEMA_INDEXES:
- param = gda_parameter_new_string (":OBJ_TYPE", "INDEX");
- gda_parameter_list_add_param (query_params, param);
- g_object_unref (param);
- break;
- case GDA_CONNECTION_SCHEMA_PROCEDURES:
- param = gda_parameter_new_string (":OBJ_TYPE", "PROCEDURE");
- gda_parameter_list_add_param (query_params, param);
- g_object_unref (param);
- break;
- case GDA_CONNECTION_SCHEMA_SEQUENCES:
- param = gda_parameter_new_string (":OBJ_TYPE", "SEQUENCE");
- gda_parameter_list_add_param (query_params, param);
- g_object_unref (param);
- break;
- case GDA_CONNECTION_SCHEMA_TRIGGERS:
- param = gda_parameter_new_string (":OBJ_TYPE", "TRIGGER");
- gda_parameter_list_add_param (query_params, param);
- g_object_unref (param);
- break;
- case GDA_CONNECTION_SCHEMA_VIEWS:
- param = gda_parameter_new_string (":OBJ_TYPE", "VIEW");
- gda_parameter_list_add_param (query_params, param);
- g_object_unref (param);
- break;
- default:
- return NULL;
- }
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
+ return FALSE;
- reclist = process_sql_commands (NULL, cnc, sql->str, query_params,
- GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
+ TO_IMPLEMENT;
+ return FALSE;
+}
- g_object_unref (query_params);
- g_string_free (sql, TRUE);
+/*
+ * put the XA transaction in the IDLE state: the connection won't accept any more modifications.
+ * This state is required by some database providers before actually going to the PREPARED state
+ */
+static gboolean
+gda_oracle_provider_xa_end (GdaServerProvider *provider, GdaConnection *cnc,
+ const GdaXaTransactionId *xid, GError **error)
+{
+ OracleConnectionData *cdata;
- if (!reclist)
- return NULL;
- recset = GDA_DATA_MODEL (reclist->data);
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+ g_return_val_if_fail (xid, FALSE);
- /* Set it here instead of the SQL query to allow i18n */
- if (recset)
- gda_server_provider_init_schema_model (recset, schema);
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
+ return FALSE;
- g_list_free (reclist);
-
- return recset;
+ TO_IMPLEMENT;
+ return FALSE;
}
-typedef struct
+/*
+ * prepares the distributed transaction: put the XA transaction in the PREPARED state
+ */
+static gboolean
+gda_oracle_provider_xa_prepare (GdaServerProvider *provider, GdaConnection *cnc,
+ const GdaXaTransactionId *xid, GError **error)
{
- const gchar *name;
- GType type;
- const gchar *synonyms;
- const gchar *comments;
-} ora_native_type;
+ OracleConnectionData *cdata;
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+ g_return_val_if_fail (xid, FALSE);
-static GdaDataModel *
-get_oracle_types (GdaConnection *cnc, GdaParameterList *params)
-{
- GdaDataModelArray *recset;
- ora_native_type *otp;
- GList *value_list;
- GValue *tmpval;
-
- ora_native_type ora_type_tab[] = {
- {"BFILE", GDA_TYPE_BLOB, NULL, "Pointer to binary file on disk"},
- {"BLOB", GDA_TYPE_BLOB, NULL, "Binary Large Object"},
- {"CHAR", G_TYPE_STRING, "CHARACTER", "Fixed length character data of length size bytes. This should be used for fixed length data. Such as codes A100, B102..."},
- {"NCHAR", G_TYPE_STRING, NULL, "Fixed length national character set data of length size bytes. This should be used for fixed length data. Such as codes A100, B102..."},
- {"CLOB", G_TYPE_STRING, NULL, "Character Large Object"},
- {"NCLOB", GDA_TYPE_BLOB, NULL, "National Character Large Object"},
- {"DATE", G_TYPE_DATE, NULL, "Valid date range"},
- {"NUMBER", GDA_TYPE_NUMERIC, "INTEGER,SMALLINT,INT,DEC,DECIMAL,NUMERIC,DOUBLE PRECISION,FLOAT,REAL", "Number having precision p and scale s."},
- {"LONG", G_TYPE_STRING, NULL, "Character data of variable length (A bigger version the VARCHAR2 datatype)"},
- {"LONG RAW", GDA_TYPE_BLOB, NULL, "Raw binary data of variable length. (not intrepreted by PL/SQL)"},
- {"RAW", GDA_TYPE_BLOB, NULL, "Raw binary data of length size bytes (size must be specified)"},
- {"ROWID", G_TYPE_STRING, NULL, "Hexadecimal string representing the unique address of a row in its table (primarily for values returned by the ROWID pseudocolumn.)"},
- {"UROWID", G_TYPE_STRING, NULL, "Hex string representing the logical address of a row of an index-organized table"},
- {"TIMESTAMP", GDA_TYPE_TIMESTAMP, NULL, "the number of digits in the fractional part of the SECOND datetime field"},
- {"VARCHAR2", G_TYPE_STRING, "VARCHAR,STRING", "Variable length character string having maximum length size bytes (size must be specified)"},
- {"NVARCHAR2", G_TYPE_STRING, NULL, "Variable length national character set string having maximum length size bytes (size must be specified)"},
- {"XMLType", G_TYPE_STRING, NULL, "XML data)"},
- };
- ora_native_type *ora_type_end = ora_type_tab+sizeof(ora_type_tab)/sizeof(ora_native_type);
-
- /* create the recordset */
- recset = GDA_DATA_MODEL_ARRAY (gda_data_model_array_new
- (gda_server_provider_get_schema_nb_columns (GDA_CONNECTION_SCHEMA_TYPES)));
- gda_server_provider_init_schema_model (GDA_DATA_MODEL (recset), GDA_CONNECTION_SCHEMA_TYPES);
-
- /* fill the recordset */
- for (otp = ora_type_tab; otp < ora_type_end; otp++) {
- value_list = NULL;
-
- g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), otp->name);
- value_list = g_list_append (value_list, tmpval);
-
- g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), "SYS");
- value_list = g_list_append (value_list, tmpval);
-
- g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), otp->comments);
- value_list = g_list_append (value_list, tmpval);
-
- g_value_set_ulong (tmpval = gda_value_new (G_TYPE_ULONG), otp->type);
- value_list = g_list_append (value_list, tmpval);
-
- g_value_set_string (tmpval = gda_value_new (G_TYPE_STRING), otp->synonyms);
- value_list = g_list_append (value_list, tmpval);
-
- gda_data_model_append_values (GDA_DATA_MODEL (recset), value_list, NULL);
- g_list_foreach (value_list, (GFunc) gda_value_free, NULL);
- g_list_free (value_list);
- }
- return GDA_DATA_MODEL (recset);
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
+ return FALSE;
+
+ TO_IMPLEMENT;
+ return FALSE;
}
-static GdaDataModel *
-get_oracle_fields_metadata (GdaConnection *cnc, GdaParameterList *params)
+/*
+ * commits the distributed transaction: actually write the prepared data to the database and
+ * terminates the XA transaction
+ */
+static gboolean
+gda_oracle_provider_xa_commit (GdaServerProvider *provider, GdaConnection *cnc,
+ const GdaXaTransactionId *xid, GError **error)
{
- GdaParameter *par;
- const gchar *tblname;
- gchar *upc_tblname;
- GList *reclist;
- gchar *sql;
- GdaOracleConnectionData *priv_data;
- GArray *col_size_array = NULL;
+ OracleConnectionData *cdata;
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
- g_return_val_if_fail (params, NULL);
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+ g_return_val_if_fail (xid, FALSE);
- /* look up the table name to get the fully qualified name. */
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data)
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
return FALSE;
- par = gda_parameter_list_find_param (params, "name");
- g_return_val_if_fail (par, NULL);
-
- tblname = g_value_get_string ((GValue *) gda_parameter_get_value (par));
- g_return_val_if_fail (tblname, NULL);
- upc_tblname = g_ascii_strup (tblname, -1);
-
- /* get the max size of the "default value" column */
- sql = g_strdup_printf ("SELECT max (t.default_length) FROM all_tab_columns t WHERE t.owner= '%s' and t.table_name= '%s'", priv_data->schema, upc_tblname);
- reclist = process_sql_commands (NULL, cnc, sql, NULL, GDA_COMMAND_OPTION_STOP_ON_ERRORS, NULL);
- g_free (sql);
-
- if (reclist) {
- GdaDataModel *recset = (GdaDataModel *) reclist->data;
- if (GDA_IS_DATA_MODEL (recset)) {
- if (gda_data_model_get_n_rows (recset) == 1) {
- const GValue *val;
- val = gda_data_model_get_value_at (recset, 0, 0);
- if (val) {
- const GdaNumeric *num;
- ub2 size;
-
- num = gda_value_get_numeric (val);
- col_size_array = g_array_sized_new (FALSE, TRUE, sizeof (ub2), 9);
- size = atoi (num->number);
- g_array_set_size (col_size_array, 9);
- g_array_insert_vals (col_size_array, 8, &size, 1);
- }
- }
- }
- g_object_unref (recset);
- g_list_free (reclist);
- }
-
- /* real SQL */
- sql = g_strdup_printf ("select t.column_name \"Column\", t.data_type \"DataType\", CASE t.char_used WHEN 'B' THEN t.data_length ELSE t.data_precision END \"Size\", t.data_scale, CASE t.nullable WHEN 'N' THEN 1 ELSE 0 END \"NotNull\", CASE WHEN c1.column_name IS NOT NULL THEN 1 ELSE 0 END \"pkey\", CASE WHEN c2.column_name IS NOT NULL OR c1.column_name IS NOT NULL THEN 1 ELSE 0 END \"uindex\", NULL, t.data_default, NULL FROM all_tab_columns t left join (SELECT i.column_name, ac.owner FROM all_constraints ac join all_ind_columns i ON (i.index_name=ac.index_name AND i.table_name=ac.table_name) where ac.constraint_type= 'P' AND ac.table_name= '%s' ) c1 on (c1.column_name=t.column_name AND c1.owner=t.owner) left join (SELECT i.column_name, ac.owner FROM all_constraints ac join all_ind_columns i ON (i.index_name=ac.index_name AND i.table_name=ac.table_name) where ac.constraint_type= 'U' AND ac.table_name= '%s' ) c2 on (c2.column_name=t.column_name AND c2.owner=t.owner) where t.ta
ble_name= '%s' AND t.owner='%s' order by t.column_id",
- upc_tblname, upc_tblname, upc_tblname, priv_data->schema);
-
- g_free(upc_tblname);
- reclist = process_sql_commands (NULL, cnc, sql, NULL,
- GDA_COMMAND_OPTION_STOP_ON_ERRORS, col_size_array);
- if (col_size_array)
- g_array_free (col_size_array, TRUE);
- g_free (sql);
-
- if (!reclist)
- return NULL;
- else {
- GdaDataModelArray *recset;
- GdaDataModel *tmprecset;
- GError *error = NULL;
-
- tmprecset = GDA_DATA_MODEL (reclist->data);
-
- recset = GDA_DATA_MODEL_ARRAY (gda_data_model_array_new
- (gda_server_provider_get_schema_nb_columns (GDA_CONNECTION_SCHEMA_FIELDS)));
- gda_server_provider_init_schema_model (GDA_DATA_MODEL (recset), GDA_CONNECTION_SCHEMA_FIELDS);
- if (!gda_data_model_import_from_model (GDA_DATA_MODEL (recset), tmprecset, FALSE, NULL, &error)) {
- gda_data_model_dump (tmprecset, stdout);
- g_warning (_("Can't convert model for fields schema: %s"),
- error && error->message ? error->message : _("No detail"));
- g_error_free (error);
- g_object_unref (recset);
- recset = NULL;
- }
-
- g_object_unref (tmprecset);
- g_list_free (reclist);
- return GDA_DATA_MODEL (recset);
- }
+ TO_IMPLEMENT;
+ return FALSE;
}
-
-/* get_schema handler for the GdaOracleProvider class */
-static GdaDataModel *
-gda_oracle_provider_get_schema (GdaServerProvider *provider,
- GdaConnection *cnc,
- GdaConnectionSchema schema,
- GdaParameterList *params)
+/*
+ * Rolls back an XA transaction, possible only if in the ACTIVE, IDLE or PREPARED state
+ */
+static gboolean
+gda_oracle_provider_xa_rollback (GdaServerProvider *provider, GdaConnection *cnc,
+ const GdaXaTransactionId *xid, GError **error)
{
- GdaDataModel *recset;
+ OracleConnectionData *cdata;
- if (cnc)
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
- else
- return NULL;
-
- switch (schema) {
- case GDA_CONNECTION_SCHEMA_AGGREGATES :
- recset = get_oracle_aggregates (cnc, params);
- break;
- case GDA_CONNECTION_SCHEMA_FIELDS :
- recset = get_oracle_fields_metadata (cnc, params);
- break;
- case GDA_CONNECTION_SCHEMA_TYPES :
- recset = get_oracle_types (cnc, params);
- break;
- case GDA_CONNECTION_SCHEMA_USERS :
- recset = get_oracle_users (cnc, params);
- break;
- case GDA_CONNECTION_SCHEMA_DATABASES :
- recset = get_oracle_databases (cnc, params);
- break;
- case GDA_CONNECTION_SCHEMA_INDEXES :
- recset = get_oracle_objects (cnc, params, schema, 1, _("Indexes"));
- break;
- case GDA_CONNECTION_SCHEMA_PROCEDURES :
- recset = get_oracle_objects (cnc, params, schema, 8, _("Procedures"));
- break;
- case GDA_CONNECTION_SCHEMA_SEQUENCES :
- recset = get_oracle_objects (cnc, params, schema, 4, _("Sequences"));
- break;
- case GDA_CONNECTION_SCHEMA_TABLES :
- recset = get_oracle_tables (cnc, params);
- break;
- case GDA_CONNECTION_SCHEMA_TRIGGERS :
- recset = get_oracle_objects (cnc, params, schema, 1, _("Triggers"));
- break;
- case GDA_CONNECTION_SCHEMA_VIEWS :
- recset = get_oracle_views (cnc, params);
- break;
- default :
- recset = NULL;
- }
- return recset;
-}
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
+ g_return_val_if_fail (xid, FALSE);
-/*
- Local Variables:
- mode:C
- c-basic-offset: 8
- End:
-*/
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
+ return FALSE;
-static const gchar*
-gda_oracle_provider_get_default_dbms_type (GdaServerProvider *provider,
- GdaConnection *cnc,
- GType type)
-{
- g_return_val_if_fail (GDA_IS_SERVER_PROVIDER (provider), NULL);
-
- if (type == G_TYPE_INT64)
- return "NUMBER(38)";
- if (type == G_TYPE_UINT64)
- return "NUMBER(38)";
- if (type == GDA_TYPE_BLOB)
- return "BLOB";
- if (type == G_TYPE_BOOLEAN)
- return "NUMBER(1)";
- if (type == G_TYPE_DATE)
- return "DATE";
- if (type == G_TYPE_DOUBLE)
- return "NUMBER";
- if (type == GDA_TYPE_GEOMETRIC_POINT)
- return "SDO_GEOMETRY";
- if (type == G_TYPE_OBJECT)
- return "CLOB";
- if (type == G_TYPE_INT)
- return "NUMBER(38)";
- if (type == GDA_TYPE_LIST)
- return "CLOB";
- if (type == GDA_TYPE_NUMERIC)
- return "NUMBER";
- if (type == G_TYPE_FLOAT)
- return "NUMBER";
- if (type == GDA_TYPE_SHORT)
- return "NUMBER(38)";
- if (type == GDA_TYPE_USHORT)
- return "NUMBER(38)";
- if (type == G_TYPE_STRING)
- return "VARCHAR2";
- if (type == GDA_TYPE_TIME)
- return "DATE";
- if (type == GDA_TYPE_TIMESTAMP)
- return "TIMESTAMP";
- if (type == G_TYPE_CHAR)
- return "CHAR";
- if (type == G_TYPE_UCHAR)
- return "CHAR";
- if (type == G_TYPE_ULONG)
- return "NUMBER(38)";
- if (type == G_TYPE_UINT)
- return "NUMBER(38)";
- if (type == G_TYPE_INVALID)
- return "CLOB";
-
- return "CLOB";
+ TO_IMPLEMENT;
+ return FALSE;
}
-static GdaDataHandler *
-gda_oracle_provider_get_data_handler (GdaServerProvider *provider,
- GdaConnection *cnc,
- GType type,
- const gchar *dbms_type)
+/*
+ * Lists all XA transactions that are in the PREPARED state
+ *
+ * Returns: a list of GdaXaTransactionId structures, which will be freed by the caller
+ */
+static GList *
+gda_oracle_provider_xa_recover (GdaServerProvider *provider, GdaConnection *cnc,
+ GError **error)
{
- GdaDataHandler *dh = NULL;
+ OracleConnectionData *cdata;
- /* REM: bin and blob types can't be translated to and from SQL in oracle, you must use
- * provider's specific virtual methods */
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+ g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
- g_return_val_if_fail (GDA_IS_SERVER_PROVIDER (provider), FALSE);
- if (cnc)
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
-
- if ((type == G_TYPE_INT64) ||
- (type == G_TYPE_UINT64) ||
- (type == G_TYPE_DOUBLE) ||
- (type == G_TYPE_INT) ||
- (type == GDA_TYPE_NUMERIC) ||
- (type == G_TYPE_FLOAT) ||
- (type == GDA_TYPE_SHORT) ||
- (type == GDA_TYPE_USHORT) ||
- (type == G_TYPE_CHAR) ||
- (type == G_TYPE_UCHAR) ||
- (type == G_TYPE_UINT)) {
- dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
- if (!dh) {
- dh = gda_handler_numerical_new ();
- gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_INT64, NULL);
- gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_UINT64, NULL);
- gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_DOUBLE, NULL);
- gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_INT, NULL);
- gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_NUMERIC, NULL);
- gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_FLOAT, NULL);
- gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_SHORT, NULL);
- gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_USHORT, NULL);
- gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_CHAR, NULL);
- gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_UCHAR, NULL);
- gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_UINT, NULL);
- g_object_unref (dh);
- }
- }
- else if (type == G_TYPE_BOOLEAN) {
- dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
- if (!dh) {
- dh = gda_handler_boolean_new ();
- gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_BOOLEAN, NULL);
- g_object_unref (dh);
- }
- }
- else if ((type == G_TYPE_DATE) ||
- (type == GDA_TYPE_TIME) ||
- (type == GDA_TYPE_TIMESTAMP)) {
- dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
- if (!dh) {
- dh = gda_handler_time_new ();
- gda_handler_time_set_sql_spec (GDA_HANDLER_TIME (dh),
- G_DATE_MONTH, G_DATE_DAY,G_DATE_YEAR,
- '/', FALSE);
- gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_DATE, NULL);
- gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_TIME, NULL);
- gda_server_provider_handler_declare (provider, dh, NULL, GDA_TYPE_TIMESTAMP, NULL);
- g_object_unref (dh);
- }
- }
- else if (type == G_TYPE_STRING) {
- dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
- if (!dh) {
- dh = gda_handler_string_new ();
- gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_STRING, NULL);
- g_object_unref (dh);
- }
- }
- else if (type == G_TYPE_ULONG) {
- dh = gda_server_provider_handler_find (provider, NULL, type, NULL);
- if (!dh) {
- dh = gda_handler_type_new ();
- gda_server_provider_handler_declare (provider, dh, NULL, G_TYPE_ULONG, NULL);
- g_object_unref (dh);
- }
- }
- else {
- /* special case: we take into account the dbms_type argument */
- if (dbms_type)
- TO_IMPLEMENT;
- }
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
+ return NULL;
- return dh;
+ TO_IMPLEMENT;
+ return NULL;
}
-static GdaSqlParser *
-gda_oracle_provider_create_parser (GdaServerProvider *provider, GdaConnection *cnc)
+/*
+ * Free connection's specific data
+ */
+static void
+gda_oracle_free_cnc_data (OracleConnectionData *cdata)
{
- g_return_val_if_fail (GDA_IS_SERVER_PROVIDER (provider), NULL);
- return (GdaSqlParser*) g_object_new (GDA_TYPE_SQL_PARSER, "tokenizer-flavour",
- GDA_SQL_PARSER_FLAVOUR_ORACLE, NULL);
+ if (!cdata)
+ return;
+
+ TO_IMPLEMENT;
+ g_free (cdata);
}
diff --git a/providers/oracle/gda-oracle-provider.h b/providers/oracle/gda-oracle-provider.h
index c795b2f..5e0338c 100644
--- a/providers/oracle/gda-oracle-provider.h
+++ b/providers/oracle/gda-oracle-provider.h
@@ -1,30 +1,29 @@
-/* GNOME DB Oracle Provider
- * Copyright (C) 2000 - 2007 The GNOME Foundation
+/* GDA oracle provider
+ * Copyright (C) 2008 The GNOME Foundation.
*
* AUTHORS:
- * Rodrigo Moya <rodrigo gnome-db org>
- * Tim Coleman <tim timcoleman com>
+ * TO_ADD: your name and email
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
*
- * This library is distributed in the hope that it will be useful,
+ * This Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
*/
#ifndef __GDA_ORACLE_PROVIDER_H__
#define __GDA_ORACLE_PROVIDER_H__
#include <libgda/gda-server-provider.h>
-#include <oci.h>
#define GDA_TYPE_ORACLE_PROVIDER (gda_oracle_provider_get_type())
#define GDA_ORACLE_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_ORACLE_PROVIDER, GdaOracleProvider))
@@ -36,39 +35,17 @@ typedef struct _GdaOracleProvider GdaOracleProvider;
typedef struct _GdaOracleProviderClass GdaOracleProviderClass;
struct _GdaOracleProvider {
- GdaServerProvider provider;
+ GdaServerProvider provider;
};
struct _GdaOracleProviderClass {
GdaServerProviderClass parent_class;
};
-/*
- * Connection data
- */
-typedef struct {
- OCIEnv *henv;
- OCIError *herr;
- OCIServer *hserver;
- OCISvcCtx *hservice;
- OCISession *hsession;
- gchar *schema; /* the same as the username which opened the connection */
-} GdaOracleConnectionData;
-
-
G_BEGIN_DECLS
-GType gda_oracle_provider_get_type (void) G_GNUC_CONST;
-GdaServerProvider *gda_oracle_provider_new (void);
-
+GType gda_oracle_provider_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif
-
-/*
- Local Variables:
- mode:C
- c-basic-offset: 8
- End:
-*/
diff --git a/providers/oracle/gda-oracle-pstmt.c b/providers/oracle/gda-oracle-pstmt.c
new file mode 100644
index 0000000..6056e43
--- /dev/null
+++ b/providers/oracle/gda-oracle-pstmt.c
@@ -0,0 +1,96 @@
+/* GDA Oracle provider
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ * TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include "gda-oracle-pstmt.h"
+
+static void gda_oracle_pstmt_class_init (GdaOraclePStmtClass *klass);
+static void gda_oracle_pstmt_init (GdaOraclePStmt *pstmt, GdaOraclePStmtClass *klass);
+static void gda_oracle_pstmt_finalize (GObject *object);
+
+static GObjectClass *parent_class = NULL;
+
+/**
+ * gda_oracle_pstmt_get_type
+ *
+ * Returns: the #GType of GdaOraclePStmt.
+ */
+GType
+gda_oracle_pstmt_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+ static const GTypeInfo info = {
+ sizeof (GdaOraclePStmtClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gda_oracle_pstmt_class_init,
+ NULL,
+ NULL,
+ sizeof (GdaOraclePStmt),
+ 0,
+ (GInstanceInitFunc) gda_oracle_pstmt_init
+ };
+
+ g_static_mutex_lock (®istering);
+ if (type == 0)
+ type = g_type_register_static (GDA_TYPE_PSTMT, "GdaOraclePStmt", &info, 0);
+ g_static_mutex_unlock (®istering);
+ }
+ return type;
+}
+
+static void
+gda_oracle_pstmt_class_init (GdaOraclePStmtClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ parent_class = g_type_class_peek_parent (klass);
+
+ /* virtual functions */
+ object_class->finalize = gda_oracle_pstmt_finalize;
+}
+
+static void
+gda_oracle_pstmt_init (GdaOraclePStmt *pstmt, GdaOraclePStmtClass *klass)
+{
+ g_return_if_fail (GDA_IS_PSTMT (pstmt));
+
+ /* initialize specific parts of @pstmt */
+ TO_IMPLEMENT;
+}
+
+static void
+gda_oracle_pstmt_finalize (GObject *object)
+{
+ GdaOraclePStmt *pstmt = (GdaOraclePStmt *) object;
+
+ g_return_if_fail (GDA_IS_PSTMT (pstmt));
+
+ /* free memory */
+ TO_IMPLEMENT; /* free some specific parts of @pstmt */
+
+ /* chain to parent class */
+ parent_class->finalize (object);
+}
diff --git a/providers/oracle/gda-oracle-pstmt.h b/providers/oracle/gda-oracle-pstmt.h
new file mode 100644
index 0000000..cef1c3b
--- /dev/null
+++ b/providers/oracle/gda-oracle-pstmt.h
@@ -0,0 +1,57 @@
+/* GDA Oracle library
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ * TO_ADD: your name and email
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GDA_ORACLE_PSTMT_H__
+#define __GDA_ORACLE_PSTMT_H__
+
+#include <providers-support/gda-pstmt.h>
+#include "gda-oracle.h"
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_ORACLE_PSTMT (gda_oracle_pstmt_get_type())
+#define GDA_ORACLE_PSTMT(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_ORACLE_PSTMT, GdaOraclePStmt))
+#define GDA_ORACLE_PSTMT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST (klass, GDA_TYPE_ORACLE_PSTMT, GdaOraclePStmtClass))
+#define GDA_IS_ORACLE_PSTMT(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GDA_TYPE_ORACLE_PSTMT))
+#define GDA_IS_ORACLE_PSTMT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GDA_TYPE_ORACLE_PSTMT))
+
+typedef struct _GdaOraclePStmt GdaOraclePStmt;
+typedef struct _GdaOraclePStmtClass GdaOraclePStmtClass;
+
+struct _GdaOraclePStmt {
+ GdaPStmt object;
+
+ /* TO_ADD: this structure holds any information necessary to reference a prepared statement, usually a connection
+ * handle from the C or C++ API
+ */
+};
+
+struct _GdaOraclePStmtClass {
+ GdaPStmtClass parent_class;
+};
+
+GType gda_oracle_pstmt_get_type (void) G_GNUC_CONST;
+/* TO_ADD: helper function to create a GdaOraclePStmt such as gda_oracle_pstmt_new() with some specific arguments */
+
+G_END_DECLS
+
+#endif
diff --git a/providers/oracle/gda-oracle-recordset.c b/providers/oracle/gda-oracle-recordset.c
index 86c45b6..450b0ad 100644
--- a/providers/oracle/gda-oracle-recordset.c
+++ b/providers/oracle/gda-oracle-recordset.c
@@ -1,9 +1,8 @@
/* GDA Oracle provider
- * Copyright (C) 1998 - 2007 The GNOME Foundation.
+ * Copyright (C) 2008 The GNOME Foundation.
*
* AUTHORS:
- * Tim Coleman <tim timcoleman com>
- * Vivien Malerba <malerba gnome-db org>
+ * TO_ADD: your name and email
*
* This Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
@@ -21,681 +20,331 @@
* Boston, MA 02111-1307, USA.
*/
-#include <glib/gi18n-lib.h>
-#include <stdlib.h>
+#include <stdarg.h>
#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/gda-util.h>
+#include <libgda/gda-connection-private.h>
#include "gda-oracle.h"
#include "gda-oracle-recordset.h"
#include "gda-oracle-provider.h"
-#include <libgda/gda-data-model.h>
-#include <oci.h>
-#include <libgda/gda-data-model-private.h>
-
-#define PARENT_TYPE GDA_TYPE_DATA_MODEL_ROW
-
-struct _GdaOracleRecordsetPrivate {
- GdaConnection *cnc;
- GdaOracleConnectionData *cdata;
-
- GList *ora_values;
- GPtrArray *rows;
- OCIStmt *hstmt;
-
- gint ncolumns;
- gint nrows;
-};
+#define _GDA_PSTMT(x) ((GdaPStmt*)(x))
static void gda_oracle_recordset_class_init (GdaOracleRecordsetClass *klass);
static void gda_oracle_recordset_init (GdaOracleRecordset *recset,
- GdaOracleRecordsetClass *klass);
-static void gda_oracle_recordset_finalize (GObject *object);
-
-static GObjectClass *parent_class = NULL;
-
-/*
- * Private functions
- */
+ GdaOracleRecordsetClass *klass);
+static void gda_oracle_recordset_dispose (GObject *object);
-static GList *
-define_columns (GdaOracleRecordsetPrivate *priv, GArray *col_size_array)
-{
- GList *fields = NULL;
- gint i;
- gint result;
- ub2 fake_type;
-
- for (i = 0; i < priv->ncolumns; i ++) {
- GdaOracleValue *ora_value = g_new0 (GdaOracleValue, 1);
-
- result = OCIParamGet (priv->hstmt,
- OCI_HTYPE_STMT,
- priv->cdata->herr,
- (dvoid **) &(ora_value->pard),
- (ub4) i+1);
- if (gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
- _("Could not get the Oracle parameter")))
- return NULL;
-
- result = OCIAttrGet ((dvoid *) (ora_value->pard),
- OCI_DTYPE_PARAM,
- &(ora_value->defined_size),
- 0,
- OCI_ATTR_DATA_SIZE,
- priv->cdata->herr);
- if (gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
- _("Could not get the parameter defined size"))) {
- OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
- return NULL;
- }
-
- result = OCIAttrGet ((dvoid *) (ora_value->pard),
- OCI_DTYPE_PARAM,
- &(ora_value->sql_type),
- 0,
- OCI_ATTR_DATA_TYPE,
- priv->cdata->herr);
-
- if (gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
- _("Could not get the parameter data type"))) {
- OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
- return NULL;
- }
-
- /* for data fetching */
- fake_type = ora_value->sql_type;
- switch (ora_value->sql_type) {
- case SQLT_NUM: /* Numerics are coerced to string */
- fake_type = SQLT_CHR;
- break;
- case SQLT_DAT: /* Convert SQLT_DAT to OCIDate */
- fake_type = SQLT_ODT;
- break;
- }
-
- ora_value->g_type = oracle_sqltype_to_g_type (ora_value->sql_type);
- if (col_size_array && (i < col_size_array->len)) {
- ub2 size;
-
- size = g_array_index (col_size_array, ub2, i);
- if (size > 0)
- ora_value->defined_size = size;
- }
- if (ora_value->g_type == GDA_TYPE_BLOB) {
- /* allocate a Lob locator */
- OCILobLocator *lob;
-
- result = OCIDescriptorAlloc ((dvoid *) priv->cdata->henv, (dvoid **) &lob,
- (ub4) gda_oracle_blob_type (ora_value->sql_type), (size_t) 0, (dvoid **) 0);
- if (gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
- _("Could not allocate Lob locator")))
- return NULL;
- ora_value->value = lob;
- ora_value->defined_size = 0;
- }
- else if (ora_value->defined_size == 0)
- ora_value->value = NULL;
- else {
- ora_value->defined_size++;
- ora_value->value = g_malloc0 (ora_value->defined_size);
- }
+/* virtual methods */
+static gint gda_oracle_recordset_fetch_nb_rows (GdaDataSelect *model);
+static gboolean gda_oracle_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
+static gboolean gda_oracle_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
+static gboolean gda_oracle_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
+static gboolean gda_oracle_recordset_fetch_at (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error);
- ora_value->hdef = (OCIDefine *) 0;
- ora_value->indicator = 0;
- result = OCIDefineByPos ((OCIStmt *) priv->hstmt,
- (OCIDefine **) &(ora_value->hdef),
- (OCIError *) priv->cdata->herr,
- (ub4) i + 1,
- ora_value->value,
- ora_value->defined_size,
- (ub2) fake_type,
- (dvoid *) &(ora_value->indicator),
- (ub2 *) 0,
- (ub2 *) 0,
- (ub4) OCI_DEFAULT);
- if (gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
- _("Could not define by position"))) {
- OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
- return NULL;
- }
-
- fields = g_list_append (fields, ora_value);
- }
- return fields;
-}
+struct _GdaOracleRecordsetPrivate {
+ GdaConnection *cnc;
+ /* TO_ADD: specific information */
+};
+static GObjectClass *parent_class = NULL;
/*
- * GdaOracleRecordset class implementation
+ * Object init and finalize
*/
-
static void
-gda_oracle_recordset_describe_column (GdaDataModel *model, gint col)
+gda_oracle_recordset_init (GdaOracleRecordset *recset,
+ GdaOracleRecordsetClass *klass)
{
- GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
- GdaOracleRecordsetPrivate *priv_data;
- GdaColumn *field_attrs;
- OCIParam *pard;
- gchar *pgchar_dummy;
- glong col_name_len;
-
- gchar name_buffer[ORA_NAME_BUFFER_SIZE + 1];
- ub2 sql_type;
- sb1 scale;
- ub1 nullable;
- ub2 defined_size;
- gint result;
-
g_return_if_fail (GDA_IS_ORACLE_RECORDSET (recset));
- g_return_if_fail (recset->priv != NULL);
-
- priv_data = recset->priv;
-
- if (!priv_data->cdata) {
- gda_connection_add_event_string (priv_data->cnc,
- _("Invalid Oracle handle"));
- return;
- }
-
- if (col >= priv_data->ncolumns) {
- gda_connection_add_event_string (priv_data->cnc,
- _("Column out of range"));
- return;
- }
-
- field_attrs = gda_data_model_describe_column (model, col);
-
- result = OCIParamGet ((dvoid *) priv_data->hstmt,
- (ub4) OCI_HTYPE_STMT,
- (OCIError *) priv_data->cdata->herr,
- (dvoid **) &pard,
- (ub4) col + 1);
- if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata, OCI_HTYPE_ERROR,
- _("Could not get the Oracle parameter information")))
- return;
-
- result = OCIAttrGet ((dvoid *) pard,
- (ub4) OCI_DTYPE_PARAM,
- (dvoid **) &pgchar_dummy,
- (ub4 *) & col_name_len,
- (ub4) OCI_ATTR_NAME,
- (OCIError *) priv_data->cdata->herr);
- if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata, OCI_HTYPE_ERROR,
- _("Could not get the Oracle column name"))) {
- OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
- return;
- }
-
- if (col_name_len > ORA_NAME_BUFFER_SIZE)
- col_name_len = ORA_NAME_BUFFER_SIZE;
-
- memcpy (name_buffer, pgchar_dummy, col_name_len);
- name_buffer[col_name_len] = '\0';
-
- result = OCIAttrGet ((dvoid *) pard,
- (ub4) OCI_DTYPE_PARAM,
- (dvoid *) &sql_type,
- (ub4 *) 0,
- (ub4) OCI_ATTR_DATA_TYPE,
- (OCIError *) priv_data->cdata->herr);
- if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata, OCI_HTYPE_ERROR,
- _("Could not get the Oracle column data type"))) {
- OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
- return;
- }
-
- result = OCIAttrGet ((dvoid *) pard,
- (ub4) OCI_DTYPE_PARAM,
- (sb1 *) &scale,
- (ub4 *) 0,
- (ub4) OCI_ATTR_SCALE,
- (OCIError *) priv_data->cdata->herr);
- if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata, OCI_HTYPE_ERROR,
- _("Could not get the Oracle column scale"))) {
- OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
- return;
- }
-
- result = OCIAttrGet ((dvoid *) pard,
- (ub4) OCI_DTYPE_PARAM,
- (ub1 *) &nullable,
- (ub4 *) 0,
- (ub4) OCI_ATTR_IS_NULL,
- (OCIError *) priv_data->cdata->herr);
- if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata, OCI_HTYPE_ERROR,
- _("Could not get the Oracle column nullable attribute"))) {
- OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
- return;
- }
-
- result = OCIAttrGet ((dvoid *) pard,
- OCI_DTYPE_PARAM,
- &defined_size,
- 0,
- OCI_ATTR_DATA_SIZE,
- priv_data->cdata->herr);
- if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata, OCI_HTYPE_ERROR,
- _("Could not get the Oracle defined size"))) {
- OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
- return;
- }
-
- gda_column_set_name (field_attrs, name_buffer);
- gda_column_set_scale (field_attrs, scale);
- gda_column_set_g_type (field_attrs, oracle_sqltype_to_g_type (sql_type));
- gda_column_set_defined_size (field_attrs, defined_size);
-
- /* FIXME */
- gda_column_set_references (field_attrs, "");
-
- /* FIXME */
- gda_column_set_primary_key (field_attrs, FALSE);
-
- /* FIXME */
- gda_column_set_unique_key (field_attrs, FALSE);
+ recset->priv = g_new0 (GdaOracleRecordsetPrivate, 1);
+ recset->priv->cnc = NULL;
- gda_column_set_allow_null (field_attrs, !(nullable == 0));
-
- OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
+ /* initialize specific information */
+ TO_IMPLEMENT;
}
-static gint
-gda_oracle_recordset_get_n_rows (GdaDataModelRow *model)
+static void
+gda_oracle_recordset_class_init (GdaOracleRecordsetClass *klass)
{
- GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
- GdaOracleRecordsetPrivate *priv_data;
- gint result = OCI_SUCCESS;
- gint nrows = -1;
-
- g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (model), 0);
- g_return_val_if_fail (recset->priv != NULL, 0);
-
- priv_data = recset->priv;
-
- if (priv_data->nrows >= 0)
- return priv_data->nrows;
-
- while (result == OCI_SUCCESS) {
- nrows += 1;
- result = OCIStmtFetch (priv_data->hstmt,
- priv_data->cdata->herr,
- (ub4) 1,
- (ub2) OCI_FETCH_NEXT,
- (ub4) OCI_DEFAULT);
- }
-
- /* reset the result set to the beginning */
- result = OCIStmtExecute (priv_data->cdata->hservice,
- priv_data->hstmt,
- priv_data->cdata->herr,
- (ub4) 0,
- (ub4) 0,
- (CONST OCISnapshot *) NULL,
- (OCISnapshot *) NULL,
- OCI_DEFAULT);
-
- if (gda_oracle_check_result (result, priv_data->cnc, priv_data->cdata,
- OCI_HTYPE_ERROR, "Could not execute Oracle statement"))
- return 0;
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GdaDataSelectClass *pmodel_class = GDA_DATA_SELECT_CLASS (klass);
- return nrows;
-}
+ parent_class = g_type_class_peek_parent (klass);
-static gint
-gda_oracle_recordset_get_n_columns (GdaDataModelRow *model)
-{
- GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
- g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (model), 0);
- g_return_val_if_fail (recset->priv != NULL, 0);
+ object_class->dispose = gda_oracle_recordset_dispose;
+ pmodel_class->fetch_nb_rows = gda_oracle_recordset_fetch_nb_rows;
+ pmodel_class->fetch_random = gda_oracle_recordset_fetch_random;
- return recset->priv->ncolumns;
+ pmodel_class->fetch_next = gda_oracle_recordset_fetch_next;
+ pmodel_class->fetch_prev = gda_oracle_recordset_fetch_prev;
+ pmodel_class->fetch_at = gda_oracle_recordset_fetch_at;
}
-static GdaRow *
-fetch_row (GdaOracleRecordset *recset, gint rownum)
+static void
+gda_oracle_recordset_dispose (GObject *object)
{
- GdaRow *row;
- gint i;
- gchar *id;
- GdaOracleRecordsetPrivate *priv;
- GList *node;
- gint result;
+ GdaOracleRecordset *recset = (GdaOracleRecordset *) object;
- g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (recset), NULL);
- g_return_val_if_fail (recset->priv != NULL, NULL);
+ g_return_if_fail (GDA_IS_ORACLE_RECORDSET (recset));
- priv = recset->priv;
+ if (recset->priv) {
+ if (recset->priv->cnc)
+ g_object_unref (recset->priv->cnc);
- row = gda_row_new (GDA_DATA_MODEL (recset), priv->ncolumns);
+ /* free specific information */
+ TO_IMPLEMENT;
+ g_free (recset->priv);
+ recset->priv = NULL;
+ }
- result = OCIStmtFetch ((OCIStmt *) priv->hstmt,
- (OCIError *) priv->cdata->herr,
- (ub4) 1,
- (ub2) OCI_FETCH_NEXT,
- (ub4) OCI_DEFAULT);
- if (result == OCI_NO_DATA)
- return NULL;
+ parent_class->dispose (object);
+}
- if (gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
- _("Could not fetch a row")))
- return NULL;
+/*
+ * Public functions
+ */
- i = 0;
- for (node = priv->ora_values; node; node = node->next) {
- GdaOracleValue *ora_value = (GdaOracleValue *) node->data;
- GValue *value = gda_row_get_value (row, i);
- gda_oracle_set_value (value, ora_value, priv->cnc);
- i += 1;
+GType
+gda_oracle_recordset_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+ static const GTypeInfo info = {
+ sizeof (GdaOracleRecordsetClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gda_oracle_recordset_class_init,
+ NULL,
+ NULL,
+ sizeof (GdaOracleRecordset),
+ 0,
+ (GInstanceInitFunc) gda_oracle_recordset_init
+ };
+ g_static_mutex_lock (®istering);
+ if (type == 0)
+ type = g_type_register_static (GDA_TYPE_DATA_SELECT, "GdaOracleRecordset", &info, 0);
+ g_static_mutex_unlock (®istering);
}
- id = g_strdup_printf ("%d", rownum);
- gda_row_set_id (row, id);
- g_free (id);
- return row;
+ return type;
}
-static GdaRow *
-gda_oracle_recordset_get_row (GdaDataModelRow *model, gint row, GError **error)
+/*
+ * the @ps struct is modified and transfered to the new data model created in
+ * this function
+ */
+GdaDataModel *
+gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_params,
+ GdaDataModelAccessFlags flags, GType *col_types)
{
- GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
- GdaOracleRecordsetPrivate *priv_data;
- GdaRow *fields = NULL;
- gint fetched_rows;
- gint i;
-
- g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (recset), NULL);
- g_return_val_if_fail (recset->priv != NULL, 0);
+ GdaOracleRecordset *model;
+ OracleConnectionData *cdata;
+ gint i;
+ GdaDataModelAccessFlags rflags;
- priv_data = recset->priv;
+ g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+ g_return_val_if_fail (ps != NULL, NULL);
- if (!priv_data->cdata) {
- gda_connection_add_event_string (priv_data->cnc,
- _("Invalid Oracle handle"));
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
return NULL;
- }
- fetched_rows = priv_data->rows->len;
-
- if (row >= priv_data->nrows && priv_data->nrows >= 0)
- return NULL;
+ /* make sure @ps reports the correct number of columns using the API*/
+ if (_GDA_PSTMT (ps)->ncols < 0)
+ /*_GDA_PSTMT (ps)->ncols = ...;*/
+ TO_IMPLEMENT;
+
+ /* completing @ps if not yet done */
+ if (!_GDA_PSTMT (ps)->types && (_GDA_PSTMT (ps)->ncols > 0)) {
+ /* create prepared statement's columns */
+ GSList *list;
+ for (i = 0; i < _GDA_PSTMT (ps)->ncols; i++)
+ _GDA_PSTMT (ps)->tmpl_columns = g_slist_prepend (_GDA_PSTMT (ps)->tmpl_columns,
+ gda_column_new ());
+ _GDA_PSTMT (ps)->tmpl_columns = g_slist_reverse (_GDA_PSTMT (ps)->tmpl_columns);
+
+ /* create prepared statement's types */
+ _GDA_PSTMT (ps)->types = g_new0 (GType, _GDA_PSTMT (ps)->ncols); /* all types are initialized to GDA_TYPE_NULL */
+ if (col_types) {
+ for (i = 0; ; i++) {
+ if (col_types [i] > 0) {
+ if (col_types [i] == G_TYPE_NONE)
+ break;
+ if (i >= _GDA_PSTMT (ps)->ncols)
+ g_warning (_("Column %d out of range (0-%d), ignoring its specified type"), i,
+ _GDA_PSTMT (ps)->ncols - 1);
+ else
+ _GDA_PSTMT (ps)->types [i] = col_types [i];
+ }
+ }
+ }
+
+ /* fill GdaColumn's data */
+ for (i=0, list = _GDA_PSTMT (ps)->tmpl_columns;
+ i < GDA_PSTMT (ps)->ncols;
+ i++, list = list->next) {
+ GdaColumn *column;
+
+ column = GDA_COLUMN (list->data);
- if (row < fetched_rows)
- return (GdaRow *) g_ptr_array_index (priv_data->rows, row);
+ /* use C API to set columns' information using gda_column_set_*() */
+ TO_IMPLEMENT;
+ }
+ }
- gda_data_model_freeze (GDA_DATA_MODEL (recset));
+ /* determine access mode: RANDOM or CURSOR FORWARD are the only supported */
+ if (flags & GDA_DATA_MODEL_ACCESS_RANDOM)
+ rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
+ else
+ rflags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;
- for (i = fetched_rows; i <= row; i += 1) {
- fields = fetch_row (recset, i);
- if (!fields)
- return NULL;
- g_ptr_array_add (priv_data->rows, fields);
- }
+ /* create data model */
+ model = g_object_new (GDA_TYPE_ORACLE_RECORDSET,
+ "prepared-stmt", ps,
+ "model-usage", rflags,
+ "exec-params", exec_params, NULL);
+ model->priv->cnc = cnc;
+ g_object_ref (cnc);
- gda_data_model_thaw (GDA_DATA_MODEL (recset));
+ /* post init specific code */
+ TO_IMPLEMENT;
- return fields;
+ return GDA_DATA_MODEL (model);
}
-static const GValue *
-gda_oracle_recordset_get_value_at (GdaDataModelRow *model, gint col, gint row)
-{
- GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
- GdaOracleRecordsetPrivate *priv_data;
- const GdaRow *fields;
- g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (recset), NULL);
- g_return_val_if_fail (recset->priv != NULL, 0);
+/*
+ * Get the number of rows in @model, if possible
+ */
+static gint
+gda_oracle_recordset_fetch_nb_rows (GdaDataSelect *model)
+{
+ GdaOracleRecordset *imodel;
- priv_data = recset->priv;
+ imodel = GDA_ORACLE_RECORDSET (model);
+ if (model->advertized_nrows >= 0)
+ return model->advertized_nrows;
- if (col >= priv_data->ncolumns)
- return NULL;
+ /* use C API to determine number of rows,if possible */
+ TO_IMPLEMENT;
- fields = gda_oracle_recordset_get_row (model, row, NULL);
- return fields != NULL ? gda_row_get_value ((GdaRow *) fields, col) : NULL;
+ return model->advertized_nrows;
}
-static gboolean
-gda_oracle_recordset_is_updatable (GdaDataModelRow *model)
+/*
+ * Create a new filled #GdaRow object for the row at position @rownum, and put it into *prow.
+ *
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ * - If *prow is NULL then a new #GdaRow object has to be created,
+ * - and otherwise *prow contains a #GdaRow object which has already been created
+ * (through a call to this very function), and in this case it should not be modified
+ * but the function may return FALSE if an error occurred.
+ *
+ * Memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row(). If new row objects are "given" to the GdaDataSelect implemantation
+ * using that method, then this method should detect when all the data model rows have been analysed
+ * (when model->nb_stored_rows == model->advertized_nrows) and then possibly discard the API handle
+ * as it won't be used anymore to fetch rows.
+ */
+static gboolean
+gda_oracle_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
{
- GdaCommandType cmd_type;
- GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
+ GdaOracleRecordset *imodel;
- g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (recset), FALSE);
+ imodel = GDA_ORACLE_RECORDSET (model);
- g_object_get (G_OBJECT (model), "command_type", &cmd_type, NULL);
+ TO_IMPLEMENT;
- return FALSE;
- /*return cmd_type == GDA_COMMAND_TYPE_TABLE ? TRUE : FALSE;*/
+ return TRUE;
}
-/* Not implemented. See bug http://bugzilla.gnome.org/show_bug.cgi?id=411811: */
-#if 0
-static GdaRow *
-gda_oracle_recordset_append_values (GdaDataModelRow *model, const GList *values, GError **error)
+/*
+ * Create and "give" filled #GdaRow object for all the rows in the model
+ */
+static gboolean
+gda_oracle_recordset_store_all (GdaDataSelect *model, GError **error)
{
- GString *sql;
- GdaRow *row;
+ GdaOracleRecordset *imodel;
gint i;
- GList *l;
- GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
- GdaOracleRecordsetPrivate *priv_data;
-
- g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (recset), NULL);
- g_return_val_if_fail (values != NULL, NULL);
- g_return_val_if_fail (gda_data_model_is_updatable (GDA_DATA_MODEL (model)), NULL);
- g_return_val_if_fail (recset->priv != NULL, 0);
-
- priv_data = recset->priv;
-
- if (priv_data->ncolumns != g_list_length ((GList *) values)) {
- gda_connection_add_event_string (
- recset->priv->cnc,
- _("Attempt to insert a row with an invalid number of columns"));
- return NULL;
- }
-
- sql = g_string_new ("INSERT INTO ");
- sql = g_string_append (sql, gda_data_model_get_command_text (GDA_DATA_MODEL (model)));
- sql = g_string_append (sql, "(");
-
- for (i = 0; i < priv_data->ncolumns; i += 1) {
- GdaColumn *fa;
- fa = gda_data_model_describe_column (GDA_DATA_MODEL (model), i);
- if (!fa) {
- gda_connection_add_event_string (
- recset->priv->cnc,
- _("Could not retrieve column's information"));
- g_string_free (sql, TRUE);
- return NULL;
- }
+ imodel = GDA_ORACLE_RECORDSET (model);
- if (i != 0)
- sql = g_string_append (sql, ", ");
- sql = g_string_append (sql, gda_column_get_name (fa));
+ /* default implementation */
+ for (i = 0; i < model->advertized_nrows; i++) {
+ GdaRow *prow;
+ if (! gda_oracle_recordset_fetch_random (model, &prow, i, error))
+ return FALSE;
}
- sql = g_string_append (sql, ") VALUES (");
-
- for (l = (GList *) values, i = 0; i < priv_data->ncolumns; i += 1, l = l->next) {
- gchar *val_str;
- const GValue *val = (const GValue *) l->data;
-
- if (!val) {
- gda_connection_add_event_string (
- recset->priv->cnc,
- _("Could not retrieve column's value"));
- g_string_free (sql, TRUE);
- return NULL;
- }
-
- if (i != 0)
- sql = g_string_append (sql, ", ");
- val_str = gda_oracle_value_to_sql_string ((GValue*) val);
- sql = g_string_append (sql, val_str);
-
- g_free (val_str);
- }
- sql = g_string_append (sql, ")");
-
- /* execute the UPDATE command */
- /* not sure what to do here yet. */
-
- g_string_free (sql, TRUE);
-
- row = gda_row_new_from_list (GDA_DATA_MODEL (model), values);
- g_ptr_array_add (recset->priv->rows, row);
-
- return row;
-}
-#endif
-
-static gboolean
-gda_oracle_recordset_remove_row (GdaDataModelRow *model, GdaRow *row, GError **error)
-{
- return FALSE;
+ return TRUE;
}
-static gboolean
-gda_oracle_recordset_update_row (GdaDataModelRow *model, GdaRow *row, GError **error)
-{
- return FALSE;
-}
-
-
/*
- * Object init and finalize
+ * Create a new filled #GdaRow object for the next cursor row, and put it into *prow.
+ *
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ * - If *prow is NULL then a new #GdaRow object has to be created,
+ * - and otherwise *prow contains a #GdaRow object which has already been created
+ * (through a call to this very function), and in this case it should not be modified
+ * but the function may return FALSE if an error occurred.
+ *
+ * Memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row().
*/
-static void
-gda_oracle_recordset_init (GdaOracleRecordset *recset, GdaOracleRecordsetClass *klass)
+static gboolean
+gda_oracle_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
{
- g_return_if_fail (GDA_IS_ORACLE_RECORDSET (recset));
- recset->priv = g_new0 (GdaOracleRecordsetPrivate, 1);
- recset->priv->rows = g_ptr_array_new ();
-}
+ GdaOracleRecordset *imodel = (GdaOracleRecordset*) model;
-static void
-gda_oracle_recordset_class_init (GdaOracleRecordsetClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GdaDataModelRowClass *model_class = GDA_DATA_MODEL_ROW_CLASS (klass);
-
- parent_class = g_type_class_peek_parent (klass);
-
- object_class->finalize = gda_oracle_recordset_finalize;
- model_class->get_n_rows = gda_oracle_recordset_get_n_rows;
- model_class->get_n_columns = gda_oracle_recordset_get_n_columns;
- model_class->get_row = gda_oracle_recordset_get_row;
- model_class->get_value_at = gda_oracle_recordset_get_value_at;
- model_class->is_updatable = gda_oracle_recordset_is_updatable;
+ TO_IMPLEMENT;
- /* Not implemented. See bug http://bugzilla.gnome.org/show_bug.cgi?id=411811: */
- model_class->append_values = /* gda_oracle_recordset_append_values */ NULL;
-
- model_class->remove_row = gda_oracle_recordset_remove_row;
- model_class->update_row = gda_oracle_recordset_update_row;
+ return TRUE;
}
-static void
-gda_oracle_free_values (GdaOracleValue *ora_value)
-{
- if (ora_value->g_type == GDA_TYPE_BLOB)
- OCIDescriptorFree((dvoid *) ora_value->value, (ub4) gda_oracle_blob_type (ora_value->sql_type));
- else
- g_free (ora_value->value);
- OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
- g_free (ora_value);
-}
-
-static void
-gda_oracle_recordset_finalize (GObject *object)
+/*
+ * Create a new filled #GdaRow object for the previous cursor row, and put it into *prow.
+ *
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ * - If *prow is NULL then a new #GdaRow object has to be created,
+ * - and otherwise *prow contains a #GdaRow object which has already been created
+ * (through a call to this very function), and in this case it should not be modified
+ * but the function may return FALSE if an error occurred.
+ *
+ * Memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row().
+ */
+static gboolean
+gda_oracle_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
{
- GdaOracleRecordset *recset = (GdaOracleRecordset *) object;
- GdaOracleRecordsetPrivate *priv_data;
-
- g_return_if_fail (recset->priv != NULL);
-
- priv_data = recset->priv;
+ GdaOracleRecordset *imodel = (GdaOracleRecordset*) model;
- if (!priv_data->cdata) {
- gda_connection_add_event_string (priv_data->cnc,
- _("Invalid Oracle handle"));
- return;
- }
-
- g_return_if_fail (GDA_IS_ORACLE_RECORDSET (recset));
+ TO_IMPLEMENT;
- while (priv_data->rows->len > 0) {
- GdaRow *row = (GdaRow *) g_ptr_array_index (priv_data->rows, 0);
-
- if (row != NULL)
- g_object_unref (row);
- g_ptr_array_remove_index (priv_data->rows, 0);
- }
- g_ptr_array_free (priv_data->rows, TRUE);
- recset->priv->rows = NULL;
-
- g_list_foreach (priv_data->ora_values, (GFunc) gda_oracle_free_values, NULL);
- if (priv_data->hstmt)
- OCIHandleFree ((dvoid *) priv_data->hstmt, OCI_HTYPE_STMT);
- parent_class->finalize (object);
+ return TRUE;
}
-
-GType
-gda_oracle_recordset_get_type (void)
+/*
+ * Create a new filled #GdaRow object for the cursor row at position @rownum, and put it into *prow.
+ *
+ * WARNING: @prow will NOT be NULL, but *prow may or may not be NULL:
+ * - If *prow is NULL then a new #GdaRow object has to be created,
+ * - and otherwise *prow contains a #GdaRow object which has already been created
+ * (through a call to this very function), and in this case it should not be modified
+ * but the function may return FALSE if an error occurred.
+ *
+ * Memory management for that new GdaRow object is left to the implementation, which
+ * can use gda_data_select_take_row().
+ */
+static gboolean
+gda_oracle_recordset_fetch_at (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0)) {
- static const GTypeInfo info = {
- sizeof (GdaOracleRecordsetClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) gda_oracle_recordset_class_init,
- NULL,
- NULL,
- sizeof (GdaOracleRecordset),
- 0,
- (GInstanceInitFunc) gda_oracle_recordset_init
- };
- type = g_type_register_static (PARENT_TYPE, "GdaOracleRecordset", &info, 0);
- }
+ GdaOracleRecordset *imodel = (GdaOracleRecordset*) model;
+
+ TO_IMPLEMENT;
- return type;
+ return TRUE;
}
-GdaOracleRecordset *
-gda_oracle_recordset_new (GdaConnection *cnc,
- GdaOracleConnectionData *cdata,
- OCIStmt *stmthp, GArray *col_size_array)
-{
- GdaOracleRecordset *recset;
- ub4 parcount;
- gint i;
-
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
- g_return_val_if_fail (cdata != NULL, NULL);
-
- OCIAttrGet ((dvoid *) stmthp,
- (ub4) OCI_HTYPE_STMT,
- (dvoid *) &parcount,
- 0,
- (ub4) OCI_ATTR_PARAM_COUNT,
- cdata->herr);
-
- recset = g_object_new (GDA_TYPE_ORACLE_RECORDSET, NULL);
- recset->priv->nrows = -1;
- recset->priv->cnc = cnc;
- recset->priv->cdata = cdata;
- recset->priv->hstmt = stmthp;
- recset->priv->ncolumns = parcount;
- recset->priv->ora_values = define_columns (recset->priv, col_size_array);
- recset->priv->nrows = gda_oracle_recordset_get_n_rows (GDA_DATA_MODEL_ROW (recset));
-
- /* define GdaColumn attributes */
- for (i = 0; i < recset->priv->ncolumns; i += 1)
- gda_oracle_recordset_describe_column (GDA_DATA_MODEL (recset), i);
-
- return recset;
-}
diff --git a/providers/oracle/gda-oracle-recordset.h b/providers/oracle/gda-oracle-recordset.h
index c23e4c4..7db421b 100644
--- a/providers/oracle/gda-oracle-recordset.h
+++ b/providers/oracle/gda-oracle-recordset.h
@@ -1,13 +1,8 @@
/* GDA Oracle provider
- * Copyright (C) 2002 - 2004 The GNOME Foundation.
+ * Copyright (C) 2008 The GNOME Foundation.
*
* AUTHORS:
- * Tim Coleman <tim timcoleman com>
- *
- * Borrowed from mysql-oracle-recordset.h, written by
- * Michael Lausch <michael lausch at>
- * Rodrigo Moya <rodrigo gnome-db org>
- * Vivien Malerba <malerba gnome-db org>
+ * TO_ADD: your name and email
*
* This Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
@@ -28,9 +23,9 @@
#ifndef __GDA_ORACLE_RECORDSET_H__
#define __GDA_ORACLE_RECORDSET_H__
-#include <libgda/gda-data-model-hash.h>
-#include <libgda/gda-value.h>
-#include <oci.h>
+#include <libgda/libgda.h>
+#include <providers-support/gda-data-select-priv.h>
+#include "gda-oracle-pstmt.h"
G_BEGIN_DECLS
@@ -40,36 +35,22 @@ G_BEGIN_DECLS
#define GDA_IS_ORACLE_RECORDSET(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GDA_TYPE_ORACLE_RECORDSET))
#define GDA_IS_ORACLE_RECORDSET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDA_TYPE_ORACLE_RECORDSET))
-
typedef struct _GdaOracleRecordset GdaOracleRecordset;
typedef struct _GdaOracleRecordsetClass GdaOracleRecordsetClass;
-typedef struct _GdaOracleRecordsetField GdaOracleRecordsetField;
typedef struct _GdaOracleRecordsetPrivate GdaOracleRecordsetPrivate;
-typedef struct _GdaOracleValue GdaOracleValue;
struct _GdaOracleRecordset {
- GdaDataModelRow model;
+ GdaDataSelect model;
GdaOracleRecordsetPrivate *priv;
};
struct _GdaOracleRecordsetClass {
- GdaDataModelRowClass parent_class;
+ GdaDataSelectClass parent_class;
};
-struct _GdaOracleValue {
- OCIDefine *hdef;
- OCIParam *pard;
- sb2 indicator;
- ub2 sql_type;
- ub2 defined_size;
- gpointer value;
- GType g_type;
-};
-
-
-GType gda_oracle_recordset_get_type (void) G_GNUC_CONST;
-GdaOracleRecordset *gda_oracle_recordset_new (GdaConnection *cnc, GdaOracleConnectionData *cdata,
- OCIStmt *stmthp, GArray *col_size_array);
+GType gda_oracle_recordset_get_type (void) G_GNUC_CONST;
+GdaDataModel *gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_params,
+ GdaDataModelAccessFlags flags, GType *col_types);
G_END_DECLS
diff --git a/providers/oracle/gda-oracle.h b/providers/oracle/gda-oracle.h
index dd3d9a6..f48ea10 100644
--- a/providers/oracle/gda-oracle.h
+++ b/providers/oracle/gda-oracle.h
@@ -1,13 +1,8 @@
-/* GDA Oracle provider
- * Copyright (C) 1998 - 2007 The GNOME Foundation.
+/* GDA oracle provider
+ * Copyright (C) 2008 The GNOME Foundation.
*
* AUTHORS:
- * Tim Coleman <tim timcoleman com>
- *
- * Borrowed from gda-mysql.h, written by:
- * Michael Lausch <michael lausch at>
- * Rodrigo Moya <rodrigo gnome-db org>
- * Vivien Malerba <malerba gnome-db org>
+ * TO_ADD: your name and email
*
* This Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
@@ -28,60 +23,21 @@
#ifndef __GDA_ORACLE_H__
#define __GDA_ORACLE_H__
-#if defined(HAVE_CONFIG_H)
-#endif
-
-#include <glib/gmacros.h>
-#include <libgda/gda-connection.h>
-#include <libgda/gda-server-provider.h>
-#include <glib/gi18n-lib.h>
-#include <libgda/gda-value.h>
-#include "gda-oracle-provider.h"
-#include "gda-oracle-recordset.h"
-#include <oci.h>
-
-#define OBJECT_DATA_ORACLE_HANDLE "GDA_Oracle_OracleHandle"
-#define GDA_ORACLE_PROVIDER_ID "GDA Oracle provider"
-#define ORA_NAME_BUFFER_SIZE 30
-
-#define gda_oracle_check_result(result, cnc, priv_data, type, msg) \
- (((result) == OCI_SUCCESS || (result) == OCI_SUCCESS_WITH_INFO) \
- ? NULL : gda_oracle_handle_error(result, cnc, priv_data, \
- type, msg, __FILE__, __LINE__))
-
-#define gda_oracle_blob_type(sqltype) \
- (((sqltype == SQLT_BFILEE) || (sqltype == SQLT_CFILEE)) ? OCI_DTYPE_FILE : OCI_DTYPE_LOB)
-
-G_BEGIN_DECLS
-
/*
- * Utility functions
+ * Provider name
*/
+#define ORACLE_PROVIDER_NAME "Oracle"
-GdaConnectionEvent *gda_oracle_make_error (dvoid *hndlp, ub4 type,
- const gchar *file, gint line);
-
-void gda_oracle_set_value (GValue *value,
- GdaOracleValue *thevalue,
- GdaConnection *cnc);
+/* TO_ADD: include headers necessary for the C or C++ API */
-gchar *gda_oracle_value_to_sql_string (GValue *value);
-
-GType oracle_sqltype_to_g_type (const ub2 sqltype);
-
-gchar *oracle_sqltype_to_string (const ub2 sqltype);
-
-GdaOracleValue *gda_value_to_oracle_value (const GValue *value);
-
-GdaConnectionEvent *gda_oracle_handle_error (gint result,
- GdaConnection *cnc,
- GdaOracleConnectionData *priv_data,
- ub4 type,
- const gchar *msg,
- const gchar *file,
- gint line);
-
-
-G_END_DECLS
+/*
+ * Provider's specific connection data
+ */
+typedef struct {
+ /* TO_ADD: this structure holds any information necessary to specialize the GdaConnection, usually a connection
+ * handle from the C or C++ API
+ */
+ int foo;
+} OracleConnectionData;
#endif
diff --git a/providers/oracle/gen_def.c b/providers/oracle/gen_def.c
new file mode 100644
index 0000000..d3ab75f
--- /dev/null
+++ b/providers/oracle/gen_def.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2007 Vivien Malerba
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This program generates tokens'ID transformation because the GdaSqlParser object uses 2 Lemon generated
+ * parsers at once, but with only one tokenizer (because each Lemon generated parser generates it own IDs for
+ * tokens).
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define MAX_SYMBOLS 500
+#define PARSER_HEADER "parser.h"
+#define FALSE 0
+#define TRUE (!FALSE)
+
+typedef struct {
+ char *key;
+ int parser_value;
+} HashEntry;
+
+HashEntry entries[MAX_SYMBOLS];
+int nb_entries; /* must remain < MAX_SYMBOLS */
+
+typedef enum {
+ TYPE_IMPOSED,
+ TYPE_PARSER
+} SourceType;
+
+static void parse_contents (FILE *stream, SourceType type);
+static HashEntry *find_entry_for_token (char *token);
+int
+main (int argc,char** argv)
+{
+ int i;
+ FILE *fd_imposed;
+ FILE *fd_parser;
+ HashEntry *illegal_entry;
+
+ memset (entries, 0, sizeof (entries));
+ /* printf ("Imposed header: %s\n", IMPOSED_HEADER); */
+ fd_imposed = fopen (IMPOSED_HEADER, "r");
+ if (!fd_imposed) {
+ printf ("Can't open '%s':%s\n", IMPOSED_HEADER, strerror (errno));
+ return 1;
+ }
+ /* printf ("Parser header: %s\n", PARSER_HEADER); */
+ fd_parser = fopen (PARSER_HEADER, "r");
+ if (!fd_parser) {
+ printf ("Can't open '%s':%s\n", PARSER_HEADER, strerror (errno));
+ return 1;
+ }
+
+ nb_entries = 0;
+ parse_contents (fd_imposed, TYPE_IMPOSED);
+ parse_contents (fd_parser, TYPE_PARSER);
+
+ fclose (fd_imposed);
+ fclose (fd_parser);
+
+ /* output notice */
+ printf ("/*\n * This file is generated by the gen_def program (see the gen_def.c file \n"
+ " * for some explanations)\n"
+ " * DO NOT EDIT MANUALLY\n */\n\n\n");
+
+ /* output */
+ illegal_entry = find_entry_for_token ("ILLEGAL");
+ printf ("gint oracle_parser_tokens[] = {\n");
+ for (i = 0; i < nb_entries; i++) {
+ HashEntry *entry = &(entries[i]);
+ if (i!= 0)
+ printf (",\n");
+ if (entry->parser_value >= 0)
+ printf ("/* %03d */ %d", i, entry->parser_value);
+ else
+ printf ("/* %03d */ %d", i, illegal_entry->parser_value);
+ }
+ printf ("};\n");
+
+ return 0;
+}
+
+static HashEntry *
+find_entry_for_token (char *token)
+{
+ int i;
+
+ for (i = 0; i < nb_entries; i++) {
+ HashEntry *e = &(entries[i]);
+ if (!strcmp (e->key, token))
+ return e;
+ }
+ return NULL;
+}
+
+
+
+static void
+parse_line (char *line, SourceType type)
+{
+ char *z, *token;
+ int value;
+ HashEntry *entry;
+
+ z = line;
+ if (strncmp (z, "#define ", 8))
+ return;
+ z += 8;
+ token = z + 2;
+ for (; *z && *z != ' '; z++);
+ *z = 0;
+ z++;
+ for (; *z == ' '; z++);
+ value = atoi (z);
+ /* printf ("%d Token: /%s/, value=%d\n", type, token, value); */
+
+ entry = find_entry_for_token (token);
+ if (!entry) {
+ nb_entries++;
+ entry = &(entries[nb_entries - 1]);
+ entry->key = malloc (sizeof (char) * (strlen (token) + 1));
+ memcpy (entry->key, token, strlen (token) + 1);
+ entry->parser_value = -1;
+ }
+ if (type == TYPE_PARSER)
+ entry->parser_value = value;
+}
+
+static void
+parse_contents (FILE *stream, SourceType type)
+{
+#define BUFSIZE 500
+ char buffer[BUFSIZE];
+ int read;
+ char *end;
+
+ read = fread (buffer, 1, BUFSIZE, stream);
+ end = buffer + read;
+ while (read > 0) {
+ char *ptr;
+
+ /* read all complete lines in buffer */
+ while (end > buffer) {
+ char *hold = NULL;
+ for (ptr = buffer; (ptr < end) && *ptr && (*ptr != '\n'); ptr++);
+ if (ptr == end)
+ break;
+ if (*ptr)
+ hold = ptr+1;
+ *ptr = 0;
+
+ /* treat the line */
+ parse_line (buffer, type);
+
+ if (hold) {
+ int l = end - hold;
+ end -= hold - buffer;
+ memmove (buffer, hold, l);
+ }
+ else
+ break;
+ }
+
+ read = fread (end, 1, BUFSIZE - (end - buffer), stream);
+ end += read;
+ }
+}
+
diff --git a/providers/oracle/libmain.c b/providers/oracle/libmain.c
index d523449..82ae921 100644
--- a/providers/oracle/libmain.c
+++ b/providers/oracle/libmain.c
@@ -1,9 +1,8 @@
/* GDA Oracle Provider
- * Copyright (C) 1998 - 2007 The GNOME Foundation
+ * Copyright (C) 2008 The GNOME Foundation
*
* AUTHORS:
- * Tim Coleman <tim timcoleman com>
- * Vivien Malerba <malerba gnome-db org>
+ * TO_ADD: your name and email
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -21,9 +20,11 @@
*/
#include <glib/gi18n-lib.h>
-#include "gda-oracle-provider.h"
+#include <gmodule.h>
#include <libgda/gda-server-provider-extra.h>
#include <libgda/binreloc/gda-binreloc.h>
+#include "gda-oracle.h"
+#include "gda-oracle-provider.h"
static gchar *module_path = NULL;
const gchar *plugin_get_name (void);
@@ -31,6 +32,26 @@ const gchar *plugin_get_description (void);
gchar *plugin_get_dsn_spec (void);
GdaServerProvider *plugin_create_provider (void);
+/*
+ * Functions executed when calling g_module_open() and g_module_close()
+ */
+const gchar *
+g_module_check_init (GModule *module)
+{
+ /*g_module_make_resident (module);*/
+ return NULL;
+}
+
+void
+g_module_unload (GModule *module)
+{
+ g_free (module_path);
+ module_path = NULL;
+}
+
+/*
+ * Normal plugin functions
+ */
void
plugin_init (const gchar *real_path)
{
@@ -41,13 +62,13 @@ plugin_init (const gchar *real_path)
const gchar *
plugin_get_name (void)
{
- return "Oracle";
+ return ORACLE_PROVIDER_NAME;
}
const gchar *
plugin_get_description (void)
{
- return _("Provider for Oracle databases");
+ return _("Example provider for C API databases");
}
gchar *
@@ -66,7 +87,7 @@ plugin_create_provider (void)
{
GdaServerProvider *prov;
- prov = gda_oracle_provider_new ();
+ prov = (GdaServerProvider*) g_object_new (GDA_TYPE_ORACLE_PROVIDER, NULL);
g_object_set_data ((GObject *) prov, "GDA_PROVIDER_DIR", module_path);
return prov;
}
diff --git a/providers/oracle/oracle_specs_create_table.xml.in b/providers/oracle/oracle_specs_create_table.xml.in
new file mode 100644
index 0000000..ede3155
--- /dev/null
+++ b/providers/oracle/oracle_specs_create_table.xml.in
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<serv_op>
+ <parameters id="TABLE_DEF_P" _name="Table's description">
+ <parameter id="TABLE_NAME" _name="Name" _descr="Table's name" gdatype="gchararray" nullok="FALSE">
+ <gda_value>table_name</gda_value>
+ </parameter>
+ </parameters>
+
+ <!-- list of fields -->
+ <gda_array id="FIELDS_A" _name="Table's columns">
+ <gda_array_field id="COLUMN_NAME" _name="Field name" gdatype="gchararray" nullok="FALSE"/>
+ <gda_array_field id="COLUMN_TYPE" _name="Data type" gdatype="gchararray" hint="datatype" nullok="FALSE"/>
+ <gda_array_field id="COLUMN_NNUL" _name="Not NULL" gdatype="gboolean"/>
+ <gda_array_field id="COLUMN_UNIQUE" _name="Unique" gdatype="gboolean"/>
+ <gda_array_field id="COLUMN_PKEY" _name="Primary key" gdatype="gboolean"/>
+ <gda_array_field id="COLUMN_DEFAULT" _name="Default" _descr="Default value" gdatype="gchararray"/>
+ <gda_array_field id="COLUMN_CHECK" _name="Check" _descr="Check constraint" gdatype="gchararray"/>
+ </gda_array>
+
+ <!-- other table constraints -->
+ <sequence id="TABLE_CONSTRAINTS_S" _name="Global constraints">
+ <parameter id="CONSTRAINT_STRING" name="Constraint" gdatype="gchararray">
+ <gda_value>CHECK (column > 0)</gda_value>
+ </parameter>
+ </sequence>
+</serv_op>
diff --git a/providers/oracle/oracle_specs_dsn.xml.in b/providers/oracle/oracle_specs_dsn.xml.in
index c3885bc..c8d7f9d 100644
--- a/providers/oracle/oracle_specs_dsn.xml.in
+++ b/providers/oracle/oracle_specs_dsn.xml.in
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<data-set-spec>
<parameters>
- <parameter id="TNSNAME" _name="TNS Name" _descr="Name of the TNS configuration to use when connecting" gdatype="gchararray" nullok="FALSE"/>
+ <parameter id="DB_NAME" _name="Database name" _descr="The name of a database to use" gdatype="gchararray" nullok="FALSE"/>
</parameters>
</data-set-spec>
diff --git a/providers/oracle/parser.y b/providers/oracle/parser.y
new file mode 100644
index 0000000..1df4145
--- /dev/null
+++ b/providers/oracle/parser.y
@@ -0,0 +1,1008 @@
+// All token codes are small integers with #defines that begin with "TK_"
+%token_prefix T_
+
+// The type of the data attached to each token is GValue. This is also the
+// default type for non-terminals.
+//
+%token_type {GValue *}
+%default_type {GValue *}
+%token_destructor {if ($$) {
+#ifdef GDA_DEBUG_NO
+ gchar *str = gda_sql_value_stringify ($$);
+ g_print ("___ token destructor /%s/\n", str)
+ g_free (str);
+#endif
+ g_value_unset ($$); g_free ($$);}}
+
+// The generated parser function takes a 4th argument as follows:
+%extra_argument {GdaSqlParserIface *pdata}
+
+// This code runs whenever there is a syntax error
+//
+%syntax_error {
+ gda_sql_parser_set_syntax_error (pdata->parser);
+}
+%stack_overflow {
+ gda_sql_parser_set_overflow_error (pdata->parser);
+}
+
+// The name of the generated procedure that implements the parser
+// is as follows:
+%name gda_lemon_oracle_parser
+
+// The following text is included near the beginning of the C source
+// code file that implements the parser.
+//
+%include {
+#include <string.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+#include <libgda/sql-parser/gda-sql-parser-private.h>
+#include <libgda/sql-parser/gda-statement-struct-util.h>
+#include <libgda/sql-parser/gda-statement-struct-trans.h>
+#include <libgda/sql-parser/gda-statement-struct-insert.h>
+#include <libgda/sql-parser/gda-statement-struct-update.h>
+#include <libgda/sql-parser/gda-statement-struct-delete.h>
+#include <libgda/sql-parser/gda-statement-struct-select.h>
+#include <libgda/sql-parser/gda-statement-struct-compound.h>
+#include <libgda/sql-parser/gda-statement-struct-parts.h>
+#include <assert.h>
+
+typedef struct {
+ GValue *fname;
+ GdaSqlExpr *expr;
+} UpdateSet;
+
+typedef struct {
+ gboolean distinct;
+ GdaSqlExpr *expr;
+} Distinct;
+
+typedef struct {
+ GdaSqlExpr *count;
+ GdaSqlExpr *offset;
+} Limit;
+
+typedef struct {
+ GSList *when_list;
+ GSList *then_list;
+} CaseBody;
+
+static GdaSqlOperatorType
+sql_operation_string_to_operator (const gchar *op)
+{
+ switch (g_ascii_toupper (*op)) {
+ case 'A':
+ return GDA_SQL_OPERATOR_TYPE_AND;
+ case 'O':
+ return GDA_SQL_OPERATOR_TYPE_OR;
+ case 'N':
+ return GDA_SQL_OPERATOR_TYPE_NOT;
+ case '=':
+ return GDA_SQL_OPERATOR_TYPE_EQ;
+ case 'I':
+ if (op[1] == 'S')
+ return GDA_SQL_OPERATOR_TYPE_IS;
+ else if (op[1] == 'N')
+ return GDA_SQL_OPERATOR_TYPE_IN;
+ break;
+ case 'L':
+ return GDA_SQL_OPERATOR_TYPE_LIKE;
+ case 'B':
+ return GDA_SQL_OPERATOR_TYPE_BETWEEN;
+ case '>':
+ if (op[1] == '=')
+ return GDA_SQL_OPERATOR_TYPE_GEQ;
+ else if (op[1] == 0)
+ return GDA_SQL_OPERATOR_TYPE_GT;
+ break;
+ case '<':
+ if (op[1] == '=')
+ return GDA_SQL_OPERATOR_TYPE_LEQ;
+ else if (op[1] == '>')
+ return GDA_SQL_OPERATOR_TYPE_DIFF;
+ else if (op[1] == 0)
+ return GDA_SQL_OPERATOR_TYPE_LT;
+ break;
+ case '!':
+ if (op[1] == '=')
+ return GDA_SQL_OPERATOR_TYPE_DIFF;
+ else if (op[1] == '~') {
+ if (op[2] == 0)
+ return GDA_SQL_OPERATOR_TYPE_NOT_REGEXP;
+ else if (op[2] == '*')
+ return GDA_SQL_OPERATOR_TYPE_NOT_REGEXP_CI;
+ }
+ break;
+ case '~':
+ if (op[1] == '*')
+ return GDA_SQL_OPERATOR_TYPE_REGEXP_CI;
+ else if (op[1] == 0)
+ return GDA_SQL_OPERATOR_TYPE_REGEXP;
+ break;
+ case 'S':
+ return GDA_SQL_OPERATOR_TYPE_SIMILAR;
+ case '|':
+ if (op[1] == '|')
+ return GDA_SQL_OPERATOR_TYPE_CONCAT;
+ else
+ return GDA_SQL_OPERATOR_TYPE_BITOR;
+ case '+':
+ return GDA_SQL_OPERATOR_TYPE_PLUS;
+ case '-':
+ return GDA_SQL_OPERATOR_TYPE_MINUS;
+ case '*':
+ return GDA_SQL_OPERATOR_TYPE_STAR;
+ case '/':
+ return GDA_SQL_OPERATOR_TYPE_DIV;
+ case '%':
+ return GDA_SQL_OPERATOR_TYPE_REM;
+ case '&':
+ return GDA_SQL_OPERATOR_TYPE_BITAND;
+ }
+ g_error ("Unhandled operator named '%s'\n", op);
+ return 0;
+}
+
+static GdaSqlOperatorType
+string_to_op_type (GValue *value)
+{
+ GdaSqlOperatorType op;
+ op = sql_operation_string_to_operator (g_value_get_string (value));
+ g_value_reset (value);
+ g_free (value);
+ return op;
+}
+
+static GdaSqlExpr *
+compose_multiple_expr (GdaSqlOperatorType op, GdaSqlExpr *left, GdaSqlExpr *right) {
+ GdaSqlExpr *ret;
+ if (left->cond && (left->cond->operator_type == op)) {
+ ret = left;
+ ret->cond->operands = g_slist_append (ret->cond->operands, right);
+ }
+ else {
+ GdaSqlOperation *cond;
+ ret = gda_sql_expr_new (NULL);
+ cond = gda_sql_operation_new (GDA_SQL_ANY_PART (ret));
+ ret->cond = cond;
+ cond->operator_type = op;
+ cond->operands = g_slist_prepend (NULL, right);
+ GDA_SQL_ANY_PART (right)->parent = GDA_SQL_ANY_PART (cond);
+ cond->operands = g_slist_prepend (cond->operands, left);
+ GDA_SQL_ANY_PART (left)->parent = GDA_SQL_ANY_PART (cond);
+ }
+ return ret;
+}
+
+static GdaSqlExpr *
+create_two_expr (GdaSqlOperatorType op, GdaSqlExpr *left, GdaSqlExpr *right) {
+ GdaSqlExpr *ret;
+ GdaSqlOperation *cond;
+ ret = gda_sql_expr_new (NULL);
+ cond = gda_sql_operation_new (GDA_SQL_ANY_PART (ret));
+ ret->cond = cond;
+ cond->operator_type = op;
+ cond->operands = g_slist_prepend (NULL, right);
+ GDA_SQL_ANY_PART (right)->parent = GDA_SQL_ANY_PART (cond);
+ cond->operands = g_slist_prepend (cond->operands, left);
+ GDA_SQL_ANY_PART (left)->parent = GDA_SQL_ANY_PART (cond);
+ return ret;
+}
+
+static GdaSqlExpr *
+create_uni_expr (GdaSqlOperatorType op, GdaSqlExpr *expr) {
+ GdaSqlExpr *ret;
+ GdaSqlOperation *cond;
+ ret = gda_sql_expr_new (NULL);
+ cond = gda_sql_operation_new (GDA_SQL_ANY_PART (ret));
+ ret->cond = cond;
+ cond->operator_type = op;
+ cond->operands = g_slist_prepend (NULL, expr);
+ GDA_SQL_ANY_PART (expr)->parent = GDA_SQL_ANY_PART (cond);
+ return ret;
+}
+
+static GdaSqlStatement *
+compose_multiple_compounds (GdaSqlStatementCompoundType ctype, GdaSqlStatement *left, GdaSqlStatement *right) {
+ GdaSqlStatement *ret;
+ GdaSqlStatementCompound *lc = (GdaSqlStatementCompound*) left->contents;
+ if (lc->compound_type == ctype) {
+ GdaSqlStatementCompound *rc = (GdaSqlStatementCompound*) right->contents;
+ if (!rc->stmt_list->next || rc->compound_type == ctype) {
+ GSList *list;
+ for (list = rc->stmt_list; list; list = list->next)
+ GDA_SQL_ANY_PART (((GdaSqlStatement*)list->data)->contents)->parent = GDA_SQL_ANY_PART (lc);
+
+ ret = left;
+ lc->stmt_list = g_slist_concat (lc->stmt_list, rc->stmt_list);
+ rc->stmt_list = NULL;
+ gda_sql_statement_free (right);
+ }
+ }
+ else {
+ ret = gda_sql_statement_new (GDA_SQL_STATEMENT_COMPOUND);
+ gda_sql_statement_compound_set_type (ret, ctype);
+ gda_sql_statement_compound_take_stmt (ret, left);
+ gda_sql_statement_compound_take_stmt (ret, right);
+ }
+ return ret;
+}
+
+}
+
+// The following directive causes tokens ABORT, AFTER, ASC, etc. to
+// fallback to ID if they will not parse as their original value.
+%fallback ID
+ ABORT AFTER ANALYZE ASC ATTACH BEFORE BEGIN CASCADE CAST CONFLICT
+ DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
+ IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH PLAN
+ QUERY KEY OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW
+ TEMP TRIGGER VACUUM VIEW VIRTUAL
+ REINDEX RENAME CTIME_KW IF
+ DELIMITER COMMIT ROLLBACK ISOLATION LEVEL SERIALIZABLE READ COMMITTED
+ UNCOMMITTED REPEATABLE WRITE ONLY SAVEPOINT RELEASE COMMENT FORCE WAIT NOWAIT BATCH.
+
+// Define operator precedence early so that this is the first occurance
+// of the operator tokens in the grammer. Keeping the operators together
+// causes them to be assigned integer values that are close together,
+// which keeps parser tables smaller.
+%left OR.
+%left AND.
+%right NOT.
+%left IS MATCH LIKE IN ISNULL NOTNULL DIFF EQ.
+%left BETWEEN.
+%left GT LEQ LT GEQ.
+%left REGEXP REGEXP_CI NOT_REGEXP NOT_REGEXP_CI.
+%left SIMILAR.
+%right ESCAPE.
+%left BITAND BITOR LSHIFT RSHIFT.
+%left PLUS MINUS.
+%left STAR SLASH REM.
+%left CONCAT.
+%left COLLATE.
+%right UMINUS UPLUS BITNOT.
+%left LP RP.
+%left JOIN INNER NATURAL LEFT RIGHT FULL CROSS.
+%left UNION EXCEPT.
+%left INTERSECT.
+%left PGCAST.
+
+// force the declaration of the ILLEGAL and SQLCOMMENT tokens
+%nonassoc ILLEGAL.
+%nonassoc SQLCOMMENT.
+
+// Input is a single SQL command
+%type stmt {GdaSqlStatement *}
+%destructor stmt {g_print ("Statement destroyed by parser: %p\n", $$); gda_sql_statement_free ($$);}
+stmt ::= cmd(C) eos. {pdata->parsed_statement = C;}
+stmt ::= compound(C) eos. {
+ GdaSqlStatementCompound *scompound = (GdaSqlStatementCompound *) C->contents;
+ if (scompound->stmt_list->next)
+ /* real compound (multiple statements) */
+ pdata->parsed_statement = C;
+ else {
+ /* false compound (only 1 select) */
+ pdata->parsed_statement = (GdaSqlStatement*) scompound->stmt_list->data;
+ GDA_SQL_ANY_PART (pdata->parsed_statement->contents)->parent = NULL;
+ g_slist_free (scompound->stmt_list);
+ scompound->stmt_list = NULL;
+ gda_sql_statement_free (C);
+ }
+}
+cmd(C) ::= LP cmd(E) RP. {C = E;}
+compound(C) ::= LP compound(E) RP. {C = E;}
+
+eos ::= SEMI.
+eos ::= END_OF_FILE.
+
+%type cmd {GdaSqlStatement *}
+%destructor cmd {gda_sql_statement_free ($$);}
+
+//
+// Transactions
+//
+cmd(C) ::= BEGIN. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);}
+cmd(C) ::= BEGIN TRANSACTION nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+ gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= BEGIN transtype(Y) TRANSACTION nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+ gda_sql_statement_trans_take_mode (C, Y);
+ gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= BEGIN transtype(Y) nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+ gda_sql_statement_trans_take_mode (C, Y);
+ gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= BEGIN transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+ gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+ gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transtype(Y). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+ gda_sql_statement_trans_take_mode (C, Y);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transtype(Y) opt_comma transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+ gda_sql_statement_trans_take_mode (C, Y);
+ gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN TRANSACTION transilev(L) opt_comma transtype(Y). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+ gda_sql_statement_trans_take_mode (C, Y);
+ gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN transtype(Y) opt_comma transilev(L). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+ gda_sql_statement_trans_take_mode (C, Y);
+ gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= BEGIN transilev(L) opt_comma transtype(Y). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_BEGIN);
+ gda_sql_statement_trans_take_mode (C, Y);
+ gda_sql_statement_trans_set_isol_level (C, L);
+}
+
+cmd(C) ::= END trans_opt_kw nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);
+ gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= COMMIT nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);
+ gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= COMMIT TRANSACTION nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);
+ gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= COMMIT FORCE STRING. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT FORCE STRING COMMA INTEGER. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT COMMENT STRING. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT COMMENT STRING ora_commit_write. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+cmd(C) ::= COMMIT ora_commit_write. {C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMMIT);}
+
+cmd(C) ::= ROLLBACK trans_opt_kw nm_opt(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_ROLLBACK);
+ gda_sql_statement_trans_take_name (C, R);
+}
+
+ora_commit_write ::= WRITE IMMEDIATE.
+ora_commit_write ::= WRITE BATCH.
+ora_commit_write ::= WRITE WAIT.
+ora_commit_write ::= WRITE NOWAIT.
+ora_commit_write ::= WRITE IMMEDIATE WAIT.
+ora_commit_write ::= WRITE IMMEDIATE NOWAIT.
+ora_commit_write ::= WRITE BATCH WAIT.
+ora_commit_write ::= WRITE BATCH NOWAIT.
+
+trans_opt_kw ::= .
+trans_opt_kw ::= TRANSACTION.
+
+opt_comma ::= .
+opt_comma ::= COMMA.
+
+%type transilev {GdaTransactionIsolation}
+transilev(L) ::= ISOLATION LEVEL SERIALIZABLE. {L = GDA_TRANSACTION_ISOLATION_SERIALIZABLE;}
+transilev(L) ::= ISOLATION LEVEL REPEATABLE READ. {L = GDA_TRANSACTION_ISOLATION_REPEATABLE_READ;}
+transilev(L) ::= ISOLATION LEVEL READ COMMITTED. {L = GDA_TRANSACTION_ISOLATION_READ_COMMITTED;}
+transilev(L) ::= ISOLATION LEVEL READ UNCOMMITTED. {L = GDA_TRANSACTION_ISOLATION_READ_UNCOMMITTED;}
+
+nm_opt(R) ::= . {R = NULL;}
+nm_opt(R) ::= nm(N). {R = N;}
+
+transtype(A) ::= DEFERRED(X). {A = X;}
+transtype(A) ::= IMMEDIATE(X). {A = X;}
+transtype(A) ::= EXCLUSIVE(X). {A = X;}
+transtype(A) ::= READ WRITE. {A = g_new0 (GValue, 1);
+ g_value_init (A, G_TYPE_STRING);
+ g_value_set_string (A, "READ_WRITE");
+}
+transtype(A) ::= READ ONLY. {A = g_new0 (GValue, 1);
+ g_value_init (A, G_TYPE_STRING);
+ g_value_set_string (A, "READ_ONLY");
+}
+
+//
+// Savepoints
+//
+cmd(C) ::= SAVEPOINT nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_SAVEPOINT);
+ gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= RELEASE SAVEPOINT nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_DELETE_SAVEPOINT);
+ gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= RELEASE nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_DELETE_SAVEPOINT);
+ gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= ROLLBACK trans_opt_kw TO nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_ROLLBACK_SAVEPOINT);
+ gda_sql_statement_trans_take_name (C, R);
+}
+
+cmd(C) ::= ROLLBACK trans_opt_kw TO SAVEPOINT nm(R). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_ROLLBACK_SAVEPOINT);
+ gda_sql_statement_trans_take_name (C, R);
+}
+
+//
+// INSERT
+//
+cmd(C) ::= INSERT opt_on_conflict(O) INTO fullname(X) inscollist_opt(F) VALUES LP exprlist(Y) RP. {
+ C = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT);
+ gda_sql_statement_insert_take_table_name (C, X);
+ gda_sql_statement_insert_take_fields_list (C, F);
+ gda_sql_statement_insert_take_1_values_list (C, Y);
+ gda_sql_statement_insert_take_on_conflict (C, O);
+}
+
+cmd(C) ::= INSERT opt_on_conflict(O) INTO fullname(X) inscollist_opt(F) VALUES LP exprlist(Y) RP ins_extra_values(E). {
+ C = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT);
+ gda_sql_statement_insert_take_table_name (C, X);
+ gda_sql_statement_insert_take_fields_list (C, F);
+ gda_sql_statement_insert_take_1_values_list (C, Y);
+ gda_sql_statement_insert_take_extra_values_list (C, E);
+ gda_sql_statement_insert_take_on_conflict (C, O);
+}
+
+cmd(C) ::= INSERT opt_on_conflict(O) INTO fullname(X) inscollist_opt(F) compound(S). {
+ C = gda_sql_statement_new (GDA_SQL_STATEMENT_INSERT);
+ gda_sql_statement_insert_take_table_name (C, X);
+ gda_sql_statement_insert_take_fields_list (C, F);
+ gda_sql_statement_insert_take_select (C, S);
+ gda_sql_statement_insert_take_on_conflict (C, O);
+}
+
+
+opt_on_conflict(O) ::= . {O = NULL;}
+opt_on_conflict(O) ::= OR ID(V). {O = V;}
+
+%type ins_extra_values {GSList*}
+%destructor ins_extra_values {GSList *list;
+ for (list = $$; list; list = list->next) {
+ g_slist_foreach ((GSList*) list->data, (GFunc) gda_sql_field_free, NULL);
+ g_slist_free ((GSList*) list->data);
+ }
+ g_slist_free ($$);
+}
+ins_extra_values(E) ::= ins_extra_values(A) COMMA LP exprlist(L) RP. {E = g_slist_append (A, L);}
+ins_extra_values(E) ::= COMMA LP exprlist(L) RP. {E = g_slist_append (NULL, L);}
+
+%type inscollist_opt {GSList*}
+%destructor inscollist_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_field_free, NULL); g_slist_free ($$);}}
+inscollist_opt(A) ::= . {A = NULL;}
+inscollist_opt(A) ::= LP inscollist(X) RP. {A = X;}
+
+%type inscollist {GSList*}
+%destructor inscollist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_field_free, NULL); g_slist_free ($$);}}
+inscollist(A) ::= inscollist(X) COMMA fullname(Y). {GdaSqlField *field;
+ field = gda_sql_field_new (NULL);
+ gda_sql_field_take_name (field, Y);
+ A = g_slist_append (X, field);
+}
+inscollist(A) ::= fullname(Y). {GdaSqlField *field = gda_sql_field_new (NULL);
+ gda_sql_field_take_name (field, Y);
+ A = g_slist_prepend (NULL, field);
+}
+
+// DELETE
+cmd(C) ::= DELETE FROM fullname(T) where_opt(X). {C = gda_sql_statement_new (GDA_SQL_STATEMENT_DELETE);
+ gda_sql_statement_delete_take_table_name (C, T);
+ gda_sql_statement_delete_take_condition (C, X);}
+
+%type where_opt {GdaSqlExpr *}
+%destructor where_opt {gda_sql_expr_free ($$);}
+where_opt(A) ::= . {A = NULL;}
+where_opt(A) ::= WHERE expr(X). {A = X;}
+
+// UPDATE
+cmd(C) ::= UPDATE opt_on_conflict(O) fullname(T) SET setlist(S) where_opt(X). {
+ GSList *list;
+ C = gda_sql_statement_new (GDA_SQL_STATEMENT_UPDATE);
+ gda_sql_statement_update_take_table_name (C, T);
+ gda_sql_statement_update_take_on_conflict (C, O);
+ gda_sql_statement_update_take_condition (C, X);
+ for (list = S; list; list = list->next) {
+ UpdateSet *set = (UpdateSet*) list->data;
+ gda_sql_statement_update_take_set_value (C, set->fname, set->expr);
+ g_free (set);
+ }
+ g_slist_free (S);
+}
+
+%type setlist {GSList*}
+%destructor setlist {GSList *list;
+ for (list = $$; list; list = list->next) {
+ UpdateSet *set = (UpdateSet*) list->data;
+ g_value_reset (set->fname); g_free (set->fname);
+ gda_sql_expr_free (set->expr);
+ g_free (set);
+ }
+ g_slist_free ($$);
+}
+setlist(A) ::= setlist(Z) COMMA fullname(X) EQ expr(Y). {UpdateSet *set;
+ set = g_new (UpdateSet, 1);
+ set->fname = X;
+ set->expr = Y;
+ A = g_slist_append (Z, set);
+}
+setlist(A) ::= fullname(X) EQ expr(Y). {UpdateSet *set;
+ set = g_new (UpdateSet, 1);
+ set->fname = X;
+ set->expr = Y;
+ A = g_slist_append (NULL, set);
+}
+
+// COMPOUND SELECT
+%type compound {GdaSqlStatement *}
+%destructor compound {gda_sql_statement_free ($$);}
+//compound(C) ::= LP compound(E) RP. {C = E;}
+compound(C) ::= selectcmd(S). {
+ C = gda_sql_statement_new (GDA_SQL_STATEMENT_COMPOUND);
+ gda_sql_statement_compound_take_stmt (C, S);
+}
+compound(C) ::= compound(L) UNION opt_compound_all(A) compound(R). {
+ C = compose_multiple_compounds (A ? GDA_SQL_STATEMENT_COMPOUND_UNION_ALL : GDA_SQL_STATEMENT_COMPOUND_UNION,
+ L, R);
+}
+
+compound(C) ::= compound(L) EXCEPT opt_compound_all(A) compound(R). {
+ C = compose_multiple_compounds (A ? GDA_SQL_STATEMENT_COMPOUND_EXCEPT_ALL : GDA_SQL_STATEMENT_COMPOUND_EXCEPT,
+ L, R);
+}
+
+compound(C) ::= compound(L) INTERSECT opt_compound_all(A) compound(R). {
+ C = compose_multiple_compounds (A ? GDA_SQL_STATEMENT_COMPOUND_INTERSECT_ALL : GDA_SQL_STATEMENT_COMPOUND_INTERSECT,
+ L, R);
+}
+
+%type opt_compound_all {gboolean}
+opt_compound_all(A) ::= . {A = FALSE;}
+opt_compound_all(A) ::= ALL. {A = TRUE;}
+
+
+// SELECT
+%type selectcmd {GdaSqlStatement *}
+%destructor selectcmd {gda_sql_statement_free ($$);}
+selectcmd(C) ::= SELECT distinct(D) selcollist(W) from(F) where_opt(Y)
+ groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
+ C = gda_sql_statement_new (GDA_SQL_STATEMENT_SELECT);
+ if (D) {
+ gda_sql_statement_select_take_distinct (C, D->distinct, D->expr);
+ g_free (D);
+ }
+ gda_sql_statement_select_take_expr_list (C, W);
+ gda_sql_statement_select_take_from (C, F);
+ gda_sql_statement_select_take_where_cond (C, Y);
+ gda_sql_statement_select_take_group_by (C, P);
+ gda_sql_statement_select_take_having_cond (C, Q);
+ gda_sql_statement_select_take_order_by (C, Z);
+ gda_sql_statement_select_take_limits (C, L.count, L.offset);
+}
+
+%type limit_opt {Limit}
+%destructor limit_opt {gda_sql_expr_free ($$.count); gda_sql_expr_free ($$.offset);}
+limit_opt(A) ::= . {A.count = NULL; A.offset = NULL;}
+limit_opt(A) ::= LIMIT expr(X). {A.count = X; A.offset = NULL;}
+limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y). {A.count = X; A.offset = Y;}
+limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). {A.count = X; A.offset = Y;}
+
+%type orderby_opt {GSList *}
+%destructor orderby_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_select_order_free, NULL); g_slist_free ($$);}}
+orderby_opt(A) ::= . {A = 0;}
+orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;}
+
+%type sortlist {GSList *}
+%destructor sortlist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_select_order_free, NULL); g_slist_free ($$);}}
+sortlist(A) ::= sortlist(X) COMMA expr(Y) sortorder(Z). {GdaSqlSelectOrder *order;
+ order = gda_sql_select_order_new (NULL);
+ order->expr = Y;
+ order->asc = Z;
+ A = g_slist_append (X, order);
+}
+sortlist(A) ::= expr(Y) sortorder(Z). {GdaSqlSelectOrder *order;
+ order = gda_sql_select_order_new (NULL);
+ order->expr = Y;
+ order->asc = Z;
+ A = g_slist_prepend (NULL, order);
+}
+
+%type sortorder {gboolean}
+sortorder(A) ::= ASC. {A = TRUE;}
+sortorder(A) ::= DESC. {A = FALSE;}
+sortorder(A) ::= . {A = TRUE;}
+
+
+%type having_opt {GdaSqlExpr *}
+%destructor having_opt {gda_sql_expr_free ($$);}
+having_opt(A) ::= . {A = NULL;}
+having_opt(A) ::= HAVING expr(X). {A = X;}
+
+%type groupby_opt {GSList*}
+%destructor groupby_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$);}}
+groupby_opt(A) ::= . {A = 0;}
+groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}
+
+%type from {GdaSqlSelectFrom *}
+%destructor from {gda_sql_select_from_free ($$);}
+from(F) ::= . {F = NULL;}
+from(F) ::= FROM seltablist(X). {F = X;}
+
+%type seltablist {GdaSqlSelectFrom *}
+%destructor seltablist {gda_sql_select_from_free ($$);}
+%type stl_prefix {GdaSqlSelectFrom *}
+%destructor stl_prefix {gda_sql_select_from_free ($$);}
+
+seltablist(L) ::= stl_prefix(P) seltarget(T) on_cond(C) using_opt(U). {
+ GSList *last;
+ if (P)
+ L = P;
+ else
+ L = gda_sql_select_from_new (NULL);
+ gda_sql_select_from_take_new_target (L, T);
+ last = g_slist_last (L->joins);
+ if (last) {
+ GdaSqlSelectJoin *join = (GdaSqlSelectJoin *) (last->data);
+ join->expr = C;
+ join->position = g_slist_length (L->targets) - 1;
+ join->use = U;
+ }
+}
+
+%type using_opt {GSList*}
+%destructor using_opt {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_field_free, NULL); g_slist_free ($$);}}
+using_opt(U) ::= USING LP inscollist(L) RP. {U = L;}
+using_opt(U) ::= . {U = NULL;}
+
+stl_prefix(P) ::= . {P = NULL;}
+stl_prefix(P) ::= seltablist(L) jointype(J). {GdaSqlSelectJoin *join;
+ P = L;
+ join = gda_sql_select_join_new (GDA_SQL_ANY_PART (P));
+ join->type = J;
+ gda_sql_select_from_take_new_join (P, join);
+}
+
+
+%type on_cond {GdaSqlExpr *}
+%destructor on_cond {gda_sql_expr_free ($$);}
+on_cond(N) ::= ON expr(E). {N = E;}
+on_cond(N) ::= . {N = NULL;}
+
+%type jointype {GdaSqlSelectJoinType}
+jointype(J) ::= COMMA. {J = GDA_SQL_SELECT_JOIN_CROSS;}
+jointype(J) ::= JOIN. {J = GDA_SQL_SELECT_JOIN_INNER;}
+jointype(J) ::= CROSS JOIN. {J = GDA_SQL_SELECT_JOIN_CROSS;}
+jointype(J) ::= INNER JOIN. {J = GDA_SQL_SELECT_JOIN_INNER;}
+jointype(J) ::= NATURAL JOIN. {J = GDA_SQL_SELECT_JOIN_NATURAL;}
+jointype(J) ::= LEFT JOIN. {J = GDA_SQL_SELECT_JOIN_LEFT;}
+jointype(J) ::= LEFT OUTER JOIN. {J = GDA_SQL_SELECT_JOIN_LEFT;}
+jointype(J) ::= RIGHT JOIN. {J = GDA_SQL_SELECT_JOIN_RIGHT;}
+jointype(J) ::= RIGHT OUTER JOIN. {J = GDA_SQL_SELECT_JOIN_RIGHT;}
+jointype(J) ::= FULL JOIN. {J = GDA_SQL_SELECT_JOIN_FULL;}
+jointype(J) ::= FULL OUTER JOIN. {J = GDA_SQL_SELECT_JOIN_FULL;}
+
+
+%type seltarget {GdaSqlSelectTarget *}
+%destructor seltarget {gda_sql_select_target_free ($$);}
+seltarget(T) ::= fullname(F) as(A). {T = gda_sql_select_target_new (NULL);
+ gda_sql_select_target_take_alias (T, A);
+ gda_sql_select_target_take_table_name (T, F);
+}
+seltarget(T) ::= fullname(F) ID(A). {T = gda_sql_select_target_new (NULL);
+ gda_sql_select_target_take_alias (T, A);
+ gda_sql_select_target_take_table_name (T, F);
+}
+seltarget(T) ::= LP compound(S) RP as(A). {T = gda_sql_select_target_new (NULL);
+ gda_sql_select_target_take_alias (T, A);
+ gda_sql_select_target_take_select (T, S);
+}
+
+%type selcollist {GSList *}
+%destructor selcollist {g_slist_foreach ($$, (GFunc) gda_sql_select_field_free, NULL); g_slist_free ($$);}
+
+%type sclp {GSList *}
+%destructor sclp {g_slist_foreach ($$, (GFunc) gda_sql_select_field_free, NULL); g_slist_free ($$);}
+sclp(A) ::= selcollist(X) COMMA. {A = X;}
+sclp(A) ::= . {A = NULL;}
+
+selcollist(L) ::= sclp(E) expr(X) as(A). {GdaSqlSelectField *field;
+ field = gda_sql_select_field_new (NULL);
+ gda_sql_select_field_take_expr (field, X);
+ gda_sql_select_field_take_alias (field, A);
+ L = g_slist_append (E, field);}
+selcollist(L) ::= sclp(E) starname(X). {GdaSqlSelectField *field;
+ field = gda_sql_select_field_new (NULL);
+ gda_sql_select_field_take_star_value (field, X);
+ L = g_slist_append (E, field);}
+
+starname(S) ::= STAR(X). {S = X;}
+starname(A) ::= nm(S) DOT STAR(X). {gchar *str;
+ str = g_strdup_printf ("%s.%s", g_value_get_string (S), g_value_get_string (X));
+ A = g_new0 (GValue, 1);
+ g_value_init (A, G_TYPE_STRING);
+ g_value_take_string (A, str);
+ g_value_reset (S); g_free (S);
+ g_value_reset (X); g_free (X);
+}
+
+starname(A) ::= nm(C) DOT nm(S) DOT STAR(X). {gchar *str;
+ str = g_strdup_printf ("%s.%s.%s", g_value_get_string (C),
+ g_value_get_string (S), g_value_get_string (X));
+ A = g_new0 (GValue, 1);
+ g_value_init (A, G_TYPE_STRING);
+ g_value_take_string (A, str);
+ g_value_reset (C); g_free (C);
+ g_value_reset (S); g_free (S);
+ g_value_reset (X); g_free (X);
+}
+
+as(A) ::= AS fullname(F). {A = F;}
+as(A) ::= AS value(F). {A = F;}
+as(A) ::= . {A = NULL;}
+
+%type distinct {Distinct *}
+%destructor distinct {if ($$) {if ($$->expr) gda_sql_expr_free ($$->expr); g_free ($$);}}
+distinct(E) ::= . {E = NULL;}
+distinct(E) ::= ALL. {E = NULL;}
+distinct(E) ::= DISTINCT. {E = g_new0 (Distinct, 1); E->distinct = TRUE;}
+distinct(E) ::= DISTINCT ON expr(X). [OR] {E = g_new0 (Distinct, 1); E->distinct = TRUE; E->expr = X;}
+
+// Non empty list of expressions
+%type nexprlist {GSList *}
+%destructor nexprlist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$);}}
+nexprlist(L) ::= nexprlist(E) COMMA expr(X). {L = g_slist_append (E, X);}
+nexprlist(L) ::= expr(E). {L = g_slist_append (NULL, E);}
+
+// List of expressions
+%type exprlist {GSList *}
+%destructor exprlist {if ($$) {g_slist_foreach ($$, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$);}}
+exprlist(L) ::= . {L = NULL;}
+exprlist(L) ::= exprlist(E) COMMA expr(X). {L = g_slist_append (E, X);}
+exprlist(L) ::= expr(E). {L = g_slist_append (NULL, E);}
+
+// A single expression
+%type expr {GdaSqlExpr *}
+%destructor expr {gda_sql_expr_free ($$);}
+expr(E) ::= pvalue(V). {E = V;}
+expr(E) ::= value(V). {E = gda_sql_expr_new (NULL); E->value = V;}
+expr(E) ::= LP expr(X) RP. {E = X;}
+expr(E) ::= fullname(V). {E = gda_sql_expr_new (NULL); E->value = V;}
+expr(E) ::= fullname(V) LP exprlist(A) RP. {GdaSqlFunction *func;
+ E = gda_sql_expr_new (NULL);
+ func = gda_sql_function_new (GDA_SQL_ANY_PART (E));
+ gda_sql_function_take_name (func, V);
+ gda_sql_function_take_args_list (func, A);
+ E->func = func;}
+expr(E) ::= fullname(V) LP compound(S) RP. {GdaSqlFunction *func;
+ GdaSqlExpr *expr;
+ E = gda_sql_expr_new (NULL);
+ func = gda_sql_function_new (GDA_SQL_ANY_PART (E));
+ gda_sql_function_take_name (func, V);
+ expr = gda_sql_expr_new (GDA_SQL_ANY_PART (func));
+ gda_sql_expr_take_select (expr, S);
+ gda_sql_function_take_args_list (func, g_slist_prepend (NULL, expr));
+ E->func = func;}
+expr(E) ::= fullname(V) LP starname(A) RP. {GdaSqlFunction *func;
+ GdaSqlExpr *expr;
+ E = gda_sql_expr_new (NULL);
+ func = gda_sql_function_new (GDA_SQL_ANY_PART (E));
+ gda_sql_function_take_name (func, V);
+ expr = gda_sql_expr_new (GDA_SQL_ANY_PART (func));
+ expr->value = A;
+ gda_sql_function_take_args_list (func, g_slist_prepend (NULL, expr));
+ E->func = func;}
+expr(E) ::= CAST LP expr(A) AS fullname(T) RP. {E = A;
+ A->cast_as = g_value_dup_string (T);
+ g_value_reset (T);
+ g_free (T);}
+expr(E) ::= expr(A) PGCAST fullname(T). {E = A;
+ A->cast_as = g_value_dup_string (T);
+ g_value_reset (T);
+ g_free (T);}
+
+expr(C) ::= expr(L) PLUS|MINUS(O) expr(R). {C = compose_multiple_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) STAR expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_TYPE_STAR, L, R);}
+expr(C) ::= expr(L) SLASH|REM(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) BITAND|BITOR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+
+expr(C) ::= MINUS expr(X). [UMINUS] {C = create_uni_expr (GDA_SQL_OPERATOR_TYPE_MINUS, X);}
+expr(C) ::= PLUS expr(X). [UPLUS] {C = create_uni_expr (GDA_SQL_OPERATOR_TYPE_PLUS, X);}
+
+expr(C) ::= expr(L) AND expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_TYPE_AND, L, R);}
+expr(C) ::= expr(L) OR expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_TYPE_OR, L, R);}
+expr(C) ::= expr(L) CONCAT expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR_TYPE_CONCAT, L, R);}
+
+expr(C) ::= expr(L) GT|LEQ|GEQ|LT(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) DIFF|EQ(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) LIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_LIKE, L, R);}
+expr(C) ::= expr(L) REGEXP|REGEXP_CI|NOT_REGEXP|NOT_REGEXP_CI|SIMILAR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
+expr(C) ::= expr(L) BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
+ C = gda_sql_expr_new (NULL);
+ cond = gda_sql_operation_new (GDA_SQL_ANY_PART (C));
+ C->cond = cond;
+ cond->operator_type = GDA_SQL_OPERATOR_TYPE_BETWEEN;
+ cond->operands = g_slist_append (NULL, L);
+ GDA_SQL_ANY_PART (L)->parent = GDA_SQL_ANY_PART (cond);
+ cond->operands = g_slist_append (cond->operands, R);
+ GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+ cond->operands = g_slist_append (cond->operands, E);
+ GDA_SQL_ANY_PART (E)->parent = GDA_SQL_ANY_PART (cond);
+}
+
+expr(C) ::= expr(L) NOT BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
+ GdaSqlExpr *expr;
+ expr = gda_sql_expr_new (NULL);
+ cond = gda_sql_operation_new (GDA_SQL_ANY_PART (expr));
+ expr->cond = cond;
+ cond->operator_type = GDA_SQL_OPERATOR_TYPE_BETWEEN;
+ cond->operands = g_slist_append (NULL, L);
+ GDA_SQL_ANY_PART (L)->parent = GDA_SQL_ANY_PART (cond);
+ cond->operands = g_slist_append (cond->operands, R);
+ GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+ cond->operands = g_slist_append (cond->operands, E);
+ GDA_SQL_ANY_PART (E)->parent = GDA_SQL_ANY_PART (cond);
+
+ C = gda_sql_expr_new (NULL);
+ cond = gda_sql_operation_new (GDA_SQL_ANY_PART (C));
+ C->cond = cond;
+ cond->operator_type = GDA_SQL_OPERATOR_TYPE_NOT;
+ cond->operands = g_slist_prepend (NULL, expr);
+ GDA_SQL_ANY_PART (expr)->parent = GDA_SQL_ANY_PART (cond);
+}
+
+expr(C) ::= NOT expr(R). {C = create_uni_expr (GDA_SQL_OPERATOR_TYPE_NOT, R);}
+expr(C) ::= BITNOT expr(R). {C = create_uni_expr (GDA_SQL_OPERATOR_TYPE_BITNOT, R);}
+expr(C) ::= expr(R) uni_op(O) . {C = create_uni_expr (O, R);}
+
+expr(C) ::= expr(L) IS expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_IS, L, R);}
+expr(E) ::= LP compound(S) RP. {E = gda_sql_expr_new (NULL); gda_sql_expr_take_select (E, S);}
+expr(E) ::= expr(R) IN LP exprlist(L) RP. {GdaSqlOperation *cond;
+ GSList *list;
+ E = gda_sql_expr_new (NULL);
+ cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+ E->cond = cond;
+ cond->operator_type = GDA_SQL_OPERATOR_TYPE_IN;
+ cond->operands = g_slist_prepend (L, R);
+ for (list = cond->operands; list; list = list->next)
+ GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(E) ::= expr(R) IN LP compound(S) RP. {GdaSqlOperation *cond;
+ GdaSqlExpr *expr;
+ E = gda_sql_expr_new (NULL);
+ cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+ E->cond = cond;
+ cond->operator_type = GDA_SQL_OPERATOR_TYPE_IN;
+
+ expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond));
+ gda_sql_expr_take_select (expr, S);
+ cond->operands = g_slist_prepend (NULL, expr);
+ cond->operands = g_slist_prepend (cond->operands, R);
+ GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(E) ::= expr(R) NOT IN LP exprlist(L) RP. {GdaSqlOperation *cond;
+ GSList *list;
+ E = gda_sql_expr_new (NULL);
+ cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+ E->cond = cond;
+ cond->operator_type = GDA_SQL_OPERATOR_TYPE_NOTIN;
+ cond->operands = g_slist_prepend (L, R);
+ for (list = cond->operands; list; list = list->next)
+ GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(E) ::= expr(R) NOT IN LP compound(S) RP. {GdaSqlOperation *cond;
+ GdaSqlExpr *expr;
+ E = gda_sql_expr_new (NULL);
+ cond = gda_sql_operation_new (GDA_SQL_ANY_PART (E));
+ E->cond = cond;
+ cond->operator_type = GDA_SQL_OPERATOR_TYPE_NOTIN;
+
+ expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond));
+ gda_sql_expr_take_select (expr, S);
+ cond->operands = g_slist_prepend (NULL, expr);
+ cond->operands = g_slist_prepend (cond->operands, R);
+ GDA_SQL_ANY_PART (R)->parent = GDA_SQL_ANY_PART (cond);
+}
+expr(A) ::= CASE case_operand(X) case_exprlist(Y) case_else(Z) END. {
+ GdaSqlCase *sc;
+ GSList *list;
+ A = gda_sql_expr_new (NULL);
+ sc = gda_sql_case_new (GDA_SQL_ANY_PART (A));
+ sc->base_expr = X;
+ sc->else_expr = Z;
+ sc->when_expr_list = Y.when_list;
+ sc->then_expr_list = Y.then_list;
+ A->case_s = sc;
+ for (list = sc->when_expr_list; list; list = list->next)
+ GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (sc);
+ for (list = sc->then_expr_list; list; list = list->next)
+ GDA_SQL_ANY_PART (list->data)->parent = GDA_SQL_ANY_PART (sc);
+}
+
+%type case_operand {GdaSqlExpr*}
+%destructor case_operand {gda_sql_expr_free ($$);}
+case_operand(A) ::= expr(X). {A = X;}
+case_operand(A) ::= . {A = NULL;}
+
+%type case_exprlist {CaseBody}
+%destructor case_exprlist {g_slist_foreach ($$.when_list, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$.when_list);
+ g_slist_foreach ($$.then_list, (GFunc) gda_sql_expr_free, NULL); g_slist_free ($$.then_list);}
+
+case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). {
+ A.when_list = g_slist_append (X.when_list, Y);
+ A.then_list = g_slist_append (X.then_list, Z);
+}
+case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
+ A.when_list = g_slist_prepend (NULL, Y);
+ A.then_list = g_slist_prepend (NULL, Z);
+}
+
+%type case_else {GdaSqlExpr*}
+%destructor case_else {gda_sql_expr_free ($$);}
+case_else(A) ::= ELSE expr(X). {A = X;}
+case_else(A) ::= . {A = NULL;}
+
+%type uni_op {GdaSqlOperatorType}
+uni_op(O) ::= ISNULL. {O = GDA_SQL_OPERATOR_TYPE_ISNULL;}
+uni_op(O) ::= IS NOTNULL. {O = GDA_SQL_OPERATOR_TYPE_ISNOTNULL;}
+
+
+// Values: for all constants (G_TYPE_STRING GValue)
+value(V) ::= NULL. {V = NULL;}
+value(V) ::= STRING(S). {V = S;}
+//value(V) ::= TEXTUAL(T). {V = T;}
+value(V) ::= INTEGER(I). {V = I;}
+value(V) ::= FLOAT(F). {V = F;}
+
+// pvalue: values which are parameters (GdaSqlExpr)
+%type pvalue {GdaSqlExpr *}
+%destructor pvalue {gda_sql_expr_free ($$);}
+pvalue(E) ::= UNSPECVAL LSBRACKET paramspec(P) RSBRACKET. {E = gda_sql_expr_new (NULL); E->param_spec = P;}
+pvalue(E) ::= value(V) LSBRACKET paramspec(P) RSBRACKET. {E = gda_sql_expr_new (NULL); E->value = V; E->param_spec = P;}
+pvalue(E) ::= SIMPLEPARAM(S). {E = gda_sql_expr_new (NULL); E->param_spec = gda_sql_param_spec_new (S);}
+
+// paramspec: parameter's specifications
+%type paramspec {GdaSqlParamSpec *}
+%destructor paramspec {gda_sql_param_spec_free ($$);}
+paramspec(P) ::= . {P = NULL;}
+paramspec(P) ::= paramspec(E) PNAME(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E;
+ gda_sql_param_spec_take_name (P, N);}
+paramspec(P) ::= paramspec(E) PDESCR(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E;
+ gda_sql_param_spec_take_descr (P, N);}
+paramspec(P) ::= paramspec(E) PTYPE(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E;
+ gda_sql_param_spec_take_type (P, N);}
+paramspec(P) ::= paramspec(E) PNULLOK(N). {if (!E) P = gda_sql_param_spec_new (NULL); else P = E;
+ gda_sql_param_spec_take_nullok (P, N);}
+
+// The name of a column or table can be any of the following:
+//
+nm(A) ::= JOIN(X). {A = X;}
+nm(A) ::= ID(X). {A = X;}
+nm(A) ::= TEXTUAL(X). {A = X;}
+
+// Fully qualified name
+fullname(A) ::= nm(X). {A = X;}
+fullname(A) ::= nm(S) DOT nm(X). {gchar *str;
+ str = g_strdup_printf ("%s.%s", g_value_get_string (S), g_value_get_string (X));
+ A = g_new0 (GValue, 1);
+ g_value_init (A, G_TYPE_STRING);
+ g_value_take_string (A, str);
+ g_value_reset (S); g_free (S);
+ g_value_reset (X); g_free (X);
+}
+
+fullname(A) ::= nm(C) DOT nm(S) DOT nm(X). {gchar *str;
+ str = g_strdup_printf ("%s.%s.%s", g_value_get_string (C),
+ g_value_get_string (S), g_value_get_string (X));
+ A = g_new0 (GValue, 1);
+ g_value_init (A, G_TYPE_STRING);
+ g_value_take_string (A, str);
+ g_value_reset (C); g_free (C);
+ g_value_reset (S); g_free (S);
+ g_value_reset (X); g_free (X);
+}
diff --git a/providers/oracle/utils.c b/providers/oracle/utils.c
deleted file mode 100644
index b776e23..0000000
--- a/providers/oracle/utils.c
+++ /dev/null
@@ -1,550 +0,0 @@
-/* GDA Oracle provider
- * Copyright (C) 2002 - 2007 The GNOME Foundation.
- *
- * AUTHORS:
- * Tim Coleman <tim timcoleman com>
- * Vivien Malerba <malerba gnome-db org>
- *
- * Borrowed from Mysql utils.c, written by:
- * Michael Lausch <michael lausch at>
- * Rodrigo Moya <rodrigo gnome-db org>
- * Vivien Malerba <malerba gnome-db org>
- *
- * This Library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this Library; see the file COPYING.LIB. If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <glib/gi18n-lib.h>
-#include <stdlib.h>
-#include <string.h>
-#include "gda-oracle.h"
-#include "gda-oracle-provider.h"
-#include "gda-oracle-blob-op.h"
-
-/*
- * gda_oracle_make_error
- * This function uses OCIErrorGet to get a description of the error to
- * display. The parameters are one of an OCIError or a OCIEnv handle
- * depending on the type, which is either OCI_HTYPE_ERROR or OCI_HTYPE_ENV.
- * Read the documentation on OCIErrorGet to understand why this is
- *
- * If the handle is NULL, which is an unhappy situation, it will set the
- * error description to "NO DESCRIPTION".
- *
- * The error number is set to the Oracle error code.
- */
-GdaConnectionEvent *
-gda_oracle_make_error (dvoid *hndlp, ub4 type, const gchar *file, gint line)
-{
- GdaConnectionEvent *error;
- gchar errbuf[512];
- ub4 errcode;
- gchar *source;
-
- error = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
-
- if (hndlp != NULL) {
- OCIErrorGet ((dvoid *) hndlp,
- (ub4) 1,
- (text *) NULL,
- &errcode,
- errbuf,
- (ub4) sizeof (errbuf),
- (ub4) type);
-
- gda_connection_event_set_description (error, errbuf);
- /*g_warning ("Oracle error:%s", errbuf);*/
- }
- else
- gda_connection_event_set_description (error, _("NO DESCRIPTION"));
-
- gda_connection_event_set_code (error, errcode);
- source = g_strdup_printf ("gda-oracle:%s:%d", file, line);
- gda_connection_event_set_source (error, source);
- g_free(source);
-
- return error;
-}
-
-/*
- * gda_oracle_check_result
- * This function is used for checking the result of an OCI
- * call. The result itself is the return value, and we
- * need the GdaConnection and GdaOracleConnectionData to do
- * our thing. The type is OCI_HTYPE_ENV or OCI_HTYPE_ERROR
- * as described for OCIErrorGet.
- *
- * The return value is true if there is no error, or false otherwise
- *
- * If the return value is OCI_SUCCESS or OCI_SUCCESS_WITH_INFO,
- * we return TRUE. Otherwise, if it is OCI_ERROR, try to get the
- * Oracle error message using gda_oracle_make_error. Otherwise,
- * make an error using the given message.
- */
-GdaConnectionEvent *
-gda_oracle_handle_error (gint result, GdaConnection *cnc,
- GdaOracleConnectionData *priv_data,
- ub4 type, const gchar *msg,
- const gchar *file, gint line)
-{
- GdaConnectionEvent *error = NULL;
- g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
-
- switch (result) {
- case OCI_SUCCESS:
- case OCI_SUCCESS_WITH_INFO:
- return NULL;
- case OCI_ERROR:
- switch(type) {
- case OCI_HTYPE_ERROR:
- error = gda_oracle_make_error (priv_data->herr, type, file, line);
- gda_connection_add_event (cnc, error);
- break;
- case OCI_HTYPE_ENV:
- error = gda_oracle_make_error (priv_data->henv, type, file, line);
- gda_connection_add_event (cnc, error);
- break;
- default:
- break;
- }
- break;
- default:
- error = gda_connection_add_event_string (cnc, msg);
- }
-
- return error;
-}
-
-GType
-oracle_sqltype_to_g_type (const ub2 sqltype)
-{
- /* an incomplete list of all the oracle types */
- switch (sqltype) {
- case SQLT_CHR:
- case SQLT_STR:
- case SQLT_VCS:
- case SQLT_RID:
- case SQLT_LNG:
- case SQLT_LVC:
- case SQLT_AFC:
- case SQLT_AVC:
- case SQLT_LAB:
- case SQLT_VST:
- return G_TYPE_STRING;
- case SQLT_NUM:
- return GDA_TYPE_NUMERIC;
- case SQLT_INT:
- return G_TYPE_INT;
- case SQLT_UIN:
- return G_TYPE_UINT;
- case SQLT_FLT:
- return G_TYPE_FLOAT;
- case SQLT_VBI:
- case SQLT_BIN:
- case SQLT_LBI:
- case SQLT_LVB:
- case SQLT_BLOB:
- case SQLT_BFILEE:
- case SQLT_CFILEE:
- case SQLT_CLOB:
- return GDA_TYPE_BLOB;
- case SQLT_DAT:
- case SQLT_ODT:
- case SQLT_DATE:
- return G_TYPE_DATE;
- case SQLT_TIME:
- case SQLT_TIME_TZ:
- return GDA_TYPE_TIME;
- case SQLT_TIMESTAMP:
- case SQLT_TIMESTAMP_TZ:
- case SQLT_TIMESTAMP_LTZ:
- return GDA_TYPE_TIMESTAMP;
- case SQLT_SLS:
- case SQLT_CUR:
- case SQLT_RDD:
- case SQLT_OSL:
- case SQLT_NTY:
- case SQLT_REF:
- case SQLT_RSET:
- case SQLT_NCO:
- case SQLT_INTERVAL_YM:
- case SQLT_INTERVAL_DS:
- case SQLT_VNU:
- case SQLT_PDN:
- case SQLT_NON:
- default:
- return G_TYPE_INVALID;
- }
-}
-
-gchar *
-oracle_sqltype_to_string (const ub2 sqltype)
-{
- /* an incomplete list of all the oracle types */
- switch (sqltype) {
- case SQLT_CHR:
- return "VARCHAR2";
- case SQLT_NUM:
- return "NUMBER";
- case SQLT_INT:
- return "INTEGER";
- case SQLT_FLT:
- return "FLOAT";
- case SQLT_STR:
- return "STRING";
- case SQLT_VNU:
- return "VARNUM";
- case SQLT_PDN:
- return "";
- case SQLT_LNG:
- return "LONG";
- case SQLT_VCS:
- return "VARCHAR";
- case SQLT_NON:
- return "";
- case SQLT_RID:
- return "ROWID";
- case SQLT_DAT:
- return "DATE";
- case SQLT_VBI:
- return "VARRAW";
- case SQLT_BIN:
- return "RAW";
- case SQLT_LBI:
- return "LONG RAW";
- case SQLT_UIN:
- return "UNSIGNED INT";
- case SQLT_SLS:
- return "";
- case SQLT_LVC:
- return "LONG VARCHAR";
- case SQLT_LVB:
- return "LONG VARRAW";
- case SQLT_AFC:
- return "CHAR";
- case SQLT_AVC:
- return "CHARZ";
- case SQLT_CUR:
- return "CURSOR";
- case SQLT_RDD:
- return "ROWID";
- case SQLT_LAB:
- return "LABEL";
- case SQLT_OSL:
- return "OSLABEL";
- case SQLT_NTY:
- return "";
- case SQLT_REF:
- return "";
- case SQLT_CLOB:
- return "CLOB";
- case SQLT_BLOB:
- return "BLOB";
- case SQLT_BFILEE:
- return "BFILE";
- case SQLT_CFILEE:
- return "CFILE";
- case SQLT_RSET:
- return "RESULT SET";
- case SQLT_NCO:
- return "";
- case SQLT_VST:
- return "";
- case SQLT_ODT:
- return "OCI DATE";
- case SQLT_DATE:
- return "ANSI DATE";
- case SQLT_TIME:
- return "TIME";
- case SQLT_TIME_TZ:
- return "TIME WITH TIME ZONE";
- case SQLT_TIMESTAMP:
- return "TIMESTAMP";
- case SQLT_TIMESTAMP_TZ:
- return "TIMESTAMP WITH TIME ZONE";
- case SQLT_INTERVAL_YM:
- return "INTERVAL YEAR TO MONTH";
- case SQLT_INTERVAL_DS:
- return "INTERVAL DAY TO SECOND";
- case SQLT_TIMESTAMP_LTZ:
- return "TIMESTAMP WITH LOCAL TIME ZONE";
- default:
- return "UNKNOWN";
- }
-}
-
-gchar *
-gda_oracle_value_to_sql_string (GValue *value)
-{
- gchar *val_str;
- gchar *ret;
- GType type;
-
- g_return_val_if_fail (value != NULL, NULL);
-
- val_str = gda_value_stringify (value);
- if (!val_str)
- return NULL;
-
- type = G_VALUE_TYPE (value);
- if ((type == G_TYPE_INT64) ||
- (type == G_TYPE_DOUBLE) ||
- (type == G_TYPE_INT) ||
- (type == GDA_TYPE_NUMERIC) ||
- (type == G_TYPE_FLOAT) ||
- (type == GDA_TYPE_SHORT) ||
- (type == G_TYPE_CHAR))
- ret = val_str;
- else {
- ret = g_strdup_printf ("\"%s\"", val_str);
- g_free(val_str);
- }
-
- return ret;
-}
-
-GdaOracleValue *
-gda_value_to_oracle_value (const GValue *value)
-{
- GdaOracleValue *ora_value;
- OCIDate *oci_date;
- GType type;
-
- ora_value = g_new0 (GdaOracleValue, 1);
-
- ora_value->g_type = G_VALUE_TYPE (value);
- ora_value->indicator = 0;
- ora_value->hdef = (OCIDefine *) 0;
- ora_value->pard = (OCIParam *) 0;
- type = ora_value->g_type;
-
- if (type == GDA_TYPE_NULL)
- ora_value->indicator = -1;
- else if ((type == G_TYPE_INT64) ||
- (type == G_TYPE_DOUBLE) ||
- (type == G_TYPE_INT) ||
- (type == GDA_TYPE_NUMERIC) ||
- (type == G_TYPE_FLOAT) ||
- (type == GDA_TYPE_SHORT) ||
- (type == G_TYPE_CHAR)) {
- gchar *val_str;
- val_str = gda_value_stringify ((GValue *) value);
- if (!val_str)
- return NULL;
-
- ora_value->sql_type = SQLT_NUM;
- ora_value->value = (void *) val_str;
- ora_value->defined_size = strlen (val_str);
- }
- else if (type == G_TYPE_DATE) {
- GDate *gda_date;
- ora_value->sql_type = SQLT_ODT;
- gda_date = (GDate*) g_value_get_boxed (value);
- oci_date = g_new0(OCIDate, 1);
- OCIDateSetDate(oci_date, gda_date->year, gda_date->month, gda_date->day);
- ora_value->defined_size = sizeof (OCIDate);
- ora_value->value = oci_date;
- }
- else if (type == GDA_TYPE_TIME) {
- GdaTime *gda_time;
- ora_value->sql_type = SQLT_ODT;
- gda_time = (GdaTime *) gda_value_get_time ((GValue *) value);
- oci_date = g_new0(OCIDate, 1);
- OCIDateSetTime(oci_date, gda_time->hour, gda_time->minute, gda_time->second);
- ora_value->defined_size = sizeof (OCIDate);
- ora_value->value = oci_date;
- }
- else if (type == GDA_TYPE_TIMESTAMP) {
- GdaTimestamp *gda_timestamp;
- ora_value->sql_type = SQLT_ODT;
- gda_timestamp = (GdaTimestamp *) gda_value_get_timestamp ((GValue *) value);
- oci_date = g_new0(OCIDate, 1);
- OCIDateSetDate(oci_date, gda_timestamp->year, gda_timestamp->month, gda_timestamp->day);
- OCIDateSetTime(oci_date, gda_timestamp->hour, gda_timestamp->minute, gda_timestamp->second);
- ora_value->defined_size = sizeof (OCIDate);
- ora_value->value = oci_date;
- }
- else if (type == GDA_TYPE_BLOB) {
- GdaBinary *bin;
-
- bin = (GdaBinary *) gda_value_get_blob ((GValue *) value);
- if (bin) {
- ora_value->sql_type = SQLT_LNG;
- ora_value->value = bin->data;
- ora_value->defined_size = bin->binary_length;
- }
- else {
- ora_value->sql_type = SQLT_CHR;
- ora_value->value = g_strdup ("");
- ora_value->defined_size = 0;
- }
- }
- else {
- gchar *val_str;
- val_str = gda_value_stringify ((GValue *) value);
- if (!val_str)
- return NULL;
-
- ora_value->sql_type = SQLT_CHR;
- ora_value->value = val_str;
- ora_value->defined_size = strlen (val_str);
- }
-
- return ora_value;
-}
-
-void
-gda_oracle_set_value (GValue *value,
- GdaOracleValue *ora_value,
- GdaConnection *cnc)
-{
- GdaTime gtime;
- GdaTimestamp timestamp;
- GdaNumeric numeric;
- sb2 year;
- ub1 month;
- ub1 day;
- ub1 hour;
- ub1 min;
- ub1 sec;
- GType type;
- gchar *string_buffer, *tmp;
-
- if (-1 == (ora_value->indicator)) {
- gda_value_set_null (value);
- return;
- }
-
- type = ora_value->g_type;
- gda_value_reset_with_type (value, type);
- if (type == G_TYPE_BOOLEAN)
- g_value_set_boolean (value, (atoi (ora_value->value)) ? TRUE: FALSE);
- else if (type == G_TYPE_STRING) {
- string_buffer = g_malloc0 (ora_value->defined_size+1);
- memcpy (string_buffer, ora_value->value, ora_value->defined_size);
- string_buffer[ora_value->defined_size] = '\0';
- g_strchomp(string_buffer);
- tmp = g_locale_to_utf8 (string_buffer, -1, NULL, NULL, NULL);
- g_value_set_string (value, tmp);
- g_free (tmp);
- g_free (string_buffer);
- }
- else if (type == G_TYPE_INT64)
- g_value_set_int64 (value, atoll (ora_value->value));
- else if (type == G_TYPE_INT)
- g_value_set_int (value, atol (ora_value->value));
- else if (type == G_TYPE_UINT)
- g_value_set_uint (value, atol (ora_value->value));
- else if (type == GDA_TYPE_SHORT)
- gda_value_set_short (value, atoi (ora_value->value));
- else if (type == G_TYPE_FLOAT)
- g_value_set_float (value, atof (ora_value->value));
- else if (type == G_TYPE_DOUBLE)
- g_value_set_double (value, atof (ora_value->value));
- else if (type == GDA_TYPE_NUMERIC) {
- string_buffer = g_malloc0 (ora_value->defined_size+1);
- memcpy (string_buffer, ora_value->value, ora_value->defined_size);
- string_buffer [ora_value->defined_size] = '\0';
- g_strchomp (string_buffer);
- numeric.number = string_buffer;
- numeric.precision = 0; /* FIXME */
- numeric.width = 0; /* FIXME */
- gda_value_set_numeric (value, &numeric);
- g_free (string_buffer);
- }
- else if (type == G_TYPE_DATE) {
- GDate *date;
- OCIDateGetDate ((CONST OCIDate *) ora_value->value,
- (sb2 *) &year,
- (ub1 *) &month,
- (ub1 *) &day);
- date = g_date_new_dmy (day, month, year);
- g_value_take_boxed (value, date);
- }
- else if (type == GDA_TYPE_GEOMETRIC_POINT) {}
- else if (type == GDA_TYPE_NULL)
- gda_value_set_null (value);
- else if (type == GDA_TYPE_TIMESTAMP) {
- OCIDateGetDate ((CONST OCIDate *) ora_value->value,
- (sb2 *) &year,
- (ub1 *) &month,
- (ub1 *) &day);
- OCIDateGetTime ((CONST OCIDate *) ora_value->value,
- (ub1 *) &hour,
- (ub1 *) &min,
- (ub1 *) &sec);
- timestamp.year = year;
- timestamp.month = month;
- timestamp.day = day;
- timestamp.hour = hour;
- timestamp.minute = min;
- timestamp.second = sec;
- timestamp.fraction = 0;
- timestamp.timezone = 0;
- gda_value_set_timestamp(value, ×tamp);
- }
- else if (type == GDA_TYPE_TIME) {
- OCIDateGetTime ((CONST OCIDate *) ora_value->value,
- (ub1 *) &hour,
- (ub1 *) &min,
- (ub1 *) &sec);
- gtime.hour = hour;
- gtime.minute = min;
- gtime.second = sec;
- gda_value_set_time (value, >ime);
- }
- else if (type == GDA_TYPE_BINARY) {
- g_warning ("GdaBinary type is not supported by Oracle");
- }
- else if (type == GDA_TYPE_BLOB) {
- GdaBlob *blob;
- GdaBlobOp *op;
- OCILobLocator *lobloc;
- GdaOracleConnectionData *priv_data;
- gint result;
-
- /* REM: we need to make a "copy" of the lob locator to give to the GdaOracleblobOp object */
- priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
- if (!priv_data) {
- gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
- gda_value_set_null (value);
- return;
- }
-
- result = OCIDescriptorAlloc ((dvoid *) priv_data->henv, (dvoid **) &lobloc,
- (ub4) gda_oracle_blob_type (ora_value->sql_type), (size_t) 0, (dvoid **) 0);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not allocate Lob locator"))) {
- gda_value_set_null (value);
- return;
- }
-
- result = OCILobAssign ((dvoid *) priv_data->henv, (dvoid *) priv_data->herr, ora_value->value, &lobloc);
- if (gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
- _("Could not copy Lob locator"))) {
- gda_value_set_null (value);
- return;
- }
-
- blob = g_new0 (GdaBlob, 1);
- op = gda_oracle_blob_op_new (cnc, lobloc);
- gda_blob_set_op (blob, op);
- g_object_unref (op);
-
- gda_value_take_blob (value, blob);
- }
- else
- g_value_set_string (value, ora_value->value);
-}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]