[gnome-db] Patch for postgres provider
- From: Gonzalo Paniagua Javier <gonzalo gnome-db org>
- To: Gnome-db list <gnome-db-list gnome org>
- Subject: [gnome-db] Patch for postgres provider
- Date: Fri, 8 Mar 2002 03:31:46 +0100
Hi!
The patch attached make the postgres provider not to use *OID
#define's any more. So it will compile against PostgreSQL 7.2
version.
I'm in doubt about one thing: the recordset is getting
information from the private data of the connection and I don't
know if the way I do is the 'correct' one. Suggestions for doing
it in a smarter way?
Also includes part of the SCHEMA_FIELD implementation (not yet
functional).
Any comments appreciated.
Index: providers/postgres/gda-postgres-provider.c
===================================================================
RCS file: /cvs/gnome/libgda/providers/postgres/gda-postgres-provider.c,v
retrieving revision 1.15
diff -u -r1.15 gda-postgres-provider.c
--- providers/postgres/gda-postgres-provider.c 25 Feb 2002 23:39:03 -0000 1.15
+++ providers/postgres/gda-postgres-provider.c 8 Mar 2002 02:22:35 -0000
@@ -21,9 +21,9 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <stdlib.h>
#include "gda-postgres.h"
#include "gda-postgres-provider.h"
-#include <stdlib.h>
static void gda_postgres_provider_class_init (GdaPostgresProviderClass *klass);
static void gda_postgres_provider_init (GdaPostgresProvider *provider,
@@ -69,16 +69,6 @@
GNOME_Database_Connection_Schema schema,
GdaParameterList *params);
-typedef struct {
- Oid oid;
- gchar *name;
-} GdaPostgresTypeDataPrivate;
-
-typedef struct {
- PGconn *pconn;
- GList *type_list; // list of GdaPostgresTypeDataPrivate
-} GdaPostgresConnectionPrivate;
-
static GObjectClass *parent_class = NULL;
/*
@@ -143,14 +133,12 @@
return type;
}
-static GList *
-get_connection_type_list (PGconn *pconn)
+static int
+get_connection_type_list (PGconn *pconn, GdaPostgresConnectionPrivate *priv_td)
{
+ GdaPostgresTypeOid *td;
PGresult *pg_res;
- GList *list;
- GdaPostgresTypeDataPrivate *priv_td;
- gint llen;
- gint i;
+ gint nrows, i;
pg_res = PQexec (pconn, "SELECT oid, typname FROM pg_type "
"WHERE typrelid = 0 AND typname !~ '^_' "
@@ -161,21 +149,21 @@
if (pg_res == NULL || PQresultStatus (pg_res) != PGRES_TUPLES_OK) {
if (pg_res) PQclear (pg_res);
- return NULL;
+ return -1;
}
- list = NULL;
- llen = PQntuples (pg_res);
- for (i = 0; i < llen; i++) {
- priv_td = g_new (GdaPostgresTypeDataPrivate, 1);
- priv_td->oid = atoi (PQgetvalue (pg_res, i, 0));
- priv_td->name = g_strdup (PQgetvalue (pg_res, i, 1));
- list = g_list_append (list, priv_td);
+ nrows = PQntuples (pg_res);
+ td = g_new0 (GdaPostgresTypeOid, nrows);
+ for (i = 0; i < nrows; i++) {
+ td[i].name = g_strdup (PQgetvalue (pg_res, i, 1));
+ td[i].oid = atoi (PQgetvalue (pg_res, i, 0));
}
PQclear (pg_res);
+ priv_td->ntypes = nrows;
+ priv_td->type_data = td;
- return list;
+ return 0;
}
/* open_connection handler for the GdaPostgresProvider class */
@@ -197,7 +185,6 @@
const gchar *pq_requiressl;
gchar *conn_string;
GdaPostgresConnectionPrivate *priv_data;
- GList *type_list;
PGconn *pconn;
PGresult *pg_res;
@@ -256,36 +243,26 @@
pg_res = PQexec (pconn, "SET DATESTYLE TO 'ISO'");
PQclear (pg_res);
- type_list = get_connection_type_list (pconn);
- if (type_list == NULL) {
+ priv_data = g_new0 (GdaPostgresConnectionPrivate, 1);
+ priv_data->pconn = pconn;
+ if (get_connection_type_list (pconn, priv_data) != 0) {
gda_server_connection_add_error (
cnc, gda_postgres_make_error (pconn));
PQfinish(pconn);
+ g_free (priv_data);
return FALSE;
}
- priv_data = g_new0 (GdaPostgresConnectionPrivate, 1);
- priv_data->pconn = pconn;
- priv_data->type_list = type_list;
g_object_set_data (G_OBJECT (cnc), OBJECT_DATA_POSTGRES_HANDLE, priv_data);
return TRUE;
}
-static void
-free_type_list (gpointer data, gpointer user_data)
-{
- GdaPostgresTypeDataPrivate *priv_td;
-
- priv_td = data;
- g_free (priv_td->name);
- g_free (priv_td);
-}
-
/* close_connection handler for the GdaPostgresProvider class */
static gboolean
gda_postgres_provider_close_connection (GdaServerProvider *provider, GdaServerConnection *cnc)
{
GdaPostgresConnectionPrivate *priv_data;
+ gint i;
GdaPostgresProvider *pg_prv = (GdaPostgresProvider *) provider;
@@ -297,8 +274,11 @@
return FALSE;
PQfinish (priv_data->pconn);
- g_list_foreach (priv_data->type_list, free_type_list, NULL);
- g_list_free (priv_data->type_list);
+
+ for (i = 0; i < priv_data->ntypes; i++)
+ g_free (priv_data->type_data[i].name);
+
+ g_free (priv_data->type_data);
g_free (priv_data);
g_object_set_data (G_OBJECT (cnc), OBJECT_DATA_POSTGRES_HANDLE, NULL);
@@ -539,14 +519,14 @@
GdaValue *value;
GList list;
GdaServerRecordsetModel *recset;
- GdaPostgresTypeDataPrivate *priv_td;
+ GdaPostgresTypeOid *td;
- priv_td = data;
+ td = data;
recset = user_data;
g_return_if_fail (GDA_IS_SERVER_RECORDSET_MODEL (recset));
- value = gda_value_new_string (priv_td->name);
+ value = gda_value_new_string (td->name);
list.data = value;
list.next = NULL;
list.prev = NULL;
@@ -561,6 +541,7 @@
{
GdaServerRecordsetModel *recset;
GdaPostgresConnectionPrivate *priv_data;
+ gint i;
g_return_val_if_fail (GDA_IS_SERVER_CONNECTION (cnc), NULL);
@@ -574,7 +555,8 @@
/* fill the recordset */
priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_POSTGRES_HANDLE);
- g_list_foreach (priv_data->type_list, add_string_row, recset);
+ for (i = 0; i < priv_data->ntypes; i++)
+ add_string_row (&priv_data->type_data[i], recset);
return GDA_SERVER_RECORDSET (recset);
}
@@ -669,6 +651,106 @@
return recset;
}
+static GdaServerRecordset *
+get_postgres_fields_metadata (GdaServerConnection *cnc, GdaParameterList *params)
+{
+ GdaPostgresConnectionPrivate *priv_data;
+ GdaServerRecordsetModel *recset;
+ gchar *query;
+ GdaParameter *par;
+ const gchar *tblname;
+ gint i, k, row_count, field_count;
+ PGresult *pg_res;
+
+ g_return_val_if_fail (GDA_IS_SERVER_CONNECTION (cnc), NULL);
+ g_return_val_if_fail (params != NULL, NULL);
+
+ par = gda_parameter_list_find (params, "name");
+ g_return_val_if_fail (par != NULL, NULL);
+
+ tblname = gda_value_get_string (gda_parameter_get_value (par));
+
+ g_return_val_if_fail (tblname != NULL, NULL);
+
+ /* Gets:
+ * column name
+ * column type oid
+ * column type modifier
+ * not null indicator
+ * has definition indicator
+ * number of element in the table for the column
+ */
+ query = g_strdup_printf (
+ "SELECT a.attname, a.atttypid, a.atttypmod, a.attnotnull, "
+ " a.atthasdef, a.attnumelname"
+ "FROM pg_class c, pg_attribute a "
+ "WHERE c.relname = '%s' and a.attnum > 0 and "
+ " a.attrelid = c.oid "
+ "ORDER BY a.attnumelname", tblname);
+
+ priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_POSTGRES_HANDLE);
+
+ pg_res = PQexec(priv_data->pconn, query);
+ g_free (query);
+ if (pg_res == NULL)
+ return NULL;
+
+ row_count = PQntuples (pg_res);
+ field_count = PQnfields (pg_res);
+
+ /*
+ * The columns for the metadata recordset are:
+ * name of the field: string
+ * data type: integer (one of GDA_TYPE_*)
+ * size: integer
+ * scale: integer
+ * primary key: boolean
+ * unique key: boolean
+ * references (name of table.field referenced): string
+ * not null: boolean
+ */
+ recset = GDA_SERVER_RECORDSET_MODEL (gda_server_recordset_model_new (cnc, 8));
+ for (i = 0; i < 8; i++) {
+ gint defined_size;
+ typedef struct {
+ gchar *col_name;
+ GdaType data_type;
+ } col_data;
+
+ col_data cols[8] = {
+ { N_("Field name") , GDA_TYPE_STRING },
+ { N_("Data type") , GDA_TYPE_INTEGER },
+ { N_("Size") , GDA_TYPE_INTEGER },
+ { N_("Scale") , GDA_TYPE_INTEGER },
+ { N_("Primary key?") , GDA_TYPE_BOOLEAN },
+ { N_("Unique index?") , GDA_TYPE_BOOLEAN },
+ { N_("References") , GDA_TYPE_STRING },
+ { N_("Not null?") , GDA_TYPE_BOOLEAN }
+ };
+
+ switch (cols[i].data_type) {
+ case GDA_TYPE_STRING:
+ defined_size = NAMEDATALEN; // defined by PostgresSQL
+ break;
+ case GDA_TYPE_INTEGER:
+ defined_size = 4;
+ break;
+ default:
+ defined_size = 1;
+ }
+
+ gda_server_recordset_model_set_field_defined_size (recset, i, defined_size);
+ gda_server_recordset_model_set_field_name (recset, i, cols[i].col_name);
+ gda_server_recordset_model_set_field_scale (recset, i, 0);
+ gda_server_recordset_model_set_field_gdatype (recset, i, cols[i].data_type);
+ // TODO: store the data for each row
+ for (k = 0; k < row_count; k++){
+ }
+ }
+
+ return GDA_SERVER_RECORDSET (recset);
+}
+
/* get_schema handler for the GdaPostgresProvider class */
static GdaServerRecordset *
gda_postgres_provider_get_schema (GdaServerProvider *provider,
@@ -694,6 +776,8 @@
return get_postgres_aggregates (cnc, params);
case GNOME_Database_Connection_SCHEMA_TRIGGERS :
return get_postgres_triggers (cnc, params);
+ case GNOME_Database_Connection_SCHEMA_FIELDS :
+ return get_postgres_fields_metadata (cnc, params);
}
return NULL;
Index: providers/postgres/gda-postgres-provider.h
===================================================================
RCS file: /cvs/gnome/libgda/providers/postgres/gda-postgres-provider.h,v
retrieving revision 1.2
diff -u -r1.2 gda-postgres-provider.h
--- providers/postgres/gda-postgres-provider.h 7 Jan 2002 23:15:45 -0000 1.2
+++ providers/postgres/gda-postgres-provider.h 8 Mar 2002 02:22:35 -0000
@@ -26,6 +26,7 @@
#include <libgda/gda-server-provider.h>
#include <libgda/gda-server-recordset-model.h>
+#include <libpq-fe.h>
#define GDA_TYPE_POSTGRES_PROVIDER (gda_postgres_provider_get_type())
#define GDA_POSTGRES_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_POSTGRES_PROVIDER, GdaPostgresProvider))
@@ -47,6 +48,19 @@
struct _GdaPostgresProviderClass {
GdaServerProviderClass parent_class;
};
+
+// Private connection data.
+typedef struct {
+ gchar *name;
+ Oid oid;
+} GdaPostgresTypeOid;
+
+typedef struct {
+ PGconn *pconn;
+ gint ntypes;
+ GdaPostgresTypeOid *type_data;
+} GdaPostgresConnectionPrivate;
+
G_BEGIN_DECLS
Index: providers/postgres/gda-postgres-recordset.c
===================================================================
RCS file: /cvs/gnome/libgda/providers/postgres/gda-postgres-recordset.c,v
retrieving revision 1.7
diff -u -r1.7 gda-postgres-recordset.c
--- providers/postgres/gda-postgres-recordset.c 14 Jan 2002 23:41:08 -0000 1.7
+++ providers/postgres/gda-postgres-recordset.c 8 Mar 2002 02:22:35 -0000
@@ -24,14 +24,66 @@
*/
#include <bonobo/bonobo-i18n.h>
+#include <string.h>
#include "gda-postgres.h"
#define OBJECT_DATA_RECSET_HANDLE "GDA_Postgres_RecsetHandle"
+typedef struct {
+ PGresult *pg_res;
+ gint ntypes;
+ GdaPostgresTypeOid *type_data;
+} GdaPostgresRecordsetPrivate;
+
/*
* Private functions
*/
+static GdaType
+gda_postgres_type_to_gda (GdaServerRecordset *recset, Oid postgres_type)
+{
+ GdaPostgresRecordsetPrivate *priv_data;
+ gint i;
+
+ priv_data = g_object_get_data (G_OBJECT (recset), OBJECT_DATA_RECSET_HANDLE);
+
+ for (i = 0; i < priv_data->ntypes; i++)
+ if (priv_data->type_data[i].oid == postgres_type)
+ break;
+
+ if (priv_data->type_data[i].oid == postgres_type) {
+ gchar *name = priv_data->type_data[i].name;
+
+ if (!strcmp (name, "boolean"))
+ return GDA_TYPE_BOOLEAN;
+ if (!strcmp (name, "int8"))
+ return GDA_TYPE_BIGINT;
+ if (!strcmp (name, "int4") || !strcmp (name, "abstime") || !strcmp (name, "oid"))
+ return GDA_TYPE_INTEGER;
+ if (!strcmp (name, "int2"))
+ return GDA_TYPE_SMALLINT;
+ if (!strcmp (name, "float4"))
+ return GDA_TYPE_SINGLE;
+ // TODO: when we have a numeric type, move "numeric".
+ if (!strcmp (name, "float8") || !strcmp (name, "numeric"))
+ return GDA_TYPE_DOUBLE;
+ if (!strncmp (name, "timestamp", 9))
+ return GDA_TYPE_TIMESTAMP;
+ if (!strcmp (name, "date"))
+ return GDA_TYPE_DATE;
+ if (!strncmp (name, "time", 4))
+ return GDA_TYPE_TIME;
+ /*TODO: by now, this one not supported
+ if (!strncmp (name, "bit", 3))
+ return GDA_TYPE_BINARY;
+ */
+ if (!strcmp (name, "point"))
+ return GDA_TYPE_GEOMETRIC_POINT;
+ }
+
+ return GDA_TYPE_STRING;
+}
+
static void
free_postgres_res (gpointer data)
{
@@ -44,6 +96,7 @@
static GdaRow *
fetch_func (GdaServerRecordset *recset, gulong rownum)
{
+ GdaPostgresRecordsetPrivate *priv_data;
GdaRow *row;
gint field_count;
gint row_count;
@@ -52,7 +105,8 @@
g_return_val_if_fail (GDA_IS_SERVER_RECORDSET (recset), NULL);
- pg_res = g_object_get_data (G_OBJECT (recset), OBJECT_DATA_RECSET_HANDLE);
+ priv_data = g_object_get_data (G_OBJECT (recset), OBJECT_DATA_RECSET_HANDLE);
+ pg_res = priv_data->pg_res;
if (!pg_res) {
gda_server_connection_add_error_string (
gda_server_recordset_get_connection (recset),
@@ -82,7 +136,7 @@
field = gda_row_get_field (row, i);
thevalue = PQgetvalue(pg_res, rownum, i);
- ftype = gda_postgres_type_to_gda (PQftype (pg_res, i));
+ ftype = gda_postgres_type_to_gda (recset, PQftype (pg_res, i));
isNull = *thevalue != '\0' ?
FALSE : PQgetisnull (pg_res, rownum, i);
@@ -96,6 +150,7 @@
static GdaRowAttributes *
describe_func (GdaServerRecordset *recset)
{
+ GdaPostgresRecordsetPrivate *priv_data;
PGresult *pg_res;
gint field_count;
gint i;
@@ -103,7 +158,8 @@
g_return_val_if_fail (GDA_IS_SERVER_RECORDSET (recset), NULL);
- pg_res = g_object_get_data (G_OBJECT (recset), OBJECT_DATA_RECSET_HANDLE);
+ priv_data = g_object_get_data (G_OBJECT (recset), OBJECT_DATA_RECSET_HANDLE);
+ pg_res = priv_data->pg_res;
if (!pg_res) {
gda_server_connection_add_error_string (
gda_server_recordset_get_connection (recset),
@@ -123,7 +179,7 @@
field_attrs = gda_row_attributes_get_field (attrs, i);
gda_field_attributes_set_name (field_attrs, PQfname (pg_res, i));
- ftype = gda_postgres_type_to_gda (PQftype (pg_res, i));
+ ftype = gda_postgres_type_to_gda (recset, PQftype (pg_res, i));
scale = (ftype == GDA_TYPE_DOUBLE) ? DBL_DIG :
(ftype == GDA_TYPE_SINGLE) ? FLT_DIG : 0;
@@ -146,13 +202,23 @@
gda_postgres_recordset_new (GdaServerConnection *cnc, PGresult *pg_res)
{
GdaServerRecordset *recset;
+ GdaPostgresRecordsetPrivate *priv_data;
+ GdaPostgresConnectionPrivate *cnc_priv_data;
g_return_val_if_fail (GDA_IS_SERVER_CONNECTION (cnc), NULL);
g_return_val_if_fail (pg_res != NULL, NULL);
recset = gda_server_recordset_new (cnc, fetch_func, describe_func);
+
+ cnc_priv_data = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_POSTGRES_HANDLE);
+
+ priv_data = g_new0 (GdaPostgresRecordsetPrivate, 1);
+ priv_data->pg_res = pg_res;
+ priv_data->ntypes = cnc_priv_data->ntypes;
+ priv_data->type_data = cnc_priv_data->type_data;
+
g_object_set_data_full (G_OBJECT (recset), OBJECT_DATA_RECSET_HANDLE,
- pg_res, (GDestroyNotify) free_postgres_res);
+ priv_data, (GDestroyNotify) free_postgres_res);
return recset;
}
Index: providers/postgres/gda-postgres.h
===================================================================
RCS file: /cvs/gnome/libgda/providers/postgres/gda-postgres.h,v
retrieving revision 1.5
diff -u -r1.5 gda-postgres.h
--- providers/postgres/gda-postgres.h 10 Jan 2002 00:14:10 -0000 1.5
+++ providers/postgres/gda-postgres.h 8 Mar 2002 02:22:35 -0000
@@ -31,7 +31,6 @@
#include <glib/gmacros.h>
#include <bonobo/bonobo-i18n.h>
#include <libgda/gda-server.h>
-#include <libpq-fe.h>
#include "gda-postgres-provider.h"
#include "gda-postgres-recordset.h"
@@ -45,7 +44,6 @@
*/
GdaError *gda_postgres_make_error (PGconn *cnc);
-GdaType gda_postgres_type_to_gda (Oid postgres_type);
void gda_postgres_set_field_data (GdaField *field, const gchar *fname,
GdaType type, const gchar *value,
gint dbsize, gboolean isNull);
Index: providers/postgres/utils.c
===================================================================
RCS file: /cvs/gnome/libgda/providers/postgres/utils.c,v
retrieving revision 1.9
diff -u -r1.9 utils.c
--- providers/postgres/utils.c 15 Jan 2002 01:53:25 -0000 1.9
+++ providers/postgres/utils.c 8 Mar 2002 02:22:35 -0000
@@ -22,8 +22,8 @@
* Boston, MA 02111-1307, USA.
*/
-#include <postgres.h>
-#include <catalog/pg_type.h>
+#include <stdlib.h>
+#include <string.h>
#include "gda-postgres.h"
GdaError *
@@ -44,48 +44,6 @@
gda_error_set_sqlstate (error, _("Not available"));
return error;
-}
-
-GdaType
-gda_postgres_type_to_gda (Oid postgres_type)
-{
- switch (postgres_type) {
- case BOOLOID :
- return GDA_TYPE_BOOLEAN;
- case BYTEAOID :
- case CHAROID :
- case NAMEOID :
- case TEXTOID :
- case BPCHAROID :
- case VARCHAROID :
- return GDA_TYPE_STRING;
- case INT8OID :
- return GDA_TYPE_BIGINT;
- case INT4OID :
- case RELTIMEOID :
- return GDA_TYPE_INTEGER;
- case INT2OID :
- return GDA_TYPE_SMALLINT;
- case FLOAT4OID :
- return GDA_TYPE_SINGLE;
- case FLOAT8OID :
- case NUMERICOID :
- return GDA_TYPE_DOUBLE;
- case ABSTIMEOID :
- case TIMESTAMPOID :
- return GDA_TYPE_TIMESTAMP;
- case DATEOID :
- return GDA_TYPE_DATE;
- case TIMEOID :
- case TIMETZOID :
- return GDA_TYPE_TIME;
- case VARBITOID :
- return GDA_TYPE_BINARY;
- case POINTOID :
- return GDA_TYPE_GEOMETRIC_POINT;
- }
-
- return GDA_TYPE_STRING;
}
/* Makes a point from a string like "(3.2,5.6)" */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]