/*
 * executed in the sub thread (the one which can manipulate @sub_model)
 */
GdaDataModel *
_gda_thread_recordset_new (GdaConnection *cnc, GdaThreadWrapper *wrapper, GdaDataModel *sub_model)
{
	GdaThreadRecordset *model;
	gint ncols, i, nblobs;
	gint *blobs_conv = NULL;
	model = GDA_THREAD_RECORDSET (g_object_new (GDA_TYPE_THREAD_RECORDSET,
						    "connection", cnc, NULL));

	_gda_data_select_share_private_data (GDA_DATA_SELECT (sub_model), 
					     GDA_DATA_SELECT (model));
	model->priv->wrapper = g_object_ref (wrapper);
	model->priv->sub_model = g_object_ref (sub_model);


	ncols = gda_data_model_get_n_columns (sub_model);
	nblobs = 0;
	for (i = 0; i < ncols; i++) {
		GdaColumn *col;
		col = gda_data_model_describe_column (sub_model, i);
		if (gda_column_get_g_type (col) == GDA_TYPE_BLOB) {
			if (!blobs_conv)
				blobs_conv = g_new0 (gint, ncols);
			blobs_conv [nblobs] = i;
			nblobs++;
		}
	}
	model->priv->blobs_conv = blobs_conv;
	model->priv->nblobs = nblobs;

	COPY_PUBLIC_DATA (sub_model, model);

        return GDA_DATA_MODEL (model);
}
Esempio n. 2
0
static void
gda_mysql_recordset_dispose (GObject  *object)
{
	GdaMysqlRecordset *recset = (GdaMysqlRecordset *) object;

	g_return_if_fail (GDA_IS_MYSQL_RECORDSET (recset));

	if (recset->priv) {
		GDA_MYSQL_PSTMT (GDA_DATA_SELECT (object)->prep_stmt)->stmt_used = FALSE;

		if (recset->priv->cnc) {
			g_object_unref (G_OBJECT(recset->priv->cnc));
			recset->priv->cnc = NULL;
		}
		if (recset->priv->tmp_row) {
			g_object_unref (G_OBJECT(recset->priv->tmp_row));
			recset->priv->tmp_row = NULL;
		}
		if (recset->priv->types)
			g_free (recset->priv->types);

		g_free (recset->priv);
		recset->priv = NULL;
	}

	parent_class->dispose (object);
}
Esempio n. 3
0
/*
 * Create a new filled #GdaRow object for the next cursor row
 *
 * Each new #GdaRow created is referenced only by imodel->priv->tmp_row (the #GdaDataSelect implementation
 * never keeps a reference to it).
 * Before a new #GdaRow gets created, the previous one, if set, is discarded.
 */
static gboolean
gda_sqlite_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
{
	GdaSqliteRecordset *imodel = (GdaSqliteRecordset*) model;

	if (imodel->priv->tmp_row) {
		g_object_unref (imodel->priv->tmp_row);
		imodel->priv->tmp_row = NULL;
	}
	if (imodel->priv->next_row_num != rownum) {
		GError *lerror = NULL;
		*prow = NULL;
		g_set_error (&lerror, GDA_DATA_MODEL_ERROR,
			     GDA_DATA_MODEL_ROW_NOT_FOUND_ERROR,
			     "%s", _("Can't set iterator on requested row"));
		gda_data_select_add_exception (GDA_DATA_SELECT (model), lerror);
		if (error)
			g_propagate_error (error, g_error_copy (lerror));
		return TRUE;
	}
	*prow = fetch_next_sqlite_row (imodel, FALSE, error);
	imodel->priv->tmp_row = *prow;

	return TRUE;
}
Esempio n. 4
0
static GdaRow *
fetch_next_oracle_row (GdaOracleRecordset *model, G_GNUC_UNUSED gboolean do_store, GError **error)
{
	int result;
	GdaRow *prow = NULL;
	GdaOraclePStmt *ps = GDA_ORACLE_PSTMT (((GdaDataSelect*)model)->prep_stmt);
	OracleConnectionData *cdata;
	GdaConnection *cnc;

	cnc = gda_data_select_get_connection ((GdaDataSelect*) model);
	cdata = (OracleConnectionData*)	gda_connection_internal_get_provider_data_error (cnc, error);
	if (!cdata)
		return NULL;

	/* fetch row */
	if (cdata->major_version > 9)
		result = OCIStmtFetch2 (ps->hstmt,
					cdata->herr,
					(ub4) 1,
					(ub2) OCI_FETCH_NEXT,
					(sb4) 1,
					(ub4) OCI_DEFAULT);
	else
		result = OCIStmtFetch (ps->hstmt,
				       cdata->herr,
				       (ub4) 1,
				       (ub2) OCI_FETCH_NEXT,
				       (ub4) OCI_DEFAULT);
	if (result == OCI_NO_DATA) {
		GDA_DATA_SELECT (model)->advertized_nrows = model->priv->next_row_num;
		return NULL;
	}
	else {
		GdaConnectionEvent *event;
		if ((event = gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
						      _("Could not fetch next row")))) {
			/* set @error */
			g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_DATA_ERROR,
				     "%s", gda_connection_event_get_description (event));

			return NULL;
		}
	}

	prow = new_row ((GdaDataSelect*) model, cnc, ps);
	gda_data_select_take_row ((GdaDataSelect*) model, prow, model->priv->next_row_num);
	model->priv->next_row_num ++;

	return prow;
}
Esempio n. 5
0
static void
compute_modification_statements (UiFormGrid *formgrid, GdaDataModel *model)
{
	/* clear existing modification statements */
	ModType mod;
	for (mod = MOD_INSERT; mod < MOD_LAST; mod++) {
		if (formgrid->priv->mod_stmt[mod]) {
			g_object_unref (formgrid->priv->mod_stmt[mod]);
			formgrid->priv->mod_stmt[mod] = NULL;
		}
	}

	if (!model || !GDA_IS_DATA_SELECT (model))
		return;

	if (! formgrid->priv->compute_mod_stmt)
		return;

	gda_data_select_compute_modification_statements_ext (GDA_DATA_SELECT (model),
							     GDA_DATA_SELECT_COND_ALL_COLUMNS, NULL);

	formgrid->priv->mod_stmt_auto_computed = TRUE;
	g_object_get (model,
		      "insert-stmt", &formgrid->priv->mod_stmt[MOD_INSERT],
		      "update-stmt", &formgrid->priv->mod_stmt[MOD_UPDATE],
		      "delete-stmt", &formgrid->priv->mod_stmt[MOD_DELETE], NULL);

	/*
	for (mod = MOD_INSERT; mod < MOD_LAST; mod++) {
		if (formgrid->priv->mod_stmt[mod]) {
			gchar *sql;
			GError *lerror = NULL;
			sql = gda_statement_to_sql_extended (formgrid->priv->mod_stmt[mod], NULL, NULL,
							     GDA_STATEMENT_SQL_PARAMS_LONG, NULL, &lerror);
			g_print ("STMT[%d] = [%s]", mod, sql ? sql : "ERR");
			if (!sql)
				g_print (" --- %s", lerror && lerror->message ? lerror->message : "No detail");
			g_clear_error (&lerror);
			g_print ("\n");
			g_free (sql);
		}
		else
			g_print ("STMT[%d] = ---\n", mod);
	}
	*/
}
Esempio n. 6
0
static void
gda_sqlite_recordset_dispose (GObject *object)
{
	GdaSqliteRecordset *recset = (GdaSqliteRecordset *) object;

	g_return_if_fail (GDA_IS_SQLITE_RECORDSET (recset));

	if (recset->priv) {
		GdaSqlitePStmt *ps;
		ps = GDA_SQLITE_PSTMT (GDA_DATA_SELECT (object)->prep_stmt);
		ps->stmt_used = FALSE;
		virt_cnc_set_working_obj (gda_data_select_get_connection ((GdaDataSelect*) recset), recset);
		SQLITE3_CALL (sqlite3_reset) (ps->sqlite_stmt);
		virt_cnc_set_working_obj (gda_data_select_get_connection ((GdaDataSelect*) recset), NULL);

		if (recset->priv->tmp_row)
			g_object_unref (recset->priv->tmp_row);
		g_free (recset->priv);
		recset->priv = NULL;
	}

	parent_class->dispose (object);
}
Esempio n. 7
0
GdaDataModel *
gda_mysql_recordset_new_direct (GdaConnection *cnc, GdaDataModelAccessFlags flags, 
				GType *col_types)
{
	GdaMysqlRecordset *model;
        MysqlConnectionData *cdata;
        gint i;
	GdaDataModelAccessFlags rflags;
	GSList *columns = NULL;

        g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);

	cdata = (MysqlConnectionData*) gda_connection_internal_get_provider_data_error (cnc, NULL);
	if (!cdata)
		return NULL;

	/* determine access mode: RANDOM or CURSOR FORWARD are the only supported */
	if (flags & GDA_DATA_MODEL_ACCESS_RANDOM)
		rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
	else
		rflags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;

	/* create data model */
        model = g_object_new (GDA_TYPE_MYSQL_RECORDSET,
			      "connection", cnc,
			      "model-usage", rflags,
			      NULL);
        model->priv->cnc = cnc;
	g_object_ref (G_OBJECT(cnc));

	/* columns & types */	
	model->priv->ncols = mysql_field_count (cdata->mysql);
	model->priv->types = g_new0 (GType, model->priv->ncols);
	
	/* create columns */
	for (i = 0; i < model->priv->ncols; i++)
		columns = g_slist_prepend (columns, gda_column_new ());
	columns = g_slist_reverse (columns);

	if (col_types) {
		for (i = 0; ; i++) {
			if (col_types [i] > 0) {
				if (col_types [i] == G_TYPE_NONE)
					break;
				if (i >= model->priv->ncols) {
					g_warning (_("Column %d out of range (0-%d), ignoring its specified type"), i,
						   model->priv->ncols - 1);
					break;
				}
				else
					model->priv->types [i] = col_types [i];
			}
		}
	}

	/* fill bind result */
	MYSQL_RES *mysql_res = mysql_store_result (cdata->mysql);
	MYSQL_FIELD *mysql_fields = mysql_fetch_fields (mysql_res);
	GSList *list;

	((GdaDataSelect *) model)->advertized_nrows = mysql_affected_rows (cdata->mysql);
	for (i=0, list = columns; 
	     i < model->priv->ncols; 
	     i++, list = list->next) {
		GdaColumn *column = GDA_COLUMN (list->data);
		
		/* use C API to set columns' information using gda_column_set_*() */
		MYSQL_FIELD *field = &mysql_fields[i];
		
		GType gtype = model->priv->types [i];
		if (gtype == GDA_TYPE_NULL) {
			gtype = _gda_mysql_type_to_gda (cdata, field->type, field->charsetnr);
			model->priv->types [i] = gtype;
		}
		gda_column_set_g_type (column, gtype);
		gda_column_set_name (column, field->name);
		gda_column_set_description (column, field->name);
	}
	gda_data_select_set_columns (GDA_DATA_SELECT (model), columns);

	/* load ALL data */
	MYSQL_ROW mysql_row;
	gint rownum;
	GdaServerProvider *prov;
	prov = gda_connection_get_provider (cnc);
	for (mysql_row = mysql_fetch_row (mysql_res), rownum = 0;
	     mysql_row;
	     mysql_row = mysql_fetch_row (mysql_res), rownum++) {
		GdaRow *row = gda_row_new (model->priv->ncols);
		gint col;
		for (col = 0; col < model->priv->ncols; col++) {
			gint i = col;
		
			GValue *value = gda_row_get_value (row, i);
			GType type = model->priv->types[i];
			char *data = mysql_row[i];

			if (!data || (type == GDA_TYPE_NULL))
				continue;

			gda_value_reset_with_type (value, type);
			if (type == G_TYPE_STRING)
				g_value_set_string (value, data);
			else {
				GdaDataHandler *dh;
				gboolean valueset = FALSE;
				dh = gda_server_provider_get_data_handler_g_type (prov, cnc, type);
				if (dh) {
					GValue *tmpvalue;
					tmpvalue = gda_data_handler_get_value_from_str (dh, data, type);
					if (tmpvalue) {
						*value = *tmpvalue;
						g_free (tmpvalue);
						valueset = TRUE;
					}
				}
				if (!valueset)
					gda_row_invalidate_value (row, value);
			}
		}
		gda_data_select_take_row ((GdaDataSelect*) model, row, rownum);
	}
	mysql_free_result (mysql_res);

        return GDA_DATA_MODEL (model);
}
Esempio n. 8
0
GtkWidget *
do_form_model_change (GtkWidget *do_widget)
{  
	if (!window) {
                GdaStatement *stmt;
		GtkWidget *vbox;
		GtkWidget *label;
		GdaDataModel *models [3];
		
		window = gtk_dialog_new_with_buttons ("Changing data in a GdauiForm",
						      GTK_WINDOW (do_widget),
						      0,
						      "Close", GTK_RESPONSE_NONE,
						      NULL);
		
		g_signal_connect (window, "response",
				  G_CALLBACK (gtk_widget_destroy), NULL);
		g_signal_connect (window, "destroy",
				  G_CALLBACK (gtk_widget_destroyed), &window);
		
		vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
		gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (window))),
				    vbox, TRUE, TRUE, 0);
		gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
		
		label = gtk_label_new ("The data in the same GdauiForm widget can be change don the fly.");
		gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

		/* creating data models */
		stmt = gda_sql_parser_parse_string (demo_parser, "SELECT * FROM products ORDER BY ref, category LIMIT 15", NULL, NULL);
		models[0] = gda_connection_statement_execute_select (demo_cnc, stmt, NULL, NULL);
		gda_data_select_compute_modification_statements (GDA_DATA_SELECT (models[0]), NULL);
		g_object_unref (stmt);

		stmt = gda_sql_parser_parse_string (demo_parser, "SELECT * FROM products WHERE price > 20.2 ORDER BY ref, category LIMIT 10", NULL, NULL);
		models[1] = gda_connection_statement_execute_select (demo_cnc, stmt, NULL, NULL);
		gda_data_select_compute_modification_statements (GDA_DATA_SELECT (models[1]), NULL);
		g_object_unref (stmt);

		stmt = gda_sql_parser_parse_string (demo_parser, "SELECT name, price, ref, category FROM products WHERE price > 20.2 ORDER BY name LIMIT 30", NULL, NULL);
		models[2] = gda_connection_statement_execute_select (demo_cnc, stmt, NULL, NULL);
		gda_data_select_compute_modification_statements (GDA_DATA_SELECT (models[2]), NULL);
		g_object_unref (stmt);

		
		/* allow choosing which data model to display */
		label = gtk_label_new ("");
		gtk_widget_set_halign (label, GTK_ALIGN_START);
                gtk_label_set_markup (GTK_LABEL (label), "<b>Choose which data model to display:</b>");
		gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

		GtkWidget *layout, *rb;
		GSList *group = NULL;
		gint i;
		layout = gtk_grid_new ();
		gtk_box_pack_start (GTK_BOX (vbox), layout, FALSE, FALSE, 0);
		
		for (i = 0; i < 3; i++) {
			gchar *str;
			str = g_strdup_printf ("%d columns x %d rows", gda_data_model_get_n_columns (models[i]),
					       gda_data_model_get_n_rows (models[i]));
			rb = gtk_radio_button_new_with_label (group, str);
			g_free (str);
			gtk_grid_attach (GTK_GRID (layout), rb, i, 0, 1, 1);
			g_signal_connect (rb, "toggled", G_CALLBACK (model_toggled_cb), models[i]);
			g_object_set_data_full (G_OBJECT (rb), "model", models[i], g_object_unref);
			group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (rb));
		}

		/* Create the form widget */
		label = gtk_label_new ("");
		gtk_widget_set_halign (label, GTK_ALIGN_START);
                gtk_label_set_markup (GTK_LABEL (label), "<b>GdauiForm:</b>");
		gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

		form = gdaui_form_new (models[0]);
		g_object_set (G_OBJECT (form), "info-flags",
                              GDAUI_DATA_PROXY_INFO_CURRENT_ROW |
                              GDAUI_DATA_PROXY_INFO_ROW_MOVE_BUTTONS |
                              GDAUI_DATA_PROXY_INFO_ROW_MODIFY_BUTTONS, NULL);
		gtk_box_pack_start (GTK_BOX (vbox), form, TRUE, TRUE, 0);

		GdaDataProxy *proxy;
		proxy = gdaui_data_proxy_get_proxy (GDAUI_DATA_PROXY (form));
		g_object_set (proxy, "cache-changes", TRUE, NULL);
	}

	gboolean visible;
	g_object_get (G_OBJECT (window), "visible", &visible, NULL);
	if (!visible)
		gtk_widget_show_all (window);
	else {
		gtk_widget_destroy (window);
		window = NULL;
	}

	return window;
}
Esempio n. 9
0
GtkWidget *
do_form_pict (GtkWidget *do_widget)
{  
	if (!window) {
		GdaStatement *stmt;
		GtkWidget *vbox;
		GtkWidget *label;
		GdaDataModel *model;
		GtkWidget *form;
		GdaSet *data_set;
		GdaHolder *param;
		GValue *value;
		
		window = gtk_dialog_new_with_buttons ("Form with the 'picture' plugin",
						      GTK_WINDOW (do_widget),
						      0,
						      GTK_STOCK_CLOSE,
						      GTK_RESPONSE_NONE,
						      NULL);
		
		g_signal_connect (window, "response",
				  G_CALLBACK (gtk_widget_destroy), NULL);
		g_signal_connect (window, "destroy",
				  G_CALLBACK (gtk_widget_destroyed), &window);
		
		vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
		gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (window))),
				    vbox, TRUE, TRUE, 0);
		gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
		
		label = gtk_label_new ("The following GdauiForm widget displays data from the 'pictures' table.\n\n"
				       "The pictures are stored as BLOB inside the database and\n"
				       "are displayed using the 'picture' plugin (right click to \n"
				       "open a menu, or double click to load an image).");
		gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
		
		/* Create the demo widget */
		stmt = gda_sql_parser_parse_string (demo_parser, "SELECT id, pict FROM pictures", NULL, NULL);
		model = gda_connection_statement_execute_select (demo_cnc, stmt, NULL, NULL);
		g_object_unref (stmt);
		gda_data_select_compute_modification_statements (GDA_DATA_SELECT (model), NULL);
		form = gdaui_form_new (model);
		g_object_unref (model);
		g_object_set (G_OBJECT (form), "info-flags",
			      GDAUI_DATA_PROXY_INFO_CURRENT_ROW |
			      GDAUI_DATA_PROXY_INFO_ROW_MOVE_BUTTONS |
			      GDAUI_DATA_PROXY_INFO_ROW_MODIFY_BUTTONS, NULL);

		/* specify that we want to use the 'picture' plugin */
		data_set = GDA_SET (gdaui_data_selector_get_data_set (GDAUI_DATA_SELECTOR (form)));
		param = gda_set_get_holder (data_set, "pict");
		value = gda_value_new_from_string ("picture", G_TYPE_STRING);
		gda_holder_set_attribute_static (param, GDAUI_ATTRIBUTE_PLUGIN, value);
		gda_value_free (value);

		gtk_box_pack_start (GTK_BOX (vbox), form, TRUE, TRUE, 0);
	}

	gboolean visible;
	g_object_get (G_OBJECT (window), "visible", &visible, NULL);
	if (!visible)
		gtk_widget_show_all (window);
	else {
		gtk_widget_destroy (window);
		window = NULL;
	}

	return window;
}
Esempio n. 10
0
GtkWidget *
do_form_rw (GtkWidget *do_widget)
{  
	if (!window) {
		GdaStatement *stmt;
		GtkWidget *vbox;
		GtkWidget *label;
		GdaDataModel *model;
		GtkWidget *form;
		
		window = gtk_dialog_new_with_buttons ("GdauiForm (RW)",
						      GTK_WINDOW (do_widget),
						      0,
						      "Close", GTK_RESPONSE_NONE,
						      NULL);
		
		g_signal_connect (window, "response",
				  G_CALLBACK (gtk_widget_destroy), NULL);
		g_signal_connect (window, "destroy",
				  G_CALLBACK (gtk_widget_destroyed), &window);
		
		vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
		gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (window))),
				    vbox, TRUE, TRUE, 0);
		gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
		
		label = gtk_label_new ("The following GdauiForm widget displays data from the 'products' table.\n\n"
				       "As modification queries are provided, the data is read-write\n(except for the 'price' "
				       "field as these queries voluntarily omit that field).");
		gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
		
		/* Create the demo widget */
		stmt = gda_sql_parser_parse_string (demo_parser, 
						    "SELECT ref, category, name, price, wh_stored FROM products", 
						    NULL, NULL);
		model = gda_connection_statement_execute_select (demo_cnc, stmt, NULL, NULL);
		g_object_unref (stmt);
		GError *error = NULL;
		if (!gda_data_select_compute_modification_statements (GDA_DATA_SELECT (model), &error)) {
			g_print ("===> %s\n", error && error->message ? error->message : "No detail");
		}
		form = gdaui_form_new (model);
		g_object_unref (model);
		g_object_set (G_OBJECT (form), "info-flags",
			      GDAUI_DATA_PROXY_INFO_CURRENT_ROW |
			      GDAUI_DATA_PROXY_INFO_ROW_MOVE_BUTTONS |
			      GDAUI_DATA_PROXY_INFO_ROW_MODIFY_BUTTONS, NULL);

		gtk_box_pack_start (GTK_BOX (vbox), form, TRUE, TRUE, 0);
	}

	gboolean visible;
	g_object_get (G_OBJECT (window), "visible", &visible, NULL);
	if (!visible)
		gtk_widget_show_all (window);
	else {
		gtk_widget_destroy (window);
		window = NULL;
	}

	return window;
}
Esempio n. 11
0
/*
 * the @ps struct is modified and transferred to the new data model created in
 * this function
 */
GdaDataModel *
gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_params,
			  GdaDataModelAccessFlags flags, GType *col_types)
{
	GdaOracleRecordset *model;
        OracleConnectionData *cdata;
        gint i;
	GdaDataModelAccessFlags rflags;

	gint nb_rows = -1;

        g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
        g_return_val_if_fail (ps != NULL, NULL);

	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, NULL);
	if (!cdata)
		return NULL;

	/* make sure @ps reports the correct number of columns using the API */
        if (_GDA_PSTMT (ps)->ncols < 0) {
		ub4 ncolumns;
		int result;
		
                /* get the number of columns in the result set */
                result = OCIAttrGet ((dvoid *) ps->hstmt,
                                     (ub4) OCI_HTYPE_STMT,
                                     (dvoid *) &ncolumns,
                                     (ub4 *) 0,
                                     (ub4) OCI_ATTR_PARAM_COUNT,
                                     cdata->herr);
                if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
                                             _("Could not get the number of columns in the result set")))
                        return NULL;
		
                _GDA_PSTMT (ps)->ncols = ncolumns;
	}

        /* completing @ps if not yet done */
        if (!_GDA_PSTMT (ps)->types && (_GDA_PSTMT (ps)->ncols > 0)) {
		/* create prepared statement's columns */
		GSList *list;
		GList *ora_values = NULL;

		for (i = 0; i < _GDA_PSTMT (ps)->ncols; i++)
			_GDA_PSTMT (ps)->tmpl_columns = g_slist_prepend (_GDA_PSTMT (ps)->tmpl_columns, 
									 gda_column_new ());
		_GDA_PSTMT (ps)->tmpl_columns = g_slist_reverse (_GDA_PSTMT (ps)->tmpl_columns);

		/* create prepared statement's types, all types are initialized to GDA_TYPE_NULL */
		_GDA_PSTMT (ps)->types = g_new (GType, _GDA_PSTMT (ps)->ncols);
		for (i = 0; i < _GDA_PSTMT (ps)->ncols; i++)
			_GDA_PSTMT (ps)->types [i] = GDA_TYPE_NULL;

		if (col_types) {
			for (i = 0; ; i++) {
				if (col_types [i] > 0) {
					if (col_types [i] == G_TYPE_NONE)
						break;
					if (i >= _GDA_PSTMT (ps)->ncols) {
						g_warning (_("Column %d out of range (0-%d), ignoring its specified type"), i,
							   _GDA_PSTMT (ps)->ncols - 1);
						break;
					}
					else
						_GDA_PSTMT (ps)->types [i] = col_types [i];
				}
			}
		}
		
		/* fill GdaColumn's data and define the GdaOracleValue structures */
		for (i=0, list = _GDA_PSTMT (ps)->tmpl_columns; 
		     i < GDA_PSTMT (ps)->ncols; 
		     i++, list = list->next) {
			GdaColumn *column;
			int result;
			GdaOracleValue *ora_value;
			gboolean use_callback = FALSE;

			ora_value = g_new0 (GdaOracleValue, 1);
			ora_values = g_list_prepend (ora_values, ora_value);

			/* parameter to get attributes */
			result = OCIParamGet (ps->hstmt,
					      OCI_HTYPE_STMT,
					      cdata->herr,
					      (dvoid **) &(ora_value->pard),
					      (ub4) i+1);
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
						     _("Could not get the Oracle parameter descripter in the result set"))) {
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
				return NULL;
			}
			
			/* data size */
			result = OCIAttrGet ((dvoid *) (ora_value->pard),
					     OCI_DTYPE_PARAM,
					     &(ora_value->defined_size),
					     0,
					     (ub4) OCI_ATTR_DATA_SIZE,
					     cdata->herr);
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
						     _("Could not get the parameter defined size"))) {
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
				return NULL;
			}
			ora_value->defined_size++;
			
			/* data type */
			result = OCIAttrGet ((dvoid *) (ora_value->pard),
					     OCI_DTYPE_PARAM,
					     &(ora_value->sql_type),
					     0,
					     OCI_ATTR_DATA_TYPE,
					     cdata->herr);
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
						     _("Could not get the parameter data type"))) {
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
				return NULL;
			}

			result = OCIAttrGet ((dvoid *) (ora_value->pard),
					     OCI_DTYPE_PARAM,
					     &(ora_value->precision),
					     0,
					     OCI_ATTR_PRECISION,
					     cdata->herr);
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
						     _("Could not get the type's precision"))) {
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
				return NULL;
			}

			result = OCIAttrGet ((dvoid *) (ora_value->pard),
					     OCI_DTYPE_PARAM,
					     &(ora_value->scale),
					     0,
					     OCI_ATTR_SCALE,
					     cdata->herr);
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
						     _("Could not get the type's scale"))) {
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
				return NULL;
			}

			/* column's name */
			text *name;
			ub4 name_len;
			
			column = GDA_COLUMN (list->data);
			result = OCIAttrGet ((dvoid *) (ora_value->pard),
                                             (ub4) OCI_DTYPE_PARAM,
                                             (dvoid **) &name,
                                             (ub4 *) &name_len,
                                             (ub4) OCI_ATTR_NAME,
                                             (OCIError *) cdata->herr);
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
                                                     _("Could not get column name in the result set"))) {
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
                                return NULL;
			}

			gchar *name_buffer;
			name_buffer = g_new (gchar, name_len + 1);
			memcpy (name_buffer, name, name_len);
                        name_buffer [name_len] = '\0';
			gda_column_set_name (column, name_buffer);
			gda_column_set_description (column, name_buffer);
			g_free (name_buffer);

			/* for data fetching  */
			if (_GDA_PSTMT (ps)->types [i] != GDA_TYPE_NULL)
				ora_value->sql_type = _g_type_to_oracle_sqltype (_GDA_PSTMT (ps)->types [i]);

			switch (ora_value->sql_type) {
			case SQLT_CHR: /* for G_TYPE_STRING => request SQLT_CHR */
			case SQLT_STR:
			case SQLT_VCS:
			case SQLT_RID:
			case SQLT_AVC:
			case SQLT_AFC:
				ora_value->sql_type = SQLT_CHR;
				if (ora_value->defined_size == 1)
					use_callback = TRUE;
				break;

			case SQLT_INT:
				ora_value->defined_size = sizeof (gint);
				break;

			case SQLT_FLT:
			case SQLT_BFLOAT:
				ora_value->defined_size = sizeof (gfloat);
				break;

			case SQLT_BDOUBLE:
				ora_value->defined_size = sizeof (gdouble);
				break;
								
			case SQLT_DAT: /* request OCIDate */
				ora_value->sql_type = SQLT_ODT;
				break;

			case SQLT_NUM: /* for GDA_TYPE_NUMERIC => request SQLT_CHR */
			case SQLT_VNU:
				ora_value->sql_type = SQLT_CHR;
				break;
				
			case SQLT_LBI:
			case SQLT_LVB:
			case SQLT_LVC:
			case SQLT_LNG:
			case SQLT_VBI:
			case SQLT_BIN:
				use_callback = TRUE;
				break;
			default:
				use_callback = TRUE;
				break;
			}
			
			if (_GDA_PSTMT (ps)->types [i] != GDA_TYPE_NULL)
				ora_value->g_type = _GDA_PSTMT (ps)->types [i];
			else
				ora_value->g_type = _oracle_sqltype_to_g_type (ora_value->sql_type, ora_value->precision, 
									       ora_value->scale);

			if (ora_value->g_type == GDA_TYPE_BLOB) {
				/* allocate a Lob locator */
				OCILobLocator *lob;
				
				result = OCIDescriptorAlloc ((dvoid *) cdata->henv, (dvoid **) &lob,
							     (ub4) gda_oracle_blob_type (ora_value->sql_type), 
							     (size_t) 0, (dvoid **) 0);
				if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
							     _("Could not allocate Lob locator"))) {
					g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
					return NULL;
				}
				ora_value->value = lob;
				ora_value->defined_size = 0;
			}
			else if (use_callback) {
				ora_value->value = NULL;
				ora_value->defined_size = 33554432; /* 32M */
			}
			else
				ora_value->value = g_malloc0 (ora_value->defined_size);
			
			ora_value->s_type = gda_g_type_to_static_type (ora_value->g_type);
			if (_GDA_PSTMT (ps)->types [i] == GDA_TYPE_NULL)
				_GDA_PSTMT (ps)->types [i] = ora_value->g_type;
			gda_column_set_g_type (column, ora_value->g_type);

#ifdef GDA_DEBUG_NO
			g_print ("**COL type is %d, GType is %s, ORA defined size is %d%s\n",
				 ora_value->sql_type,
				 g_type_name (ora_value->g_type),
				 ora_value->defined_size - 1,
				 use_callback ? " using callback": "");
#endif

			ora_value->hdef = (OCIDefine *) 0;
			ora_value->indicator = 0;
			result = OCIDefineByPos ((OCIStmt *) ps->hstmt,
						 (OCIDefine **) &(ora_value->hdef),
						 (OCIError *) cdata->herr,
						 (ub4) i + 1,
						 ora_value->value,
						 ora_value->defined_size,
						 ora_value->sql_type,
						 (dvoid *) &(ora_value->indicator),
						 &(ora_value->rlen),
						 &(ora_value->rcode),
						 (ub4) (use_callback ? OCI_DYNAMIC_FETCH : OCI_DEFAULT));
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
						     _("Could not define by position"))) {
				OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
				return NULL;
			}

			if (use_callback) {
				result = OCIDefineDynamic ((OCIDefine *) (ora_value->hdef),
							   (OCIError *) (cdata->herr),
							   (dvoid*) (ora_value),
							   (OCICallbackDefine) ora_def_callback);
				if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
							     _("Could not define by position"))) {
					OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
					g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
					return NULL;
				}
			}

			ora_value->use_callback = use_callback;
		}

		ps->ora_values = g_list_reverse (ora_values);
        }

	/* determine access mode: RANDOM or CURSOR FORWARD are the only supported; if CURSOR BACKWARD
         * is requested, then we need RANDOM mode */
        if (flags & GDA_DATA_MODEL_ACCESS_RANDOM)
                rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
        else if (flags & GDA_DATA_MODEL_ACCESS_CURSOR_BACKWARD)
                rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
        else
                rflags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;

	ub4 prefetch;
	prefetch = (ub4) (100);
	OCIAttrSet (ps->hstmt, OCI_HTYPE_STMT,
		    &prefetch, 0,
		    OCI_ATTR_PREFETCH_ROWS, cdata->herr);

	/* create data model */
        model = g_object_new (GDA_TYPE_ORACLE_RECORDSET, 
			      "connection", cnc,
			      "prepared-stmt", ps, 
			      "model-usage", rflags, 
			      "exec-params", exec_params, NULL);
	GDA_DATA_SELECT (model)->advertized_nrows = nb_rows;
	
        return GDA_DATA_MODEL (model);
}
Esempio n. 12
0
static GdaRow *
fetch_next_sqlite_row (GdaSqliteRecordset *model, gboolean do_store, GError **error)
{
	int rc;
	SqliteConnectionData *cdata;
	GdaSqlitePStmt *ps;
	GdaRow *prow = NULL;
	GdaConnection *cnc;
	glong length;

	cnc = gda_data_select_get_connection ((GdaDataSelect*) model);
	cdata = (SqliteConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
	if (!cdata)
		return NULL;
	ps = GDA_SQLITE_PSTMT (GDA_DATA_SELECT (model)->prep_stmt);

	virt_cnc_set_working_obj (gda_data_select_get_connection ((GdaDataSelect*) model), model);

	if (model->priv->empty_forced)
		rc = SQLITE_DONE;
	else		
		rc = SQLITE3_CALL (sqlite3_step) (ps->sqlite_stmt);
	switch (rc) {
	case  SQLITE_ROW: {
		gint col, real_col;
		prow = gda_row_new (_GDA_PSTMT (ps)->ncols);
		for (col = 0; col < _GDA_PSTMT (ps)->ncols; col++) {
			GValue *value;
			GType type = _GDA_PSTMT (ps)->types [col];
			
			real_col = col + ps->nb_rowid_columns;

			if (type == GDA_TYPE_NULL) {
				type = fuzzy_get_gtype (cdata, ps, col);
				if (type == GDA_TYPE_BLOB) {
					/* extra check: make sure we have a rowid for this blob, or fallback to binary */
					if (ps->rowid_hash) {
						gint oidcol = 0;
						const char *ctable;
						ctable = SQLITE3_CALL (sqlite3_column_name) (ps->sqlite_stmt, real_col);
						if (ctable)
							oidcol = GPOINTER_TO_INT (g_hash_table_lookup (ps->rowid_hash,
												       ctable));
						if (oidcol == 0) {
							ctable = SQLITE3_CALL (sqlite3_column_table_name) (ps->sqlite_stmt, real_col);
							if (ctable)
								oidcol = GPOINTER_TO_INT (g_hash_table_lookup (ps->rowid_hash, 
													       ctable));
						}
						if (oidcol == 0)
							type = GDA_TYPE_BINARY;
					}
					else
						type = GDA_TYPE_BINARY;
				}
				if (type != GDA_TYPE_NULL) {
					GdaColumn *column;
					
					_GDA_PSTMT (ps)->types [col] = type;
					column = gda_data_model_describe_column (GDA_DATA_MODEL (model), col);
					gda_column_set_g_type (column, type);
					column = (GdaColumn *) g_slist_nth_data (_GDA_PSTMT (ps)->tmpl_columns, col);
					gda_column_set_g_type (column, type);
				}
			}
			
			/* fill GValue */
			value = gda_row_get_value (prow, col);
			GError *may_error;
			may_error = (GError*) SQLITE3_CALL (sqlite3_column_blob) (ps->sqlite_stmt, real_col);
			if (may_error && g_hash_table_lookup (error_blobs_hash, may_error)) {
				/*g_print ("Row invalidated: [%s]\n", may_error->message);*/
				gda_row_invalidate_value_e (prow, value, may_error);
				g_hash_table_remove (error_blobs_hash, may_error);
			}
			else if (SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt, real_col) == NULL) {
				/* we have a NULL value */
				gda_value_set_null (value);
			}
			else {
				gda_value_reset_with_type (value, type);
				
				if (type == GDA_TYPE_NULL)
					;
				else if (type == G_TYPE_INT) {
					gint64 i;
					i = SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col);
					if ((i > G_MAXINT) || (i < G_MININT)) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Integer value is too big"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						g_value_set_int (value, (gint) i);
				}
				else if (type == G_TYPE_UINT) {
					guint64 i;
					i = (gint64) SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col);
					if (i > G_MAXUINT) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Integer value is too big"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						g_value_set_uint (value, (gint) i);
				}
				else if (type == G_TYPE_INT64)
					g_value_set_int64 (value, SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col));
				else if (type == G_TYPE_UINT64)
					g_value_set_uint64 (value, (guint64) SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt,
												   real_col));
				else if (type == G_TYPE_DOUBLE)
					g_value_set_double (value, SQLITE3_CALL (sqlite3_column_double) (ps->sqlite_stmt,
											  real_col));
				else if (type == G_TYPE_STRING)
					g_value_set_string (value, (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt,
												  real_col));
				else if (type == GDA_TYPE_BINARY) {
					GdaBinary *bin;
					
					bin = gda_binary_new ();
					length = SQLITE3_CALL (sqlite3_column_bytes) (ps->sqlite_stmt, real_col);
					if (length > 0) {
						gda_binary_set_data (bin, SQLITE3_CALL (sqlite3_column_blob) (ps->sqlite_stmt, /* Flawfinder: ignore */
												       real_col), length);
					}
					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_CALL (sqlite3_column_name) (ps->sqlite_stmt, real_col);
						if (ctable)
							oidcol = GPOINTER_TO_INT (g_hash_table_lookup (ps->rowid_hash,
												       ctable));
						if (oidcol == 0) {
							ctable = SQLITE3_CALL (sqlite3_column_table_name) (ps->sqlite_stmt, real_col);
							if (ctable)
								oidcol = GPOINTER_TO_INT (g_hash_table_lookup (ps->rowid_hash, 
													       ctable));
						}
					}
					if (oidcol != 0) {
						gint64 rowid;
						rowid = SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, oidcol - 1); /* remove 1
													       because it was added in the first place */
						bop = _gda_sqlite_blob_op_new (cnc,
									       SQLITE3_CALL (sqlite3_column_database_name) (ps->sqlite_stmt, 
													    real_col),
									       SQLITE3_CALL (sqlite3_column_table_name) (ps->sqlite_stmt,
													 real_col),
									       SQLITE3_CALL (sqlite3_column_origin_name) (ps->sqlite_stmt,
													  real_col),
									      rowid);
					}
					if (!bop) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Unable to open BLOB"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else {
						GdaBlob *blob;
						blob = gda_blob_new ();
						gda_blob_set_op (blob, bop);
						g_object_unref (bop);
						gda_value_take_blob (value, blob);
					}
				}
				else if (type == G_TYPE_BOOLEAN)
					g_value_set_boolean (value, SQLITE3_CALL (sqlite3_column_int) (ps->sqlite_stmt, real_col) == 0 ? FALSE : TRUE);
				else if (type == G_TYPE_DATE) {
					GDate date;
					if (!gda_parse_iso8601_date (&date, 
								     (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt, 
												    real_col))) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     _("Invalid date '%s' (date format should be YYYY-MM-DD)"), 
							     (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt, real_col));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						g_value_set_boxed (value, &date);
				}
				else if (type == GDA_TYPE_TIME) {
					GdaTime timegda;
					if (!gda_parse_iso8601_time (&timegda, 
								     (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt, 
												    real_col))) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     _("Invalid time '%s' (time format should be HH:MM:SS[.ms])"), 
							     (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt, real_col));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else {
						if (timegda.timezone == GDA_TIMEZONE_INVALID)
							timegda.timezone = 0; /* set to GMT */
						gda_value_set_time (value, &timegda);
					}
				}
				else if (type == GDA_TYPE_TIMESTAMP) {
					GdaTimestamp timestamp;
					if (!gda_parse_iso8601_timestamp (&timestamp, 
									  (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt,
													 real_col))) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     _("Invalid timestamp '%s' (format should be YYYY-MM-DD HH:MM:SS[.ms])"), 
							     (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt, real_col));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else {
						if (timestamp.timezone == GDA_TIMEZONE_INVALID)
							timestamp.timezone = 0; /* set to GMT */
						gda_value_set_timestamp (value, &timestamp);
					}
				}
				else if (type == G_TYPE_CHAR) {
					gint64 i;
					i = (gint64) SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col);
					if ((i > G_MAXINT8) || (i < G_MININT8)) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Integer value is too big"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						g_value_set_schar (value, (gchar) i);
				}
				else if (type == G_TYPE_UCHAR) {
					gint64 i;
					i = (gint64) SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col);
					if ((i > G_MAXUINT8) || (i < 0)) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Integer value is too big"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						g_value_set_uchar (value, (guchar) i);
				}
				else if (type == GDA_TYPE_SHORT) {
					gint64 i;
					i = (gint64) SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col);
					if ((i > G_MAXSHORT) || (i < G_MINSHORT)) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Integer value is too big"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						gda_value_set_short (value, (guchar) i);
				}
				else if (type == GDA_TYPE_USHORT) {
					gint64 i;
					i = (gint64) SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col);
					if ((i > G_MAXUSHORT) || (i < 0)) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Integer value is too big"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						gda_value_set_ushort (value, (guchar) i);
				}
				else {
					GError *lerror = NULL;
					g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
						     GDA_SERVER_PROVIDER_DATA_ERROR,
						     "Unhandled type '%s' in SQLite recordset",
						     gda_g_type_to_string (_GDA_PSTMT (ps)->types [col]));
					gda_row_invalidate_value_e (prow, value, lerror);
				}
			}
		}
		
		if (do_store) {
			/* insert row */
			gda_data_select_take_row (GDA_DATA_SELECT (model), prow, model->priv->next_row_num);
		}
		model->priv->next_row_num ++;
		break;
	}
	case SQLITE_BUSY:
		/* nothing to do */
		break;
	case SQLITE_DONE:
		GDA_DATA_SELECT (model)->advertized_nrows = model->priv->next_row_num;
		SQLITE3_CALL (sqlite3_reset) (ps->sqlite_stmt);
		break;
	case SQLITE_READONLY:
	case SQLITE_MISUSE:
		g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
			     GDA_SERVER_PROVIDER_INTERNAL_ERROR, 
			      "%s", _("SQLite provider fatal internal error"));
		break;
	case SQLITE_ERROR:
	default: {
		GError *lerror = NULL;
		SQLITE3_CALL (sqlite3_reset) (ps->sqlite_stmt);
		if (rc == SQLITE_IOERR_TRUNCATE)
			g_set_error (&lerror, GDA_DATA_MODEL_ERROR,
				     GDA_DATA_MODEL_TRUNCATED_ERROR, "%s", _("Truncated data"));
		else
			g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
				     GDA_SERVER_PROVIDER_INTERNAL_ERROR, 
				     "%s", SQLITE3_CALL (sqlite3_errmsg) (cdata->connection));
		gda_data_select_add_exception (GDA_DATA_SELECT (model), lerror);
		if (rc == SQLITE_ERROR)
			g_propagate_error (error, g_error_copy (lerror));
		GDA_DATA_SELECT (model)->advertized_nrows = model->priv->next_row_num;
		break;
	}
	}

	virt_cnc_set_working_obj (gda_data_select_get_connection ((GdaDataSelect*) model), NULL);

	return prow;
}
Esempio n. 13
0
int
main (int argc, char *argv[])
{
        gda_init ();

        GdaConnection *cnc;
	GError *error = NULL;
	GdaStatement *stmt;
	GdaDataModel *model;
	gchar *str;
	GValue *name;

	/* open connection */
	cnc = open_connection ();

	/* begin transaction */
	if (! gda_connection_begin_transaction (cnc, NULL, GDA_TRANSACTION_ISOLATION_UNKNOWN,
						&error)) {
		g_print ("Could not begin transaction: %s\n",
                         error && error->message ? error->message : "No detail");
                exit (1);
	}
	
	/* execute SELECT */
	stmt = gda_sql_parser_parse_string (parser, "SELECT id, name FROM customers ORDER BY id", NULL, NULL);
	g_assert (stmt);
	model = gda_connection_statement_execute_select (cnc, stmt, NULL, &error);
	g_object_unref (stmt);
	if (!model) {
		g_print ("Could not execute SELECT statement: %s\n",
                         error && error->message ? error->message : "No detail");
                exit (1);
	}

	g_print ("** Data model is:\n");
	gda_data_model_dump (model, stdout);

	/*
	 * make sure the mete data is up to date
	 */
	g_print ("Computing meta data, this may take a while; in real applications, this should be cached to avoid waiting\n");
	if (! gda_connection_update_meta_store (cnc, NULL, &error)) {
		g_print ("Could not fetch meta data: %s\n",
                         error && error->message ? error->message : "No detail");
                exit (1);
	}

	/*
	 * Make the data model compute the modification statements which
	 * will actually be executed when the data model is modified
	 */
	if (! gda_data_select_compute_modification_statements (GDA_DATA_SELECT (model), &error)) {
		g_print ("Could not compute modification statements: %s\n",
                         error && error->message ? error->message : "No detail");
                exit (1);
	}

	g_object_get (G_OBJECT (model), "update-stmt", &stmt, NULL);
	str = gda_statement_to_sql (stmt, NULL, NULL);
	g_print ("Computed UPDATE: %s\n", str);
	g_free (str);
	g_object_unref (stmt);
	g_object_get (G_OBJECT (model), "delete-stmt", &stmt, NULL);
	str = gda_statement_to_sql (stmt, NULL, NULL);
	g_print ("Computed DELETE: %s\n", str);
	g_free (str);
	g_object_unref (stmt);
	g_object_get (G_OBJECT (model), "insert-stmt", &stmt, NULL);
	str = gda_statement_to_sql (stmt, NULL, NULL);
	g_print ("Computed INSERT: %s\n", str);
	g_free (str);
	g_object_unref (stmt);

	/*
	 * remove row 0 (1st row)
	 */
	g_print ("\n\n** Removing row 0\n");
	if (! gda_data_model_remove_row (model, 0, &error)) {
		g_print ("Could not remove row 0: %s\n",
                         error && error->message ? error->message : "No detail");
                exit (1);
	}
	g_print ("** Data model is now:\n");
	gda_data_model_dump (model, stdout);
	g_print ("** Table's contents is now:\n");
	display_customers (cnc);

	/*
	 * add a row: the row's values is a list of GValue pointers 
	 * (or NULL pointers where the default value should be inserted
	 */
	GList *list;
	g_print ("\n\n** Adding a row\n");
	list = g_list_append (NULL, NULL); 
	g_value_set_string ((name = gda_value_new (G_TYPE_STRING)), "Hiro");
	list = g_list_append (list, name);
	if (gda_data_model_append_values (model, list, &error) == -1) {
		g_print ("Could not add a row: %s\n",
                         error && error->message ? error->message : "No detail");
                exit (1);
	}
	gda_value_free (name);
	g_list_free (list);
	g_print ("** Data model is now:\n");
	gda_data_model_dump (model, stdout);
	g_print ("** Table's contents is now:\n");
	display_customers (cnc);

	/*
	 * alter row 2
	 */
	g_print ("\n\n** Modifying row 2\n");
	g_value_set_string ((name = gda_value_new (G_TYPE_STRING)), "Tom");
	if (! gda_data_model_set_value_at (model, 1, 2, name, &error)) {
		g_print ("Could not modify row 2: %s\n",
                         error && error->message ? error->message : "No detail");
                exit (1);
	}
	gda_value_free (name);
	g_print ("** Data model is now:\n");
	gda_data_model_dump (model, stdout);
	g_print ("** Table's contents is now:\n");
	display_customers (cnc);

	/* rollback transaction */
	gda_connection_rollback_transaction (cnc, NULL, NULL);

        gda_connection_close (cnc);

        return 0;
}