[gnome-db] Oracle provider changes



Here's another installment of Oracle provider changes and improvements.

Here's the changelog entry:

2002-06-28  Tim Coleman <tim timcoleman com>
        * providers/oracle/gda-oracle-provider.c:
                - Added code to retrieve public/unique/foreign key information
                  for schema purposes.
                - Free up more Oracle memory when bad things happen
                - Added a function to retrieve list of Oracle tablespaces
                  for schema purposes.
        * providers/oracle/gda-oracle-recordset.c:
                - Free up more Oracle memory when bad things happen
                - Clean up the get_n_rows code to work properly
        * providers/oracle/utils.c:
                - only allocate memory for the string buffer when I need
                  it.

Attached are the oracle provider diff and changelog diff to be applied.

Thanks,

-- 
Tim Coleman <tim timcoleman com>                       [43.28 N 80.31 W]
BMath, Honours Combinatorics and Optimization, University of Waterloo
 "They that can give up essential liberty to obtain a little temporary
  safety deserve neither liberty nor safety." -- Benjamin Franklin
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/libgda/providers/oracle/Makefile.am,v
retrieving revision 1.5
diff -u -u -r1.5 Makefile.am
--- Makefile.am	21 Jun 2002 18:39:31 -0000	1.5
+++ Makefile.am	28 Jun 2002 04:36:07 -0000
@@ -2,8 +2,7 @@
 provider_LTLIBRARIES = libgda-oracle.la
 
 INCLUDES = \
-	-I$(top_srcdir) \
-	-I$(top_builddir) \
+	-I. \
 	$(LIBGDA_CFLAGS) \
 	$(ORACLE_CFLAGS)
 
Index: gda-oracle-provider.c
===================================================================
RCS file: /cvs/gnome/libgda/providers/oracle/gda-oracle-provider.c,v
retrieving revision 1.6
diff -u -u -r1.6 gda-oracle-provider.c
--- gda-oracle-provider.c	21 Jun 2002 18:39:31 -0000	1.6
+++ gda-oracle-provider.c	28 Jun 2002 04:36:08 -0000
@@ -81,6 +81,12 @@
 	GdaValueType data_type;
 } GdaOracleColData;
 
+typedef struct {
+	gboolean primary_key;
+	gboolean unique;
+	gchar *references;
+} GdaOracleIndexData;
+
 /*
  * GdaOracleProvider class implementation
  */
@@ -217,8 +223,10 @@
 				(size_t) 0, 
 				(dvoid **) 0);
 	if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
-			_("Could not allocate the Oracle error handle")))
+			_("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,
@@ -227,8 +235,11 @@
 				(size_t) 0,
 				(dvoid **) 0);
 	if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
-			_("Could not allocate the Oracle server handle")))
+			_("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;
+	}
 
 	/* create the session handle */
 	result = OCIHandleAlloc ((dvoid *) priv_data->henv,
@@ -237,8 +248,12 @@
 				(size_t) 0,
 				(dvoid **) 0);
 	if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ENV,
-			_("Could not allocate the Oracle session handle")))
+			_("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 (strlen(username) > 0)
@@ -263,8 +278,13 @@
 				(ub4) strlen (ora_tnsname),
 				OCI_DEFAULT);
 	if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-			_("Could not attach to the Oracle server")))
+			_("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, 
@@ -274,8 +294,13 @@
 				(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")))
+			_("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, 
@@ -285,8 +310,13 @@
 				(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")))
+			_("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, 
@@ -296,8 +326,13 @@
 				(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")))
+			_("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,
@@ -309,6 +344,9 @@
 			_("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;
 	}
@@ -321,8 +359,14 @@
 				(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")))
+			_("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;
+	}
 
 	/* attach the oracle connection data to the gda connection object */
 	g_object_set_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE, priv_data);
@@ -419,8 +463,10 @@
 				(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")))
+			_("Could not prepare the Oracle statement"))) {
+		OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
 		return NULL;
+	}
 
 	/* Bind parameters */
 	if (params != NULL) {
@@ -449,8 +495,10 @@
 						(ub4 *) 0,
 						(ub4) OCI_DEFAULT);
 			if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-					_("Could not bind the Oracle statement parameter")))
+					_("Could not bind the Oracle statement parameter"))) {
+				OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
 				return NULL;
+			}
 		}
 	}
 	return stmthp;
@@ -492,8 +540,10 @@
 						OCI_ATTR_STMT_TYPE,
 						priv_data->herr);
 			if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-					_("Could not get the Oracle statement type")))
+					_("Could not get the Oracle statement type"))) {
+				OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
 				return NULL;
+			}
 				
 
 			result = OCIStmtExecute (priv_data->hservice,
@@ -508,8 +558,10 @@
 				continue;
 
 			if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-					_("Could not execute the Oracle statement")))
+					_("Could not execute the Oracle statement"))) {
+				OCIHandleFree ((dvoid *) stmthp, OCI_HTYPE_STMT);
 				return NULL;
+			}
 
 			/* get the number of columns in the result set */
 			result = OCIAttrGet ((dvoid *) stmthp,
@@ -519,8 +571,10 @@
 						(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")))
+					_("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;
@@ -534,8 +588,10 @@
 							(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")))
+						_("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,
@@ -544,8 +600,10 @@
 							(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")))
+						_("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);
@@ -750,8 +808,10 @@
 				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")))
+			_("Could not set the Oracle transaction name"))) {
+		OCIHandleFree ((dvoid *) ora_xaction->txnhp, OCI_HTYPE_TRANS);
 		return FALSE;
+	}
 	
 
 	/* attach the transaction to the service context */
@@ -762,8 +822,10 @@
 				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")))
+			_("Could not attach the transaction to the service context"))) {
+		OCIHandleFree ((dvoid *) ora_xaction->txnhp, OCI_HTYPE_TRANS);
 		return FALSE;
+	}
 
 	/* start the transaction */
 	result = OCITransStart (priv_data->hservice, 
@@ -771,8 +833,10 @@
 				60, 
 				OCI_TRANS_NEW);
 	if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-			_("Could not start the Oracle transaction")))
-		return FALSE;
+			_("Could not start the Oracle transaction"))) {
+		OCIHandleFree ((dvoid *) ora_xaction->txnhp, OCI_HTYPE_TRANS);
+		return FALSE; 
+	}
 
 	g_object_set_data (G_OBJECT (xaction), OBJECT_DATA_ORACLE_HANDLE, ora_xaction);
 	return TRUE;
@@ -828,6 +892,7 @@
 			_("Could not commit the Oracle transaction")))
 		return FALSE;
 
+	OCIHandleFree ((dvoid *) ora_xaction->txnhp, OCI_HTYPE_TRANS);
 	return TRUE;
 
 }
@@ -873,6 +938,7 @@
 			_("Could not rollback the Oracle transaction")))
 		return FALSE;
 
+	OCIHandleFree ((dvoid *) ora_xaction->txnhp, OCI_HTYPE_TRANS);
 	return TRUE;
 }
 
@@ -1003,6 +1069,136 @@
 	return 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);
+}
+
+static GHashTable *
+get_oracle_index_data (GdaConnection *cnc, const gchar *tblname)
+{
+	GList *reclist;
+	GdaDataModel *recset;
+	GdaOracleIndexData *index_data;
+	GdaParameterList *query_params = gda_parameter_list_new ();
+	GString *references;
+	gint nrows;
+	GString *colname;
+	GString *newcolname;
+	GHashTable *h_table = g_hash_table_new (g_str_hash, g_str_equal);
+	GdaValue *value;
+	gint i;
+
+
+	gchar *sql = g_strdup ("SELECT substr (c1.column_name,1,30) column_name, "
+				"con.constraint_type constraint_type, "
+				"'' uniqueness, "
+				"c2.table_name reference "
+				"FROM user_cons_columns c1, user_cons_columns c2, user_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 con.r_constraint_name = c2.constraint_name "
+				"UNION "
+				"SELECT substr (c.column_name,1,30) column_name, "
+				"t.constraint_type constraint_type, "
+				"substr (i.uniqueness, 1, 6) uniqueness, "
+				"'' reference "
+				"FROM user_indexes i, user_ind_columns c, user_constraints t "
+				"WHERE i.table_name = upper (:TBLNAME) "
+				"AND t.constraint_type != 'R' "
+				"AND i.index_name = c.index_name "
+				"AND i.index_name = t.constraint_name "
+				"ORDER BY 1" );
+
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+
+	gda_parameter_list_add_parameter (query_params, 
+			gda_parameter_new_string (":TBLNAME", tblname));
+
+	reclist = process_sql_commands (NULL, cnc, sql, 
+			query_params, GDA_COMMAND_OPTION_STOP_ON_ERRORS);
+	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)
+		return NULL;
+
+	index_data = g_new0 (GdaOracleIndexData, 1);
+	references = g_string_new ("");
+
+	value = gda_data_model_get_value_at (recset, 0, 0);
+	colname = g_string_right_trim (g_string_new (gda_value_get_string (value)));
+
+	for (i = 0; i < nrows; i += 1) {
+		gchar *constraint_type = "";
+
+		value = gda_data_model_get_value_at (recset, 1, i);
+		if (!value)
+			continue;
+		if (gda_value_is_null (value))
+			continue;
+
+		constraint_type = g_strdup (gda_value_get_string (value));
+
+		if (!strcmp (constraint_type, "P"))
+			index_data->primary_key = TRUE;
+
+		value = gda_data_model_get_value_at (recset, 2, i);
+		if (value) 
+			if (!gda_value_is_null (value))
+				if (!strcmp (gda_value_get_string (value), "UNIQUE"))  
+					index_data->unique = TRUE;
+
+		if (!strcmp (constraint_type, "R")) {
+			value = 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, gda_value_get_string (value)));
+				}
+		}
+
+		if (i == nrows - 1) {
+			index_data->references = g_strdup (references->str);
+			g_hash_table_insert (h_table, colname->str, index_data);
+			break;
+		}
+
+		value = gda_data_model_get_value_at (recset, 0, i+1);
+		newcolname = g_string_right_trim (g_string_new (gda_value_get_string (value)));
+
+		if (strcmp (colname->str, newcolname->str)) {
+			index_data->references = g_strdup (references->str);
+			g_hash_table_insert (h_table, colname->str, index_data);
+
+			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_free (recset);
+	return h_table;
+}
+
+
 static GList *
 gda_oracle_fill_md_data (const gchar *tblname, 
 			GdaDataModelArray *recset,
@@ -1017,6 +1213,7 @@
 	ub2 numcols;
 	GList *list = NULL;
 	gint result;
+	GHashTable *h_table_index;
 
 	priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_ORACLE_HANDLE);
 
@@ -1040,8 +1237,10 @@
 				OCI_PTYPE_TABLE,
 				(OCIDescribe *) dschp);
 	if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-			_("Could not describe the Oracle table")))
+			_("Could not describe the Oracle table"))) {
+		OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
 		return NULL;
+	}
 
 	/* Get the parameter handle */
 	result = OCIAttrGet ((dvoid *) dschp,
@@ -1051,8 +1250,10 @@
 				(ub4) OCI_ATTR_PARAM,
 				(OCIError *) priv_data->herr);
 	if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-			_("Could not get the Oracle parameter handle")))
+			_("Could not get the Oracle parameter handle"))) {
+		OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
 		return NULL;
+	}
 
 	/* Get the number of columns */
 	result = OCIAttrGet ((dvoid *) parmh,
@@ -1062,8 +1263,10 @@
 				(ub4) OCI_ATTR_NUM_COLS,
 				(OCIError *) priv_data->herr);
 	if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-			_("Could not get the number of columns in the table")))
+			_("Could not get the number of columns in the table"))) {
+		OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
 		return NULL;
+	}
 
 	result = OCIAttrGet ((dvoid *) parmh,
 				(ub4) OCI_DTYPE_PARAM,
@@ -1072,8 +1275,12 @@
 				(ub4) OCI_ATTR_LIST_COLUMNS,
 				(OCIError *) priv_data->herr);
 	if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-			_("Could not get the column list")))
+			_("Could not get the column list"))) {
+		OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
 		return NULL;
+	}
+
+	h_table_index = get_oracle_index_data (cnc, tblname);
 
 	for (i = 1; i <= numcols; i += 1) {
 		text *strp;
@@ -1085,6 +1292,8 @@
 		ub2 defined_size;
 		ub2 scale;
 
+		GdaOracleIndexData *index_data;
+
 		GdaValue *value;
 		GList *rowlist = NULL;
 
@@ -1095,8 +1304,10 @@
 					(dvoid **) &colhd,
 					(ub2) i);
 		if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				_("Could not get the Oracle column handle")))
+				_("Could not get the Oracle column handle"))) {
+			OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
 			return NULL;
+		}
 		
 		/* Field name */
 		result = OCIAttrGet ((dvoid *) colhd,
@@ -1106,11 +1317,14 @@
 					(ub4) OCI_ATTR_NAME,
 					(OCIError *) priv_data->herr);
 		if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				_("Could not get the Oracle field name")))
+				_("Could not get the Oracle field name"))) {
+			OCIDescriptorFree ((dvoid *) colhd, OCI_DTYPE_PARAM);
+			OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
 			return NULL;
+		}
 
 		colname = g_malloc0 (sizep + 1);
-		memcpy (colname, strp, (size_t) sizep);
+		memcpy (colname, strp, sizep);
 		colname[sizep] = '\0';
 		value = gda_value_new_string (colname);
 		rowlist = g_list_append (rowlist, value);
@@ -1124,8 +1338,11 @@
 					(ub4) OCI_ATTR_DATA_TYPE,
 					(OCIError *) priv_data->herr);
 		if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				_("Could not get the Oracle field data type")))
+				_("Could not get the Oracle field data type"))) {
+			OCIDescriptorFree ((dvoid *) colhd, OCI_DTYPE_PARAM);
+			OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
 			return NULL;
+		}
 
 		typename = oracle_sqltype_to_string (type);
 		value = gda_value_new_string (typename);
@@ -1139,8 +1356,11 @@
 					(ub4) OCI_ATTR_DATA_SIZE,
 					(OCIError *) priv_data->herr);
 		if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				_("Could not get the Oracle field defined size")))
+				_("Could not get the Oracle field defined size"))) {
+			OCIDescriptorFree ((dvoid *) colhd, OCI_DTYPE_PARAM);
+			OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
 			return NULL;
+		}
 
 		value = gda_value_new_integer (defined_size);
 		rowlist = g_list_append (rowlist, value);
@@ -1153,8 +1373,11 @@
 					(ub4) OCI_ATTR_SCALE,
 					(OCIError *) priv_data->herr);
 		if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				_("Could not get the Oracle field scale")))
+				_("Could not get the Oracle field scale"))) {
+			OCIDescriptorFree ((dvoid *) colhd, OCI_DTYPE_PARAM);
+			OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
 			return NULL;
+		}
 
 		value = gda_value_new_integer (scale);
 		rowlist = g_list_append (rowlist, value);
@@ -1167,28 +1390,52 @@
 					(ub4) OCI_ATTR_DATA_SIZE,
 					(OCIError *) priv_data->herr);
 		if (!gda_oracle_check_result (result, cnc, priv_data, OCI_HTYPE_ERROR,
-				_("Could not get the Oracle field nullable attribute")))
+				_("Could not get the Oracle field nullable attribute"))) {
+			OCIDescriptorFree ((dvoid *) colhd, OCI_DTYPE_PARAM);
+			OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
 			return NULL;
+		}
 
 		value = gda_value_new_boolean (nullable > 0);
 		rowlist = g_list_append (rowlist, value);
 
+		if (!h_table_index) {
+			index_data = g_new0 (GdaOracleIndexData, 1);
+			index_data->primary_key = FALSE;
+			index_data->unique = FALSE;
+			index_data->references = g_strdup ("");
+		} else {
+			index_data = g_hash_table_lookup (h_table_index, colname);
+		}
+
+		if (!index_data) {
+			index_data = g_new0 (GdaOracleIndexData, 1);
+			index_data->primary_key = FALSE;
+			index_data->unique = FALSE;
+			index_data->references = g_strdup ("");
+		}
+
 		/* primary key? */
-		value = gda_value_new_boolean (FALSE); // FIXME
+		value = gda_value_new_boolean (index_data->primary_key);
 		rowlist = g_list_append (rowlist, value);
 
 		/* unique? */
-		value = gda_value_new_boolean (FALSE); // FIXME
+		value = gda_value_new_boolean (index_data->unique);
 		rowlist = g_list_append (rowlist, value);
 
 		/* references */
-		value = gda_value_new_string ("");  // FIXME
+		value = gda_value_new_string (index_data->references);
 		rowlist = g_list_append (rowlist, value);
 
+		g_free (index_data);
+
 		list = g_list_append (list, rowlist);
 		rowlist = NULL;
+
+		OCIDescriptorFree ((dvoid *) colhd, OCI_DTYPE_PARAM);
 	}
 
+	OCIHandleFree ((dvoid *) dschp, OCI_HTYPE_DESCRIBE);
 	return list;
 }
 
@@ -1214,6 +1461,28 @@
 	return recset;
 }
 
+static GdaDataModel *
+get_oracle_databases (GdaConnection *cnc, GdaParameterList *params)
+{
+	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);
+
+	g_free (sql);
+
+	if (!reclist)
+		return NULL;
+
+	recset = GDA_DATA_MODEL (reclist->data);
+	g_list_free (reclist);
+
+	return recset;
+}
 /*
  * get_oracle_objects
  *
@@ -1233,7 +1502,7 @@
 	GList *reclist;
 	GdaDataModel *recset;
 	GdaParameterList *query_params = gda_parameter_list_new ();
-        GString *sql = g_string_new ("SELECT OBJECT_NAME FROM USER_OBJECTS WHERE OBJECT_TYPE=:OBJ_TYPE");
+        gchar *sql = g_strdup ("SELECT OBJECT_NAME FROM USER_OBJECTS WHERE OBJECT_TYPE=:OBJ_TYPE");
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
 
@@ -1267,11 +1536,11 @@
 		return NULL;
 	}
 
-	reclist = process_sql_commands (NULL, cnc, sql->str, query_params,
+	reclist = process_sql_commands (NULL, cnc, sql, query_params,
 			GDA_COMMAND_OPTION_STOP_ON_ERRORS);
 
 	gda_parameter_list_free (query_params);
-	g_string_free (sql, TRUE);
+	g_free (sql);
 
 	if (!reclist)
 		return NULL;
@@ -1343,7 +1612,6 @@
 	tblname = gda_value_get_string ((GdaValue *) gda_parameter_get_value (par));
 	g_return_val_if_fail (tblname != NULL, NULL);
 
-
 	recset = gda_oracle_init_md_recset (cnc);
 	list = gda_oracle_fill_md_data (tblname, recset, cnc);
 	g_list_foreach (list, add_g_list_row, recset);
@@ -1374,6 +1642,9 @@
 		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);
Index: gda-oracle-recordset.c
===================================================================
RCS file: /cvs/gnome/libgda/providers/oracle/gda-oracle-recordset.c,v
retrieving revision 1.3
diff -u -u -r1.3 gda-oracle-recordset.c
--- gda-oracle-recordset.c	20 Jun 2002 18:15:26 -0000	1.3
+++ gda-oracle-recordset.c	28 Jun 2002 04:36:08 -0000
@@ -80,8 +80,10 @@
 					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")))
+				_("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,
@@ -91,8 +93,10 @@
 					priv->cdata->herr);
 
 		if (!gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
-				_("Could not get the parameter data type")))
+				_("Could not get the parameter data type"))) {
+			OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
 			return NULL;
+		}
 
 		switch (ora_value->sql_type) {
 		case SQLT_NUM: // Numerics are coerced to string
@@ -120,8 +124,10 @@
 					(ub2 *) 0, 
 					(ub4) OCI_DEFAULT);
 		if (!gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
-				_("Could not define by position")))
+				_("Could not define by position"))) {
+			OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
 			return NULL;
+		}
 
 		fields = g_list_append (fields, ora_value);
 	}
@@ -185,8 +191,10 @@
 				(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")))
+			_("Could not get the Oracle column name"))) {
+		OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
 		return NULL;
+	}
 
 	memcpy (name_buffer, pgchar_dummy, col_name_len);
 	name_buffer[col_name_len] = '\0';
@@ -198,8 +206,10 @@
 				(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")))
+			_("Could not get the Oracle column data type"))) {
+		OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
 		return NULL;
+	}
 
 	result = OCIAttrGet ((dvoid *) pard,
 				(ub4) OCI_DTYPE_PARAM,
@@ -208,8 +218,10 @@
 				(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")))
+			_("Could not get the Oracle column scale"))) {
+		OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
 		return NULL;
+	}
 
 	result = OCIAttrGet ((dvoid *) pard,
 				(ub4) OCI_DTYPE_PARAM,
@@ -218,8 +230,10 @@
 				(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")))
+			_("Could not get the Oracle column nullable attribute"))) {
+		OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
 		return NULL;
+	}
 
 	result = OCIAttrGet ((dvoid *) pard,
 				OCI_DTYPE_PARAM,
@@ -228,8 +242,10 @@
 				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")))
+			_("Could not get the Oracle defined size"))) {
+		OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
 		return NULL;
+	}
 
 	gda_field_attributes_set_name (field_attrs, name_buffer);
 	gda_field_attributes_set_scale (field_attrs, scale);
@@ -247,6 +263,8 @@
 
 	gda_field_attributes_set_allow_null (field_attrs, !(nullable == 0));
 	
+	OCIDescriptorFree ((dvoid *) pard, OCI_DTYPE_PARAM);
+
 	return field_attrs;
 }
 
@@ -255,40 +273,45 @@
 {
 	GdaOracleRecordset *recset = (GdaOracleRecordset *) model;
 	GdaOracleRecordsetPrivate *priv_data;
-	gint i = 0;
-	gint fetch_status = OCI_SUCCESS;
+	gint result = OCI_SUCCESS;
+	gint nrows;
 
 	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;
+	nrows = priv_data->nrows;
 
-	while (fetch_status == OCI_SUCCESS) {
-		i += 1;
-		fetch_status = OCIStmtFetch (priv_data->hstmt,
-				priv_data->cdata->herr,
-				(ub4) 1,
-				(ub2) OCI_FETCH_NEXT,
-				(ub4) OCI_DEFAULT);
-	}
+	if (nrows >= 0) 
+		return nrows;
 
-	priv_data->nrows = i-1;
+	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
-	OCIStmtExecute (priv_data->cdata->hservice,
-			priv_data->hstmt,
-			priv_data->cdata->herr,
-			(ub4) ((OCI_STMT_SELECT == priv_data->cdata->stmt_type) ? 0 : 1),
-			(ub4) 0,
-			(CONST OCISnapshot *) NULL,
-			(OCISnapshot *) NULL,
-			OCI_DEFAULT);
+	result = OCIStmtExecute (priv_data->cdata->hservice,
+				priv_data->hstmt,
+				priv_data->cdata->herr,
+				(ub4) ((OCI_STMT_SELECT == priv_data->cdata->stmt_type) ? 0 : 1),
+				(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;
+	}
 
+	priv_data->ora_values = define_columns (priv_data);
 
-	return priv_data->nrows;
+	return nrows;
 }
 
 static gint
@@ -309,7 +332,7 @@
 	gchar *id;
 	GdaOracleRecordsetPrivate *priv;
 	GList *node;
-	ub4 status;
+	gint result;
 
 	g_return_val_if_fail (GDA_IS_ORACLE_RECORDSET (recset), NULL);
 	g_return_val_if_fail (recset->priv != NULL, NULL);
@@ -318,21 +341,18 @@
 
 	row = gda_row_new (priv->ncolumns);
 
-	status = OCIStmtFetch ((OCIStmt *) priv->hstmt,
+	result = OCIStmtFetch ((OCIStmt *) priv->hstmt,
 				(OCIError *) priv->cdata->herr,
 				(ub4) 1,
 				(ub2) OCI_FETCH_NEXT,
 				(ub4) OCI_DEFAULT); 
-	switch (status) {
-	case OCI_SUCCESS:
-	case OCI_SUCCESS_WITH_INFO:
-		break;
-	case OCI_NO_DATA:
+	if (result == OCI_NO_DATA) 
 		return NULL;
-	default:
-		gda_connection_add_error_string (priv->cnc, _("An error occurred during fetch"));
+
+	if (!gda_oracle_check_result (result, priv->cnc, priv->cdata, OCI_HTYPE_ERROR,
+			_("Could not fetch a row"))) 
 		return NULL;
-	}
+
 
 	i = 0;
 	for (node = g_list_first (priv->ora_values); node != NULL; 
@@ -362,6 +382,7 @@
 	g_return_val_if_fail (recset->priv != NULL, 0);
 
 	priv_data = recset->priv;
+
 	if (!priv_data->cdata) {
 		gda_connection_add_error_string (priv_data->cnc,
 						_("Invalid Oracle handle"));
@@ -370,10 +391,10 @@
 
 	fetched_rows = priv_data->rows->len;
 
-	if (row >= priv_data->nrows && priv_data->nrows > 0)
+	if (row >= priv_data->nrows && priv_data->nrows >= 0)
 		return NULL;
 
-	if (row < fetched_rows)
+	if (row < fetched_rows) 
 		return (const GdaRow *) g_ptr_array_index (priv_data->rows, row);
 
 	gda_data_model_freeze (GDA_DATA_MODEL (recset));
@@ -495,15 +516,6 @@
 
 	g_string_free (sql, TRUE);
 
-	/*
-	if (rc != 0) {
-		gda_connection_add_error (
-			recset->priv->cnc, gda_oracle_make_error 
-			
-		return NULL;
-	}
-	*/
-
 	row = gda_row_new_from_list (values);
 	g_ptr_array_add (recset->priv->rows, row);
 
@@ -530,11 +542,8 @@
 gda_oracle_recordset_init (GdaOracleRecordset *recset, GdaOracleRecordsetClass *klass)
 {
 	g_return_if_fail (GDA_IS_ORACLE_RECORDSET (recset));
-
         recset->priv = g_new0 (GdaOracleRecordsetPrivate, 1);
-	recset->priv->cnc = NULL;
-	recset->priv->rows = g_ptr_array_new ();
-	recset->priv->cdata = NULL;
+        recset->priv->rows = g_ptr_array_new ();
 }
 
 static void
@@ -557,25 +566,46 @@
 	model_class->update_row = gda_oracle_recordset_update_row;
 }
 
+static void 
+gda_oracle_free_values (GdaOracleValue *ora_value)
+{
+	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)
 {
 	GdaOracleRecordset *recset = (GdaOracleRecordset *) object;
+	GdaOracleRecordsetPrivate *priv_data;
+
+	g_return_if_fail (recset->priv != NULL);
+
+	priv_data = recset->priv;
+
+	if (!priv_data->cdata) {
+		gda_connection_add_error_string (priv_data->cnc, 
+						_("Invalid Oracle handle"));
+		return NULL;
+	}
 
 	g_return_if_fail (GDA_IS_ORACLE_RECORDSET (recset));
 
-	while (recset->priv->rows->len > 0) {
-		GdaRow *row = (GdaRow *) g_ptr_array_index (recset->priv->rows, 0);
+	while (priv_data->rows->len > 0) {
+		GdaRow *row = (GdaRow *) g_ptr_array_index (priv_data->rows, 0);
 
 		if (row != NULL) 
 			gda_row_free (row);
-		g_ptr_array_remove_index (recset->priv->rows, 0);
+		g_ptr_array_remove_index (priv_data->rows, 0);
 	}
-	g_ptr_array_free (recset->priv->rows, TRUE);
+	g_ptr_array_free (priv_data->rows, TRUE);
 	recset->priv->rows = NULL;
 
-	if (recset->priv->hstmt)
-		OCIHandleFree ((dvoid *)recset->priv->hstmt, OCI_HTYPE_STMT);
+	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);
 }
@@ -623,12 +653,13 @@
 			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->nrows = gda_oracle_recordset_get_n_rows (GDA_DATA_MODEL (recset));
 	recset->priv->ora_values = define_columns (recset->priv);
+	recset->priv->nrows = gda_oracle_recordset_get_n_rows (GDA_DATA_MODEL (recset));
 
 	return recset;
 }
Index: utils.c
===================================================================
RCS file: /cvs/gnome/libgda/providers/oracle/utils.c,v
retrieving revision 1.3
diff -u -u -r1.3 utils.c
--- utils.c	20 Jun 2002 18:15:26 -0000	1.3
+++ utils.c	28 Jun 2002 04:36:08 -0000
@@ -364,7 +364,7 @@
 	ub1 month;
 	ub1 day;
 
-	gchar string_buffer[ora_value->defined_size+1];
+	gchar *string_buffer;
 
 	if (-1 == (ora_value->indicator)) {
 		gda_value_set_null (value);
@@ -376,6 +376,7 @@
 		gda_value_set_boolean (value, (atoi (ora_value->value)) ? TRUE: FALSE);
 		break;
 	case GDA_VALUE_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';
 		gda_value_set_string (value, string_buffer);
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/libgda/ChangeLog,v
retrieving revision 1.308
diff -u -u -r1.308 ChangeLog
--- ChangeLog	21 Jun 2002 18:39:14 -0000	1.308
+++ ChangeLog	28 Jun 2002 04:40:58 -0000
@@ -1,3 +1,18 @@
+2002-06-28  Tim Coleman <tim timcoleman com>
+	* providers/oracle/gda-oracle-provider.c:
+		- Added code to retrieve public/unique/foreign key information
+		  for schema purposes.
+		- Free up more Oracle memory when bad things happen
+		- Added a function to retrieve list of Oracle tablespaces
+		  for schema purposes.
+	* providers/oracle/gda-oracle-recordset.c:
+		- Free up more Oracle memory when bad things happen
+		- Clean up the get_n_rows code to work properly
+	* providers/oracle/utils.c:
+		- only allocate memory for the string buffer when I need
+		  it.
+	
+
 2002-06-21  Rodrigo Moya <rodrigo gnome-db org>
 
 	* libsql/Makefile.am: missing header files to SOURCES.


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]