[libgda] More work on the Oracle provider
- From: Vivien Malerba <vivien src gnome org>
- To: svn-commits-list gnome org
- Subject: [libgda] More work on the Oracle provider
- Date: Fri, 8 May 2009 09:52:27 -0400 (EDT)
commit 3f92a4cd0c7e2eb596d2c1f74e60fa59fd1ff9f1
Author: Vivien Malerba <malerba gnome-db org>
Date: Wed May 6 22:01:01 2009 +0200
More work on the Oracle provider
* providers/oracle:
- use the callback API to fetch results for variable length data types
- implemented more meta data retreival
- booleans (which is not an Oracle data type) are interpreted as 0 an !0
- better handling of OCI types
* libgda/gda-data-meta-wrapper.c: bug fixes
* libgda/gda-meta-store.c: bug fixes
* providers/postgres/gda-postgres-meta.c: bug fixes
---
ChangeLog | 11 +
libgda/gda-data-meta-wrapper.c | 64 +++-
libgda/gda-meta-store.c | 2 +-
providers/oracle/gda-oracle-meta.c | 545 ++++++++++++++++++++++++++++++-
providers/oracle/gda-oracle-provider.c | 312 +++++++++++++++++-
providers/oracle/gda-oracle-recordset.c | 394 ++++++++++++----------
providers/oracle/gda-oracle-util.c | 361 ++++++++++++++------
providers/oracle/gda-oracle-util.h | 52 +++-
providers/oracle/gda-oracle.h | 4 +
providers/postgres/gda-postgres-meta.c | 10 +-
10 files changed, 1417 insertions(+), 338 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 7fcfd31..5788eee 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2009-05-06 Vivien Malerba <malerba gnome-db org>
+
+ * providers/oracle:
+ - use the callback API to fetch results for variable length data types
+ - implemented more meta data retreival
+ - booleans (which is not an Oracle data type) are interpreted as 0 an !0
+ - better handling of OCI types
+ * libgda/gda-data-meta-wrapper.c: bug fixes
+ * libgda/gda-meta-store.c: bug fixes
+ * providers/postgres/gda-postgres-meta.c: bug fixes
+
2009-05-05 Vivien Malerba <malerba gnome-db org>
* libgda/gda-sql-builder.c:
diff --git a/libgda/gda-data-meta-wrapper.c b/libgda/gda-data-meta-wrapper.c
index 17bf87e..288a6f4 100644
--- a/libgda/gda-data-meta-wrapper.c
+++ b/libgda/gda-data-meta-wrapper.c
@@ -406,7 +406,7 @@ identifier_needs_quotes (const gchar *str, GdaSqlIdentifierStyle mode)
{
const gchar *ptr;
for (ptr = str; *ptr; ptr++) {
- if ((*ptr == ' ') || (*ptr == '"') ||
+ if ((*ptr == ' ') ||
((mode == GDA_SQL_IDENTIFIERS_LOWER_CASE) && (*ptr != g_ascii_tolower (*ptr))) ||
((mode == GDA_SQL_IDENTIFIERS_UPPER_CASE) && (*ptr != g_ascii_toupper (*ptr))))
return TRUE;
@@ -414,6 +414,26 @@ identifier_needs_quotes (const gchar *str, GdaSqlIdentifierStyle mode)
return FALSE;
}
+static gboolean
+identifier_is_all_lower (const gchar *str)
+{
+ const gchar *ptr;
+ for (ptr = str; *ptr; ptr++) {
+ if (*ptr != g_ascii_tolower (*ptr))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gchar *
+to_lower (gchar *str)
+{
+ gchar *ptr;
+ for (ptr = str; *ptr; ptr++)
+ *ptr = g_ascii_tolower (*ptr);
+ return str;
+}
+
/*
* Returns:
* - NULL if no changes are necessary from the current value
@@ -432,29 +452,41 @@ compute_value (const GValue *value, GdaSqlIdentifierStyle mode)
return NULL;
if ((*str == '"') && (str[strlen(str) - 1] == '"'))
return NULL; /* already quoted */
- if (identifier_needs_quotes (str, mode)) {
- gchar **sa = g_strsplit (str, ".", 0);
- if (sa[1]) {
- gint i;
- for (i = 0; sa[i]; i++) {
- if (identifier_needs_quotes (sa[i], mode)) {
- gchar *tmp = gda_sql_identifier_add_quotes (sa[i]);
- g_free (sa[i]);
- sa[i] = tmp;
- }
+ gchar **sa = g_strsplit (str, ".", 0);
+ if (sa[1]) {
+ gint i;
+ gboolean onechanged = FALSE;
+ for (i = 0; sa[i]; i++) {
+ if (identifier_needs_quotes (sa[i], mode)) {
+ gchar *tmp = gda_sql_identifier_add_quotes (sa[i]);
+ g_free (sa[i]);
+ sa[i] = tmp;
+ onechanged = TRUE;
+ }
+ else if (! identifier_is_all_lower (sa[i])) {
+ to_lower (sa[i]);
+ onechanged = TRUE;
}
+ }
+ if (onechanged) {
retval = gda_value_new (G_TYPE_STRING);
g_value_take_string (retval, g_strjoinv (".", sa));
}
- else {
+ }
+ else {
+ if (identifier_needs_quotes (str, mode)) {
retval = gda_value_new (G_TYPE_STRING);
g_value_take_string (retval, gda_sql_identifier_add_quotes (str));
}
- g_strfreev (sa);
- return retval;
+ else if (! identifier_is_all_lower (str)) {
+ gchar *tmp;
+ tmp = to_lower (g_strdup (str));
+ retval = gda_value_new (G_TYPE_STRING);
+ g_value_take_string (retval, tmp);
+ }
}
- else
- return NULL;
+ g_strfreev (sa);
+ return retval;
}
/*
diff --git a/libgda/gda-meta-store.c b/libgda/gda-meta-store.c
index 2e89aa7..498300c 100644
--- a/libgda/gda-meta-store.c
+++ b/libgda/gda-meta-store.c
@@ -2502,7 +2502,7 @@ gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name,
context.column_values = g_new (GValue *, context.size);
for (k = 0; k < tfk->cols_nb; k++) {
- context.column_values [k] = (GValue*) gda_data_model_get_value_at (wrapped_data,
+ context.column_values [k] = (GValue*) gda_data_model_get_value_at (new_data,
tfk->ref_pk_cols_array[k], i, error);
if (!context.column_values [k]) {
g_free (context.column_values);
diff --git a/providers/oracle/gda-oracle-meta.c b/providers/oracle/gda-oracle-meta.c
index 3791e70..06e5fc1 100644
--- a/providers/oracle/gda-oracle-meta.c
+++ b/providers/oracle/gda-oracle-meta.c
@@ -32,6 +32,7 @@
#include <libgda/gda-data-model-array.h>
#include <libgda/gda-set.h>
#include <libgda/gda-holder.h>
+#include "gda-oracle-util.h"
/*
* predefined statements' IDs
@@ -39,7 +40,16 @@
typedef enum {
I_STMT_CATALOG,
I_STMT_SCHEMAS_ALL,
- I_STMT_SCHEMA_NAMED
+ I_STMT_SCHEMA_NAMED,
+ I_STMT_TABLES_ALL,
+ I_STMT_TABLES_ALL_RAW,
+ I_STMT_TABLES,
+ I_STMT_TABLE_NAMED,
+ I_STMT_VIEWS_ALL,
+ I_STMT_VIEWS,
+ I_STMT_VIEW_NAMED,
+ I_STMT_COLUMNS_OF_TABLE,
+ I_STMT_COLUMNS_ALL,
} InternalStatementItem;
@@ -51,10 +61,37 @@ static gchar *internal_sql[] = {
"select ora_database_name from dual",
/* I_STMT_SCHEMAS_ALL */
- "SELECT ora_database_name, username, username, CASE WHEN username = user THEN 1 ELSE 0 END FROM all_users",
+ "SELECT ora_database_name, username, username, CASE WHEN username IN ('SYS', 'SYSTEM', 'DBSNMP', 'OUTLN', 'MDSYS', 'ORDSYS', 'ORDPLUGINS', 'CTXSYS', 'DSSYS', 'PERFSTAT', 'WKPROXY', 'WKSYS', 'WMSYS', 'XDB', 'ANONYMOUS', 'ODM', 'ODM_MTR', 'OLAPSYS', 'TRACESVR', 'REPADMIN') THEN 1 ELSE 0 END FROM all_users",
/* I_STMT_SCHEMA_NAMED */
- "SELECT ora_database_name, username, username, CASE WHEN username = user THEN 1 ELSE 0 END FROM all_users WHERE username = ##name::string",
+ "SELECT ora_database_name, username, username, CASE WHEN username IN ('SYS', 'SYSTEM', 'DBSNMP', 'OUTLN', 'MDSYS', 'ORDSYS', 'ORDPLUGINS', 'CTXSYS', 'DSSYS', 'PERFSTAT', 'WKPROXY', 'WKSYS', 'WMSYS', 'XDB', 'ANONYMOUS', 'ODM', 'ODM_MTR', 'OLAPSYS', 'TRACESVR', 'REPADMIN') THEN 1 ELSE 0 END FROM all_users WHERE username = ##name::string",
+
+ /* I_STMT_TABLES_ALL */
+ "SELECT ora_database_name, a.owner, a.table_name, 'BASE TABLE', 1, c.comments, CASE WHEN a.owner = user THEN a.table_name ELSE a.owner || '.' || a.table_name END, a.owner || '.' || a.table_name, a.owner FROM all_tables a LEFT JOIN ALL_TAB_COMMENTS c ON (a.table_name=c.table_name) UNION SELECT ora_database_name, v.owner, v.view_name, 'VIEW', 0, c.comments, CASE WHEN v.owner = user THEN v.view_name ELSE v.owner || '.' || v.view_name END, v.owner || '.' || v.view_name, v.owner FROM all_views v LEFT JOIN ALL_TAB_COMMENTS c ON (v.view_name=c.table_name)",
+
+ /* I_STMT_TABLES_ALL_RAW */
+ "SELECT ora_database_name, a.owner, a.table_name FROM all_tables a UNION SELECT ora_database_name, v.owner, v.view_name FROM all_views v",
+
+ /* I_STMT_TABLES */
+ "SELECT ora_database_name, a.owner, a.table_name, 'BASE TABLE', 1, c.comments, CASE WHEN a.owner = user THEN a.table_name ELSE a.owner || '.' || a.table_name END, a.owner || '.' || a.table_name, a.owner FROM all_tables a LEFT JOIN ALL_TAB_COMMENTS c ON (a.table_name=c.table_name) WHERE a.owner = ##schema::string UNION SELECT ora_database_name, v.owner, v.view_name, 'VIEW', 0, c.comments, CASE WHEN v.owner = user THEN v.view_name ELSE v.owner || '.' || v.view_name END, v.owner || '.' || v.view_name, v.owner FROM all_views v LEFT JOIN ALL_TAB_COMMENTS c ON (v.view_name=c.table_name) WHERE v.owner = ##schema::string",
+
+ /* I_STMT_TABLE_NAMED */
+ "SELECT ora_database_name, a.owner, a.table_name, 'BASE TABLE', 1, c.comments, CASE WHEN a.owner = user THEN a.table_name ELSE a.owner || '.' || a.table_name END, a.owner || '.' || a.table_name, a.owner FROM all_tables a LEFT JOIN ALL_TAB_COMMENTS c ON (a.table_name=c.table_name) WHERE a.owner = ##schema::string AND a.table_name = ##name::string UNION SELECT ora_database_name, v.owner, v.view_name, 'VIEW', 0, c.comments, CASE WHEN v.owner = user THEN v.view_name ELSE v.owner || '.' || v.view_name END, v.owner || '.' || v.view_name, v.owner FROM all_views v LEFT JOIN ALL_TAB_COMMENTS c ON (v.view_name=c.table_name) WHERE v.owner = ##schema::string AND v.view_name = ##name::string",
+
+ /* I_STMT_VIEWS_ALL */
+ "SELECT ora_database_name, v.owner, v.view_name, v.text, NULL, 0 FROM all_views v",
+
+ /* I_STMT_VIEWS */
+ "SELECT ora_database_name, v.owner, v.view_name, v.text, NULL, 0 FROM all_views v WHERE v.owner = ##schema::string",
+
+ /* I_STMT_VIEW_NAMED */
+ "SELECT ora_database_name, v.owner, v.view_name, v.text, NULL, 0 FROM all_views v WHERE v.owner = ##schema::string AND v.view_name = ##name::string",
+
+ /* I_STMT_COLUMNS_OF_TABLE */
+ "SELECT ora_database_name, tc.owner, tc.table_name, tc.column_name, tc.column_id, tc.data_default, decode(tc.nullable,'N',0,'Y',1), tc.data_type, NULL, 'gchararray', CASE WHEN tc.char_used = 'C' THEN tc.char_length ELSE NULL END as clen, CASE WHEN tc.char_used = 'B' THEN tc.char_length ELSE NULL END as olen, tc.data_precision, tc.data_scale, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, c.comments FROM ALL_TAB_COLUMNS tc LEFT JOIN ALL_COL_COMMENTS c ON (tc.owner = c.owner AND tc.table_name=c.table_name AND tc.column_name = c.column_name) WHERE tc.table_name = ##name::string ORDER BY tc.column_id",
+
+ /* I_STMT_COLUMNS_ALL */
+ "SELECT ora_database_name, tc.owner, tc.table_name, tc.column_name, tc.column_id, tc.data_default, decode(tc.nullable,'N',0,'Y',1), tc.data_type, NULL, 'gchararray', CASE WHEN tc.char_used = 'C' THEN tc.char_length ELSE NULL END as clen, CASE WHEN tc.char_used = 'B' THEN tc.char_length ELSE NULL END as olen, tc.data_precision, tc.data_scale, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, c.comments FROM ALL_TAB_COLUMNS tc LEFT JOIN ALL_COL_COMMENTS c ON (tc.owner = c.owner AND tc.table_name=c.table_name AND tc.column_name = c.column_name) ORDER BY tc.table_name, tc.column_id"
};
/*
@@ -106,6 +143,7 @@ _gda_oracle_meta__info (GdaServerProvider *prov, GdaConnection *cnc,
error);
if (!model)
return FALSE;
+ gda_meta_store_set_identifiers_style (store, GDA_SQL_IDENTIFIERS_UPPER_CASE);
retval = gda_meta_store_modify_with_context (store, context, model, error);
g_object_unref (model);
@@ -148,6 +186,7 @@ _gda_oracle_meta_udt (GdaServerProvider *prov, GdaConnection *cnc,
*/
if (!model)
return FALSE;
+ gda_meta_store_set_identifiers_style (store, GDA_SQL_IDENTIFIERS_UPPER_CASE);
retval = gda_meta_store_modify_with_context (store, context, model, error);
g_object_unref (model);
@@ -290,6 +329,7 @@ _gda_oracle_meta__schemata (GdaServerProvider *prov, GdaConnection *cnc,
GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
if (!model)
return FALSE;
+ gda_meta_store_set_identifiers_style (store, GDA_SQL_IDENTIFIERS_UPPER_CASE);
retval = gda_meta_store_modify_with_context (store, context, model, error);
g_object_unref (model);
@@ -312,6 +352,7 @@ _gda_oracle_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc,
GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
if (!model)
return FALSE;
+ gda_meta_store_set_identifiers_style (store, GDA_SQL_IDENTIFIERS_UPPER_CASE);
retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
}
else {
@@ -322,6 +363,7 @@ _gda_oracle_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc,
if (!model)
return FALSE;
+ gda_meta_store_set_identifiers_style (store, GDA_SQL_IDENTIFIERS_UPPER_CASE);
retval = gda_meta_store_modify (store, context->table_name, model, "schema_name = ##name::string", error,
"name", schema_name_n, NULL);
}
@@ -330,12 +372,51 @@ _gda_oracle_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc,
return retval;
}
+static GType col_types_tables[] = {G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_NONE};
+static GType col_types_views[] = {G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_NONE};
+
+
gboolean
_gda_oracle_meta__tables_views (GdaServerProvider *prov, GdaConnection *cnc,
- GdaMetaStore *store, GdaMetaContext *context, GError **error)
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
{
- TO_IMPLEMENT;
- return TRUE;
+ GdaDataModel *tables_model, *views_model;
+ gboolean retval = TRUE;
+
+ OracleConnectionData *cdata;
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
+ return FALSE;
+
+ tables_model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_TABLES_ALL], NULL,
+ GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_tables,
+ error);
+ if (!tables_model)
+ return FALSE;
+ views_model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_VIEWS_ALL], NULL,
+ GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_views,
+ error);
+ if (!views_model) {
+ g_object_unref (tables_model);
+ return FALSE;
+ }
+
+ gda_meta_store_set_identifiers_style (store, GDA_SQL_IDENTIFIERS_UPPER_CASE);
+
+ GdaMetaContext c2;
+ c2 = *context; /* copy contents, just because we need to modify @context->table_name */
+ if (retval) {
+ c2.table_name = "_tables";
+ retval = gda_meta_store_modify_with_context (store, &c2, tables_model, error);
+ }
+ if (retval) {
+ c2.table_name = "_views";
+ retval = gda_meta_store_modify_with_context (store, &c2, views_model, error);
+ }
+ g_object_unref (tables_model);
+ g_object_unref (views_model);
+
+ return retval;
}
gboolean
@@ -344,23 +425,459 @@ _gda_oracle_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc,
const GValue *table_catalog, const GValue *table_schema,
const GValue *table_name_n)
{
- TO_IMPLEMENT;
- return TRUE;
+ GdaDataModel *tables_model, *views_model;
+ gboolean retval = TRUE;
+
+ OracleConnectionData *cdata;
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
+ return FALSE;
+
+ if (! gda_holder_set_value (gda_set_get_holder (i_set, "schema"), table_schema, error))
+ return FALSE;
+
+ if (!table_name_n) {
+ tables_model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_TABLES], i_set,
+ GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_tables,
+ error);
+ if (!tables_model)
+ return FALSE;
+ views_model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_VIEWS], i_set,
+ GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_views,
+ error);
+ if (!views_model) {
+ g_object_unref (tables_model);
+ return FALSE;
+ }
+ }
+ else {
+ if (! gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name_n, error))
+ return FALSE;
+ tables_model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_TABLE_NAMED], i_set,
+ GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_tables,
+ error);
+ if (!tables_model)
+ return FALSE;
+ views_model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_VIEW_NAMED], i_set,
+ GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types_views,
+ error);
+ if (!views_model) {
+ g_object_unref (tables_model);
+ return FALSE;
+ }
+ }
+
+ gda_meta_store_set_identifiers_style (store, GDA_SQL_IDENTIFIERS_UPPER_CASE);
+
+ GdaMetaContext c2;
+ c2 = *context; /* copy contents, just because we need to modify @context->table_name */
+ if (retval) {
+ c2.table_name = "_tables";
+ retval = gda_meta_store_modify_with_context (store, &c2, tables_model, error);
+ }
+ if (retval) {
+ c2.table_name = "_views";
+ retval = gda_meta_store_modify_with_context (store, &c2, views_model, error);
+ }
+ g_object_unref (tables_model);
+ g_object_unref (views_model);
+
+ return retval;
+}
+
+/*
+ * Returns: a new G_TYPE_STRING GValue
+ */
+static GValue *
+oracle_identifier_to_value (const gchar *sqlid)
+{
+ GValue *v;
+ g_return_val_if_fail (sqlid, NULL);
+
+ v = gda_value_new (G_TYPE_STRING);
+ if (g_ascii_isalnum (*sqlid)) {
+ const gchar *ptr;
+ for (ptr = sqlid; *ptr; ptr++) {
+ if ((*ptr == ' ') || (*ptr != g_ascii_toupper (*ptr))) {
+ /* add quotes */
+ g_value_take_string (v, gda_sql_identifier_add_quotes (sqlid));
+ return v;
+ }
+ }
+
+ g_value_set_string (v, sqlid);
+ }
+ else
+ g_value_take_string (v, gda_sql_identifier_add_quotes (sqlid));
+ return v;
}
gboolean
_gda_oracle_meta__columns (GdaServerProvider *prov, GdaConnection *cnc,
- GdaMetaStore *store, GdaMetaContext *context, GError **error)
+ GdaMetaStore *store, GdaMetaContext *context, GError **error)
{
- TO_IMPLEMENT;
- return TRUE;
+ GdaDataModel *model, *tables;
+ gboolean retval = FALSE;
+ gint i, nrows;
+ OracleConnectionData *cdata;
+
+ cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
+ if (!cdata)
+ return FALSE;
+
+ /* use a prepared statement for the "base" model */
+ tables = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLES_ALL_RAW], NULL, error);
+ if (!tables)
+ return FALSE;
+
+ model = gda_data_model_array_new_with_g_types (24, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_INT, G_TYPE_STRING, G_TYPE_BOOLEAN,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_BOOLEAN, G_TYPE_STRING);
+
+ /* fill in @model */
+ const GValue *cv0 = NULL;
+ GList *values = NULL;
+ nrows = gda_data_model_get_n_rows (tables);
+ for (i = 0; i < nrows; i++) {
+ const GValue *cv1, *cv2;
+ values = NULL;
+
+ if (!cv0) {
+ cv0 = gda_data_model_get_value_at (tables, 0, i, error);
+ if (!cv0)
+ goto out;
+ }
+ if (!(cv1 = gda_data_model_get_value_at (tables, 1, i, error)) ||
+ !(cv2 = gda_data_model_get_value_at (tables, 2, i, error)))
+ goto out;
+
+ /* Allocate the Describe handle */
+ int result;
+ OCIDescribe *dschp = (OCIDescribe *) 0;
+ GdaConnectionEvent *event;
+
+ result = OCIHandleAlloc ((dvoid *) cdata->henv,
+ (dvoid **) &dschp,
+ (ub4) OCI_HTYPE_DESCRIBE,
+ (size_t) 0,
+ (dvoid **) 0);
+ if ((event = gda_oracle_check_result ((result), (cnc), (cdata), OCI_HTYPE_ERROR,
+ _("Could not fetch next row")))) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", gda_connection_event_get_description (event));
+ goto out;
+ }
+
+ /* Describe the table */
+ gchar *fq_tblname;
+ const gchar *schema_name, *table_name;
+ GValue *v1, *v2;
+ v1 = oracle_identifier_to_value (g_value_get_string (cv1));
+ schema_name = g_value_get_string (v1);
+ v2 = oracle_identifier_to_value (g_value_get_string (cv2));
+ table_name = g_value_get_string (v2);
+ fq_tblname = g_strdup_printf ("%s.%s", schema_name, table_name);
+ gda_value_free (v1);
+ gda_value_free (v2);
+
+ result = OCIDescribeAny (cdata->hservice,
+ cdata->herr,
+ (text *) fq_tblname,
+ strlen (fq_tblname),
+ OCI_OTYPE_NAME,
+ 0,
+ OCI_PTYPE_UNK,
+ (OCIDescribe *) dschp);
+ g_free (fq_tblname);
+ if ((event = gda_oracle_check_result ((result), (cnc), (cdata), OCI_HTYPE_ERROR,
+ _("Could not get a description handle")))) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", gda_connection_event_get_description (event));
+ OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
+ goto out;
+ }
+
+
+ /* Get the parameter handle */
+ OCIParam *parmh;
+ result = OCIAttrGet ((dvoid *) dschp,
+ (ub4) OCI_HTYPE_DESCRIBE,
+ (dvoid **) &parmh,
+ (ub4 *) 0,
+ (ub4) OCI_ATTR_PARAM,
+ (OCIError *) cdata->herr);
+ if ((event = gda_oracle_check_result ((result), (cnc), (cdata), OCI_HTYPE_ERROR,
+ _("Could not get parameter handle")))) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", gda_connection_event_get_description (event));
+ OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
+ goto out;
+ }
+
+ /* Get the number of columns */
+ ub2 numcols;
+ OCIParam *collsthd;
+ result = OCIAttrGet ((dvoid *) parmh,
+ (ub4) OCI_DTYPE_PARAM,
+ (dvoid *) &numcols,
+ (ub4 *) 0,
+ (ub4) OCI_ATTR_NUM_COLS,
+ (OCIError *) cdata->herr);
+ if ((event = gda_oracle_check_result ((result), (cnc), (cdata), OCI_HTYPE_ERROR,
+ _("Could not get attribute")))) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", gda_connection_event_get_description (event));
+ OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
+ goto out;
+ }
+
+ result = OCIAttrGet ((dvoid *) parmh,
+ (ub4) OCI_DTYPE_PARAM,
+ (dvoid *) &collsthd,
+ (ub4 *) 0,
+ (ub4) OCI_ATTR_LIST_COLUMNS,
+ (OCIError *) cdata->herr);
+ if ((event = gda_oracle_check_result ((result), (cnc), (cdata), OCI_HTYPE_ERROR,
+ _("Could not get attribute")))) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", gda_connection_event_get_description (event));
+ OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
+ goto out;
+ }
+
+ /* fetch information for each column, loop starts at 1! */
+ gint col;
+ for (col = 1; col <= numcols; col++) {
+ /* column's catalog, schema, table */
+ GValue *v;
+ values = g_list_prepend (NULL, (gpointer) cv0);
+ v = oracle_identifier_to_value (g_value_get_string (cv1));
+ values = g_list_prepend (values, v);
+ v = oracle_identifier_to_value (g_value_get_string (cv2));
+ values = g_list_prepend (values, v);
+
+ /* Get the column handle */
+ OCIParam *colhd;
+ result = OCIParamGet ((dvoid *) collsthd,
+ (ub4) OCI_DTYPE_PARAM,
+ (OCIError *) cdata->herr,
+ (dvoid **) &colhd,
+ (ub2) col);
+ if ((event = gda_oracle_check_result ((result), (cnc), (cdata), OCI_HTYPE_ERROR,
+ _("Could not get attribute")))) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", gda_connection_event_get_description (event));
+ OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
+ goto out;
+ }
+
+ /* Field name */
+ text *strp;
+ ub4 sizep;
+ result = OCIAttrGet ((dvoid *) colhd,
+ (ub4) OCI_DTYPE_PARAM,
+ (dvoid *) &strp,
+ (ub4 *) &sizep,
+ (ub4) OCI_ATTR_NAME,
+ (OCIError *) cdata->herr);
+ if ((event = gda_oracle_check_result ((result), (cnc), (cdata), OCI_HTYPE_ERROR,
+ _("Could not get attribute")))) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", gda_connection_event_get_description (event));
+ OCIDescriptorFree ((dvoid *) colhd, OCI_DTYPE_PARAM);
+ OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
+ goto out;
+ }
+ gchar *tmpname;
+ tmpname = (gchar*) g_malloc (sizep + 1);
+ strncpy (tmpname, strp, sizep);
+ tmpname[sizep] = 0;
+ v = oracle_identifier_to_value (tmpname);
+ g_free (tmpname);
+ values = g_list_prepend (values, v);
+
+ /* ordinal position */
+ g_value_set_int ((v = gda_value_new (G_TYPE_INT)), col);
+ values = g_list_prepend (values, v);
+
+ /* default */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* Not null? */
+ ub1 nullable;
+ result = OCIAttrGet ((dvoid *)colhd,
+ (ub4) OCI_DTYPE_PARAM,
+ (dvoid *) &nullable,
+ (ub4 *) 0,
+ (ub4) OCI_ATTR_IS_NULL,
+ (OCIError *) cdata->herr);
+ if ((event = gda_oracle_check_result ((result), (cnc), (cdata), OCI_HTYPE_ERROR,
+ _("Could not get attribute")))) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", gda_connection_event_get_description (event));
+ OCIDescriptorFree ((dvoid *) colhd, OCI_DTYPE_PARAM);
+ OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
+ goto out;
+ }
+ g_value_set_boolean ((v = gda_value_new (G_TYPE_BOOLEAN)), ! (nullable > 0));
+ values = g_list_prepend (values, v);
+
+ /* Data type */
+ ub2 type;
+ ub1 precision;
+ sb1 scale;
+ result = OCIAttrGet ((dvoid *)colhd,
+ (ub4) OCI_DTYPE_PARAM,
+ (dvoid *) &type,
+ (ub4 *) 0,
+ (ub4) OCI_ATTR_DATA_TYPE,
+ (OCIError *) cdata->herr);
+ if ((event = gda_oracle_check_result ((result), (cnc), (cdata), OCI_HTYPE_ERROR,
+ _("Could not get attribute")))) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", gda_connection_event_get_description (event));
+ OCIDescriptorFree ((dvoid *) colhd, OCI_DTYPE_PARAM);
+ OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
+ goto out;
+ }
+
+ result = OCIAttrGet ((dvoid *)colhd,
+ (ub4) OCI_DTYPE_PARAM,
+ (dvoid *) &precision,
+ (ub4 *) 0,
+ (ub4) OCI_ATTR_PRECISION,
+ (OCIError *) cdata->herr);
+ if ((event = gda_oracle_check_result ((result), (cnc), (cdata), OCI_HTYPE_ERROR,
+ _("Could not get attribute")))) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", gda_connection_event_get_description (event));
+ OCIDescriptorFree ((dvoid *) colhd, OCI_DTYPE_PARAM);
+ OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
+ goto out;
+ }
+
+ result = OCIAttrGet ((dvoid *)colhd,
+ (ub4) OCI_DTYPE_PARAM,
+ (dvoid *) &scale,
+ (ub4 *) 0,
+ (ub4) OCI_ATTR_SCALE,
+ (OCIError *) cdata->herr);
+ if ((event = gda_oracle_check_result ((result), (cnc), (cdata), OCI_HTYPE_ERROR,
+ _("Could not get attribute")))) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", gda_connection_event_get_description (event));
+ OCIDescriptorFree ((dvoid *) colhd, OCI_DTYPE_PARAM);
+ OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
+ goto out;
+ }
+
+ g_value_set_string ((v = gda_value_new (G_TYPE_STRING)), _oracle_sqltype_to_string (type));
+ values = g_list_prepend (values, v);
+
+ /* array spec */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* GType */
+ const gchar *ctmp;
+ ctmp = g_type_name (_oracle_sqltype_to_g_type (type, precision, scale));
+ g_value_set_string ((v = gda_value_new (G_TYPE_STRING)),
+ ctmp ? ctmp : "GdaBinary");
+ values = g_list_prepend (values, v);
+
+ /* character_maximum_length */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* character_octet_length */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* numeric_precision */
+ g_value_set_int ((v = gda_value_new (G_TYPE_INT)), precision);
+ values = g_list_prepend (values, v);
+
+ /* numeric_scale */
+ g_value_set_int ((v = gda_value_new (G_TYPE_INT)), scale);
+ values = g_list_prepend (values, v);
+
+ /* datetime_precision */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* character_set_catalog */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* character_set_schema */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* character_set_name */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* collation_catalog */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* collation_schema */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* collation_name */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* extra */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* is_updatable */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* column_comments */
+ values = g_list_prepend (values, gda_value_new_null ());
+
+ /* add to @model */
+ gint newrow;
+ values = g_list_reverse (values);
+ newrow = gda_data_model_append_values (model, values, error);
+
+ /* free values */
+ g_list_foreach (values->next, (GFunc) gda_value_free, NULL);
+ g_list_free (values);
+ values = NULL;
+ if (newrow == -1)
+ goto out;
+ }
+
+ OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
+ }
+ retval = TRUE;
+
+ out:
+ if (values) {
+ /* in case of error */
+ values = g_list_reverse (values);
+ g_list_foreach (values->next, (GFunc) gda_value_free, NULL);
+ g_list_free (values);
+ }
+
+ /* modify meta store with @model */
+ if (retval) {
+ FILE *out;
+ out = fopen ("_columns", "w");
+ gda_data_model_dump (model, out);
+ fclose (out);
+
+ gda_meta_store_set_identifiers_style (store, GDA_SQL_IDENTIFIERS_UPPER_CASE);
+ retval = gda_meta_store_modify_with_context (store, context, model, error);
+ }
+ g_object_unref (tables);
+ g_object_unref (model);
+
+ return retval;
}
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)
+ GdaMetaStore *store, GdaMetaContext *context, GError **error,
+ const GValue *table_catalog, const GValue *table_schema,
+ const GValue *table_name)
{
TO_IMPLEMENT;
return TRUE;
diff --git a/providers/oracle/gda-oracle-provider.c b/providers/oracle/gda-oracle-provider.c
index 42253f8..7bdf4c6 100644
--- a/providers/oracle/gda-oracle-provider.c
+++ b/providers/oracle/gda-oracle-provider.c
@@ -252,6 +252,29 @@ gda_oracle_provider_class_init (GdaOracleProviderClass *klass)
/* thread safe */
provider_class->limiting_thread = NULL;
+
+ /* static types */
+ static_types = g_new (GType, GDA_STYPE_NULL + 1);
+ static_types[GDA_STYPE_INT] = G_TYPE_INT;
+ static_types[GDA_STYPE_STRING] = G_TYPE_STRING;
+ static_types[GDA_STYPE_BOOLEAN] = G_TYPE_BOOLEAN;
+ static_types[GDA_STYPE_DATE] = G_TYPE_DATE;
+ static_types[GDA_STYPE_TIME] = GDA_STYPE_TIME;
+ static_types[GDA_STYPE_TIMESTAMP] = GDA_STYPE_TIMESTAMP;
+ static_types[GDA_STYPE_INT64] = G_TYPE_INT64;
+ static_types[GDA_STYPE_UINT] = G_TYPE_UINT;
+ static_types[GDA_STYPE_FLOAT] = G_TYPE_FLOAT;
+ static_types[GDA_STYPE_DOUBLE] = G_TYPE_DOUBLE;
+ static_types[GDA_STYPE_LONG] = G_TYPE_LONG;
+ static_types[GDA_STYPE_ULONG] = G_TYPE_ULONG;
+ static_types[GDA_STYPE_NUMERIC] = GDA_STYPE_NUMERIC;
+ static_types[GDA_STYPE_BINARY] = GDA_STYPE_BINARY;
+ static_types[GDA_STYPE_BLOB] = GDA_STYPE_BLOB;
+ static_types[GDA_STYPE_CHAR] = G_TYPE_CHAR;
+ static_types[GDA_STYPE_SHORT] = GDA_STYPE_SHORT;
+ static_types[GDA_STYPE_GTYPE] = G_TYPE_GTYPE;
+ static_types[GDA_STYPE_GEOMETRIC_POINT] = GDA_STYPE_GEOMETRIC_POINT;
+ static_types[GDA_STYPE_NULL] = GDA_TYPE_NULL;
}
static void
@@ -613,6 +636,35 @@ gda_oracle_provider_open_connection (GdaServerProvider *provider, GdaConnection
cdata->schema = g_ascii_strup (username, -1);
gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_oracle_free_cnc_data);
+ /* get version */
+ gchar version [512];
+ cdata->version = NULL;
+ cdata->major_version = 8;
+ cdata->minor_version = 0;
+ result = OCIServerVersion (cdata->hservice, cdata->herr, version, 511, OCI_HTYPE_SVCCTX);
+ if ((result == OCI_SUCCESS) || (result = OCI_SUCCESS_WITH_INFO)) {
+ cdata->version = g_strdup (version);
+ gchar *tmp, *ptr;
+ tmp = g_ascii_strdown (version, -1);
+ ptr = strstr (tmp, "release");
+ if (ptr) {
+ for (ptr += 7; *ptr; ptr++) {
+ if (! g_ascii_isspace (*ptr))
+ break;
+ }
+ if (g_ascii_isdigit (*ptr)) {
+ cdata->major_version = *ptr - '0';
+ ptr++;
+ if (*ptr) {
+ ptr++;
+ if (g_ascii_isdigit (*ptr))
+ cdata->minor_version = *ptr - '0';
+ }
+ }
+ }
+ g_free (tmp);
+ }
+
/* Optionnally set some attributes for the newly opened connection (encoding to UTF-8 for example )*/
if (! execute_raw_command (cnc, "ALTER SESSION SET NLS_DATE_FORMAT = 'MM/DD/YYYY'") ||
! execute_raw_command (cnc, "ALTER SESSION SET NLS_NUMERIC_CHARACTERS = \". \"")) {
@@ -674,6 +726,7 @@ static const gchar *
gda_oracle_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc)
{
OracleConnectionData *cdata;
+ static guchar version[512];
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
@@ -681,8 +734,8 @@ gda_oracle_provider_get_server_version (GdaServerProvider *provider, GdaConnecti
cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
if (!cdata)
return FALSE;
- TO_IMPLEMENT;
- return NULL;
+
+ return cdata->version;
}
/*
@@ -1154,7 +1207,11 @@ gda_oracle_provider_create_parser (GdaServerProvider *provider, GdaConnection *c
* 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 *oracle_render_select (GdaSqlStatementSelect *stmt, GdaSqlRenderingContext *context, GError **error);
static gchar *oracle_render_select_target (GdaSqlSelectTarget *target, GdaSqlRenderingContext *context, GError **error);
+static gchar *oracle_render_expr (GdaSqlExpr *expr, GdaSqlRenderingContext *context,
+ gboolean *is_default, gboolean *is_null,
+ GError **error);
static gchar *
gda_oracle_provider_statement_to_sql (GdaServerProvider *provider, GdaConnection *cnc,
@@ -1173,7 +1230,9 @@ gda_oracle_provider_statement_to_sql (GdaServerProvider *provider, GdaConnection
memset (&context, 0, sizeof (context));
context.params = params;
context.flags = flags;
+ context.render_select = (GdaSqlRenderingFunc) oracle_render_select;
context.render_select_target = (GdaSqlRenderingFunc) oracle_render_select_target;
+ context.render_expr = oracle_render_expr; /* render "FALSE" as 0 and TRUE as !0 */
str = gda_statement_to_sql_real (stmt, &context, error);
@@ -1224,6 +1283,214 @@ oracle_render_select_target (GdaSqlSelectTarget *target, GdaSqlRenderingContext
return NULL;
}
+static gchar *
+oracle_render_select (GdaSqlStatementSelect *stmt, GdaSqlRenderingContext *context, GError **error)
+{
+ GString *string;
+ gchar *str;
+ GSList *list;
+
+ g_return_val_if_fail (stmt, NULL);
+ g_return_val_if_fail (GDA_SQL_ANY_PART (stmt)->type == GDA_SQL_ANY_STMT_SELECT, NULL);
+
+ string = g_string_new ("SELECT ");
+ /* distinct */
+ if (stmt->distinct) {
+ g_string_append (string, "DISTINCT ");
+ if (stmt->distinct_expr) {
+ str = context->render_expr (stmt->distinct_expr, context, NULL, NULL, error);
+ if (!str) goto err;
+ g_string_append (string, "ON ");
+ g_string_append (string, str);
+ g_string_append_c (string, ' ');
+ g_free (str);
+ }
+ }
+
+ /* selected expressions */
+ for (list = stmt->expr_list; list; list = list->next) {
+ str = context->render_select_field (GDA_SQL_ANY_PART (list->data), context, error);
+ if (!str) goto err;
+ if (list != stmt->expr_list)
+ g_string_append (string, ", ");
+ g_string_append (string, str);
+ g_free (str);
+ }
+
+ /* FROM */
+ if (stmt->from) {
+ str = context->render_select_from (GDA_SQL_ANY_PART (stmt->from), context, error);
+ if (!str) goto err;
+ g_string_append_c (string, ' ');
+ g_string_append (string, str);
+ g_free (str);
+ }
+ else {
+ g_string_append (string, " FROM DUAL");
+ }
+
+ /* WHERE */
+ if (stmt->where_cond) {
+ g_string_append (string, " WHERE ");
+ str = context->render_expr (stmt->where_cond, context, NULL, NULL, error);
+ if (!str) goto err;
+ g_string_append (string, str);
+ g_free (str);
+ }
+
+ /* LIMIT */
+ if (stmt->limit_count) {
+ if (stmt->where_cond)
+ g_string_append (string, " AND");
+ else
+ g_string_append (string, " WHERE");
+
+ if (stmt->limit_offset) {
+ g_set_error (error, GDA_STATEMENT_ERROR, GDA_STATEMENT_SYNTAX_ERROR,
+ _("Oracle does not support the offset with a limit"));
+ goto err;
+ }
+ else {
+ g_string_append (string, " ROWNUM <= (");
+ str = context->render_expr (stmt->limit_count, context, NULL, NULL, error);
+ if (!str) goto err;
+ g_string_append (string, str);
+ g_free (str);
+ g_string_append_c (string, ')');
+ }
+ }
+
+ /* GROUP BY */
+ for (list = stmt->group_by; list; list = list->next) {
+ str = context->render_expr (list->data, context, NULL, NULL, error);
+ if (!str) goto err;
+ if (list != stmt->group_by)
+ g_string_append (string, ", ");
+ else
+ g_string_append (string, " GROUP BY ");
+ g_string_append (string, str);
+ g_free (str);
+ }
+
+ /* HAVING */
+ if (stmt->having_cond) {
+ g_string_append (string, " HAVING ");
+ str = context->render_expr (stmt->having_cond, context, NULL, NULL, error);
+ if (!str) goto err;
+ g_string_append (string, str);
+ g_free (str);
+ }
+
+ /* ORDER BY */
+ for (list = stmt->order_by; list; list = list->next) {
+ str = context->render_select_order (GDA_SQL_ANY_PART (list->data), context, error);
+ if (!str) goto err;
+ if (list != stmt->order_by)
+ g_string_append (string, ", ");
+ else
+ g_string_append (string, " ORDER BY ");
+ g_string_append (string, str);
+ g_free (str);
+ }
+
+ str = string->str;
+ g_string_free (string, FALSE);
+ return str;
+
+ err:
+ g_string_free (string, TRUE);
+ return NULL;
+}
+
+static gchar *
+oracle_render_expr (GdaSqlExpr *expr, GdaSqlRenderingContext *context,
+ gboolean *is_default, gboolean *is_null,
+ GError **error)
+{
+ GString *string;
+ gchar *str = NULL;
+
+ g_return_val_if_fail (expr, NULL);
+ g_return_val_if_fail (GDA_SQL_ANY_PART (expr)->type == GDA_SQL_ANY_EXPR, NULL);
+
+ if (is_default)
+ *is_default = FALSE;
+ if (is_null)
+ *is_null = FALSE;
+
+ /* can't have:
+ * - expr->cast_as && expr->param_spec
+ */
+ if (!gda_sql_any_part_check_structure (GDA_SQL_ANY_PART (expr), error)) return NULL;
+
+ string = g_string_new ("");
+ if (expr->param_spec) {
+ str = context->render_param_spec (expr->param_spec, expr, context, is_default, is_null, error);
+ if (!str) goto err;
+ }
+ else if (expr->value) {
+ str = gda_value_stringify (expr->value);
+ if (!str) goto err;
+ if (is_null && gda_value_is_null (expr->value))
+ *is_null = TRUE;
+ else if (is_default && (G_VALUE_TYPE (expr->value) == G_TYPE_STRING) &&
+ !g_ascii_strcasecmp (g_value_get_string (expr->value), "default"))
+ *is_default = TRUE;
+ else if (!g_ascii_strcasecmp (str, "FALSE")) {
+ g_free (str);
+ str = g_strdup ("0");
+ }
+ else if (!g_ascii_strcasecmp (str, "TRUE")) {
+ g_free (str);
+ str = g_strdup ("1");
+ }
+ }
+ else if (expr->func) {
+ str = context->render_function (GDA_SQL_ANY_PART (expr->func), context, error);
+ if (!str) goto err;
+ }
+ else if (expr->cond) {
+ str = context->render_operation (GDA_SQL_ANY_PART (expr->cond), context, error);
+ if (!str) goto err;
+ }
+ else if (expr->select) {
+ gchar *str1;
+ str1 = context->render_select (GDA_SQL_ANY_PART (expr->select), context, error);
+ if (!str1) goto err;
+ str = g_strdup_printf ("(%s)", str1);
+ g_free (str1);
+ }
+ else if (expr->case_s) {
+ str = context->render_case (GDA_SQL_ANY_PART (expr->case_s), context, error);
+ if (!str) goto err;
+ }
+ else {
+ if (is_null)
+ *is_null = TRUE;
+ str = g_strdup ("NULL");
+ }
+
+ if (!str) {
+ /* TO REMOVE */
+ str = g_strdup ("[...]");
+ }
+
+ if (expr->cast_as)
+ g_string_append_printf (string, "CAST (%s AS %s)", str, expr->cast_as);
+ else
+ g_string_append (string, str);
+ g_free (str);
+
+ str = string->str;
+ g_string_free (string, FALSE);
+ return str;
+
+ err:
+ g_string_free (string, TRUE);
+ return NULL;
+}
+
+
/*
* Statement prepare request
*
@@ -1392,7 +1659,13 @@ gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
/* 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)) {
+ GError *lerror = NULL;
+ if (!gda_oracle_provider_statement_prepare (provider, cnc, stmt, &lerror)) {
+ if (lerror && (lerror->domain == GDA_STATEMENT_ERROR) &&
+ (lerror->code == GDA_STATEMENT_SYNTAX_ERROR)) {
+ g_propagate_error (error, lerror);
+ return 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,
@@ -1401,6 +1674,7 @@ gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
* Don't call gda_connection_add_prepared_statement() with this new prepared statement
* as it will be destroyed once used.
*/
+
TO_IMPLEMENT;
return NULL;
}
@@ -1421,7 +1695,8 @@ gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
const gchar *pname = (gchar *) list->data;
gchar *real_pname = NULL;
GdaHolder *h;
-
+ GdaOracleValue *ora_value = NULL;
+
/* find requested parameter */
if (!params) {
event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
@@ -1457,13 +1732,13 @@ gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
else {
/* bind param to NULL */
/* Hint: Indicator Variables, see p. 118 */
- TO_IMPLEMENT;
+ ora_value = g_new0 (GdaOracleValue, 1);
+ ora_value->indicator = -1;
empty_rs = TRUE;
- continue;
}
}
- if (!gda_holder_is_valid (h)) {
+ else if (!gda_holder_is_valid (h)) {
if (! allow_noparam) {
gchar *str;
str = g_strdup_printf (_("Parameter '%s' is invalid"), pname);
@@ -1476,15 +1751,17 @@ gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
}
else {
/* bind param to NULL */
- TO_IMPLEMENT;
+ ora_value = g_new0 (GdaOracleValue, 1);
+ ora_value->indicator = -1;
empty_rs = TRUE;
- continue;
}
}
/* actual binding using the C API, for parameter at position @i */
- const GValue *value = gda_holder_get_value (h);
- GdaOracleValue *ora_value = _gda_value_to_oracle_value (value);
+ if (!ora_value) {
+ const GValue *value = gda_holder_get_value (h);
+ ora_value = _gda_value_to_oracle_value (value);
+ }
OCIBind *bindpp = (OCIBind *) 0;
int result;
result = OCIBindByName ((dvoid *) ps->hstmt,
@@ -1566,8 +1843,9 @@ gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
(ub4) 0,
(CONST OCISnapshot *) NULL,
(OCISnapshot *) NULL,
- OCI_STMT_SCROLLABLE_READONLY); /* not OCI_COMMIT_ON_SUCCESS because transactions are
- handled separately */
+ OCI_DEFAULT);
+ /* or OCI_STMT_SCROLLABLE_READONLY, not OCI_COMMIT_ON_SUCCESS because transactions are
+ handled separately */
event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
_("Could not execute the Oracle statement"));
@@ -1652,7 +1930,8 @@ gda_oracle_provider_statement_execute (GdaServerProvider *provider, GdaConnectio
}
data_model = 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 */
+ if (data_model)
+ gda_connection_internal_statement_executed (cnc, stmt, params, NULL); /* required: help @cnc keep some stats */
g_object_unref (ps);
return (GObject*) data_model;
}
@@ -1846,8 +2125,9 @@ gda_oracle_free_cnc_data (OracleConnectionData *cdata)
OCIHandleFree ((dvoid *) cdata->herr, OCI_HTYPE_ERROR);
if (cdata->henv)
OCIHandleFree ((dvoid *) cdata->henv, OCI_HTYPE_ENV);
- if (cdata->schema)
- g_free(cdata->schema);
+
+ g_free (cdata->schema);
+ g_free (cdata->version);
g_free (cdata);
}
diff --git a/providers/oracle/gda-oracle-recordset.c b/providers/oracle/gda-oracle-recordset.c
index fe978cc..4b91804 100644
--- a/providers/oracle/gda-oracle-recordset.c
+++ b/providers/oracle/gda-oracle-recordset.c
@@ -31,6 +31,7 @@
#include "gda-oracle-util.h"
#define _GDA_PSTMT(x) ((GdaPStmt*)(x))
+#define BUFFER_SIZE 4095 /* size of the buffer to fecth data from the server using the callback API (OCIDefineDynamic) */
static void gda_oracle_recordset_class_init (GdaOracleRecordsetClass *klass);
static void gda_oracle_recordset_init (GdaOracleRecordset *recset,
@@ -48,10 +49,14 @@ static GdaRow *new_row (GdaDataSelect *imodel, GdaConnection *cnc, GdaOraclePSt
struct _GdaOracleRecordsetPrivate {
gint next_row_num;
- gboolean is_scrollable; /* if FALSE => in RANDOM access mode we need to perform some caching like for SQLite */
};
static GObjectClass *parent_class = NULL;
+#ifdef GDA_DEBUG
+#define TS_DIFF(a,b) (((b).tv_sec * 1000000 + (b).tv_usec) - ((a).tv_sec * 1000000 + (a).tv_usec))
+#include <sys/time.h>
+#endif
+
/*
* Object init and finalize
*/
@@ -61,7 +66,6 @@ gda_oracle_recordset_init (GdaOracleRecordset *recset,
{
g_return_if_fail (GDA_IS_ORACLE_RECORDSET (recset));
recset->priv = g_new0 (GdaOracleRecordsetPrivate, 1);
- recset->priv->is_scrollable = FALSE;
recset->priv->next_row_num = 0;
}
@@ -129,6 +133,44 @@ gda_oracle_recordset_get_type (void)
return type;
}
+static sb4
+ora_def_callback (GdaOracleValue *ora_value,
+ OCIDefine *def,
+ ub4 iter,
+ dvoid **bufpp,
+ ub4 **alenpp,
+ ub1 *piecep,
+ dvoid **indpp,
+ ub2 **rcodep)
+{
+ if (!ora_value->value) {
+ /* 1st chunk */
+ ora_value->defined_size = 0;
+ ora_value->value = g_new0 (guchar, BUFFER_SIZE + 1);
+ *bufpp = ora_value->value;
+ }
+ else {
+ /* other chunks */
+ ora_value->defined_size += ora_value->xlen; /* previous's chunk's real size */
+#ifdef GDA_DEBUG_NO
+ gint i;
+ g_print ("XLEN= %d\n", ora_value->xlen);
+ for (i = 0 ; i < ora_value->defined_size; i++)
+ g_print ("SO FAR[%d]=[%d]%c\n", i, ((gchar*) ora_value->value)[i],
+ g_unichar_isgraph (((gchar*) ora_value->value)[i]) ? ((gchar*) ora_value->value)[i] : '-');
+#endif
+ ora_value->value = g_renew (guchar, ora_value->value, ora_value->defined_size + BUFFER_SIZE);
+ *bufpp = ora_value->value + ora_value->defined_size;
+ }
+
+ ora_value->xlen = BUFFER_SIZE;
+ *alenpp = &(ora_value->xlen);
+ *indpp = (dvoid *) &(ora_value->indicator);
+ *rcodep = (ub2 *) &(ora_value->rcode);
+
+ return OCI_CONTINUE;
+}
+
/*
* the @ps struct is modified and transfered to the new data model created in
* this function
@@ -141,10 +183,8 @@ gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_p
OracleConnectionData *cdata;
gint i;
GdaDataModelAccessFlags rflags;
- int result;
gint nb_rows = -1;
- gboolean is_scrollable = FALSE;
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
g_return_val_if_fail (ps != NULL, NULL);
@@ -206,6 +246,7 @@ gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_p
GdaColumn *column;
int result;
GdaOracleValue *ora_value;
+ gboolean use_callback = FALSE;
ora_value = g_new0 (GdaOracleValue, 1);
ora_values = g_list_prepend (ora_values, ora_value);
@@ -227,13 +268,14 @@ gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_p
OCI_DTYPE_PARAM,
&(ora_value->defined_size),
0,
- OCI_ATTR_DATA_SIZE,
+ (ub4) OCI_ATTR_DATA_SIZE,
cdata->herr);
if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
_("Could not get the parameter defined size"))) {
g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
return NULL;
}
+ ora_value->defined_size++;
/* data type */
result = OCIAttrGet ((dvoid *) (ora_value->pard),
@@ -248,6 +290,37 @@ gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_p
return NULL;
}
+ result = OCIAttrGet ((dvoid *) (ora_value->pard),
+ OCI_DTYPE_PARAM,
+ &(ora_value->precision),
+ 0,
+ OCI_ATTR_PRECISION,
+ cdata->herr);
+ if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
+ _("Could not get the type's precision"))) {
+ g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
+ return NULL;
+ }
+
+ result = OCIAttrGet ((dvoid *) (ora_value->pard),
+ OCI_DTYPE_PARAM,
+ &(ora_value->scale),
+ 0,
+ OCI_ATTR_SCALE,
+ cdata->herr);
+ if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
+ _("Could not get the type's scale"))) {
+ g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
+ return NULL;
+ }
+
+#ifdef GDA_DEBUG_NO
+ g_print ("--COL type is %d, GType is %s, ORA defined size is %d\n",
+ ora_value->sql_type,
+ g_type_name (ora_value->g_type),
+ ora_value->defined_size - 1);
+#endif
+
/* column's name */
text *name;
ub4 name_len;
@@ -274,30 +347,58 @@ gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_p
g_free (name_buffer);
/* for data fetching */
- ub2 fake_type;
- fake_type = ora_value->sql_type;
+ if (_GDA_PSTMT (ps)->types [i] != GDA_TYPE_NULL)
+ ora_value->sql_type = _g_type_to_oracle_sqltype (_GDA_PSTMT (ps)->types [i]);
+
switch (ora_value->sql_type) {
- case SQLT_NUM: /* Numerics are coerced to string */
- fake_type = SQLT_CHR;
+ case SQLT_CHR: /* for G_TYPE_STRING => request SQLT_CHR */
+ case SQLT_STR:
+ case SQLT_VCS:
+ case SQLT_RID:
+ case SQLT_AVC:
+ case SQLT_AFC:
+ ora_value->sql_type = SQLT_CHR;
+ if (ora_value->defined_size == 1)
+ use_callback = TRUE;
+ break;
+
+ case SQLT_INT:
+ ora_value->defined_size = sizeof (gint);
break;
- case SQLT_DAT: /* Convert SQLT_DAT to OCIDate */
- fake_type = SQLT_ODT;
+
+ case SQLT_FLT:
+ case SQLT_BFLOAT:
+ ora_value->defined_size = sizeof (gfloat);
+ break;
+
+ case SQLT_BDOUBLE:
+ ora_value->defined_size = sizeof (gdouble);
+ break;
+
+ case SQLT_DAT: /* request OCIDate */
+ ora_value->sql_type = SQLT_ODT;
+ break;
+
+ case SQLT_NUM: /* for GDA_TYPE_NUMERIC => request SQLT_CHR */
+ case SQLT_VNU:
+ ora_value->sql_type = SQLT_CHR;
+ break;
+
+ case SQLT_LBI:
+ case SQLT_LVB:
+ case SQLT_LVC:
+ case SQLT_LNG:
+ case SQLT_VBI:
+ case SQLT_BIN:
+ use_callback = TRUE;
break;
}
if (_GDA_PSTMT (ps)->types [i] != GDA_TYPE_NULL)
ora_value->g_type = _GDA_PSTMT (ps)->types [i];
else
- 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;
- }
- */
+ ora_value->g_type = _oracle_sqltype_to_g_type (ora_value->sql_type, ora_value->precision,
+ ora_value->scale);
if (ora_value->g_type == GDA_TYPE_BLOB) {
/* allocate a Lob locator */
OCILobLocator *lob;
@@ -313,13 +414,22 @@ gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_p
ora_value->value = lob;
ora_value->defined_size = 0;
}
- else if (ora_value->defined_size == 0)
+ else if (use_callback) {
ora_value->value = NULL;
- else {
- ora_value->defined_size++;
- ora_value->value = g_malloc0 (ora_value->defined_size);
+ ora_value->defined_size = 33554432; /* 32M */
}
+ else
+ ora_value->value = g_malloc0 (ora_value->defined_size);
+ ora_value->s_type = gda_g_type_to_static_type (ora_value->g_type);
+#ifdef GDA_DEBUG_NO
+ g_print ("**COL type is %d, GType is %s, ORA defined size is %d%s\n",
+ ora_value->sql_type,
+ g_type_name (ora_value->g_type),
+ ora_value->defined_size - 1,
+ use_callback ? " using callback": "");
+#endif
+
ora_value->hdef = (OCIDefine *) 0;
ora_value->indicator = 0;
result = OCIDefineByPos ((OCIStmt *) ps->hstmt,
@@ -328,71 +438,51 @@ gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_p
(ub4) i + 1,
ora_value->value,
ora_value->defined_size,
- (ub2) fake_type,
+ ora_value->sql_type,
(dvoid *) &(ora_value->indicator),
- (ub2 *) 0,
- (ub2 *) 0,
- (ub4) OCI_DEFAULT);
+ &(ora_value->rlen),
+ &(ora_value->rcode),
+ (ub4) (use_callback ? OCI_DYNAMIC_FETCH : OCI_DEFAULT));
if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
_("Could not define by position"))) {
OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
return NULL;
}
+
+ if (use_callback) {
+ result = OCIDefineDynamic ((OCIDefine *) (ora_value->hdef),
+ (OCIError *) (cdata->herr),
+ (dvoid*) (ora_value),
+ (OCICallbackDefine) ora_def_callback);
+ if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
+ _("Could not define by position"))) {
+ OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
+ g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
+ return NULL;
+ }
+ }
+
+ ora_value->use_callback = use_callback;
}
ps->ora_values = g_list_reverse (ora_values);
}
- /* determine if cursor is scrollable or not as "Remote mapped queries cannot be used with scrollable cursors"
- * or so says dthe doc.
- * Also set the prefetch rows number */
- result = OCIStmtFetch2 (ps->hstmt,
- cdata->herr,
- (ub4) 1,
- (ub2) OCI_FETCH_LAST,
- (sb4) 0,
- (ub4) OCI_DEFAULT);
- if (result == OCI_NO_DATA)
- nb_rows = 0;
- else if (result != OCI_ERROR) {
- is_scrollable = TRUE;
-
- /* get number of rows */
- ub4 pos;
- result = OCIAttrGet (ps->hstmt, OCI_HTYPE_STMT,
- (dvoid *) &pos, NULL,
- OCI_ATTR_CURRENT_POSITION, cdata->herr);
- if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
- _("Could not get the current position")))
- return NULL;
- nb_rows = pos;
-
- /* go back to 1st row */
- result = OCIStmtFetch2 (ps->hstmt,
- cdata->herr,
- (ub4) 1,
- (ub2) OCI_FETCH_FIRST,
- (sb4) 0,
- (ub4) OCI_DEFAULT);
- if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
- _("Could not move to position")))
- return NULL;
-
- /* set prefetch size */
- ub4 prefetch;
- prefetch = (ub4) ((gfloat) nb_rows * 0.2);
- if (prefetch > 1)
- OCIAttrSet (ps->hstmt, OCI_HTYPE_STMT,
- &prefetch, 0,
- OCI_ATTR_PREFETCH_ROWS, cdata->herr);
- }
-
- /* 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;
+ /* determine access mode: RANDOM or CURSOR FORWARD are the only supported; if CURSOR BACKWARD
+ * is requested, then we need RANDOM mode */
+ if (flags & GDA_DATA_MODEL_ACCESS_RANDOM)
+ rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
+ else if (flags & GDA_DATA_MODEL_ACCESS_CURSOR_BACKWARD)
+ rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
+ else
+ rflags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;
+
+ ub4 prefetch;
+ prefetch = (ub4) (100);
+ OCIAttrSet (ps->hstmt, OCI_HTYPE_STMT,
+ &prefetch, 0,
+ OCI_ATTR_PREFETCH_ROWS, cdata->herr);
/* create data model */
model = g_object_new (GDA_TYPE_ORACLE_RECORDSET,
@@ -401,9 +491,6 @@ gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_p
"model-usage", rflags,
"exec-params", exec_params, NULL);
GDA_DATA_SELECT (model)->advertized_nrows = nb_rows;
- GDA_ORACLE_RECORDSET (model)->priv->is_scrollable = is_scrollable;
-
- g_print ("DETECTED %d rows, %s\n", nb_rows, is_scrollable ? "SCROLLABLE" : "NON SCROLLABLE");
return GDA_DATA_MODEL (model);
}
@@ -420,30 +507,41 @@ fetch_next_oracle_row (GdaOracleRecordset *model, gboolean do_store, GError **er
cnc = gda_data_select_get_connection ((GdaDataSelect*) model);
cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
if (!cdata)
- return FALSE;
+ return NULL;
/* fetch row */
- result = OCIStmtFetch2 (ps->hstmt,
- cdata->herr,
- (ub4) 1,
- (ub2) OCI_FETCH_NEXT,
- (sb4) 1,
- (ub4) OCI_DEFAULT);
+ if (cdata->major_version > 9)
+ result = OCIStmtFetch2 (ps->hstmt,
+ cdata->herr,
+ (ub4) 1,
+ (ub2) OCI_FETCH_NEXT,
+ (sb4) 1,
+ (ub4) OCI_DEFAULT);
+ else
+ result = OCIStmtFetch (ps->hstmt,
+ cdata->herr,
+ (ub4) 1,
+ (ub2) OCI_FETCH_NEXT,
+ (ub4) OCI_DEFAULT);
if (result == OCI_NO_DATA) {
GDA_DATA_SELECT (model)->advertized_nrows = model->priv->next_row_num;
return NULL;
}
- else if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
- _("Could not fetch requested row"))) {
- /* set @error */
- TO_IMPLEMENT;
- return FALSE;
+ else {
+ GdaConnectionEvent *event;
+ if ((event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
+ _("Could not fetch next row")))) {
+ /* set @error */
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", gda_connection_event_get_description (event));
+
+ return NULL;
+ }
}
-
+
prow = new_row ((GdaDataSelect*) model, cnc, ps);
- gda_data_select_take_row (model, prow, model->priv->next_row_num);
+ gda_data_select_take_row ((GdaDataSelect*) model, prow, model->priv->next_row_num);
model->priv->next_row_num ++;
- g_print ("Next row: %d\n", model->priv->next_row_num);
return prow;
}
@@ -462,9 +560,17 @@ gda_oracle_recordset_fetch_nb_rows (GdaDataSelect *model)
if (model->advertized_nrows >= 0)
return model->advertized_nrows;
+ struct timeval stm1, stm2;
+
+ gettimeofday (&stm1, NULL);
+
for (prow = fetch_next_oracle_row (imodel, TRUE, NULL);
prow;
prow = fetch_next_oracle_row (imodel, TRUE, NULL));
+
+ gettimeofday (&stm2, NULL);
+ /*g_print ("TOTAL time to get nb rows: %0.2f ms\n", (float) (TS_DIFF(stm1,stm2) / 1000.));*/
+
return model->advertized_nrows;
}
@@ -486,42 +592,31 @@ gda_oracle_recordset_fetch_nb_rows (GdaDataSelect *model)
static gboolean
gda_oracle_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
{
- int result;
- GdaOraclePStmt *ps = GDA_ORACLE_PSTMT (model->prep_stmt);
+ GdaOracleRecordset *imodel;
OracleConnectionData *cdata;
GdaConnection *cnc;
if (*prow)
return TRUE;
+ imodel = GDA_ORACLE_RECORDSET (model);
cnc = gda_data_select_get_connection (model);
cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
if (!cdata)
return FALSE;
- if (GDA_ORACLE_RECORDSET (model)->priv->is_scrollable) {
- /* fetch row */
- result = OCIStmtFetch2 (ps->hstmt,
- cdata->herr,
- (ub4) 1,
- (ub2) OCI_FETCH_ABSOLUTE,
- (sb4) rownum + 1,
- (ub4) OCI_DEFAULT);
- if (result == OCI_NO_DATA) {
- model->advertized_nrows = rownum - 1;
- }
- else if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
- _("Could not fetch requested row"))) {
- /* set @error */
- TO_IMPLEMENT;
+ for (; imodel->priv->next_row_num <= rownum; ) {
+ *prow = fetch_next_oracle_row (imodel, TRUE, error);
+ if (!*prow) {
+ /*if (GDA_DATA_SELECT (model)->advertized_nrows >= 0), it's not an error */
+ if ((GDA_DATA_SELECT (model)->advertized_nrows >= 0) &&
+ (imodel->priv->next_row_num < rownum)) {
+ g_set_error (error, 0,
+ GDA_DATA_MODEL_ROW_OUT_OF_RANGE_ERROR,
+ _("Row %d not found"), rownum);
+ }
return FALSE;
}
-
- *prow = new_row (model, cnc, ps);
- gda_data_select_take_row (model, *prow, rownum);
- }
- else {
- TO_IMPLEMENT;
}
return TRUE;
}
@@ -561,39 +656,11 @@ gda_oracle_recordset_store_all (GdaDataSelect *model, GError **error)
static gboolean
gda_oracle_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
{
- int result;
- GdaOraclePStmt *ps = GDA_ORACLE_PSTMT (model->prep_stmt);
- OracleConnectionData *cdata;
- GdaConnection *cnc;
-
if (*prow)
return TRUE;
- cnc = gda_data_select_get_connection (model);
- cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data (cnc);
- if (!cdata)
- return FALSE;
-
- /* fetch row */
- result = OCIStmtFetch2 (ps->hstmt,
- cdata->herr,
- (ub4) 1,
- (ub2) OCI_FETCH_NEXT,
- (sb4) 1,
- (ub4) OCI_DEFAULT);
- if (result == OCI_NO_DATA) {
- model->advertized_nrows = rownum - 1;
- }
- else if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
- _("Could not fetch requested row"))) {
- /* set @error */
- TO_IMPLEMENT;
- return FALSE;
- }
-
- *prow = new_row (model, cnc, ps);
- gda_data_select_take_row (model, *prow, rownum);
- return TRUE;
+ *prow = fetch_next_oracle_row ((GdaOracleRecordset*) model, TRUE, error);
+ return *prow ? TRUE : FALSE;
}
/*
@@ -611,8 +678,6 @@ gda_oracle_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownu
static gboolean
gda_oracle_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
{
- int result;
- GdaOraclePStmt *ps = GDA_ORACLE_PSTMT (model->prep_stmt);
OracleConnectionData *cdata;
GdaConnection *cnc;
@@ -624,31 +689,8 @@ gda_oracle_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint rownu
if (!cdata)
return FALSE;
- if (GDA_ORACLE_RECORDSET (model)->priv->is_scrollable) {
- /* fetch row */
- result = OCIStmtFetch2 (ps->hstmt,
- cdata->herr,
- (ub4) 1,
- (ub2) OCI_FETCH_PRIOR,
- (sb4) 1,
- (ub4) OCI_DEFAULT);
- if (result == OCI_NO_DATA) {
- model->advertized_nrows = rownum - 1;
- }
- else if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
- _("Could not fetch requested row"))) {
- /* set @error */
- TO_IMPLEMENT;
- return FALSE;
- }
-
- *prow = new_row (model, cnc, ps);
- gda_data_select_take_row (model, *prow, rownum);
- }
- else {
- TO_IMPLEMENT;
- }
- return TRUE;
+ g_warning ("Internal implementation error: non scrollable cursor requested to go backward!\n");
+ return FALSE;
}
/*
diff --git a/providers/oracle/gda-oracle-util.c b/providers/oracle/gda-oracle-util.c
index caed135..2930efc 100644
--- a/providers/oracle/gda-oracle-util.c
+++ b/providers/oracle/gda-oracle-util.c
@@ -48,13 +48,11 @@
GdaConnectionEvent *
_gda_oracle_make_error (dvoid *hndlp, ub4 type, const gchar *file, gint line)
{
- GdaConnectionEvent *error;
+ GdaConnectionEvent *error = NULL;
gchar errbuf[512];
ub4 errcode;
gchar *source;
- error = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
-
if (hndlp != NULL) {
OCIErrorGet ((dvoid *) hndlp,
(ub4) 1,
@@ -64,16 +62,25 @@ _gda_oracle_make_error (dvoid *hndlp, ub4 type, const gchar *file, gint line)
(ub4) sizeof (errbuf),
(ub4) type);
- gda_connection_event_set_description (error, errbuf);
- /*g_warning ("Oracle error:%s", errbuf);*/
+ if (errcode != 1405) {
+ error = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+ gda_connection_event_set_description (error, errbuf);
+ /*g_warning ("Oracle error:%s", errbuf);*/
+ if (errcode == 600)
+ g_warning ("Maybe an Oracle bug...");
+ }
}
- else
+ else {
+ error = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
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);
+ if (error) {
+ 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;
}
@@ -114,10 +121,12 @@ _gda_oracle_handle_error (gint result, GdaConnection *cnc,
break;
case OCI_HTYPE_ENV:
error = _gda_oracle_make_error (cdata->henv, type, file, line);
- gda_connection_add_event (cnc, error);
+ if (error)
+ gda_connection_add_event (cnc, error);
break;
default:
- error = gda_connection_add_event_string (cnc, msg);
+ if (error)
+ error = gda_connection_add_event_string (cnc, msg);
gda_connection_add_event (cnc, error);
break;
}
@@ -131,13 +140,15 @@ _gda_oracle_handle_error (gint result, GdaConnection *cnc,
error = gda_connection_add_event_string (cnc, msg);
}
+#ifdef GDA_DEBUG
if (error)
g_print ("HANDLED error: %s\n", gda_connection_event_get_description (error));
+#endif
return error;
}
GType
-_oracle_sqltype_to_g_type (const ub2 sqltype)
+_oracle_sqltype_to_g_type (const ub2 sqltype, sb2 precision, sb1 scale)
{
/* an incomplete list of all the oracle types */
switch (sqltype) {
@@ -145,28 +156,40 @@ _oracle_sqltype_to_g_type (const ub2 sqltype)
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:
+ case SQLT_AFC:
return G_TYPE_STRING;
case SQLT_NUM:
- return GDA_TYPE_NUMERIC;
+ case SQLT_VNU:
+ if (scale == 0)
+ return G_TYPE_INT;
+ else if ((precision != 0) && (scale == -127))
+ return G_TYPE_FLOAT;
+ else return GDA_TYPE_NUMERIC;
case SQLT_INT:
return G_TYPE_INT;
case SQLT_UIN:
return G_TYPE_UINT;
+ case SQLT_BFLOAT:
case SQLT_FLT:
return G_TYPE_FLOAT;
+ case SQLT_BDOUBLE:
+ return G_TYPE_DOUBLE;
+
+ case SQLT_LVC:
+ case SQLT_LVB:
case SQLT_VBI:
case SQLT_BIN:
+ case SQLT_LNG:
case SQLT_LBI:
- case SQLT_LVB:
+ case SQLT_RDD:
+ case SQLT_NTY:
+ case SQLT_REF:
+ return GDA_TYPE_BINARY;
case SQLT_BLOB:
- case SQLT_BFILEE:
- case SQLT_CFILEE:
+ case SQLT_FILE:
+ //case SQLT_BFILEE:
+ //case SQLT_CFILEE:
case SQLT_CLOB:
return GDA_TYPE_BLOB;
case SQLT_DAT:
@@ -180,24 +203,69 @@ _oracle_sqltype_to_g_type (const ub2 sqltype)
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:
+ //case SQLT_VST:
+ //case SQLT_SLS:
+ //case SQLT_CUR:
+ //case SQLT_OSL:
+
+ //case SQLT_RSET:
+ //case SQLT_NCO:
+ //case SQLT_INTERVAL_YM:
+ //case SQLT_INTERVAL_DS:
+ //case SQLT_PDN:
+ //case SQLT_NON:
default:
return G_TYPE_INVALID;
}
}
+ub2
+_g_type_to_oracle_sqltype (GType type)
+{
+ if (type == G_TYPE_BOOLEAN)
+ return SQLT_INT;
+ else if (type == G_TYPE_STRING)
+ return SQLT_CHR;
+ else if (type == G_TYPE_INT)
+ return SQLT_INT;
+ else if (type == G_TYPE_DATE)
+ return SQLT_ODT;
+ else if (type == GDA_TYPE_TIME)
+ return SQLT_TIME;
+ else if (type == G_TYPE_INT64)
+ return SQLT_CHR;
+ else if (type == G_TYPE_UINT)
+ return SQLT_UIN;
+ else if (type == G_TYPE_ULONG)
+ return SQLT_INT;
+ else if (type == G_TYPE_LONG)
+ return SQLT_INT;
+ else if (type == GDA_TYPE_SHORT)
+ return SQLT_INT;
+ else if (type == G_TYPE_FLOAT)
+ return SQLT_BFLOAT;
+ else if (type == G_TYPE_DOUBLE)
+ return SQLT_BDOUBLE;
+ else if (type == GDA_TYPE_NUMERIC)
+ return SQLT_CHR;
+ else if (type == GDA_TYPE_GEOMETRIC_POINT)
+ return SQLT_CHR;
+ else if (type == GDA_TYPE_TIMESTAMP)
+ return SQLT_TIMESTAMP;
+ else if (type == GDA_TYPE_BINARY)
+ return SQLT_LNG;
+ else if (type == GDA_TYPE_BLOB)
+ return SQLT_BLOB;
+ else if (type == G_TYPE_GTYPE)
+ return SQLT_CHR;
+ else if (type == G_TYPE_CHAR)
+ return SQLT_INT;
+ else {
+ g_warning ("Internal implementation missing: type %s not handled", g_type_name (type));
+ return SQLT_LNG;
+ }
+}
+
gchar *
_oracle_sqltype_to_string (const ub2 sqltype)
{
@@ -210,18 +278,20 @@ _oracle_sqltype_to_string (const ub2 sqltype)
case SQLT_INT:
return "INTEGER";
case SQLT_FLT:
+ case SQLT_BFLOAT:
+ case SQLT_BDOUBLE:
return "FLOAT";
case SQLT_STR:
return "STRING";
case SQLT_VNU:
return "VARNUM";
- case SQLT_PDN:
+ //case SQLT_PDN:
return "";
case SQLT_LNG:
return "LONG";
case SQLT_VCS:
return "VARCHAR";
- case SQLT_NON:
+ //case SQLT_NON:
return "";
case SQLT_RID:
return "ROWID";
@@ -235,7 +305,7 @@ _oracle_sqltype_to_string (const ub2 sqltype)
return "LONG RAW";
case SQLT_UIN:
return "UNSIGNED INT";
- case SQLT_SLS:
+ //case SQLT_SLS:
return "";
case SQLT_LVC:
return "LONG VARCHAR";
@@ -245,18 +315,18 @@ _oracle_sqltype_to_string (const ub2 sqltype)
return "CHAR";
case SQLT_AVC:
return "CHARZ";
- case SQLT_CUR:
+ //case SQLT_CUR:
return "CURSOR";
case SQLT_RDD:
return "ROWID";
- case SQLT_LAB:
+ //case SQLT_LAB:
return "LABEL";
- case SQLT_OSL:
+ //case SQLT_OSL:
return "OSLABEL";
case SQLT_NTY:
- return "";
+ return "NAMED DATA TYPE";
case SQLT_REF:
- return "";
+ return "REF";
case SQLT_CLOB:
return "CLOB";
case SQLT_BLOB:
@@ -265,11 +335,11 @@ _oracle_sqltype_to_string (const ub2 sqltype)
return "BFILE";
case SQLT_CFILEE:
return "CFILE";
- case SQLT_RSET:
+ //case SQLT_RSET:
return "RESULT SET";
- case SQLT_NCO:
+ //case SQLT_NCO:
return "";
- case SQLT_VST:
+ //case SQLT_VST:
return "";
case SQLT_ODT:
return "OCI DATE";
@@ -283,14 +353,14 @@ _oracle_sqltype_to_string (const ub2 sqltype)
return "TIMESTAMP";
case SQLT_TIMESTAMP_TZ:
return "TIMESTAMP WITH TIME ZONE";
- case SQLT_INTERVAL_YM:
+ //case SQLT_INTERVAL_YM:
return "INTERVAL YEAR TO MONTH";
- case SQLT_INTERVAL_DS:
+ //case SQLT_INTERVAL_DS:
return "INTERVAL DAY TO SECOND";
case SQLT_TIMESTAMP_LTZ:
return "TIMESTAMP WITH LOCAL TIME ZONE";
default:
- return "UNKNOWN";
+ return "UNDEFINED";
}
}
@@ -400,6 +470,21 @@ _gda_value_to_oracle_value (const GValue *value)
ora_value->defined_size = 0;
}
}
+ else if (type == GDA_TYPE_BINARY) {
+ GdaBinary *bin;
+
+ bin = (GdaBinary *) gda_value_get_binary ((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);
@@ -421,59 +506,42 @@ _gda_oracle_set_value (GValue *value,
{
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)) {
+ if (ora_value->indicator == -1) {
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';
+ gda_value_reset_with_type (value, ora_value->g_type);
+ switch (ora_value->s_type) {
+ case GDA_STYPE_INT:
+ g_value_set_int (value, *((gint *) ora_value->value));
+ break;
+ case GDA_STYPE_STRING: {
+ gchar *string_buffer, *tmp;
+
+ string_buffer = (gchar *) ora_value->value;
+ string_buffer [ora_value->rlen] = '\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);
+ //tmp = g_locale_to_utf8 (string_buffer, -1, NULL, NULL, NULL);
+ //g_value_take_string (value, tmp);
+ g_value_set_string (value, string_buffer);
+ if (ora_value->use_callback) {
+ g_free (string_buffer);
+ ora_value->value = NULL;
+ }
+ break;
}
- else if (type == G_TYPE_DATE) {
+ case GDA_STYPE_BOOLEAN:
+ g_value_set_boolean (value, (*((gint *) ora_value->value)) ? TRUE: FALSE);
+ break;
+ case GDA_STYPE_DATE: {
GDate *date;
OCIDateGetDate ((CONST OCIDate *) ora_value->value,
(sb2 *) &year,
@@ -481,11 +549,20 @@ _gda_oracle_set_value (GValue *value,
(ub1 *) &day);
date = g_date_new_dmy (day, month, year);
g_value_take_boxed (value, date);
+ break;
}
- else if (type == GDA_TYPE_GEOMETRIC_POINT) {}
- else if (type == GDA_TYPE_NULL)
- gda_value_set_null (value);
- else if (type == GDA_TYPE_TIMESTAMP) {
+ case GDA_STYPE_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);
+ break;
+ }
+ case GDA_STYPE_TIMESTAMP: {
OCIDateGetDate ((CONST OCIDate *) ora_value->value,
(sb2 *) &year,
(ub1 *) &month,
@@ -503,21 +580,57 @@ _gda_oracle_set_value (GValue *value,
timestamp.fraction = 0;
timestamp.timezone = 0;
gda_value_set_timestamp(value, ×tamp);
+ break;
}
- 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);
+ case GDA_STYPE_INT64:
+ g_value_set_int64 (value, atoll (ora_value->value));
+ break;
+ case GDA_STYPE_UINT:
+ g_value_set_uint (value, *((guint*) ora_value->value));
+ break;
+ case GDA_STYPE_FLOAT:
+ g_value_set_float (value, *((gfloat*) ora_value->value));
+ break;
+ case GDA_STYPE_DOUBLE:
+ g_value_set_double (value, *((gdouble*) ora_value->value));
+ break;
+ case GDA_STYPE_LONG:
+ TO_IMPLEMENT;
+ break;
+ case GDA_STYPE_ULONG:
+ TO_IMPLEMENT;
+ break;
+ case GDA_STYPE_NUMERIC: {
+ GdaNumeric *numeric;
+ g_assert (!ora_value->use_callback);
+
+ numeric = g_new0 (GdaNumeric, 1);
+ numeric->number = g_malloc0 (ora_value->defined_size);
+ memcpy (numeric->number, ora_value->value, ora_value->defined_size);
+ numeric->number [ora_value->rlen] = '\0';
+ g_strchomp (numeric->number);
+ numeric->precision = ora_value->precision;
+ numeric->width = ora_value->scale;
+ g_value_take_boxed (value, numeric);
+ break;
}
- else if (type == GDA_TYPE_BINARY) {
- g_warning ("GdaBinary type is not supported by Oracle");
+ case GDA_STYPE_BINARY: {
+ GdaBinary *bin;
+
+ bin = g_new0 (GdaBinary, 1);
+ if (ora_value->use_callback) {
+ bin->data = ora_value->value;
+ ora_value->value = NULL;
+ }
+ else {
+ bin->data = g_new (guchar, ora_value->rlen);
+ memcpy (bin->data, ora_value->value, ora_value->rlen);
+ }
+ bin->binary_length = ora_value->rlen;
+ gda_value_take_binary (value, bin);
+ break;
}
- else if (type == GDA_TYPE_BLOB) {
+ case GDA_STYPE_BLOB: {
GdaBlob *blob;
GdaBlobOp *op;
OCILobLocator *lobloc;
@@ -553,9 +666,30 @@ _gda_oracle_set_value (GValue *value,
g_object_unref (op);
gda_value_take_blob (value, blob);
+ break;
+ }
+ case GDA_STYPE_CHAR: {
+ TO_IMPLEMENT; /* test that value fits in */
+ g_value_set_char (value, *((gchar*) ora_value->value));
+ break;
+ }
+ case GDA_STYPE_SHORT: {
+ TO_IMPLEMENT; /* test that value fits in */
+ gda_value_set_short (value, *((gint*) ora_value->value));
+ break;
+ }
+ case GDA_STYPE_GTYPE:
+ TO_IMPLEMENT;
+ break;
+ case GDA_STYPE_GEOMETRIC_POINT:
+ TO_IMPLEMENT;
+ break;
+ case GDA_STYPE_NULL:
+ gda_value_set_null (value);
+ break;
+ default:
+ g_assert_not_reached ();
}
- else
- g_value_set_string (value, ora_value->value);
}
void
@@ -568,3 +702,16 @@ _gda_oracle_value_free (GdaOracleValue *ora_value)
OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
g_free (ora_value);
}
+
+GType *static_types = NULL;
+GdaStaticType
+gda_g_type_to_static_type (GType type)
+{
+ GdaStaticType st;
+ for (st = 0; st < GDA_STYPE_NULL; st++) {
+ if (static_types [st] == type)
+ return st;
+ }
+ g_error ("Missing type '%s' in GDA static types", g_type_name (type));
+ return 0;
+}
diff --git a/providers/oracle/gda-oracle-util.h b/providers/oracle/gda-oracle-util.h
index 55c4892..e381553 100644
--- a/providers/oracle/gda-oracle-util.h
+++ b/providers/oracle/gda-oracle-util.h
@@ -36,15 +36,60 @@ G_BEGIN_DECLS
#define gda_oracle_blob_type(sqltype) \
((((sqltype) == SQLT_BFILEE) || ((sqltype) == SQLT_CFILEE)) ? OCI_DTYPE_FILE : OCI_DTYPE_LOB)
+/*
+ * Static types
+ */
+typedef enum {
+ GDA_STYPE_INT,
+ GDA_STYPE_STRING,
+ GDA_STYPE_BOOLEAN,
+ GDA_STYPE_DATE,
+ GDA_STYPE_TIME,
+ GDA_STYPE_TIMESTAMP,
+ GDA_STYPE_INT64,
+ GDA_STYPE_UINT,
+ GDA_STYPE_FLOAT,
+ GDA_STYPE_DOUBLE,
+ GDA_STYPE_LONG,
+ GDA_STYPE_ULONG,
+ GDA_STYPE_NUMERIC,
+ GDA_STYPE_BINARY,
+ GDA_STYPE_BLOB,
+ GDA_STYPE_CHAR,
+ GDA_STYPE_SHORT,
+ GDA_STYPE_GTYPE,
+ GDA_STYPE_GEOMETRIC_POINT,
+
+ GDA_STYPE_NULL /* MUST be last */
+} GdaStaticType;
+extern GType *static_types;
+GdaStaticType gda_g_type_to_static_type (GType type);
+/*
+ @indicator
+ -2 item length > variable size so data truncated
+ -1 value is NULL
+ 0 value is in host variable
+ >0 item length > variable, indicator is length before truncation
+*/
typedef struct {
OCIDefine *hdef;
OCIParam *pard;
+ gboolean use_callback;
+
sb2 indicator;
- ub2 sql_type;
- ub2 defined_size;
+ ub2 rlen; /* length of data returned after fetch */
+ ub2 rcode; /* column level return codes */
+ ub4 xlen;
+
+ ub2 sql_type; /* Oracle type */
+ ub4 defined_size;
+ sb2 precision;
+ sb1 scale;
+
gpointer value;
GType g_type;
+ GdaStaticType s_type;
} GdaOracleValue;
GdaConnectionEvent *_gda_oracle_make_error (dvoid *hndlp, ub4 type, const gchar *file, gint line);
@@ -52,7 +97,8 @@ GdaConnectionEvent *_gda_oracle_handle_error (gint result, GdaConnection *cnc,
OracleConnectionData *cdata,
ub4 type, const gchar *msg,
const gchar *file, gint line);
-GType _oracle_sqltype_to_g_type (const ub2 sqltype);
+GType _oracle_sqltype_to_g_type (const ub2 sqltype, sb2 precision, sb1 scale);
+ub2 _g_type_to_oracle_sqltype (GType type);
gchar * _oracle_sqltype_to_string (const ub2 sqltype);
gchar * _gda_oracle_value_to_sql_string (GValue *value);
GdaOracleValue *_gda_value_to_oracle_value (const GValue *value);
diff --git a/providers/oracle/gda-oracle.h b/providers/oracle/gda-oracle.h
index 1afd601..f5e485c 100644
--- a/providers/oracle/gda-oracle.h
+++ b/providers/oracle/gda-oracle.h
@@ -42,6 +42,10 @@ typedef struct {
OCISvcCtx *hservice;
OCISession *hsession;
gchar *schema; /* the same as the username which opened the connection */
+
+ gchar *version;
+ guint8 major_version;
+ guint8 minor_version;
} OracleConnectionData;
#endif
diff --git a/providers/postgres/gda-postgres-meta.c b/providers/postgres/gda-postgres-meta.c
index 299b323..0a971e6 100644
--- a/providers/postgres/gda-postgres-meta.c
+++ b/providers/postgres/gda-postgres-meta.c
@@ -314,7 +314,7 @@ _gda_postgres_meta__btypes (GdaServerProvider *prov, GdaConnection *cnc,
/* use a proxy to customize @model */
proxy = (GdaDataModel*) gda_data_proxy_new (model);
- gda_data_proxy_set_sample_size ((GdaDataProxy*) proxy, 0);
+ g_object_set (G_OBJECT (proxy), "defer-sync", FALSE, "sample-size", 0, NULL);
nrows = gda_data_model_get_n_rows (model);
for (i = 0; i < nrows; i++) {
const GValue *value;
@@ -809,7 +809,7 @@ gboolean _gda_postgres_meta__columns (GdaServerProvider *prov, GdaConnection *cn
/* use a proxy to customize @model */
proxy = (GdaDataModel*) gda_data_proxy_new (model);
- gda_data_proxy_set_sample_size ((GdaDataProxy*) proxy, 0);
+ g_object_set (G_OBJECT (proxy), "defer-sync", FALSE, "sample-size", 0, NULL);
nrows = gda_data_model_get_n_rows (model);
for (i = 0; i < nrows; i++) {
const GValue *value;
@@ -913,7 +913,7 @@ _gda_postgres_meta_columns (GdaServerProvider *prov, GdaConnection *cnc,
/* use a proxy to customize @model */
proxy = (GdaDataModel*) gda_data_proxy_new (model);
- gda_data_proxy_set_sample_size ((GdaDataProxy*) proxy, 0);
+ g_object_set (G_OBJECT (proxy), "defer-sync", FALSE, "sample-size", 0, NULL);
nrows = gda_data_model_get_n_rows (model);
for (i = 0; i < nrows; i++) {
const GValue *value;
@@ -1410,7 +1410,7 @@ _gda_postgres_meta__routine_col (GdaServerProvider *prov, GdaConnection *cnc,
/* use a proxy to customize @model */
proxy = (GdaDataModel*) gda_data_proxy_new (model);
- gda_data_proxy_set_sample_size ((GdaDataProxy*) proxy, 0);
+ g_object_set (G_OBJECT (proxy), "defer-sync", FALSE, "sample-size", 0, NULL);
nrows = gda_data_model_get_n_rows (model);
for (i = 0; i < nrows; i++) {
const GValue *cvalue;
@@ -1477,7 +1477,7 @@ GdaDataModel *model, *proxy;
/* use a proxy to customize @model */
proxy = (GdaDataModel*) gda_data_proxy_new (model);
- gda_data_proxy_set_sample_size ((GdaDataProxy*) proxy, 0);
+ g_object_set (G_OBJECT (proxy), "defer-sync", FALSE, "sample-size", 0, NULL);
nrows = gda_data_model_get_n_rows (model);
for (i = 0; i < nrows; i++) {
const GValue *cvalue;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]