示例#1
0
static gboolean
data_model_errors_set_value_at (GdaDataModel *model, gint col, gint row, const GValue *value, GError **error)
{
	gboolean retval = TRUE;
	DataModelErrors *imodel;

	g_return_val_if_fail (IS_DATA_MODEL_ERRORS (model), FALSE);
	imodel = DATA_MODEL_ERRORS (model);
	g_return_val_if_fail (imodel->priv, FALSE);

	if ((col < 0) || (col > NCOLS)) {
		gchar *tmp;
		tmp = g_strdup_printf ("Column %d out of range (0-%d)", col, NCOLS-1);
		g_set_error (error, TEST_ERROR, TEST_ERROR_GENERIC, "%s", tmp);
		g_free (tmp);
		return FALSE;
	}

	GdaRow *drow;
	drow =  g_ptr_array_index (imodel->priv->rows, row);
	if (drow) {
		GValue *dvalue;
		dvalue = gda_row_get_value (drow, col);
		gda_value_reset_with_type (dvalue, G_VALUE_TYPE (value));
		g_value_copy (value, dvalue);
		gda_data_model_row_updated (model, row);
	}
	else {
		g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ROW_NOT_FOUND_ERROR,
			      "%s", "Row not found");
		retval = FALSE;
	}

	return retval;
}
示例#2
0
static const GValue *
data_model_errors_get_value_at (GdaDataModel *model, gint col, gint row, GError **error)
{
	DataModelErrors *imodel;
	GValue *value = NULL;
	GdaRow *drow;

	g_return_val_if_fail (IS_DATA_MODEL_ERRORS (model), NULL);
	imodel = DATA_MODEL_ERRORS (model);
	g_return_val_if_fail (imodel->priv, NULL);

	if ((col < 0) || (col > NCOLS)) {
		gchar *tmp;
		tmp = g_strdup_printf ("Column %d out of range (0-%d)", col, NCOLS-1);
		g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_COLUMN_OUT_OF_RANGE_ERROR,
			      "%s", tmp);
		g_free (tmp);
		return NULL;
	}

	if (row >= (gint)imodel->priv->rows->len) {
		gchar *str;
		if (imodel->priv->rows->len > 0)
			str = g_strdup_printf ("Row %d out of range (0-%d)", row,
					       imodel->priv->rows->len - 1);
		else
			str = g_strdup_printf ("Row %d not found (empty data model)", row);
		g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ROW_OUT_OF_RANGE_ERROR,
			      "%s", str);
		g_free (str);
                return NULL;
        }

	drow =  g_ptr_array_index (imodel->priv->rows, row);
	if (drow) {
		GValue *val = gda_row_get_value (drow, col);
		if (G_VALUE_TYPE (val) == G_TYPE_INVALID) {
			/* simulates an error */
			g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
				     "%s", "Simulated error");
		}
		else
			value = val;
	}
	else
		g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ROW_NOT_FOUND_ERROR,
			      "%s", "Row not found");

	return value;
}
static void
alter_blob_values (GdaThreadRecordset *rs, GdaRow **prow)
{
	gint i;
	for (i = 0; i < rs->priv->nblobs; i++) {
		GValue *value = gda_row_get_value (*prow, rs->priv->blobs_conv[i]);
		if (G_VALUE_TYPE (value) == GDA_TYPE_BLOB) {
			GdaBlob *blob;
			blob = (GdaBlob*) gda_value_get_blob (value);
			if (blob->op) {
				GdaBlobOp *nop;
				nop = _gda_thread_blob_op_new (rs->priv->wrapper, blob->op);
				g_object_unref (blob->op);
				blob->op = nop;
			}
		}
	}
}
示例#4
0
/* create a new GdaRow from the last read row */
static GdaRow *
new_row (GdaDataSelect *imodel, GdaConnection *cnc, GdaOraclePStmt *ps)
{
	GdaRow *prow;
	GList *nodes;
	gint i;

	prow = gda_row_new (((GdaDataSelect*) imodel)->prep_stmt->ncols);
	for (i = 0, nodes = ps->ora_values;
	     nodes; 
	     i++, nodes = nodes->next) {
		GdaOracleValue *ora_value = (GdaOracleValue *) nodes->data;
                GValue *value = gda_row_get_value (prow, i); 
                _gda_oracle_set_value (value, ora_value, cnc);
	}

	return prow;
}
示例#5
0
static GdaRow *
create_new_row (GdaDataAccessWrapper *model)
{
	gint i;
	GdaRow *row;

	row = gda_row_new (model->priv->nb_cols);
	for (i = 0; i < model->priv->nb_cols; i++) {
		GdaHolder *holder;
		GValue *dest;
		dest = gda_row_get_value (row, i);
		if (model->priv->rows_mapping)
			holder = gda_set_get_nth_holder ((GdaSet *) model->priv->iter, model->priv->rows_mapping [i]);
		else
			holder = gda_set_get_nth_holder ((GdaSet *) model->priv->iter, i);
		if (holder) {
			const GValue *cvalue = gda_holder_get_value (holder);
			if (cvalue) {
				gda_value_reset_with_type (dest, G_VALUE_TYPE ((GValue *) cvalue));
				g_value_copy (cvalue, dest);
			}
			else
				gda_value_set_null (dest);
		}
		else
			gda_row_invalidate_value (row, dest);
	}

	gint *ptr;
	ptr = g_new (gint, 1);
	*ptr = model->priv->iter_row;
	g_hash_table_insert (model->priv->rows, ptr, row);
	/*g_print ("%s(%d)\n", __FUNCTION__, model->priv->iter_row);*/

	return row;
}
示例#6
0
static GdaRow *
new_row_from_mysql_stmt (GdaMysqlRecordset *imodel, G_GNUC_UNUSED gint rownum, GError **error)
{
	//g_print ("%s(): NCOLS=%d  ROWNUM=%d\n", __func__, ((GdaDataSelect *) imodel)->prep_stmt->ncols, rownum);
	int res;
	MYSQL_BIND *mysql_bind_result;
	g_return_val_if_fail (imodel->priv->mysql_stmt != NULL, NULL);

	mysql_bind_result = ((GdaMysqlPStmt *) ((GdaDataSelect *) imodel)->prep_stmt)->mysql_bind_result;
	g_assert (mysql_bind_result);

	res = mysql_stmt_fetch (imodel->priv->mysql_stmt);
	if (res == MYSQL_NO_DATA) {
		/* should not happen */
		g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
			     "%s", "No more data, please report this bug to "
			     "http://bugzilla.gnome.org/ for the \"libgda\" product and the MySQL provider.");
	}
	else if (res == MYSQL_DATA_TRUNCATED) {
		GString *string;

		string = g_string_new ("Truncated data, please report this bug to "
				       "http://bugzilla.gnome.org/ for the \"libgda\" product and the MySQL provider.");

		gint col;
		for (col = 0; col < ((GdaDataSelect *) imodel)->prep_stmt->ncols; ++col) {
			my_bool truncated;
			mysql_bind_result[col].error = &truncated;
			mysql_stmt_fetch_column (imodel->priv->mysql_stmt, &(mysql_bind_result[col]),
						 (unsigned int)col, 0);
			if (truncated)
				g_string_append_printf (string, "\n  column %d is truncated\n", col);
			mysql_bind_result[col].error = NULL;
		}
		g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR, "%s", string->str);
		g_string_free (string, TRUE);

		return NULL;
	}
	else if (res) {
		_gda_mysql_make_error (imodel->priv->cnc, NULL, imodel->priv->mysql_stmt, error);
		return NULL;
	}

	/* g_print ("%s: SQL=%s\n", __func__, ((GdaDataSelect *) imodel)->prep_stmt->sql); */

	
	GdaRow *row = gda_row_new (((GdaDataSelect *) imodel)->prep_stmt->ncols);
	gint col;
	for (col = 0; col < ((GdaDataSelect *) imodel)->prep_stmt->ncols; ++col) {
		gint i = col;
		
		GValue *value = gda_row_get_value (row, i);
		GType type = ((GdaDataSelect *) imodel)->prep_stmt->types[i];
		
		/*g_print ("%s: #%d : TYPE=%d, GTYPE=%s\n", __func__, i, mysql_bind_result[i].buffer_type, g_type_name (type));*/

		my_bool is_null = FALSE;
		unsigned long length;
		
		g_memmove (&is_null, mysql_bind_result[i].is_null, sizeof (my_bool));
		if (is_null) {
			gda_value_set_null (value);
			continue;
		}
		else
			gda_value_reset_with_type (value, type);

		switch (mysql_bind_result[i].buffer_type) {
		case MYSQL_TYPE_SHORT: {
			short int bvalue = 0;
			g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue));
			g_value_set_int (value, bvalue);
			break;
		}
		case MYSQL_TYPE_TINY: {
			signed char bvalue = 0;
			g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue));
			g_value_set_int (value, bvalue);
			break;
		}
		case MYSQL_TYPE_INT24:
		case MYSQL_TYPE_LONG:
		case MYSQL_TYPE_YEAR: {
			int bvalue = 0;
			g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue));
			
			if (type == G_TYPE_INT)
				g_value_set_int (value, bvalue);
			else if (type == G_TYPE_LONG)
				g_value_set_long (value, (long) bvalue);
			else if (type == G_TYPE_BOOLEAN)
				g_value_set_boolean (value, bvalue ? TRUE : FALSE);
			else {
				gda_row_invalidate_value (row, value);
				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
					     GDA_SERVER_PROVIDER_DATA_ERROR,
					     _("Type %s not mapped for value %d"),
					     g_type_name (type), bvalue);
			}
			break;
		}
		case MYSQL_TYPE_LONGLONG: {
			long long bvalue = 0;
			g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue));

			if (type == G_TYPE_BOOLEAN)
				g_value_set_boolean (value, bvalue ? TRUE : FALSE);
			else if (type == G_TYPE_INT)
				g_value_set_int (value, bvalue);
			else if (type == G_TYPE_LONG)
				g_value_set_long (value, bvalue);
			else {
				gda_row_invalidate_value (row, value);
				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
					     GDA_SERVER_PROVIDER_DATA_ERROR,
					     _("Type %s not mapped for value %lld"),
					     g_type_name (type), bvalue);
			}
			break;
		}
		case MYSQL_TYPE_NULL:
			gda_value_set_null (value);
			break;
		case MYSQL_TYPE_TIME:
		case MYSQL_TYPE_DATE:
		case MYSQL_TYPE_DATETIME:
		case MYSQL_TYPE_TIMESTAMP: {
			MYSQL_TIME bvalue = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
			g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue));

			if (type == GDA_TYPE_TIME) {
				GdaTime time = {
					.hour = bvalue.hour,
					.minute = bvalue.minute,
					.second = bvalue.second,
					.fraction = bvalue.second_part,
					.timezone = 0 /* GMT */
				};
				gda_value_set_time (value, &time);
			}
			else if (type == G_TYPE_DATE) {
				GDate *date = g_date_new_dmy
					((bvalue.day != 0) ? bvalue.day : 1,
					 (bvalue.month != 0) ? bvalue.month : 1,
					 (bvalue.year != 0) ? bvalue.year : 1970);
				g_value_take_boxed (value, date);
			}
			else if (type == GDA_TYPE_TIMESTAMP) {
				GdaTimestamp timestamp = {
					.year = bvalue.year,
					.month = bvalue.month,
					.day = bvalue.day,
					.hour = bvalue.hour,
					.minute = bvalue.minute,
					.second = bvalue.second,
					.fraction = bvalue.second_part,
					.timezone = 0 /* GMT */
				};
				gda_value_set_timestamp (value, &timestamp);
			}
			else {
				gda_row_invalidate_value (row, value);
				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
					     GDA_SERVER_PROVIDER_DATA_ERROR,
					     _("Type %s not mapped for value %d/%d/%d %d:%d:%d.%lu"),
					     g_type_name (type), bvalue.year, bvalue.month,
					     bvalue.day, bvalue.hour, bvalue.minute,
					     bvalue.second, bvalue.second_part);
			}
			break;
		}
		case MYSQL_TYPE_FLOAT: {
			float bvalue = 0.;
			g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue));
			
			if (type == G_TYPE_FLOAT)
				g_value_set_float (value, (float) bvalue);
			else {
				gda_row_invalidate_value (row, value);
				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
					     GDA_SERVER_PROVIDER_DATA_ERROR,
					     _("Type %s not mapped for value %f"),
					     g_type_name (type), bvalue);
			}			
			break;
		}
		case MYSQL_TYPE_DOUBLE: {
			double bvalue = 0.0;
			g_memmove (&bvalue, mysql_bind_result[i].buffer, sizeof (bvalue));
			
			if (type == G_TYPE_DOUBLE)
				g_value_set_double (value, bvalue);
			else {
				gda_row_invalidate_value (row, value);
				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
					     GDA_SERVER_PROVIDER_DATA_ERROR,
					     _("Type %s not mapped for value %f"),
					     g_type_name (type), bvalue);
			}
			break;
		}
		case MYSQL_TYPE_STRING:
		case MYSQL_TYPE_VAR_STRING:
		case MYSQL_TYPE_BLOB:
		case MYSQL_TYPE_TINY_BLOB:
		case MYSQL_TYPE_MEDIUM_BLOB:
		case MYSQL_TYPE_LONG_BLOB:
		case MYSQL_TYPE_NEWDECIMAL:
		case MYSQL_TYPE_DECIMAL:
		case MYSQL_TYPE_BIT: {
			char *bvalue = NULL;
			g_memmove (&length, mysql_bind_result[i].length, sizeof (unsigned long));
			if (length > 0) {
				bvalue = g_malloc (length + 1);
				memcpy (bvalue, mysql_bind_result[i].buffer, length);
				bvalue [length] = 0;
			}
			
			if (type == G_TYPE_STRING)
				g_value_set_string (value, bvalue);
			else if (type == GDA_TYPE_BINARY) {
				GdaBinary binary = {
					.data = (guchar*) bvalue,
					.binary_length = length
				};
				gda_value_set_binary (value, &binary);
			}
			else if (type == GDA_TYPE_BLOB) {
				/* we don't use GdaMysqlBlobOp because it looks like the MySQL
				 * API does not support BLOBs accessed in a random way,
				 * so we return the whole BLOB at once */
				GdaBlob blob = { {(guchar*) bvalue, length}, NULL };
				gda_value_set_blob (value, &blob);
			}
			else if (type == GDA_TYPE_NUMERIC) {
				if (length > 0) {
					GdaNumeric *numeric;
					numeric = gda_numeric_new ();
					gda_numeric_set_from_string (numeric, bvalue);
					gda_numeric_set_precision (numeric, 6);
					gda_numeric_set_width (numeric, length);
					gda_value_set_numeric (value, numeric);
					gda_numeric_free (numeric);
				}
			}
			else if (type == G_TYPE_DOUBLE) {
				if (length > 0)
					g_value_set_double (value, g_ascii_strtod (bvalue, NULL));
				else {
					/* error: wrong column type */
					gda_row_invalidate_value (row, value);
					g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
						     GDA_SERVER_PROVIDER_DATA_ERROR,
						     _("Invalid column bind data type. %d\n"),
						     mysql_bind_result[i].buffer_type);
					break;
				}
			}
			else if (type == G_TYPE_INT) {
				if (length > 0)
					g_value_set_int (value, atoi (bvalue));
				else {
					/* error: wrong column type */
					gda_row_invalidate_value (row, value);
					g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
						     GDA_SERVER_PROVIDER_DATA_ERROR,
						     _("Invalid column bind data type. %d\n"),
						     mysql_bind_result[i].buffer_type);
					break;
				}
			}
			else if (type == G_TYPE_BOOLEAN) {
				if (length > 0)
					g_value_set_boolean (value, atoi (bvalue));
				else {
					/* error: wrong column type */
					gda_row_invalidate_value (row, value);
					g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
						     GDA_SERVER_PROVIDER_DATA_ERROR,
						     _("Invalid column bind data type. %d\n"),
						     mysql_bind_result[i].buffer_type);
					break;
				}
			}
			else {
				gda_row_invalidate_value (row, value);
				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
					     GDA_SERVER_PROVIDER_DATA_ERROR,
					     _("Type %s not mapped for value %s"),
					     g_type_name (type), bvalue);
			}
			g_free (bvalue);
			break;
		}
示例#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);
}
示例#8
0
static void
data_model_errors_init (DataModelErrors *model,
			G_GNUC_UNUSED DataModelErrorsClass *klass)
{
	gsize i;
	g_return_if_fail (IS_DATA_MODEL_ERRORS (model));

	model->priv = g_new0 (DataModelErrorsPrivate, 1);
	
	/* columns */
	model->priv->columns = NULL;
	for (i = 0; i < NCOLS; i++) {
		GdaColumn *col;
		gchar *str;
		col = gda_column_new ();
		gda_column_set_g_type (col, G_TYPE_STRING);
		str = g_strdup_printf ("col%" G_GSIZE_FORMAT, i);
		gda_column_set_name (col, str);
		gda_column_set_description (col, str);
		g_object_set (G_OBJECT (col), "id", str, NULL);
		g_free (str);

		model->priv->columns = g_slist_append (model->priv->columns, col);
	}

	/* rows */
	model->priv->rows = g_ptr_array_new (); /* array of GdaRow pointers */
	for (i = 0; i < (sizeof (data) / sizeof (ARow)); i++) {
		ARow *arow = &(data[i]);
		GdaRow *row = gda_row_new (NCOLS);
		GValue *value;
		value = gda_row_get_value (row, 0);
		if (arow->col0) {
			if (*arow->col0 == '-')
				G_VALUE_TYPE (value) = G_TYPE_INVALID;
			else {
				gda_value_reset_with_type (value, G_TYPE_STRING);
				g_value_set_string (value, arow->col0);
			}
		}

		value = gda_row_get_value (row, 1);
		if (arow->col1) {
			if (*arow->col1 == '-')
				G_VALUE_TYPE (value) = G_TYPE_INVALID;
			else {
				gda_value_reset_with_type (value, G_TYPE_STRING);
				g_value_set_string (value, arow->col1);
			}
		}

		value = gda_row_get_value (row, 2);
		if (arow->col2) {
			if (*arow->col2 == '-')
				G_VALUE_TYPE (value) = G_TYPE_INVALID;
			else {
				gda_value_reset_with_type (value, G_TYPE_STRING);
				g_value_set_string (value, arow->col2);
			}
		}

		value = gda_row_get_value (row, 3);
		if (arow->col3) {
			if (*arow->col3 == '-')
				G_VALUE_TYPE (value) = G_TYPE_INVALID;
			else {
				gda_value_reset_with_type (value, G_TYPE_STRING);
				g_value_set_string (value, arow->col3);
			}
		}

		g_ptr_array_add (model->priv->rows, row);
	}
}
示例#9
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;
}
示例#10
0
static const GValue *
gda_data_access_wrapper_get_value_at (GdaDataModel *model, gint col, gint row, GError **error)
{
	GdaDataAccessWrapper *imodel;

	g_return_val_if_fail (GDA_IS_DATA_ACCESS_WRAPPER (model), NULL);
	imodel = (GdaDataAccessWrapper*) model;
	g_return_val_if_fail (imodel->priv, NULL);
	g_return_val_if_fail (imodel->priv->model, NULL);
	g_return_val_if_fail (row >= 0, NULL);

	if (col >= imodel->priv->nb_cols) {
		g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_COLUMN_OUT_OF_RANGE_ERROR,
			     _("Column %d out of range (0-%d)"), col, imodel->priv->nb_cols - 1);
		return NULL;
	}

	if (!imodel->priv->rows) {
		/* imodel->priv->model is a random access model, use it */
		if (imodel->priv->rows_mapping)
			return gda_data_model_get_value_at (imodel->priv->model, imodel->priv->rows_mapping [col],
							    row, error);
		else
			return gda_data_model_get_value_at (imodel->priv->model, col, row, error);
	}
	else {
		GdaRow *gda_row;
		gint tmp;
		tmp = row;
		gda_row = g_hash_table_lookup (imodel->priv->rows, &tmp);
		if (gda_row) {
			GValue *val = gda_row_get_value (gda_row, col);
			if (gda_row_value_is_valid (gda_row, val))
				return val;
			else
				return NULL;
		}
		else {
			g_assert (imodel->priv->iter);
			if (imodel->priv->iter_row < 0) {
				if (gda_data_model_iter_move_next (imodel->priv->iter)) {
					tmp = row;
					gda_row = g_hash_table_lookup (imodel->priv->rows, &tmp);
					if (row == imodel->priv->iter_row) {
						GValue *val = gda_row_get_value (gda_row, col);
						if (gda_row_value_is_valid (gda_row, val))
							return val;
						else
							return NULL;
					}
				}
				else {
					g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
						      "%s", _("Can't set iterator's position"));
					return NULL;
				}
			}
				
			gda_row = NULL;
			if (row != imodel->priv->iter_row) {
				if (row > imodel->priv->iter_row) {
					/* need to move forward */
					while ((imodel->priv->iter_row < row) && 
					       gda_data_model_iter_move_next (imodel->priv->iter));
				}
				else {
					/* need to move backwards */
					g_assert (imodel->priv->model_access_flags & GDA_DATA_MODEL_ACCESS_CURSOR_BACKWARD);
					while ((imodel->priv->iter_row > row) && 
					       gda_data_model_iter_move_prev (imodel->priv->iter)) ;
				}
			}

			if (! (imodel->priv->model_access_flags & GDA_DATA_MODEL_ACCESS_CURSOR_BACKWARD) ||
			    ! (imodel->priv->model_access_flags & GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD)) {
				tmp = row;
				gda_row = g_hash_table_lookup (imodel->priv->rows, &tmp);

				if (gda_row) {
					GValue *val = gda_row_get_value (gda_row, col);
					if (gda_row_value_is_valid (gda_row, val))
						return val;
					else
						return NULL;
				}
			}
			else {
				/* in this case iter can be moved forward and backward at will => we only
				 * need to keep a pool of GdaRow for performances reasons */
				tmp = row;
				gda_row = g_hash_table_lookup (imodel->priv->rows, &tmp);

				if (!gda_row) {
					if (! imodel->priv->rows_buffer_array) {
						imodel->priv->rows_buffer_array = g_array_sized_new (FALSE, FALSE, 
												     sizeof (GdaRow*),
												     ROWS_POOL_SIZE);
						imodel->priv->rows_buffer_index = g_array_sized_new (FALSE, FALSE, 
												     sizeof (gint), 
												     ROWS_POOL_SIZE);
					}
					else if (imodel->priv->rows_buffer_array->len == ROWS_POOL_SIZE) {
						/* get rid of the oldest row (was model's index_row row)*/
						gint index_row;

						index_row = g_array_index (imodel->priv->rows_buffer_index, gint,
									   ROWS_POOL_SIZE - 1);
						g_array_remove_index (imodel->priv->rows_buffer_array,
								      ROWS_POOL_SIZE - 1);
						g_array_remove_index (imodel->priv->rows_buffer_index,
								      ROWS_POOL_SIZE - 1);
						g_hash_table_remove (imodel->priv->rows, &index_row);
					}
					if (gda_data_model_iter_move_to_row (imodel->priv->iter, row)) {
						gda_row = create_new_row (imodel);
						g_array_prepend_val (imodel->priv->rows_buffer_array, gda_row);
						g_array_prepend_val (imodel->priv->rows_buffer_index, imodel->priv->iter_row);
					}
				}

				GValue *val;
				val = gda_row ? gda_row_get_value (gda_row, col) : NULL;
				if (gda_row && gda_row_value_is_valid (gda_row, val))
					return val;
				else
					return NULL;
			}
		}
	}

	g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
		      "%s", _("Can't access data"));
	return NULL;
}