libgda r3279 - in trunk: . libgda libgda/sqlite tests/data-models tests/parser tests/providers tools
- From: vivien svn gnome org
- To: svn-commits-list gnome org
- Subject: libgda r3279 - in trunk: . libgda libgda/sqlite tests/data-models tests/parser tests/providers tools
- Date: Fri, 9 Jan 2009 20:40:50 +0000 (UTC)
Author: vivien
Date: Fri Jan 9 20:40:50 2009
New Revision: 3279
URL: http://svn.gnome.org/viewvc/libgda?rev=3279&view=rev
Log:
2009-01-09 Vivien Malerba <malerba gnome-db org>
* libgda/gda-util.[ch]: added gda_compute_select_statement_from_update()
* libgda/sqlite/:
- added BLOB support for the SQLite provider
- report an error when getting a gint from a too big gint64 value
* tests/: updated test data related to the gda_g_type_to_string() changes
* configure.in
* tools/:
- added a '-v' command line option to display version
- added a man page for gda-sql
- optionnally create symlink from "<prog>" to the "<prog>-4.0" program names
Added:
trunk/libgda/sqlite/gda-sqlite-blob-op.c
trunk/libgda/sqlite/gda-sqlite-blob-op.h
trunk/tools/gda-sql.1.in
Modified:
trunk/ChangeLog
trunk/configure.in
trunk/libgda/gda-util.c
trunk/libgda/gda-util.h
trunk/libgda/sqlite/Makefile.am
trunk/libgda/sqlite/README
trunk/libgda/sqlite/gda-sqlite-provider.c
trunk/libgda/sqlite/gda-sqlite-pstmt.c
trunk/libgda/sqlite/gda-sqlite-pstmt.h
trunk/libgda/sqlite/gda-sqlite-recordset.c
trunk/libgda/sqlite/utils.c
trunk/tests/data-models/data1.xml
trunk/tests/data-models/pmodel_data_customers.xml
trunk/tests/data-models/pmodel_data_locations.xml
trunk/tests/parser/testdata.xml
trunk/tests/parser/testvalid.xml
trunk/tests/providers/DATA_actor.xml
trunk/tests/providers/DATA_film.xml
trunk/tests/providers/DATA_film_actor.xml
trunk/tests/providers/DATA_language.xml
trunk/tests/providers/TYPES_SCHEMA_Mdb.xml
trunk/tests/providers/TYPES_SCHEMA_MySQL.xml
trunk/tests/providers/TYPES_SCHEMA_Oracle.xml
trunk/tests/providers/TYPES_SCHEMA_PostgreSQL.xml
trunk/tests/providers/TYPES_SCHEMA_SQLite.xml
trunk/tools/ (props changed)
trunk/tools/Makefile.am
trunk/tools/gda-sql.c
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Fri Jan 9 20:40:50 2009
@@ -7,6 +7,7 @@
AC_CONFIG_SRCDIR(libgda/libgda.h.in)
AM_INIT_AUTOMAKE(1.8 -Wall no-define dist-bzip2)
+
AC_SUBST(GDA_VERSION, major.minor.micro)
# ABI version:
@@ -19,6 +20,9 @@
AC_SUBST(GDA_ABI_VERSION, $LIBGDA_ABI_VERSION)
LIBGDA_ABI_NAME="\\\"libgda-$LIBGDA_ABI_VERSION\\\""
+gdasysconfdir="$sysconfdir"
+AC_SUBST(gdasysconfdir)
+
m4_undefine([major])
m4_undefine([minor])
m4_undefine([micro])
@@ -1445,6 +1449,12 @@
fi
AC_SUBST(REBUILD)
+#
+# enable setting the Gda SQL console as default version (makes a symlink)
+#
+AC_ARG_ENABLE(default-binary, [ --enable-default-binary install tools as the default binaries (default=yes)], , enable_default_binary=yes)
+AM_CONDITIONAL(DEFAULT_BINARY, test "x$enable_default_binary" = xyes)
+
AC_SUBST(LIBGDA_CFLAGS)
AC_SUBST(LIBGDA_LIBS)
@@ -1490,6 +1500,7 @@
libgda-report/RML/trml2pdf/Makefile
libgda-xslt/Makefile
tools/Makefile
+tools/gda-sql-4.0.1:tools/gda-sql.1.in
tools/binreloc/Makefile
testing/Makefile
tests/Makefile
Modified: trunk/libgda/gda-util.c
==============================================================================
--- trunk/libgda/gda-util.c (original)
+++ trunk/libgda/gda-util.c Fri Jan 9 20:40:50 2009
@@ -1035,6 +1035,57 @@
}
/**
+ * gda_compute_select_statement_from_update
+ * @update_stmt: an UPDATE statement
+ * @error: a place to store errors, or %NULL
+ *
+ * Computes a SELECT statement which selects all the rows the @update_stmt would update. Beware
+ * however that this GdaSqlStatement does not select anything (ie it would be rendered as "SELECT FROM ... WHERE ...")
+ * and before being useable, one needs to add some fields to actually select.
+ */
+GdaSqlStatement *
+gda_compute_select_statement_from_update (GdaStatement *update_stmt, GError **error)
+{
+ GdaSqlStatement *upd_stmt;
+ GdaSqlStatement *sel_stmt;
+ GdaSqlStatementUpdate *ust;
+ GdaSqlStatementSelect *sst;
+
+ g_return_val_if_fail (update_stmt, NULL);
+ g_object_get (G_OBJECT (update_stmt), "structure", &upd_stmt, NULL);
+ g_return_val_if_fail (upd_stmt, NULL);
+ g_return_val_if_fail (upd_stmt->stmt_type == GDA_SQL_STATEMENT_UPDATE, NULL);
+
+ ust = (GdaSqlStatementUpdate*) upd_stmt->contents;
+ sst = g_new0 (GdaSqlStatementSelect, 1);
+
+ if (!ust->table || !ust->table->table_name) {
+ g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
+ "%s", _("Missing table name in UPDATE statement"));
+ return NULL;
+ }
+
+ /* FROM */
+ GdaSqlSelectTarget *target;
+ sst->from = gda_sql_select_from_new (GDA_SQL_ANY_PART (sst));
+ target = gda_sql_select_target_new (GDA_SQL_ANY_PART (sst->from));
+ sst->from->targets = g_slist_prepend (NULL, target);
+ target->expr = gda_sql_expr_new (GDA_SQL_ANY_PART (target));
+ g_value_set_string ((target->expr->value = gda_value_new (G_TYPE_STRING)), ust->table->table_name);
+
+ /* WHERE */
+ sst->where_cond = gda_sql_expr_copy (ust->cond);
+ GDA_SQL_ANY_PART (sst->where_cond)->parent = GDA_SQL_ANY_PART (sst);
+
+ gda_sql_statement_free (upd_stmt);
+
+ sel_stmt = gda_sql_statement_new (GDA_SQL_STATEMENT_SELECT);
+ sel_stmt->contents = sst;
+
+ return sel_stmt;
+}
+
+/**
* gda_identifier_hash
* @id: an identifier string
*
Modified: trunk/libgda/gda-util.h
==============================================================================
--- trunk/libgda/gda-util.h (original)
+++ trunk/libgda/gda-util.h Fri Jan 9 20:40:50 2009
@@ -67,11 +67,12 @@
/*
* Statement computation from meta store
*/
-GdaSqlExpr *gda_compute_unique_table_row_condition (GdaSqlStatementSelect *stsel, GdaMetaTable *mtable,
- gboolean require_pk, GError **error);
-gboolean gda_compute_dml_statements (GdaConnection *cnc, GdaStatement *select_stmt, gboolean require_pk,
- GdaStatement **insert_stmt, GdaStatement **update_stmt, GdaStatement **delete_stmt,
- GError **error);
+GdaSqlExpr *gda_compute_unique_table_row_condition (GdaSqlStatementSelect *stsel, GdaMetaTable *mtable,
+ gboolean require_pk, GError **error);
+gboolean gda_compute_dml_statements (GdaConnection *cnc, GdaStatement *select_stmt, gboolean require_pk,
+ GdaStatement **insert_stmt, GdaStatement **update_stmt, GdaStatement **delete_stmt,
+ GError **error);
+GdaSqlStatement *gda_compute_select_statement_from_update (GdaStatement *update_stmt, GError **error);
/*
* DSN and connection string manipulations
Modified: trunk/libgda/sqlite/Makefile.am
==============================================================================
--- trunk/libgda/sqlite/Makefile.am (original)
+++ trunk/libgda/sqlite/Makefile.am Fri Jan 9 20:40:50 2009
@@ -24,6 +24,8 @@
sqliteheaders = gda-sqlite-provider.h
libgda_sqlite_la_SOURCES = \
$(sqliteheaders) \
+ gda-sqlite-blob-op.c \
+ gda-sqlite-blob-op.h \
gda-sqlite-ddl.c \
gda-sqlite-ddl.h \
gda-sqlite-handler-bin.c \
Modified: trunk/libgda/sqlite/README
==============================================================================
--- trunk/libgda/sqlite/README (original)
+++ trunk/libgda/sqlite/README Fri Jan 9 20:40:50 2009
@@ -1,3 +1,6 @@
+Which version of SQLite is used:
+================================
+
When embedded SQLITE is used:
* HAVE_SQLITE is *not* defined
* patch it to add the PRAGMA command
@@ -13,3 +16,34 @@
1 - make SQLite implement the required PRAGMA (patch proposed)
2 - don't use the required PRAGMA at all, and manage to intercept the sqlite3CreateFunc call
when statically linked (=> modify the source code of SQLite)
+
+
+
+
+BLOB handling in SQLite:
+========================
+
+SQLite now supports incremental I/O for BLOBS. Any data in any column can be accessed
+with this API.
+
+When writing a blob to the database:
+------------------------------------
+Opening a blob requires the following information:
+* the database name
+* the table name
+* the column name
+* the ROWID
+
+The first 3 pieces of information can be obtained from the INSERT or UPDATE statement
+itself.
+
+The ROWID can be obtained using sqlite3_last_insert_rowid() for an INSERT or must be queried
+for an UPDATE.
+
+When reading a blob from the database:
+--------------------------------------
+Opening a blob requires the following information:
+* the database name: use sqlite3_column_database_name()
+* the table name: use sqlite3_column_table_name()
+* the column name: use sqlite3_column_origin_name()
+* the ROWID: get it from the SELECT as the last row.
Added: trunk/libgda/sqlite/gda-sqlite-blob-op.c
==============================================================================
--- (empty file)
+++ trunk/libgda/sqlite/gda-sqlite-blob-op.c Fri Jan 9 20:40:50 2009
@@ -0,0 +1,306 @@
+/* GDA Sqlite provider
+ * Copyright (C) 2009 The GNOME Foundation
+ *
+ * AUTHORS:
+ * Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <glib/gi18n-lib.h>
+#include <string.h>
+#include <libgda/libgda.h>
+#include "gda-sqlite.h"
+#include "gda-sqlite-blob-op.h"
+#include <sql-parser/gda-sql-parser.h>
+
+struct _GdaSqliteBlobOpPrivate {
+ sqlite3_blob *sblob;
+};
+
+static void gda_sqlite_blob_op_class_init (GdaSqliteBlobOpClass *klass);
+static void gda_sqlite_blob_op_init (GdaSqliteBlobOp *blob,
+ GdaSqliteBlobOpClass *klass);
+static void gda_sqlite_blob_op_finalize (GObject *object);
+
+static glong gda_sqlite_blob_op_get_length (GdaBlobOp *op);
+static glong gda_sqlite_blob_op_read (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size);
+static glong gda_sqlite_blob_op_write (GdaBlobOp *op, GdaBlob *blob, glong offset);
+
+static GObjectClass *parent_class = NULL;
+
+/*
+ * Object init and finalize
+ */
+GType
+gda_sqlite_blob_op_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+ static const GTypeInfo info = {
+ sizeof (GdaSqliteBlobOpClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gda_sqlite_blob_op_class_init,
+ NULL,
+ NULL,
+ sizeof (GdaSqliteBlobOp),
+ 0,
+ (GInstanceInitFunc) gda_sqlite_blob_op_init
+ };
+ g_static_mutex_lock (®istering);
+ if (type == 0)
+ type = g_type_register_static (GDA_TYPE_BLOB_OP, "GdaSqliteBlobOp", &info, 0);
+ g_static_mutex_unlock (®istering);
+ }
+ return type;
+}
+
+static void
+gda_sqlite_blob_op_init (GdaSqliteBlobOp *op, GdaSqliteBlobOpClass *klass)
+{
+ g_return_if_fail (GDA_IS_SQLITE_BLOB_OP (op));
+
+ op->priv = g_new0 (GdaSqliteBlobOpPrivate, 1);
+ op->priv->sblob = NULL;
+}
+
+static void
+gda_sqlite_blob_op_class_init (GdaSqliteBlobOpClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GdaBlobOpClass *blob_class = GDA_BLOB_OP_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->finalize = gda_sqlite_blob_op_finalize;
+ blob_class->get_length = gda_sqlite_blob_op_get_length;
+ blob_class->read = gda_sqlite_blob_op_read;
+ blob_class->write = gda_sqlite_blob_op_write;
+}
+
+static void
+gda_sqlite_blob_op_finalize (GObject * object)
+{
+ GdaSqliteBlobOp *bop = (GdaSqliteBlobOp *) object;
+
+ g_return_if_fail (GDA_IS_SQLITE_BLOB_OP (bop));
+
+ /* free specific information */
+ if (bop->priv->sblob)
+ sqlite3_blob_close (bop->priv->sblob);
+ g_free (bop->priv);
+ bop->priv = NULL;
+
+ parent_class->finalize (object);
+}
+
+GdaBlobOp *
+gda_sqlite_blob_op_new (SqliteConnectionData *cdata, const gchar *db_name, const gchar *table_name,
+ const gchar *column_name, sqlite3_int64 rowid)
+{
+ GdaSqliteBlobOp *bop = NULL;
+ int rc;
+ sqlite3_blob *sblob;
+ gchar *db, *table;
+ gboolean free_strings = TRUE;
+
+ g_return_val_if_fail (table_name, NULL);
+ g_return_val_if_fail (column_name, NULL);
+
+ if (db_name) {
+ db = (gchar *) db_name;
+ table = (gchar *) table_name;
+ free_strings = FALSE;
+ }
+ else if (! _split_identifier_string (g_strdup (table_name), &db, &table))
+ return NULL;
+
+ rc = sqlite3_blob_open (cdata->connection, db ? db : "main", table, column_name, rowid,
+ 1, /* Read & Write */
+ &(sblob));
+ if (rc != SQLITE_OK) {
+ /*g_print ("ERROR: %s\n", sqlite3_errmsg (cdata->connection));*/
+ goto out;
+ }
+
+ bop = g_object_new (GDA_TYPE_SQLITE_BLOB_OP, NULL);
+ bop->priv->sblob = sblob;
+
+ out:
+ if (free_strings) {
+ g_free (db);
+ g_free (table);
+ }
+ return (GdaBlobOp*) bop;
+}
+
+/*
+ * Get length request
+ */
+static glong
+gda_sqlite_blob_op_get_length (GdaBlobOp *op)
+{
+ GdaSqliteBlobOp *bop;
+ int len;
+
+ g_return_val_if_fail (GDA_IS_SQLITE_BLOB_OP (op), -1);
+ bop = GDA_SQLITE_BLOB_OP (op);
+ g_return_val_if_fail (bop->priv, -1);
+ g_return_val_if_fail (bop->priv->sblob, -1);
+
+ len = sqlite3_blob_bytes (bop->priv->sblob);
+ return len >= 0 ? len : 0;
+}
+
+/*
+ * Blob read request
+ */
+static glong
+gda_sqlite_blob_op_read (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size)
+{
+ GdaSqliteBlobOp *bop;
+ GdaBinary *bin;
+ int rc;
+
+ g_return_val_if_fail (GDA_IS_SQLITE_BLOB_OP (op), -1);
+ bop = GDA_SQLITE_BLOB_OP (op);
+ g_return_val_if_fail (bop->priv, -1);
+ g_return_val_if_fail (bop->priv->sblob, -1);
+ if (offset >= G_MAXINT)
+ return -1;
+ g_return_val_if_fail (blob, -1);
+
+ if (offset > G_MAXINT)
+ return -1;
+ if (size > G_MAXINT)
+ return -1;
+
+ bin = (GdaBinary *) blob;
+ if (bin->data)
+ g_free (bin->data);
+ bin->data = g_new0 (guchar, size);
+ bin->binary_length = 0;
+
+ /* fetch blob data using C API into bin->data, and set bin->binary_length */
+ int rsize;
+ int len;
+
+ len = sqlite3_blob_bytes (bop->priv->sblob);
+ if (len < 0)
+ return -1;
+ else if (len == 0)
+ return 0;
+
+ rsize = (int) size;
+ if (offset >= len)
+ return -1;
+
+ if (len - offset < rsize)
+ rsize = len - offset;
+
+ rc = sqlite3_blob_read (bop->priv->sblob, bin->data, rsize, offset);
+ if (rc != SQLITE_OK) {
+ g_free (bin->data);
+ bin->data = NULL;
+ return -1;
+ }
+ bin->binary_length = rsize;
+
+ return bin->binary_length;
+}
+
+/*
+ * Blob write request
+ */
+static glong
+gda_sqlite_blob_op_write (GdaBlobOp *op, GdaBlob *blob, glong offset)
+{
+ GdaSqliteBlobOp *bop;
+ GdaBinary *bin;
+ glong nbwritten = -1;
+ int len;
+
+ g_return_val_if_fail (GDA_IS_SQLITE_BLOB_OP (op), -1);
+ bop = GDA_SQLITE_BLOB_OP (op);
+ g_return_val_if_fail (bop->priv, -1);
+ g_return_val_if_fail (bop->priv->sblob, -1);
+ g_return_val_if_fail (blob, -1);
+
+ len = sqlite3_blob_bytes (bop->priv->sblob);
+ if (len < 0)
+ return -1;
+
+ if (blob->op && (blob->op != op)) {
+ /* use data through blob->op */
+ #define buf_size 16384
+ gint nread = 0;
+ GdaBlob *tmpblob = g_new0 (GdaBlob, 1);
+ tmpblob->op = blob->op;
+
+ nbwritten = 0;
+
+ for (nread = gda_blob_op_read (tmpblob->op, tmpblob, nbwritten, buf_size);
+ nread > 0;
+ nread = gda_blob_op_read (tmpblob->op, tmpblob, nbwritten, buf_size)) {
+ int tmp_written;
+ int rc;
+ int wlen;
+
+ if (nread + offset + nbwritten > len)
+ wlen = len - offset - nbwritten;
+ else
+ wlen = nread;
+
+ rc = sqlite3_blob_write (bop->priv->sblob, ((GdaBinary *)tmpblob)->data, wlen, offset + nbwritten);
+ if (rc != SQLITE_OK)
+ tmp_written = -1;
+ else
+ tmp_written = wlen;
+
+ if (tmp_written < 0) {
+ /* treat error */
+ gda_blob_free ((gpointer) tmpblob);
+ return -1;
+ }
+ nbwritten += tmp_written;
+ if (nread < buf_size)
+ /* nothing more to read */
+ break;
+ }
+ gda_blob_free ((gpointer) tmpblob);
+ }
+ else {
+ /* write blob using bin->data and bin->binary_length */
+ int rc;
+ int wlen;
+ bin = (GdaBinary *) blob;
+ if (bin->binary_length + offset > len)
+ wlen = len - offset;
+ else
+ wlen = bin->binary_length;
+
+ rc = sqlite3_blob_write (bop->priv->sblob, bin->data, wlen, offset);
+ if (rc != SQLITE_OK)
+ nbwritten = -1;
+ else
+ nbwritten = wlen;
+ }
+
+ return nbwritten;
+}
Added: trunk/libgda/sqlite/gda-sqlite-blob-op.h
==============================================================================
--- (empty file)
+++ trunk/libgda/sqlite/gda-sqlite-blob-op.h Fri Jan 9 20:40:50 2009
@@ -0,0 +1,56 @@
+/* GDA Sqlite provider
+ * Copyright (C) 2009 The GNOME Foundation
+ *
+ * AUTHORS:
+ * Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GDA_SQLITE_BLOB_OP_H__
+#define __GDA_SQLITE_BLOB_OP_H__
+
+#include <libgda/gda-blob-op.h>
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_SQLITE_BLOB_OP (gda_sqlite_blob_op_get_type())
+#define GDA_SQLITE_BLOB_OP(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_SQLITE_BLOB_OP, GdaSqliteBlobOp))
+#define GDA_SQLITE_BLOB_OP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST (klass, GDA_TYPE_SQLITE_BLOB_OP, GdaSqliteBlobOpClass))
+#define GDA_IS_SQLITE_BLOB_OP(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GDA_TYPE_SQLITE_BLOB_OP))
+#define GDA_IS_SQLITE_BLOB_OP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDA_TYPE_SQLITE_BLOB_OP))
+
+typedef struct _GdaSqliteBlobOp GdaSqliteBlobOp;
+typedef struct _GdaSqliteBlobOpClass GdaSqliteBlobOpClass;
+typedef struct _GdaSqliteBlobOpPrivate GdaSqliteBlobOpPrivate;
+
+struct _GdaSqliteBlobOp {
+ GdaBlobOp parent;
+ GdaSqliteBlobOpPrivate *priv;
+};
+
+struct _GdaSqliteBlobOpClass {
+ GdaBlobOpClass parent_class;
+};
+
+GType gda_sqlite_blob_op_get_type (void) G_GNUC_CONST;
+GdaBlobOp *gda_sqlite_blob_op_new (SqliteConnectionData *cdata, const gchar *db_name, const gchar *table_name,
+ const gchar *column_name, sqlite3_int64 rowid);
+
+G_END_DECLS
+
+#endif
+
Modified: trunk/libgda/sqlite/gda-sqlite-provider.c
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-provider.c (original)
+++ trunk/libgda/sqlite/gda-sqlite-provider.c Fri Jan 9 20:40:50 2009
@@ -1,5 +1,5 @@
/* GDA SQLite provider
- * Copyright (C) 1998 - 2008 The GNOME Foundation.
+ * Copyright (C) 1998 - 2009 The GNOME Foundation.
*
* AUTHORS:
* Rodrigo Moya <rodrigo gnome-db org>
@@ -37,6 +37,7 @@
#include "gda-sqlite-ddl.h"
#include "gda-sqlite-meta.h"
#include "gda-sqlite-handler-bin.h"
+#include "gda-sqlite-blob-op.h"
#include <libgda/gda-connection-private.h>
#include <libgda/binreloc/gda-binreloc.h>
#include <libgda/gda-set.h>
@@ -56,6 +57,141 @@
static GHashTable *db_connections_hash = NULL;
#endif
+/* TMP */
+typedef struct {
+ GdaSqlStatement *stmt;
+ gchar *db;
+ gchar *table;
+ gchar *column;
+ GdaBlob *blob;
+} PendingBlob;
+
+static PendingBlob*
+make_pending_blob (GdaStatement *stmt, GdaHolder *holder, GError **error)
+{
+ PendingBlob *pb = NULL;
+ GdaSqlStatement *sqlst;
+ const gchar *hname;
+
+ g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
+ g_return_val_if_fail (GDA_IS_HOLDER (holder), NULL);
+ hname = gda_holder_get_id (holder);
+ g_return_val_if_fail (hname && *hname, NULL);
+
+ g_object_get (G_OBJECT (stmt), "structure", &sqlst, NULL);
+ g_return_val_if_fail (sqlst, NULL);
+
+ switch (sqlst->stmt_type) {
+ case GDA_SQL_STATEMENT_INSERT: {
+ GdaSqlStatementInsert *istmt = (GdaSqlStatementInsert*) sqlst->contents;
+ gint pos = -1;
+ GSList *vll;
+ for (vll = istmt->values_list; vll && (pos == -1); vll = vll->next) {
+ GSList *vlist;
+ gint p;
+ for (p = 0, vlist = (GSList *) vll->data;
+ vlist;
+ p++, vlist = vlist->next) {
+ GdaSqlExpr *expr = (GdaSqlExpr *) vlist->data;
+ if (!expr->param_spec)
+ continue;
+ if (expr->param_spec->name &&
+ !strcmp (expr->param_spec->name, hname)) {
+ pos = p;
+ break;
+ }
+ }
+ }
+ if (pos == -1) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_INTERNAL_ERROR,
+ _("Parameter '%s' not found is statement"), hname);
+ goto out;
+ }
+ GdaSqlField *field;
+ field = g_slist_nth_data (istmt->fields_list, pos);
+ if (!field) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_INTERNAL_ERROR,
+ _("Parameter '%s' does not correspond to a table's column"),
+ hname);
+ goto out;
+ }
+ pb = g_new0 (PendingBlob, 1);
+ pb->table = istmt->table->table_name;
+ pb->column = field->field_name;
+ break;
+ }
+ case GDA_SQL_STATEMENT_UPDATE: {
+ GdaSqlStatementUpdate *ustmt = (GdaSqlStatementUpdate*) sqlst->contents;
+ gint pos = -1;
+ GSList *vlist;
+ gint p;
+ for (p = 0, vlist = ustmt->expr_list;
+ vlist;
+ p++, vlist = vlist->next) {
+ GdaSqlExpr *expr = (GdaSqlExpr *) vlist->data;
+ if (!expr->param_spec)
+ continue;
+ if (expr->param_spec->name &&
+ !strcmp (expr->param_spec->name, hname)) {
+ pos = p;
+ break;
+ }
+ }
+ if (pos == -1) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_INTERNAL_ERROR,
+ _("Parameter '%s' not found is statement"), hname);
+ goto out;
+ }
+ GdaSqlField *field;
+ field = g_slist_nth_data (ustmt->fields_list, pos);
+ if (!field) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_INTERNAL_ERROR,
+ _("Parameter '%s' does not correspond to a table's column"),
+ hname);
+ goto out;
+ }
+ pb = g_new0 (PendingBlob, 1);
+ pb->table = ustmt->table->table_name;
+ pb->column = field->field_name;
+ break;
+ }
+ default:
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_NON_SUPPORTED_ERROR,
+ "%s",_("Binding a BLOB for this type of statement is not supported"));
+ goto out;
+ }
+
+ out:
+ if (pb)
+ pb->stmt = sqlst;
+ else
+ gda_sql_statement_free (sqlst);
+ return pb;
+}
+
+static void
+pending_blobs_free_list (GSList *blist)
+{
+ if (!blist)
+ return;
+ GSList *l;
+ for (l = blist; l; l = l->next) {
+ PendingBlob *pb = (PendingBlob*) l->data;
+ if (pb->stmt)
+ gda_sql_statement_free (pb->stmt);
+ g_free (pb);
+ }
+
+ g_slist_free (blist);
+}
+
+/* TMP */
+
/*
* GObject methods
*/
@@ -1592,6 +1728,95 @@
}
}
+/*
+ * Creates a new GdaStatement, as a copy of @stmt, and adds new OID columns, one for each table involved
+ * in the SELECT
+ * The GHashTable created (as @out_hash) contains:
+ * - key = table name
+ * - value = column number in the SELECT (use GPOINTER_TO_INT)
+ *
+ * This step is required for BLOBs which needs to table's ROWID to be opened. The extra columns
+ * won't appear in the final result set.
+ */
+static GdaStatement *
+add_oid_columns (GdaStatement *stmt, GHashTable **out_hash, gint *out_nb_cols_added)
+{
+ GHashTable *hash = NULL;
+ GdaStatement *nstmt;
+ GdaSqlStatement *sqlst;
+ GdaSqlStatementSelect *sst;
+ gint nb_cols_added = 0;
+ gint add_index;
+
+ *out_hash = NULL;
+ *out_nb_cols_added = 0;
+
+ GdaSqlStatementType type;
+ type = gda_statement_get_statement_type (stmt);
+ if (type == GDA_SQL_STATEMENT_COMPOUND) {
+ TO_IMPLEMENT;
+ return g_object_ref (stmt);
+ }
+ else if (type != GDA_SQL_STATEMENT_SELECT) {
+ return g_object_ref (stmt);
+ }
+
+ g_object_get (G_OBJECT (stmt), "structure", &sqlst, NULL);
+ g_assert (sqlst);
+ hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ sst = (GdaSqlStatementSelect*) sqlst->contents;
+
+ if (!sst->from) {
+ gda_sql_statement_free (sqlst);
+ return g_object_ref (stmt);
+ }
+
+ add_index = g_slist_length (sst->expr_list);
+ GSList *list;
+ for (list = sst->from->targets; list; list = list->next) {
+ GdaSqlSelectTarget *target = (GdaSqlSelectTarget*) list->data;
+ GdaSqlSelectField *field;
+
+ if (!target->table_name)
+ continue;
+
+ /* add a field */
+ field = gda_sql_select_field_new (GDA_SQL_ANY_PART (sst));
+ sst->expr_list = g_slist_append (sst->expr_list, field);
+
+ field->expr = gda_sql_expr_new (GDA_SQL_ANY_PART (field));
+
+ gchar *str;
+ const gchar *name;
+ if (target->as)
+ name = target->as;
+ else
+ name = target->table_name;
+ if (gda_sql_identifier_needs_quotes (name)) {
+ gchar *tmp;
+ tmp = gda_sql_identifier_add_quotes (target->table_name);
+ str = g_strdup_printf ("%s.rowid", tmp);
+ g_free (tmp);
+ }
+ else
+ str = g_strdup_printf ("%s.rowid", name);
+ g_value_take_string ((field->expr->value = gda_value_new (G_TYPE_STRING)), str);
+
+ /* add to hash table */
+ g_hash_table_insert (hash, g_strdup (name), GINT_TO_POINTER (add_index));
+ nb_cols_added ++;
+ }
+
+ /* prepare return */
+ nstmt = (GdaStatement*) g_object_new (GDA_TYPE_STATEMENT, "structure", sqlst, NULL);
+ gda_sql_statement_free (sqlst);
+
+ *out_hash = hash;
+ *out_nb_cols_added = nb_cols_added;
+
+ return nstmt;
+}
+
static GdaSqlitePStmt *
real_prepare (GdaServerProvider *provider, GdaConnection *cnc, GdaStatement *stmt, GError **error)
{
@@ -1603,6 +1828,10 @@
GdaSqlitePStmt *ps;
GdaSet *params = NULL;
GSList *used_params = NULL;
+
+ GdaStatement *real_stmt;
+ GHashTable *hash;
+ gint nb_rows_added;
/* get SQLite's private data */
cdata = (SqliteConnectionData*) gda_connection_internal_get_provider_data (cnc);
@@ -1613,7 +1842,8 @@
if (! gda_statement_get_parameters (stmt, ¶ms, error))
return NULL;
- sql = gda_sqlite_provider_statement_to_sql (provider, cnc, stmt, params, GDA_STATEMENT_SQL_PARAMS_AS_QMARK,
+ real_stmt = add_oid_columns (stmt, &hash, &nb_rows_added);
+ sql = gda_sqlite_provider_statement_to_sql (provider, cnc, real_stmt, params, GDA_STATEMENT_SQL_PARAMS_AS_QMARK,
&used_params, error);
if (!sql)
goto out_err;
@@ -1658,9 +1888,14 @@
gda_pstmt_set_gda_statement (_GDA_PSTMT (ps), stmt);
_GDA_PSTMT (ps)->param_ids = param_ids;
_GDA_PSTMT (ps)->sql = sql;
+ ps->rowid_hash = hash;
+ ps->nb_rowid_columns = nb_rows_added;
return ps;
out_err:
+ if (hash)
+ g_hash_table_destroy (hash);
+ g_object_unref (real_stmt);
if (used_params)
g_slist_free (used_params);
if (params)
@@ -1721,7 +1956,7 @@
where->cond = cond;
cond->operator_type = GDA_SQL_OPERATOR_TYPE_EQ;
expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond));
- g_value_set_string ((value = gda_value_new (G_TYPE_STRING)), "_rowid_");
+ g_value_set_string ((value = gda_value_new (G_TYPE_STRING)), "rowid");
expr->value = value;
cond->operands = g_slist_append (NULL, expr);
gchar *str;
@@ -1806,6 +2041,151 @@
}
}
+/*
+ * This function opens any blob which has been inserted or updated as a ZERO blob (the blob currently
+ * only contains zeros) and fills its contents with the blob passed as parameter when executing the statement.
+ *
+ * @blobs_list is freed here
+ */
+static GdaConnectionEvent *
+fill_blob_data (GdaConnection *cnc, GdaSet *params,
+ SqliteConnectionData *cdata, GdaSqlitePStmt *pstmt, GSList *blobs_list, GError **error)
+{
+ if (!blobs_list)
+ /* nothing to do */
+ return NULL;
+
+ const gchar *str = NULL;
+ GdaStatement *stmt;
+ sqlite3_int64 rowid = -1;
+ GdaDataModel *model = NULL;
+ GError *lerror = NULL;
+
+ /* get single ROWID or a list of ROWID */
+ stmt = gda_pstmt_get_gda_statement (GDA_PSTMT (pstmt));
+ if (!stmt) {
+ g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_INTERNAL_ERROR, "%s",
+ _("Prepared statement has no associated GdaStatement"));
+ goto blobs_out;
+ }
+ if (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_INSERT) {
+ rowid = sqlite3_last_insert_rowid (cdata->connection);
+ }
+ else if (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_UPDATE) {
+ GdaSqlStatement *sel_stmt;
+ GdaSqlStatementSelect *sst;
+ sel_stmt = gda_compute_select_statement_from_update (stmt, &lerror);
+ if (!sel_stmt)
+ goto blobs_out;
+ sst = (GdaSqlStatementSelect*) sel_stmt->contents;
+ GdaSqlSelectField *oidfield;
+ oidfield = gda_sql_select_field_new (GDA_SQL_ANY_PART (sst));
+ sst->expr_list = g_slist_prepend (NULL, oidfield);
+ oidfield->expr = gda_sql_expr_new (GDA_SQL_ANY_PART (oidfield));
+ g_value_set_string ((oidfield->expr->value = gda_value_new (G_TYPE_STRING)), "rowid");
+
+ GdaStatement *select;
+ select = (GdaStatement *) g_object_new (GDA_TYPE_STATEMENT, "structure", sel_stmt, NULL);
+ gda_sql_statement_free (sel_stmt);
+ model = gda_connection_statement_execute_select (cnc, select, params, &lerror);
+ if (!model) {
+ g_object_unref (select);
+ goto blobs_out;
+ }
+ g_object_unref (select);
+ }
+
+ /* actual blob filling */
+ GSList *list;
+ for (list = blobs_list; list; list = list->next) {
+ PendingBlob *pb = (PendingBlob*) list->data;
+
+ if (rowid >= 0) {
+ /*g_print ("Filling BLOB @ %s.%s.%s, rowID %ld\n", pb->db, pb->table, pb->column, rowid);*/
+ GdaSqliteBlobOp *bop;
+ bop = (GdaSqliteBlobOp*) gda_sqlite_blob_op_new (cdata, pb->db, pb->table, pb->column, rowid);
+ if (!bop) {
+ str = _("Can't create SQLite BLOB handle");
+ goto blobs_out;
+ }
+ if (gda_blob_op_write (GDA_BLOB_OP (bop), pb->blob, 0) < 0) {
+ str = _("Can't write to SQLite's BLOB");
+ g_object_unref (bop);
+ goto blobs_out;
+ }
+ g_object_unref (bop);
+ }
+ else if (model) {
+ gint nrows, i;
+ nrows = gda_data_model_get_n_rows (model);
+ for (i = 0; i < nrows; i++) {
+ const GValue *cvalue;
+ cvalue = gda_data_model_get_value_at (model, 0, i, &lerror);
+ if (!cvalue) {
+ g_object_unref (model);
+ goto blobs_out;
+ }
+ rowid = g_value_get_int64 (cvalue);
+ GdaSqliteBlobOp *bop;
+ bop = (GdaSqliteBlobOp*) gda_sqlite_blob_op_new (cdata, pb->db, pb->table, pb->column, rowid);
+ if (!bop) {
+ str = _("Can't create SQLite BLOB handle");
+ g_object_unref (model);
+ goto blobs_out;
+ }
+ if (gda_blob_op_write (GDA_BLOB_OP (bop), pb->blob, 0) < 0) {
+ str = _("Can't write to SQLite's BLOB");
+ g_object_unref (bop);
+ g_object_unref (model);
+ goto blobs_out;
+ }
+ g_object_unref (bop);
+ }
+ g_object_unref (model);
+ }
+ else
+ str = _("Can't identify the ROWID of the blob to fill");
+ }
+
+ blobs_out:
+ pending_blobs_free_list (blobs_list);
+
+ if (str) {
+ GdaConnectionEvent *event;
+ event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+ gda_connection_event_set_description (event, str);
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_DATA_ERROR, "%s", str);
+ return event;
+ }
+ if (lerror) {
+ GdaConnectionEvent *event;
+ event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+ gda_connection_event_set_description (event, lerror->message ? lerror->message : _("No detail"));
+ g_propagate_error (error, lerror);
+ return event;
+ }
+ return NULL;
+}
+
+static gboolean
+check_transaction_started (GdaConnection *cnc, gboolean *out_started)
+{
+ GdaTransactionStatus *trans;
+
+ trans = gda_connection_get_transaction_status (cnc);
+ if (!trans) {
+ if (!gda_connection_begin_transaction (cnc, NULL,
+ GDA_TRANSACTION_ISOLATION_UNKNOWN, NULL))
+ return FALSE;
+ else
+ *out_started = TRUE;
+ }
+ return TRUE;
+}
+
+
/*
* Execute statement request
*/
@@ -1890,6 +2270,7 @@
/* create a SQLitePreparedStatement */
ps = gda_sqlite_pstmt_new (sqlite_stmt);
_GDA_PSTMT (ps)->sql = sql;
+
new_ps = TRUE;
}
else
@@ -1945,6 +2326,9 @@
GSList *list;
GdaConnectionEvent *event = NULL;
int i;
+ GSList *blobs_list = NULL; /* list of PendingBlob structures */
+ gboolean transaction_started = FALSE;
+
for (i = 1, list = _GDA_PSTMT (ps)->param_ids; list; list = list->next, i++) {
const gchar *pname = (gchar *) list->data;
GdaHolder *h = NULL;
@@ -2036,10 +2420,56 @@
else if (G_VALUE_TYPE (value) == G_TYPE_UCHAR)
sqlite3_bind_int (ps->sqlite_stmt, i, g_value_get_uchar (value));
else if (G_VALUE_TYPE (value) == GDA_TYPE_BLOB) {
- TO_IMPLEMENT; /* use sqlite3_bind_zeroblob () */
- GdaBinary *bin = (GdaBinary *) gda_value_get_blob (value);
- sqlite3_bind_blob (ps->sqlite_stmt, i,
- bin->data, bin->binary_length, SQLITE_TRANSIENT);
+ gulong blob_len;
+ GdaBlob *blob = (GdaBlob*) gda_value_get_blob (value);
+ const gchar *str = NULL;
+
+ /* Start a transaction if necessary */
+ if (!check_transaction_started (cnc, &transaction_started))
+ str = _("Cannot start transaction");
+ else {
+ /* force reading the complete BLOB into memory */
+ if (blob->op)
+ blob_len = gda_blob_op_get_length (blob->op);
+ else
+ blob_len = ((GdaBinary*) blob)->binary_length;
+ if (blob_len < 0)
+ str = _("Can't get BLOB's length");
+ else if (blob_len >= G_MAXINT)
+ str = _("BLOB is too big");
+ }
+
+ if (str) {
+ event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+ gda_connection_event_set_description (event, str);
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_DATA_ERROR, "%s", str);
+ break;
+ }
+
+ PendingBlob *pb;
+ GError *lerror = NULL;
+ pb = make_pending_blob (stmt, h, &lerror);
+ if (!pb) {
+ event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+ gda_connection_event_set_description (event,
+ lerror && lerror->message ? lerror->message : _("No detail"));
+
+ g_propagate_error (error, lerror);
+ break;
+ }
+ pb->blob = blob;
+ blobs_list = g_slist_prepend (blobs_list, pb);
+
+ if (sqlite3_bind_zeroblob (ps->sqlite_stmt, i, (int) blob_len) !=
+ SQLITE_OK) {
+ event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+ gda_connection_event_set_description (event,
+ lerror && lerror->message ? lerror->message : _("No detail"));
+
+ g_propagate_error (error, lerror);
+ break;
+ }
}
else if (G_VALUE_TYPE (value) == GDA_TYPE_BINARY) {
GdaBinary *bin = (GdaBinary *) gda_value_get_binary (value);
@@ -2096,6 +2526,9 @@
gda_connection_add_event (cnc, event);
if (new_ps)
g_object_unref (ps);
+ pending_blobs_free_list (blobs_list);
+ if (transaction_started)
+ gda_connection_rollback_transaction (cnc, NULL, NULL);
return NULL;
}
@@ -2124,6 +2557,9 @@
g_object_unref (ps);
if (allow_noparam)
g_object_set (data_model, "auto-reset", TRUE, NULL);
+ pending_blobs_free_list (blobs_list);
+ if (transaction_started)
+ gda_connection_commit_transaction (cnc, NULL, NULL);
return data_model;
}
else {
@@ -2146,6 +2582,9 @@
gda_connection_internal_statement_executed (cnc, stmt, params, event);
if (new_ps)
g_object_unref (ps);
+ pending_blobs_free_list (blobs_list);
+ if (transaction_started)
+ gda_connection_rollback_transaction (cnc, NULL, NULL);
return NULL;
}
else {
@@ -2154,46 +2593,52 @@
TO_IMPLEMENT;
if (new_ps)
g_object_unref (ps);
+ pending_blobs_free_list (blobs_list);
+ if (transaction_started)
+ gda_connection_rollback_transaction (cnc, NULL, NULL);
return NULL;
}
}
else {
+ /* fill blobs's data */
+ event = fill_blob_data (cnc, params, cdata, ps, blobs_list, error);
+ if (event) {
+ /* an error occurred */
+ if (new_ps)
+ g_object_unref (ps);
+ if (transaction_started)
+ gda_connection_rollback_transaction (cnc, NULL, NULL);
+ return NULL;
+ }
+
GObject *set;
gchar *str = NULL;
-
- event = NULL;
set = (GObject*) gda_set_new_inline (1, "IMPACTED_ROWS", G_TYPE_INT, changes, NULL);
if (! g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "DELETE", 6))
str = g_strdup_printf ("DELETE %d (see SQLite documentation for a \"DELETE * FROM table\" query)",
changes);
- else {
- if (! g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "INSERT", 6)) {
- sqlite3_int64 last_id;
- last_id = sqlite3_last_insert_rowid (handle);
- str = g_strdup_printf ("INSERT %lld %d", last_id, changes);
- if (last_inserted_row)
- *last_inserted_row = make_last_inserted_set (cnc, stmt, last_id);
+ else if (! g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "INSERT", 6)) {
+ sqlite3_int64 last_id;
+ last_id = sqlite3_last_insert_rowid (handle);
+ str = g_strdup_printf ("INSERT %lld %d", last_id, changes);
+ if (last_inserted_row)
+ *last_inserted_row = make_last_inserted_set (cnc, stmt, last_id);
+ }
+ else if (!g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "UPDATE", 6))
+ str = g_strdup_printf ("UPDATE %d", changes);
+ else if (*(_GDA_PSTMT (ps)->sql)) {
+ gchar *tmp = g_ascii_strup (_GDA_PSTMT (ps)->sql, -1);
+ for (str = tmp; *str && (*str != ' ') && (*str != '\t') &&
+ (*str != '\n'); str++);
+ *str = 0;
+ if (changes > 0) {
+ str = g_strdup_printf ("%s %d", tmp,
+ changes);
+ g_free (tmp);
}
- else {
- if (!g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "DELETE", 6))
- str = g_strdup_printf ("DELETE %d", changes);
- else {
- if (*(_GDA_PSTMT (ps)->sql)) {
- gchar *tmp = g_ascii_strup (_GDA_PSTMT (ps)->sql, -1);
- for (str = tmp; *str && (*str != ' ') && (*str != '\t') &&
- (*str != '\n'); str++);
- *str = 0;
- if (changes > 0) {
- str = g_strdup_printf ("%s %d", tmp,
- changes);
- g_free (tmp);
- }
- else
- str = tmp;
- }
- }
- }
- }
+ else
+ str = tmp;
+ }
if (str) {
event = gda_connection_event_new (GDA_CONNECTION_EVENT_NOTICE);
gda_connection_event_set_description (event, str);
@@ -2203,6 +2648,8 @@
gda_connection_internal_statement_executed (cnc, stmt, params, event);
if (new_ps)
g_object_unref (ps);
+ if (transaction_started)
+ gda_connection_commit_transaction (cnc, NULL, NULL);
return set;
}
}
Modified: trunk/libgda/sqlite/gda-sqlite-pstmt.c
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-pstmt.c (original)
+++ trunk/libgda/sqlite/gda-sqlite-pstmt.c Fri Jan 9 20:40:50 2009
@@ -1,5 +1,5 @@
/* GDA library
- * Copyright (C) 2008 The GNOME Foundation.
+ * Copyright (C) 2008 - 2009 The GNOME Foundation.
*
* AUTHORS:
* Vivien Malerba <malerba gnome-db org>
@@ -78,6 +78,8 @@
g_return_if_fail (GDA_IS_PSTMT (pstmt));
pstmt->sqlite_stmt = NULL;
pstmt->stmt_used = FALSE;
+ pstmt->rowid_hash = NULL;
+ pstmt->nb_rowid_columns = 0;
}
static void
@@ -91,6 +93,9 @@
if (pstmt->sqlite_stmt)
sqlite3_finalize (pstmt->sqlite_stmt);
+ if (pstmt->rowid_hash)
+ g_hash_table_destroy (pstmt->rowid_hash);
+
/* chain to parent class */
parent_class->finalize (object);
}
Modified: trunk/libgda/sqlite/gda-sqlite-pstmt.h
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-pstmt.h (original)
+++ trunk/libgda/sqlite/gda-sqlite-pstmt.h Fri Jan 9 20:40:50 2009
@@ -1,5 +1,5 @@
/* GDA common library
- * Copyright (C) 2008 The GNOME Foundation.
+ * Copyright (C) 2008 - 2009 The GNOME Foundation.
*
* AUTHORS:
* Vivien Malerba <malerba gnome-db org>
@@ -46,7 +46,9 @@
sqlite3_stmt *sqlite_stmt;
gboolean stmt_used; /* TRUE if a recorset already uses this prepared statement,
- necessary because only one recordset can use sqlite_stmt at a time */
+ * necessary because only one recordset can use sqlite_stmt at a time */
+ GHashTable *rowid_hash;
+ gint nb_rowid_columns;
};
struct _GdaSqlitePStmtClass {
Modified: trunk/libgda/sqlite/gda-sqlite-recordset.c
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-recordset.c (original)
+++ trunk/libgda/sqlite/gda-sqlite-recordset.c Fri Jan 9 20:40:50 2009
@@ -1,5 +1,5 @@
/* GDA SQLite provider
- * Copyright (C) 1998 - 2008 The GNOME Foundation.
+ * Copyright (C) 1998 - 2009 The GNOME Foundation.
*
* AUTHORS:
* Rodrigo Moya <rodrigo gnome-db org>
@@ -28,6 +28,7 @@
#include "gda-sqlite.h"
#include "gda-sqlite-recordset.h"
#include "gda-sqlite-provider.h"
+#include "gda-sqlite-blob-op.h"
#include <libgda/gda-util.h>
#include <libgda/gda-connection-private.h>
@@ -200,8 +201,8 @@
_gda_sqlite_compute_types_hash (cdata);
/* make sure @ps reports the correct number of columns */
- if (_GDA_PSTMT (ps)->ncols < 0)
- _GDA_PSTMT (ps)->ncols = sqlite3_column_count (ps->sqlite_stmt);
+ if (_GDA_PSTMT (ps)->ncols < 0)
+ _GDA_PSTMT (ps)->ncols = sqlite3_column_count (ps->sqlite_stmt) - ps->nb_rowid_columns;
/* completing ps */
g_assert (! ps->stmt_used);
@@ -275,11 +276,17 @@
if (_GDA_PSTMT (ps)->types [colnum] != GDA_TYPE_NULL)
return _GDA_PSTMT (ps)->types [colnum];
- ctype = sqlite3_column_decltype (ps->sqlite_stmt, colnum);
- if (ctype)
- gtype = GPOINTER_TO_INT (g_hash_table_lookup (cdata->types, ctype));
- if (gtype == GDA_TYPE_NULL)
- gtype = _gda_sqlite_compute_g_type (sqlite3_column_type (ps->sqlite_stmt, colnum));
+ ctype = sqlite3_column_origin_name (ps->sqlite_stmt, colnum);
+ if (ctype && !strcmp (ctype, "rowid"))
+ gtype = G_TYPE_INT64;
+ else {
+ ctype = sqlite3_column_decltype (ps->sqlite_stmt, colnum);
+
+ if (ctype)
+ gtype = GPOINTER_TO_INT (g_hash_table_lookup (cdata->types, ctype));
+ if (gtype == GDA_TYPE_NULL)
+ gtype = _gda_sqlite_compute_g_type (sqlite3_column_type (ps->sqlite_stmt, colnum));
+ }
return gtype;
}
@@ -337,8 +344,20 @@
if (type == GDA_TYPE_NULL)
;
- else if (type == G_TYPE_INT)
- g_value_set_int (value, sqlite3_column_int (ps->sqlite_stmt, col));
+ else if (type == G_TYPE_INT) {
+ gint64 i;
+ i = sqlite3_column_int (ps->sqlite_stmt, col);
+ if ((i > G_MAXINT) || (i < G_MININT)) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", _("Integer value is too big"));
+ has_error = TRUE;
+ break;
+ }
+ g_value_set_int (value, (gint) i);
+ }
+ else if (type == G_TYPE_INT64)
+ g_value_set_int64 (value, sqlite3_column_int64 (ps->sqlite_stmt, col));
else if (type == G_TYPE_DOUBLE)
g_value_set_double (value, sqlite3_column_double (ps->sqlite_stmt, col));
else if (type == G_TYPE_STRING)
@@ -357,6 +376,46 @@
bin->binary_length = 0;
gda_value_take_binary (value, bin);
}
+ else if (type == GDA_TYPE_BLOB) {
+ GdaBlobOp *bop = NULL;
+ gint oidcol = 0;
+
+ if (ps->rowid_hash) {
+ const char *ctable;
+ ctable = sqlite3_column_name (ps->sqlite_stmt, col);
+ if (ctable)
+ oidcol = GPOINTER_TO_INT (g_hash_table_lookup (ps->rowid_hash,
+ ctable));
+ if (oidcol == 0) {
+ ctable = sqlite3_column_table_name (ps->sqlite_stmt, col);
+ if (ctable)
+ oidcol = GPOINTER_TO_INT (g_hash_table_lookup (ps->rowid_hash,
+ ctable));
+ }
+ }
+ if (oidcol != 0) {
+ gint64 rowid;
+ rowid = sqlite3_column_int64 (ps->sqlite_stmt, oidcol);
+ bop = gda_sqlite_blob_op_new (cdata,
+ sqlite3_column_database_name (ps->sqlite_stmt, col),
+ sqlite3_column_table_name (ps->sqlite_stmt, col),
+ sqlite3_column_origin_name (ps->sqlite_stmt, col),
+ rowid);
+ }
+ if (!bop) {
+ g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+ GDA_SERVER_PROVIDER_DATA_ERROR,
+ "%s", _("Unable to open BLOB"));
+ has_error = TRUE;
+ break;
+ }
+ else {
+ GdaBlob *blob;
+ blob = g_new0 (GdaBlob, 1);
+ blob->op = bop;
+ gda_value_take_blob (value, blob);
+ }
+ }
else if (type == G_TYPE_BOOLEAN)
g_value_set_boolean (value, sqlite3_column_int (ps->sqlite_stmt, col) == 0 ? FALSE : TRUE);
else if (type == G_TYPE_DATE) {
Modified: trunk/libgda/sqlite/utils.c
==============================================================================
--- trunk/libgda/sqlite/utils.c (original)
+++ trunk/libgda/sqlite/utils.c Fri Jan 9 20:40:50 2009
@@ -1,5 +1,5 @@
/* GNOME DB Postgres Provider
- * Copyright (C) 1998 - 2006 The GNOME Foundation
+ * Copyright (C) 1998 - 2009 The GNOME Foundation
*
* AUTHORS:
* Gonzalo Paniagua Javier <gonzalo gnome-db org>
@@ -65,7 +65,8 @@
g_hash_table_insert (types, g_strdup ("real"), GINT_TO_POINTER (G_TYPE_DOUBLE));
g_hash_table_insert (types, g_strdup ("text"), GINT_TO_POINTER (G_TYPE_STRING));
g_hash_table_insert (types, g_strdup ("string"), GINT_TO_POINTER (G_TYPE_STRING));
- g_hash_table_insert (types, g_strdup ("blob"), GINT_TO_POINTER (GDA_TYPE_BINARY));
+ g_hash_table_insert (types, g_strdup ("binary"), GINT_TO_POINTER (GDA_TYPE_BINARY));
+ g_hash_table_insert (types, g_strdup ("blob"), GINT_TO_POINTER (GDA_TYPE_BLOB));
}
GType
@@ -80,7 +81,7 @@
case SQLITE_TEXT:
return G_TYPE_STRING;
case SQLITE_BLOB:
- return GDA_TYPE_BINARY;
+ return GDA_TYPE_BLOB;
case SQLITE_NULL:
return GDA_TYPE_NULL;
default:
Modified: trunk/tests/data-models/data1.xml
==============================================================================
--- trunk/tests/data-models/data1.xml (original)
+++ trunk/tests/data-models/data1.xml Fri Jan 9 20:40:50 2009
@@ -1,15 +1,15 @@
<?xml version="1.0"?>
<gda_array id="FIELDS_A" name="Table's columns">
- <gda_array_field id="COLUMN_NAME" name="Field name" title="Field name" gdatype="gchararray"/>
- <gda_array_field id="COLUMN_TYPE" name="Data type" title="Data type" gdatype="gchararray"/>
+ <gda_array_field id="COLUMN_NAME" name="Field name" title="Field name" gdatype="string"/>
+ <gda_array_field id="COLUMN_TYPE" name="Data type" title="Data type" gdatype="string"/>
<gda_array_field id="COLUMN_SIZE" name="Size" title="Size" gdatype="guint" nullok="TRUE"/>
<gda_array_field id="COLUMN_SCALE" name="Scale" title="Scale" gdatype="guint" nullok="TRUE"/>
- <gda_array_field id="COLUMN_NNUL" name="Not NULL" title="Not NULL" gdatype="gboolean"/>
- <gda_array_field id="COLUMN_AUTOINC" name="Auto increment" title="Auto increment" gdatype="gboolean"/>
- <gda_array_field id="COLUMN_UNIQUE" name="Unique" title="Unique" gdatype="gboolean"/>
- <gda_array_field id="COLUMN_PKEY" name="Primary key" title="Primary key" gdatype="gboolean"/>
- <gda_array_field id="COLUMN_DEFAULT" name="Default" title="Default" gdatype="gchararray"/>
- <gda_array_field id="COLUMN_CHECK" name="Check" title="Check" gdatype="gchararray"/>
+ <gda_array_field id="COLUMN_NNUL" name="Not NULL" title="Not NULL" gdatype="boolean"/>
+ <gda_array_field id="COLUMN_AUTOINC" name="Auto increment" title="Auto increment" gdatype="boolean"/>
+ <gda_array_field id="COLUMN_UNIQUE" name="Unique" title="Unique" gdatype="boolean"/>
+ <gda_array_field id="COLUMN_PKEY" name="Primary key" title="Primary key" gdatype="boolean"/>
+ <gda_array_field id="COLUMN_DEFAULT" name="Default" title="Default" gdatype="string"/>
+ <gda_array_field id="COLUMN_CHECK" name="Check" title="Check" gdatype="string"/>
<gda_array_data>
<gda_array_row>
<gda_value>id</gda_value>
Modified: trunk/tests/data-models/pmodel_data_customers.xml
==============================================================================
--- trunk/tests/data-models/pmodel_data_customers.xml (original)
+++ trunk/tests/data-models/pmodel_data_customers.xml Fri Jan 9 20:40:50 2009
@@ -1,11 +1,11 @@
<?xml version="1.0"?>
<gda_array id="EXPORT" name="Exported Data">
- <gda_array_field id="FI0" name="id" title="id" gdatype="gint"/>
- <gda_array_field id="FI1" name="name" title="name" gdatype="gchararray"/>
- <gda_array_field id="FI2" name="last_update" title="last_update" gdatype="GdaTimestamp"/>
- <gda_array_field id="FI3" name="default_served_by" title="default_served_by" gdatype="gint" nullok="TRUE"/>
- <gda_array_field id="FI4" name="country" title="country" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI5" name="city" title="city" gdatype="gchararray" nullok="TRUE"/>
+ <gda_array_field id="FI0" name="id" title="id" gdatype="int"/>
+ <gda_array_field id="FI1" name="name" title="name" gdatype="string"/>
+ <gda_array_field id="FI2" name="last_update" title="last_update" gdatype="timestamp"/>
+ <gda_array_field id="FI3" name="default_served_by" title="default_served_by" gdatype="int" nullok="TRUE"/>
+ <gda_array_field id="FI4" name="country" title="country" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI5" name="city" title="city" gdatype="string" nullok="TRUE"/>
<gda_array_data>
<gda_array_row>
<gda_value>2</gda_value>
Modified: trunk/tests/data-models/pmodel_data_locations.xml
==============================================================================
--- trunk/tests/data-models/pmodel_data_locations.xml (original)
+++ trunk/tests/data-models/pmodel_data_locations.xml Fri Jan 9 20:40:50 2009
@@ -1,8 +1,8 @@
<?xml version="1.0"?>
<gda_array id="EXPORT" name="Exported Data">
- <gda_array_field id="FI0" name="country" title="country" gdatype="gchararray"/>
- <gda_array_field id="FI1" name="city" title="city" gdatype="gchararray"/>
- <gda_array_field id="FI2" name="shortcut" title="shortcut" gdatype="gchararray"/>
+ <gda_array_field id="FI0" name="country" title="country" gdatype="string"/>
+ <gda_array_field id="FI1" name="city" title="city" gdatype="string"/>
+ <gda_array_field id="FI2" name="shortcut" title="shortcut" gdatype="string"/>
<gda_array_data>
<gda_array_row>
<gda_value>FR</gda_value>
Modified: trunk/tests/parser/testdata.xml
==============================================================================
--- trunk/tests/parser/testdata.xml (original)
+++ trunk/tests/parser/testdata.xml Fri Jan 9 20:40:50 2009
@@ -24,12 +24,12 @@
<test id="3">
<sql>##pname::gint</sql>
- <expected>{"statements":[{"statement":{"sql":"##pname::gint","stmt_type":"UNKNOWN","contents":[{"value":null,"param_spec":{"name":"pname","descr":null,"type":"gint","is_param":true,"nullok":false}}]}}]}</expected>
+ <expected>{"statements":[{"statement":{"sql":"##pname::gint","stmt_type":"UNKNOWN","contents":[{"value":null,"param_spec":{"name":"pname","descr":null,"type":"int","is_param":true,"nullok":false}}]}}]}</expected>
</test>
<test id="4">
<sql>##pname::gint::null</sql>
- <expected>{"statements":[{"statement":{"sql":"##pname::gint::null","stmt_type":"UNKNOWN","contents":[{"value":null,"param_spec":{"name":"pname","descr":null,"type":"gint","is_param":true,"nullok":true}}]}}]}</expected>
+ <expected>{"statements":[{"statement":{"sql":"##pname::gint::null","stmt_type":"UNKNOWN","contents":[{"value":null,"param_spec":{"name":"pname","descr":null,"type":"int","is_param":true,"nullok":true}}]}}]}</expected>
</test>
<!-- Extendend param notation, unspec value -->
@@ -45,7 +45,7 @@
<test id="7">
<sql>## /* type:gint */</sql>
- <expected>{"statements":[{"statement":{"sql":"## \/* type:gint *\/","stmt_type":"UNKNOWN","contents":[{"value":null,"param_spec":{"name":null,"descr":null,"type":"gint","is_param":true,"nullok":false}}]}}]}</expected>
+ <expected>{"statements":[{"statement":{"sql":"## \/* type:gint *\/","stmt_type":"UNKNOWN","contents":[{"value":null,"param_spec":{"name":null,"descr":null,"type":"int","is_param":true,"nullok":false}}]}}]}</expected>
</test>
<test id="8">
@@ -97,13 +97,13 @@
<!-- Extendend param notation, with value -->
<test id="17">
<sql>12 /* type:gint name:myparam */</sql>
- <expected>{"statements":[{"statement":{"sql":"12 \/* type:gint name:myparam *\/","stmt_type":"UNKNOWN","contents":[{"value":"12","param_spec":{"name":"myparam","descr":null,"type":"gint","is_param":true,"nullok":false}}]}}]}</expected>
+ <expected>{"statements":[{"statement":{"sql":"12 \/* type:gint name:myparam *\/","stmt_type":"UNKNOWN","contents":[{"value":"12","param_spec":{"name":"myparam","descr":null,"type":"int","is_param":true,"nullok":false}}]}}]}</expected>
</test>
<test id="18">
<sql>'A string' /* name:'A string param' type:'gchararray' */</sql>
- <expected>{"statements":[{"statement":{"sql":"'A string' \/* name:'A string param' type:'gchararray' *\/","stmt_type":"UNKNOWN","contents":[{"value":"'A string'","param_spec":{"name":"A string param","descr":null,"type":"gchararray","is_param":true,"nullok":false}}]}}]}</expected>
+ <expected>{"statements":[{"statement":{"sql":"'A string' \/* name:'A string param' type:'gchararray' *\/","stmt_type":"UNKNOWN","contents":[{"value":"'A string'","param_spec":{"name":"A string param","descr":null,"type":"string","is_param":true,"nullok":false}}]}}]}</expected>
</test>
<!-- multiple parts in single statement -->
@@ -860,7 +860,7 @@
<test id="2229">
<sql>select * from table limit ##limval::gint</sql>
- <expected>{"statements":[{"statement":{"sql":"select * from table limit ##limval::gint","stmt_type":"SELECT","contents":{"distinct":"false","fields":[{"expr":{"value":"*"}}],"from":{"targets":[{"expr":{"value":"table"},"table_name":"table"}]},"limit":{"value":null,"param_spec":{"name":"limval","descr":null,"type":"gint","is_param":true,"nullok":false}}}}}]}</expected>
+ <expected>{"statements":[{"statement":{"sql":"select * from table limit ##limval::gint","stmt_type":"SELECT","contents":{"distinct":"false","fields":[{"expr":{"value":"*"}}],"from":{"targets":[{"expr":{"value":"table"},"table_name":"table"}]},"limit":{"value":null,"param_spec":{"name":"limval","descr":null,"type":"int","is_param":true,"nullok":false}}}}}]}</expected>
</test>
<test id="2230">
Modified: trunk/tests/parser/testvalid.xml
==============================================================================
--- trunk/tests/parser/testvalid.xml (original)
+++ trunk/tests/parser/testvalid.xml Fri Jan 9 20:40:50 2009
@@ -58,26 +58,26 @@
<test id="pre3">
<sql valid="t">SELECT * FROM sales_orga</sql>
<normalized>{"statement":{"sql":"SELECT * FROM sales_orga","stmt_type":"SELECT","contents":{"distinct":"false","fields":[{"expr":{"value":"id_salesrep"},"field_name":"id_salesrep"},{"expr":{"value":"id_role"},"field_name":"id_role"},{"expr":{"value":"note"},"field_name":"note"}],"from":{"targets":[{"expr":{"value":"sales_orga"},"table_name":"sales_orga"}]}}}}</normalized>
- <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"sales_orga","fields":["id_salesrep","id_role","note"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+2","descr":null,"type":"gchararray","is_param":false,"nullok":true}}]]}}}</insert>
+ <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"sales_orga","fields":["id_salesrep","id_role","note"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+2","descr":null,"type":"string","is_param":false,"nullok":true}}]]}}}</insert>
<update/>
<delete/>
</test>
<test id="0">
<sql valid="t">SELECT id, name FROM customers</sql>
- <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["id","name"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"gchararray","is_param":false,"nullok":false}}]]}}}</insert>
- <update>{"statement":{"sql":null,"stmt_type":"UPDATE","contents":{"table":"customers","fields":["id","name"],"expressions":[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"gchararray","is_param":false,"nullok":false}}],"condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-0","descr":null,"type":"gint","is_param":false,"nullok":false}}}}}}}</update>
- <delete>{"statement":{"sql":null,"stmt_type":"DELETE","contents":{"table":"customers","condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-0","descr":null,"type":"gint","is_param":false,"nullok":false}}}}}}}</delete>
+ <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["id","name"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"string","is_param":false,"nullok":false}}]]}}}</insert>
+ <update>{"statement":{"sql":null,"stmt_type":"UPDATE","contents":{"table":"customers","fields":["id","name"],"expressions":[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"string","is_param":false,"nullok":false}}],"condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-0","descr":null,"type":"int","is_param":false,"nullok":false}}}}}}}</update>
+ <delete>{"statement":{"sql":null,"stmt_type":"DELETE","contents":{"table":"customers","condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-0","descr":null,"type":"int","is_param":false,"nullok":false}}}}}}}</delete>
</test>
<test id="0.1">
<sql valid="t">SELECT id, 3.14, name FROM customers</sql>
- <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["id","name"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+2","descr":null,"type":"gchararray","is_param":false,"nullok":false}}]]}}}</insert>
+ <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["id","name"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+2","descr":null,"type":"string","is_param":false,"nullok":false}}]]}}}</insert>
</test>
<test id="0.2">
<sql valid="t">SELECT id, 3.14, name, id FROM customers</sql>
- <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["id","name"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+2","descr":null,"type":"gchararray","is_param":false,"nullok":false}}]]}}}</insert>
+ <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["id","name"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+2","descr":null,"type":"string","is_param":false,"nullok":false}}]]}}}</insert>
</test>
<test id="0.3">
@@ -99,15 +99,15 @@
<test id="N1">
<sql valid="t">SELECT name, *, city FROM customers</sql>
<normalized>{"statement":{"sql":"SELECT name, *, city FROM customers","stmt_type":"SELECT","contents":{"distinct":"false","fields":[{"expr":{"value":"name"},"field_name":"name"},{"expr":{"value":"id"},"field_name":"id"},{"expr":{"value":"name"},"field_name":"name"},{"expr":{"value":"default_served_by"},"field_name":"default_served_by"},{"expr":{"value":"country"},"field_name":"country"},{"expr":{"value":"city"},"field_name":"city"},{"expr":{"value":"city"},"field_name":"city"}],"from":{"targets":[{"expr":{"value":"customers"},"table_name":"customers"}]}}}}</normalized>
- <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["name","id","default_served_by","country","city"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gchararray","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"gint","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"gchararray","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"gchararray","is_param":false,"nullok":true}}]]}}}</insert>
- <update>{"statement":{"sql":null,"stmt_type":"UPDATE","contents":{"table":"customers","fields":["name","id","default_served_by","country","city"],"expressions":[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gchararray","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"gint","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"gchararray","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"gchararray","is_param":false,"nullok":true}}],"condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"gint","is_param":false,"nullok":false}}}}}}}</update>
- <delete>{"statement":{"sql":null,"stmt_type":"DELETE","contents":{"table":"customers","condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"gint","is_param":false,"nullok":false}}}}}}}</delete>
+ <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["name","id","default_served_by","country","city"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"string","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"int","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"string","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"string","is_param":false,"nullok":true}}]]}}}</insert>
+ <update>{"statement":{"sql":null,"stmt_type":"UPDATE","contents":{"table":"customers","fields":["name","id","default_served_by","country","city"],"expressions":[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"string","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"int","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"string","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"string","is_param":false,"nullok":true}}],"condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"int","is_param":false,"nullok":false}}}}}}}</update>
+ <delete>{"statement":{"sql":null,"stmt_type":"DELETE","contents":{"table":"customers","condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"int","is_param":false,"nullok":false}}}}}}}</delete>
</test>
<test id="N2">
<sql valid="t">SELECT s.* FROM sales_orga as s</sql>
<normalized>{"statement":{"sql":"SELECT s.* FROM sales_orga as s","stmt_type":"SELECT","contents":{"distinct":"false","fields":[{"expr":{"value":"s.id_salesrep"},"field_name":"id_salesrep","table_name":"s"},{"expr":{"value":"s.id_role"},"field_name":"id_role","table_name":"s"},{"expr":{"value":"s.note"},"field_name":"note","table_name":"s"}],"from":{"targets":[{"expr":{"value":"sales_orga"},"table_name":"sales_orga","as":"s"}]}}}}</normalized>
- <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"sales_orga","fields":["id_salesrep","id_role","note"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+2","descr":null,"type":"gchararray","is_param":false,"nullok":true}}]]}}}</insert>
+ <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"sales_orga","fields":["id_salesrep","id_role","note"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+2","descr":null,"type":"string","is_param":false,"nullok":true}}]]}}}</insert>
<update></update>
<delete></delete>
<update needpk="f"></update>
@@ -117,25 +117,25 @@
<test id="N3">
<sql valid="t">SELECT "name", c.*, "id" FROM customers as c</sql>
<normalized>{"statement":{"sql":"SELECT \"name\", c.*, \"id\" FROM customers as c","stmt_type":"SELECT","contents":{"distinct":"false","fields":[{"expr":{"value":"\"name\""},"field_name":"\"name\""},{"expr":{"value":"c.id"},"field_name":"id","table_name":"c"},{"expr":{"value":"c.name"},"field_name":"name","table_name":"c"},{"expr":{"value":"c.default_served_by"},"field_name":"default_served_by","table_name":"c"},{"expr":{"value":"c.country"},"field_name":"country","table_name":"c"},{"expr":{"value":"c.city"},"field_name":"city","table_name":"c"},{"expr":{"value":"\"id\""},"field_name":"\"id\""}],"from":{"targets":[{"expr":{"value":"customers"},"table_name":"customers","as":"c"}]}}}}</normalized>
- <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["\"name\"","id","default_served_by","country","city"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gchararray","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"gint","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"gchararray","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"gchararray","is_param":false,"nullok":true}}]]}}}</insert>
- <update>{"statement":{"sql":null,"stmt_type":"UPDATE","contents":{"table":"customers","fields":["\"name\"","id","default_served_by","country","city"],"expressions":[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gchararray","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"gint","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"gchararray","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"gchararray","is_param":false,"nullok":true}}],"condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"gint","is_param":false,"nullok":false}}}}}}}</update>
- <delete>{"statement":{"sql":null,"stmt_type":"DELETE","contents":{"table":"customers","condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"gint","is_param":false,"nullok":false}}}}}}}</delete>
+ <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["\"name\"","id","default_served_by","country","city"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"string","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"int","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"string","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"string","is_param":false,"nullok":true}}]]}}}</insert>
+ <update>{"statement":{"sql":null,"stmt_type":"UPDATE","contents":{"table":"customers","fields":["\"name\"","id","default_served_by","country","city"],"expressions":[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"string","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"int","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"string","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"string","is_param":false,"nullok":true}}],"condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"int","is_param":false,"nullok":false}}}}}}}</update>
+ <delete>{"statement":{"sql":null,"stmt_type":"DELETE","contents":{"table":"customers","condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"int","is_param":false,"nullok":false}}}}}}}</delete>
</test>
<test id="N4">
<sql valid="t">SELECT "name", "customers".*, "id" FROM customers as c</sql>
<normalized>{"statement":{"sql":"SELECT \"name\", \"customers\".*, \"id\" FROM customers as c","stmt_type":"SELECT","contents":{"distinct":"false","fields":[{"expr":{"value":"\"name\""},"field_name":"\"name\""},{"expr":{"value":"\"customers\".id"},"field_name":"id","table_name":"\"customers\""},{"expr":{"value":"\"customers\".name"},"field_name":"name","table_name":"\"customers\""},{"expr":{"value":"\"customers\".default_served_by"},"field_name":"default_served_by","table_name":"\"customers\""},{"expr":{"value":"\"customers\".country"},"field_name":"country","table_name":"\"customers\""},{"expr":{"value":"\"customers\".city"},"field_name":"city","table_name":"\"customers\""},{"expr":{"value":"\"id\""},"field_name":"\"id\""}],"from":{"targets":[{"expr":{"value":"customers"},"table_name":"customers","as":"c"}]}}}}</normalized>
- <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["\"name\"","id","default_served_by","country","city"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gchararray","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"gint","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"gchararray","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"gchararray","is_param":false,"nullok":true}}]]}}}</insert>
- <update>{"statement":{"sql":null,"stmt_type":"UPDATE","contents":{"table":"customers","fields":["\"name\"","id","default_served_by","country","city"],"expressions":[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gchararray","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"gint","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"gchararray","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"gchararray","is_param":false,"nullok":true}}],"condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"gint","is_param":false,"nullok":false}}}}}}}</update>
- <delete>{"statement":{"sql":null,"stmt_type":"DELETE","contents":{"table":"customers","condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"gint","is_param":false,"nullok":false}}}}}}}</delete>
+ <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["\"name\"","id","default_served_by","country","city"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"string","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"int","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"string","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"string","is_param":false,"nullok":true}}]]}}}</insert>
+ <update>{"statement":{"sql":null,"stmt_type":"UPDATE","contents":{"table":"customers","fields":["\"name\"","id","default_served_by","country","city"],"expressions":[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"string","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"int","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"string","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"string","is_param":false,"nullok":true}}],"condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"int","is_param":false,"nullok":false}}}}}}}</update>
+ <delete>{"statement":{"sql":null,"stmt_type":"DELETE","contents":{"table":"customers","condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"int","is_param":false,"nullok":false}}}}}}}</delete>
</test>
<test id="N5">
<sql valid="t">SELECT NaMe, c."*", ID FROM customers as c</sql>
<normalized>{"statement":{"sql":"SELECT NaMe, c.\"*\", ID FROM customers as c","stmt_type":"SELECT","contents":{"distinct":"false","fields":[{"expr":{"value":"NaMe"},"field_name":"NaMe"},{"expr":{"value":"c.id"},"field_name":"id","table_name":"c"},{"expr":{"value":"c.name"},"field_name":"name","table_name":"c"},{"expr":{"value":"c.default_served_by"},"field_name":"default_served_by","table_name":"c"},{"expr":{"value":"c.country"},"field_name":"country","table_name":"c"},{"expr":{"value":"c.city"},"field_name":"city","table_name":"c"},{"expr":{"value":"ID"},"field_name":"ID"}],"from":{"targets":[{"expr":{"value":"customers"},"table_name":"customers","as":"c"}]}}}}</normalized>
- <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["NaMe","id","default_served_by","country","city"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gchararray","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"gint","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"gchararray","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"gchararray","is_param":false,"nullok":true}}]]}}}</insert>
- <update>{"statement":{"sql":null,"stmt_type":"UPDATE","contents":{"table":"customers","fields":["NaMe","id","default_served_by","country","city"],"expressions":[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"gchararray","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"gint","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"gint","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"gchararray","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"gchararray","is_param":false,"nullok":true}}],"condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"gint","is_param":false,"nullok":false}}}}}}}</update>
- <delete>{"statement":{"sql":null,"stmt_type":"DELETE","contents":{"table":"customers","condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"gint","is_param":false,"nullok":false}}}}}}}</delete>
+ <insert>{"statement":{"sql":null,"stmt_type":"INSERT","contents":{"table":"customers","fields":["NaMe","id","default_served_by","country","city"],"values":[[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"string","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"int","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"string","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"string","is_param":false,"nullok":true}}]]}}}</insert>
+ <update>{"statement":{"sql":null,"stmt_type":"UPDATE","contents":{"table":"customers","fields":["NaMe","id","default_served_by","country","city"],"expressions":[{"value":null,"param_spec":{"name":"+0","descr":null,"type":"string","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+1","descr":null,"type":"int","is_param":false,"nullok":false}},{"value":null,"param_spec":{"name":"+3","descr":null,"type":"int","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+4","descr":null,"type":"string","is_param":false,"nullok":true}},{"value":null,"param_spec":{"name":"+5","descr":null,"type":"string","is_param":false,"nullok":true}}],"condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"int","is_param":false,"nullok":false}}}}}}}</update>
+ <delete>{"statement":{"sql":null,"stmt_type":"DELETE","contents":{"table":"customers","condition":{"operation":{"operator":"=","operand0":{"value":"id"},"operand1":{"value":null,"param_spec":{"name":"-1","descr":null,"type":"int","is_param":false,"nullok":false}}}}}}}</delete>
</test>
</testdata>
Modified: trunk/tests/providers/DATA_actor.xml
==============================================================================
--- trunk/tests/providers/DATA_actor.xml (original)
+++ trunk/tests/providers/DATA_actor.xml Fri Jan 9 20:40:50 2009
@@ -1,9 +1,9 @@
<?xml version="1.0"?>
<gda_array id="EXPORT" name="Exported Data">
- <gda_array_field id="FI0" name="actor_id" title="actor_id" gdatype="gint" nullok="TRUE"/>
- <gda_array_field id="FI1" name="first_name" title="first_name" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI2" name="last_name" title="last_name" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI3" name="last_update" title="last_update" gdatype="GdaTimestamp" nullok="TRUE"/>
+ <gda_array_field id="FI0" name="actor_id" title="actor_id" gdatype="int" nullok="TRUE"/>
+ <gda_array_field id="FI1" name="first_name" title="first_name" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI2" name="last_name" title="last_name" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI3" name="last_update" title="last_update" gdatype="timestamp" nullok="TRUE"/>
<gda_array_data>
<gda_array_row>
<gda_value>1</gda_value>
Modified: trunk/tests/providers/DATA_film.xml
==============================================================================
--- trunk/tests/providers/DATA_film.xml (original)
+++ trunk/tests/providers/DATA_film.xml Fri Jan 9 20:40:50 2009
@@ -1,18 +1,18 @@
<?xml version="1.0"?>
<gda_array id="EXPORT" name="Exported Data">
- <gda_array_field id="FI0" name="film_id" title="film_id" gdatype="gint" nullok="TRUE"/>
- <gda_array_field id="FI1" name="title" title="title" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI2" name="description" title="description" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI3" name="release_year" title="release_year" gdatype="gint" nullok="TRUE"/>
+ <gda_array_field id="FI0" name="film_id" title="film_id" gdatype="int" nullok="TRUE"/>
+ <gda_array_field id="FI1" name="title" title="title" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI2" name="description" title="description" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI3" name="release_year" title="release_year" gdatype="int" nullok="TRUE"/>
<gda_array_field id="FI4" name="language_id" title="language_id" gdatype="GdaShort" nullok="TRUE"/>
<gda_array_field id="FI5" name="original_language_id" title="original_language_id" gdatype="GdaShort" nullok="TRUE"/>
<gda_array_field id="FI6" name="rental_duration" title="rental_duration" gdatype="GdaShort" nullok="TRUE"/>
<gda_array_field id="FI7" name="rental_rate" title="rental_rate" gdatype="GdaNumeric" nullok="TRUE"/>
<gda_array_field id="FI8" name="length" title="length" gdatype="GdaShort" nullok="TRUE"/>
<gda_array_field id="FI9" name="replacement_cost" title="replacement_cost" gdatype="GdaNumeric" nullok="TRUE"/>
- <gda_array_field id="FI10" name="rating" title="rating" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI11" name="last_update" title="last_update" gdatype="GdaTimestamp" nullok="TRUE"/>
- <gda_array_field id="FI12" name="special_features" title="special_features" gdatype="gchararray" nullok="TRUE"/>
+ <gda_array_field id="FI10" name="rating" title="rating" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI11" name="last_update" title="last_update" gdatype="timestamp" nullok="TRUE"/>
+ <gda_array_field id="FI12" name="special_features" title="special_features" gdatype="string" nullok="TRUE"/>
<gda_array_data>
<gda_array_row>
<gda_value>1</gda_value>
Modified: trunk/tests/providers/DATA_film_actor.xml
==============================================================================
--- trunk/tests/providers/DATA_film_actor.xml (original)
+++ trunk/tests/providers/DATA_film_actor.xml Fri Jan 9 20:40:50 2009
@@ -2,7 +2,7 @@
<gda_array id="EXPORT" name="Exported Data">
<gda_array_field id="FI0" name="actor_id" title="actor_id" gdatype="GdaShort" nullok="TRUE"/>
<gda_array_field id="FI1" name="film_id" title="film_id" gdatype="GdaShort" nullok="TRUE"/>
- <gda_array_field id="FI2" name="last_update" title="last_update" gdatype="GdaTimestamp" nullok="TRUE"/>
+ <gda_array_field id="FI2" name="last_update" title="last_update" gdatype="timestamp" nullok="TRUE"/>
<gda_array_data>
<gda_array_row>
<gda_value>1</gda_value>
Modified: trunk/tests/providers/DATA_language.xml
==============================================================================
--- trunk/tests/providers/DATA_language.xml (original)
+++ trunk/tests/providers/DATA_language.xml Fri Jan 9 20:40:50 2009
@@ -1,8 +1,8 @@
<?xml version="1.0"?>
<gda_array id="EXPORT" name="Exported Data">
- <gda_array_field id="FI0" name="language_id" title="language_id" gdatype="gint" nullok="TRUE"/>
- <gda_array_field id="FI1" name="name" title="name" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI2" name="last_update" title="last_update" gdatype="GdaTimestamp" nullok="TRUE"/>
+ <gda_array_field id="FI0" name="language_id" title="language_id" gdatype="int" nullok="TRUE"/>
+ <gda_array_field id="FI1" name="name" title="name" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI2" name="last_update" title="last_update" gdatype="timestamp" nullok="TRUE"/>
<gda_array_data>
<gda_array_row>
<gda_value>1</gda_value>
Modified: trunk/tests/providers/TYPES_SCHEMA_Mdb.xml
==============================================================================
--- trunk/tests/providers/TYPES_SCHEMA_Mdb.xml (original)
+++ trunk/tests/providers/TYPES_SCHEMA_Mdb.xml Fri Jan 9 20:40:50 2009
@@ -1,10 +1,10 @@
<?xml version="1.0"?>
<gda_array id="EXPORT" name="Exported Data">
- <gda_array_field id="FI0" name="Type" title="Type" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI1" name="Owner" title="Owner" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI2" name="Comments" title="Comments" gdatype="gchararray" nullok="TRUE"/>
+ <gda_array_field id="FI0" name="Type" title="Type" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI1" name="Owner" title="Owner" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI2" name="Comments" title="Comments" gdatype="string" nullok="TRUE"/>
<gda_array_field id="FI3" name="GDA type" title="GDA type" gdatype="gulong" nullok="TRUE"/>
- <gda_array_field id="FI4" name="Synonyms" title="Synonyms" gdatype="gchararray" nullok="TRUE"/>
+ <gda_array_field id="FI4" name="Synonyms" title="Synonyms" gdatype="string" nullok="TRUE"/>
<gda_array_data>
<gda_array_row>
<gda_value>boolean</gda_value>
Modified: trunk/tests/providers/TYPES_SCHEMA_MySQL.xml
==============================================================================
--- trunk/tests/providers/TYPES_SCHEMA_MySQL.xml (original)
+++ trunk/tests/providers/TYPES_SCHEMA_MySQL.xml Fri Jan 9 20:40:50 2009
@@ -1,10 +1,10 @@
<?xml version="1.0"?>
<gda_array id="EXPORT" name="Exported Data">
- <gda_array_field id="FI0" name="Type" title="Type" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI1" name="Owner" title="Owner" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI2" name="Comments" title="Comments" gdatype="gchararray" nullok="TRUE"/>
+ <gda_array_field id="FI0" name="Type" title="Type" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI1" name="Owner" title="Owner" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI2" name="Comments" title="Comments" gdatype="string" nullok="TRUE"/>
<gda_array_field id="FI3" name="GDA type" title="GDA type" gdatype="gulong" nullok="TRUE"/>
- <gda_array_field id="FI4" name="Synonyms" title="Synonyms" gdatype="gchararray" nullok="TRUE"/>
+ <gda_array_field id="FI4" name="Synonyms" title="Synonyms" gdatype="string" nullok="TRUE"/>
<gda_array_data>
<gda_array_row>
<gda_value>bool</gda_value>
Modified: trunk/tests/providers/TYPES_SCHEMA_Oracle.xml
==============================================================================
--- trunk/tests/providers/TYPES_SCHEMA_Oracle.xml (original)
+++ trunk/tests/providers/TYPES_SCHEMA_Oracle.xml Fri Jan 9 20:40:50 2009
@@ -1,10 +1,10 @@
<?xml version="1.0"?>
<gda_array id="EXPORT" name="Exported Data">
- <gda_array_field id="FI0" name="Type" title="Type" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI1" name="Owner" title="Owner" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI2" name="Comments" title="Comments" gdatype="gchararray" nullok="TRUE"/>
+ <gda_array_field id="FI0" name="Type" title="Type" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI1" name="Owner" title="Owner" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI2" name="Comments" title="Comments" gdatype="string" nullok="TRUE"/>
<gda_array_field id="FI3" name="GDA type" title="GDA type" gdatype="gulong" nullok="TRUE"/>
- <gda_array_field id="FI4" name="Synonyms" title="Synonyms" gdatype="gchararray" nullok="TRUE"/>
+ <gda_array_field id="FI4" name="Synonyms" title="Synonyms" gdatype="string" nullok="TRUE"/>
<gda_array_data>
<gda_array_row>
<gda_value>BFILE</gda_value>
Modified: trunk/tests/providers/TYPES_SCHEMA_PostgreSQL.xml
==============================================================================
--- trunk/tests/providers/TYPES_SCHEMA_PostgreSQL.xml (original)
+++ trunk/tests/providers/TYPES_SCHEMA_PostgreSQL.xml Fri Jan 9 20:40:50 2009
@@ -1,8 +1,8 @@
<?xml version="1.0"?>
<gda_array id="EXPORT" name="Exported Data">
- <gda_array_field id="FI0" name="short_type_name" title="short_type_name" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI1" name="gtype" title="gtype" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI2" name="comments" title="comments" gdatype="gchararray" nullok="TRUE"/>
+ <gda_array_field id="FI0" name="short_type_name" title="short_type_name" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI1" name="gtype" title="gtype" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI2" name="comments" title="comments" gdatype="string" nullok="TRUE"/>
<gda_array_field id="FI3" name="synonyms" title="synonyms" gdatype="null" nullok="TRUE"/>
<gda_array_data>
<gda_array_row>
Modified: trunk/tests/providers/TYPES_SCHEMA_SQLite.xml
==============================================================================
--- trunk/tests/providers/TYPES_SCHEMA_SQLite.xml (original)
+++ trunk/tests/providers/TYPES_SCHEMA_SQLite.xml Fri Jan 9 20:40:50 2009
@@ -1,9 +1,9 @@
<?xml version="1.0"?>
<gda_array id="EXPORT" name="Exported Data">
- <gda_array_field id="FI0" name="short_type_name" title="short_type_name" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI1" name="gtype" title="gtype" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI2" name="comments" title="comments" gdatype="gchararray" nullok="TRUE"/>
- <gda_array_field id="FI3" name="synonyms" title="synonyms" gdatype="gchararray" nullok="TRUE"/>
+ <gda_array_field id="FI0" name="short_type_name" title="short_type_name" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI1" name="gtype" title="gtype" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI2" name="comments" title="comments" gdatype="string" nullok="TRUE"/>
+ <gda_array_field id="FI3" name="synonyms" title="synonyms" gdatype="string" nullok="TRUE"/>
<gda_array_data>
<gda_array_row>
<gda_value>blob</gda_value>
Modified: trunk/tools/Makefile.am
==============================================================================
--- trunk/tools/Makefile.am (original)
+++ trunk/tools/Makefile.am Fri Jan 9 20:40:50 2009
@@ -90,3 +90,51 @@
EXTRA_DIST = gda-sql.ico \
$(webdata_DATA)
+
+mans = \
+ gda-sql-4.0.1
+
+man_MANS = \
+ $(mans)
+
+install-data-hook:
+if DEFAULT_BINARY
+ @list='$(mans)'; \
+ for i in $$list; do \
+ s=`echo $$i | sed -e 's/.*\\(.\\)$$/\1/'`; \
+ n=`echo $$i | sed -e 's/-[^-]*$$//'`; \
+ f="$$n.$$s"; \
+ echo "cd $(DESTDIR)$(mandir)/man$$s"; \
+ cd $(DESTDIR)$(mandir)/man$$s; \
+ echo "rm -f $$f"; \
+ rm -f $$f; \
+ echo "ln -s $$i $$f"; \
+ ln -s $$i $$f; \
+ done
+endif
+
+uninstall-local:
+if DEFAULT_BINARY
+ @list='$(mans)'; \
+ for i in $$list; do \
+ s=`echo $$i | sed -e 's/.*\\(.\\)$$/\1/'`; \
+ n=`echo $$i | sed -e 's/-[^-]*$$//'`; \
+ f="$$n.$$s"; \
+ echo " rm -f $(DESTDIR)$(mandir)/man$$s/$$f"; \
+ rm -f $(DESTDIR)$(mandir)/man$$s/$$f; \
+ done
+endif
+
+install-exec-hook:
+if DEFAULT_BINARY
+ cd $(DESTDIR)$(bindir) \
+ && rm -f gda-list-config$(EXEEXT) gda-sql$(EXEEXT) gda-list-server-op$(EXEEXT) \
+ && $(LN_S) gda-list-config-4.0$(EXEEXT) gda-list-config$(EXEEXT) \
+ && $(LN_S) gda-sql-4.0$(EXEEXT) gda-sql$(EXEEXT) \
+ && $(LN_S) gda-list-server-op-4.0$(EXEEXT) gda-list-server-op$(EXEEXT)
+endif
+
+uninstall-local:
+if DEFAULT_BINARY
+ rm -f $(DESTDIR)$(bindir)/gda-list-config$(EXEEXT) $(DESTDIR)$(bindir)/gda-sql$(EXEEXT) $(DESTDIR)$(bindir)/gda-list-server-op$(EXEEXT)
+endif
\ No newline at end of file
Added: trunk/tools/gda-sql.1.in
==============================================================================
--- (empty file)
+++ trunk/tools/gda-sql.1.in Fri Jan 9 20:40:50 2009
@@ -0,0 +1,294 @@
+.TH gda-sql 1 "January 09 2009" "Version @PACKAGE_VERSION@" "LIBGDA Manual Pages"
+
+.SH NAME
+gda-sql - an SQL console based on Libgda
+
+.SH SYNOPSIS
+.B gda-sql
+[\-\-help] [-v] [\-\-version]
+[\-p] [\-\-no\-password\-ask]
+[\-o] [\-\-output\-file \fI<filename>\fP]
+[\-C] [\-\-command]
+[\-f] [\-\-commands\-file \fI<filename>\fP]
+[\-i] [\-\-interractive]
+[\-l] [\-\-list\-dsn]
+[\-L] [\-\-list\-providers]
+[\-s] [\-\-http\-port \fI<port>\fP]
+[\-t] [\-\-http\-token \fI<token phrase>\fP] ...
+
+.SH DESCRIPTION
+.PP
+gda-sql is an SQL console based on the \fILibgda\fP library.
+.PP
+It enables you to type in queries interactively, issue them to be executed by a connection, and see the
+query results.
+.PP
+Several connections can be opened at the same time, allowing you to switch the active connection to any
+opened connection. When starting, gda-sql opens a connection for each connection specified on the command
+line (plus optionnally one corresponding to the \fBGDA_SQL_CNC\fP environment variable). The prompt
+indicates the current connection used when executing commands.
+
+.PP
+Alternatively, input can be from a file.
+In addition, it provides a number of meta-commands and various shell-like features to facilitate writing
+scripts and automating a wide variety of tasks.
+
+
+
+.SH OPTIONS
+.l
+gda-sql accepts the following options:
+.TP 8
+.B \-\-help
+Show command\-line options.
+.TP 8
+.B \-p, \-\-no\-password\-ask
+Don't ask for a password when it is empty.
+.TP 8
+.B \-o, \-\-output\-file \fI<filename>\fP
+Specifies a file to which outputs are redirected.
+.TP 8
+.B \-C, \-\-command
+Run only single command (SQL or internal) and exit.
+.TP 8
+.B \-f, \-\-commands\-file \fI<filename>\fP
+Execute commands from \fI<filename>\fP, then exit (except if \-i specified).
+.TP 8
+.B \-i, \-\-interractive
+Keep the console opened after executing a file (used with the \-f option).
+.TP 8
+.B \-l, \-\-list\-dsn
+List configured data sources and exit.
+.TP 8
+.B \-l, \-\-list\-providers
+List installed database providers and exit
+.TP 8
+.B \-s, \-\-http\-port \fI<port>\fP
+Starts the embedded HTTP server on port \fI<port>\fP
+.TP 8
+.B \-t, \-\-http\-token \fI<token phrase>\fP
+Requires HTTP clients to authenticate by providing the \fI<token phrase>\fP
+(empty phrase by default)
+
+
+
+.SH ENVIRONMENT
+gda-sql respects a number of environment variables.
+.PP
+.TP 8
+.B GDA_SQL_CNC
+to define a connection to systematically be opened when the program starts.
+.TP 8
+.B PAGER
+to define a text pager program to use (by default determined by the system).
+.TP 8
+.B GDA_NO_PAGER
+to specify that no text pager should be used.
+.TP 8
+.B GDA_SQL_EDITOR EDITOR VISUAL
+to define a text editor to be used (variables are examined in this order).
+.TP 8
+.B GDA_SQL_VIEWER_PNG
+to define a PNG viewer.
+.TP 8
+.B GDA_SQL_VIEWER_PDF
+to define a PDF viewer.
+.TP 8
+.B GDA_SQL_HISTFILE
+to define the history file name to use (by default .gdasql_history), set to NO_HISTORY
+to disable history logging.
+
+.TP 0
+gda-sql can be compiled with support for binary relocatibility.
+This will cause data, plug-ins and configuration files to be searched
+relative to the location of the gda-sql executable file.
+
+
+.SH FILES
+gda-sql stores data source definitions (DSN) in Libgda defined files
+(\fB$HOME\fP/.libgda/config and @gdasysconfdir@/libgda- GDA_ABI_VERSION@/config
+where ${prefix} is typically /usr).
+
+For each connection defined by a DSN, the meta data is stored in a
+\fB$HOME\fP/.libgda/gda-sql-<DSN>.db file.
+
+
+.SH SQL commands
+You can run any SQL understood by the database engine of the current connection.
+Additionnally SQL statement can contain variables expressed as \fI##<name>::<type>\fP
+where \fI<name>\fP is the variable's name and \fI<type>\fP is its declared type (which
+can be "int", "string", "boolean", "time", "date", "timestamp" (and other types defined
+by GLib's syntax).
+
+Use the \fI.set\fP internal command to set variable's values.
+
+.SH Internal commands
+In addition to SQL commands, gda-sql supports internal commands which differ from SQL
+commands because they start with the "." or "\\" character. These commands are:
+
+.IP \fB.?\fP
+Lists all internal commands
+.IP \fB.bind\fP
+Bind two or more connections into a single new one (allowing SQL commands to be executed across multiple
+connections). \fB.bind <CNC_NAME> <CNC_NAME1> <CNC_NAME2> [<CNC_NAME> ...]\fP creates a new connection named
+\fI<CNC_NAME>\fP which binds the tables of the \fI<CNC_NAME1>\fP, \fI<CNC_NAME2>\fP and any other
+connection specified.
+.IP \fB.c\fP
+Opens a connection or sets the current connection.
+
+\fB.c <CNC_NAME> <DSN_NAME> [USER [PASSWORD]]\fP opens a connection internally known as \fI<CNC_NAME>\fP,
+using the specified DSN.
+
+\fB.c <CNC_NAME> <CNC_DEFINITION> [USER [PASSWORD]] \fP opens a connection internally known as \fI<CNC_NAME>\fP,
+using a connection specified by \fI<CNC_DEFINITION>\fP which is similar to the \fI<DSN_DEFINITION>\fP parameter
+of the \fB.lc\fP command.
+
+\fB.c <CNC_NAME>\fP sets the current connection to the connection known as \fI<CNC_NAME>\fP.
+
+\fB.c ~\fP or \fB.c ~<CNC_NAME>\fP set the current connection to the meta data corresponding to the
+current connection (for the first notation) or to the meta data corresponding to the \fI<CNC_NAME>\fP
+connection.
+.IP \fB.close\fP
+Closes a connection. Full syntax is: \fB.close <CNC_NAME>\fP.
+.IP \fB.cd\fP
+Changes the current working directory. Full syntax is: \fB.cd <DIR_NAME>\fP.
+.IP \fB.copyright\fP
+Displays copyright information.
+.IP \fB.d\fP
+Lists all database objects if no argument is provided. \fB.d <OBJ_NAME>\fP gives details about
+the specified object and \fB.d <SCHEMA>.*\fP lists all objects in specified schema.
+.IP \fB.dn\fP
+Lists all schemas if no argument is provided. \fB.d <SCHEMA_NAME>\fP lists specified schema.
+.IP \fB.dt\fP
+Lists all tables if no argument is provided. \fB.d <TABLE_NAME>\fP lists specified table.
+.IP \fB.dv\fP
+Lists all views if no argument is provided. \fB.d <VIEW_NAME>\fP lists specified view.
+.IP \fB.e\fP
+Edits the query buffer with external editor, if no argument is provided. \fB.e <FILE_NAME>\fP
+edits the specified file name. The external editor can be specified using environment variables.
+.IP \fB.echo\fP
+Sends output to stdout, full command is: \fB.echo [<TEXT>]\fP.
+.IP \fB.export\fP
+Exports internal parameter or table's value to the FILE file. Internal parameters are named values
+used when SQL statement containing variables are executed.
+
+\fB.export <NAME> <FILE_NAME>\fP exports the contents of the \fI<NAME>\fP parameter to the specified
+file.
+
+\fB.export <TABLE> <COLUMN> <ROW_CONDITION> <FILE_NAME>\fP exports the value of the \fI<TABLE>\fP
+table, column \fI<COLUMN>\fP for the row selected by \fI<ROW_CONDITION>\fP to the specified
+file. This is most usefull to export BLOBs.
+.IP \fB.g\fP
+Executes the contents of the query buffer, if no parameter is provided. \fB.g <QUERY_BUFFER_NAME>\fP
+Executes the contents of the specified query buffer. A named query buffer is created using the
+\fB.qs\fP command.
+.IP \fB.graph\fP
+Creates a graph of tables showing their relations (based on foreign key constraints). If no argument
+is provided, the graph lists all tables. \fB.graph <TABLE_NAME> [<TABLE_NAME>...]\fP creates a graph
+listing the specified tables.
+
+The generated graph is created as the "gdaph.dot" file. If the \fBGDA_SQL_VIEWER_PNG\fP or \fBGDA_SQL_VIEWER_PDF\fP
+environment variables are set and if the "dot" program (from GraphViz) is found, then the graph is displayed (if
+a display is available).
+.IP \fB.H\fP
+Set output format. Full syntax is: \fB.H [HTML|XML|CSV|DEFAULT]\fP.
+.IP \fB.http\fP
+Starts/stops the embedded HTTP server. Full syntax is \fB.http [<port> [<authentication_token>]]\fP, where
+\fI<authentication_token>\fP is an optional token phrase which HTTP clients are required to send to authenticate.
+.IP \fB.i\fP
+Executes commands from file the specified file: \fB.i <FILE_NAME>\fP.
+.IP \fB.l\fP
+Lists all data sources if no argument is provided. \fB.l <DSN>\fP lists information about
+the specified DSN.
+.IP \fB.lp\fP
+Lists all available database providers if no argument is provided. \fB.lp <provider>\fP lists
+information about the specified provider.
+.IP \fB.lc\fP
+Declares a DSN. Full syntax is: \fB.lc <DSN_NAME> <DSN_DEFINITION> [<DESCRIPTION>]\fP.
+The \fI<DSN_DEFINITION>\fP format is: \fI<provider>://[<username>[:<password>] ]<connection_params>\fP
+where \fI<connection_params>\fP is a semi-colon (";") separated list of <key>=<value> pairs
+where \fI<key>\fP is defined when using \fB.lp <provider>\fP (if \fI<value>\fP contains
+non alphanumeric characters, they should be represented as specified by the RFC 1738).
+
+If a DSN with a similar name already exists, it is first removed.
+
+For example: ".lc mydsn PostgreSQL://HOST=moon;DB_NAME=mydb".
+.IP \fB.lr\fP
+Removes a DSN declaration. Full syntax is: \fB.lc <DSN_NAME>\fP.
+.IP \fB.meta\fP
+Updates the current connection's meta data (use this command after having modified the
+database's schema).
+.IP \fB.o\fP
+Sends output to a file or |pipe. Full syntax is: \fB.o <FILE_NAME>\fP or \fB.o |<COMMAND>\fP.
+.IP \fB.q\fP
+Quits the application.
+.IP \fB.qecho\fP
+Sends output to the output stream (stdout). Full syntax is: \fB.qecho <TEXT>\fP.
+.IP \fB.qa\fP
+Lists all saved query buffers in dictionary.
+.IP \fB.qd\fP
+Deletes a query buffer from the dictionary. Full syntax is: \fB.qd <QUERY_BUFFER_NAME>\fP
+.IP \fB.ql\fP
+Loads query buffer from dictionary into the current query buffer.
+Full syntax is: \fB.ql <QUERY_BUFFER_NAME>\fP.
+.IP \fB.qp\fP
+Shows the contents of the current query buffer.
+.IP \fB.qr\fP
+Resets the query buffer to empty if no argument is provided. \fB.qr <FILE _NAME>\fP loads
+the specified file into the query buffer.
+.IP \fB.qs\fP
+Saves query buffer to dictionary, full syntax is \fB.qs <QUERY_BUFFER_NAME>\fP. This creates
+a new query buffer with the specified name in the dictionary, containing the current query
+buffer.
+.IP \fB.qw\fP
+Writes the query buffer to the specified file, full syntax is \fB.qw <FILE_NAME>\fP.
+.IP \fB.s\fP
+Show commands history. \fB.s <FILE_NAME>\fP saves command history to specified file.
+.IP \fB.set\fP
+Sets, shows or lists internal parameters.
+
+\fB.set\fP lists all the defined internal parameters.
+
+\fB.set <NAME> <VALUE>\fP (re)defines the internal parameter named \fI<NAME>\fP to the
+specified value (which can be the \fI_null_\fP literal to set it to NULL).
+
+\fB.set <NAME>\fP shows the contents of the internal parameter named \fI<NAME>\fP.
+.IP \fB.setex\fP
+Set internal parameter as the contents of the FILE file or from an existing table's
+value.
+
+\fB.setex <NAME> <FILE_NAME>\fP (re)defines the the internal parameter named \fI<NAME>\fP
+with the contents of the specified file name.
+
+\fB.setex <NAME> <TABLE> <COLUMN> <ROW_CONDITION>\fP (re)defines the the internal parameter named \fI<NAME>\fP
+with the value of the \fI<TABLE>\fP table, column \fI<COLUMN>\fP for the row selected by \fI<ROW_CONDITION>\fP.This is most usefull to export BLOBs.
+.IP \fB.unset\fP
+Unset (delete) internal parameter.
+
+\fB.unset\fP unsets all the internal parameters.
+
+\fB.unset <NAME>\fP unsets the internal parameter named \fI<NAME>\fP.
+.SH SUGGESTIONS AND BUG REPORTS
+Any bugs found should be reported to the online bug-tracking system
+available on the web at http://bugzilla.gnome.org/. Before reporting
+bugs, please check to see if the bug has already been reported.
+
+When reporting bugs, it is important to include a reliable way to
+reproduce the bug, version number of gda-sql, OS name
+and version, and any relevant hardware specs. If a bug is causing a
+crash, it is very useful if a stack trace can be provided. And of
+course, patches to rectify the bug are even better.
+
+
+.SH OTHER INFO
+Consult the Libgda's home page at http://www.gnome-db.org/.
+
+.SH AUTHORS
+Vivien Malerba (for Libgda's authors, please consult the AUTORS file
+within the Libgda's sources)
+
+
+.SH "SEE ALSO"
+.BR psql (1),
+.BR mysql (1),
+.BR sqlite3 (1)
Modified: trunk/tools/gda-sql.c
==============================================================================
--- trunk/tools/gda-sql.c (original)
+++ trunk/tools/gda-sql.c Fri Jan 9 20:40:50 2009
@@ -54,6 +54,7 @@
#endif
/* options */
+gboolean show_version = FALSE;
gboolean ask_pass = FALSE;
gchar *single_command = NULL;
@@ -72,6 +73,7 @@
#endif
static GOptionEntry entries[] = {
+ { "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, "Show version information and exit", NULL },
{ "no-password-ask", 'p', 0, G_OPTION_ARG_NONE, &ask_pass, "Don't ask for a password when it is empty", NULL },
{ "output-file", 'o', 0, G_OPTION_ARG_STRING, &outfile, "Output file", "output file"},
@@ -82,7 +84,7 @@
{ "list-providers", 'L', 0, G_OPTION_ARG_NONE, &list_providers, "List installed database providers and exit", NULL },
#ifdef HAVE_LIBSOUP
{ "http-port", 's', 0, G_OPTION_ARG_INT, &http_port, "Run embedded HTTP server on specified port", "port" },
- { "http-token", 't', 0, G_OPTION_ARG_STRING, &auth_token, "Authentication token (required to authenticate clients)", "token" },
+ { "http-token", 't', 0, G_OPTION_ARG_STRING, &auth_token, "Authentication token (required to authenticate clients)", "token phrase" },
#endif
{ NULL }
};
@@ -166,6 +168,11 @@
}
g_option_context_free (context);
+ if (show_version) {
+ g_print (_("GDA SQL console version " PACKAGE_VERSION "\n"));
+ return 0;
+ }
+
gda_init ();
sql_gbr_init ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]