示例#1
0
void
_gda_oracle_set_value (GValue *value, 
		       GdaOracleValue *ora_value,
		       GdaConnection *cnc)
{
	GdaTime gtime;
	GdaTimestamp timestamp;
	sb2 year;
	ub1 month;
	ub1 day;
	ub1 hour;
	ub1 min;
	ub1 sec;

	if (ora_value->indicator == -1) {
		gda_value_set_null (value);
		return;
	}

	gda_value_reset_with_type (value, ora_value->g_type);
	switch (ora_value->s_type) {
	case GDA_STYPE_INT:
		g_value_set_int (value, *((gint *) ora_value->value));
		break;
	case GDA_STYPE_STRING: {
		gchar *string_buffer, *tmp;
		
		string_buffer = (gchar *) ora_value->value;
		string_buffer [ora_value->rlen] = '\0';
		g_strchomp (string_buffer);
		//tmp = g_locale_to_utf8 (string_buffer, -1, NULL, NULL, NULL);
		//g_value_take_string (value, tmp);
		g_value_set_string (value, string_buffer);
		if (ora_value->use_callback) {
			g_free (string_buffer);
			ora_value->value = NULL;
		}
		break;
	}
	case GDA_STYPE_BOOLEAN:
		g_value_set_boolean (value, (*((gint *) ora_value->value)) ? TRUE: FALSE);
		break;
	case GDA_STYPE_DATE: {
		GDate *date;
		OCIDateGetDate ((CONST OCIDate *) ora_value->value,
				(sb2 *) &year,
				(ub1 *) &month,
				(ub1 *) &day);
		date = g_date_new_dmy (day, month, year);
		g_value_take_boxed (value, date);
		break;
	}
	case GDA_STYPE_TIME: {
		OCIDateGetTime ((CONST OCIDate *) ora_value->value,
				(ub1 *) &hour,
				(ub1 *) &min,
				(ub1 *) &sec);
		gtime.hour = hour;
		gtime.minute = min;
		gtime.second = sec;
		gda_value_set_time (value, &gtime);
		break;
	}
	case GDA_STYPE_TIMESTAMP: {
		OCIDateGetDate ((CONST OCIDate *) ora_value->value,
				(sb2 *) &year,
				(ub1 *) &month,
				(ub1 *) &day);
		OCIDateGetTime ((CONST OCIDate *) ora_value->value,
				(ub1 *) &hour,
				(ub1 *) &min,
				(ub1 *) &sec);
		timestamp.year = year;
		timestamp.month = month;
		timestamp.day = day;
		timestamp.hour = hour;
		timestamp.minute = min;
		timestamp.second = sec;
		timestamp.fraction = 0;
		timestamp.timezone = 0;
		gda_value_set_timestamp(value, &timestamp);
		break;
	}
	case GDA_STYPE_INT64:
		TO_IMPLEMENT; /* test that value fits in */
		g_value_set_int64 (value, atoll (ora_value->value));
		break;
	case GDA_STYPE_UINT64:
		TO_IMPLEMENT; /* test that value fits in */
		g_value_set_uint64 (value, atoll (ora_value->value));
		break;
	case GDA_STYPE_UINT:
		TO_IMPLEMENT; /* test that value fits in */
		g_value_set_uint (value, *((guint*) ora_value->value));
		break;
	case GDA_STYPE_FLOAT:
		g_value_set_float (value, *((gfloat*) ora_value->value));
		break;
	case GDA_STYPE_DOUBLE:
		g_value_set_double (value, *((gdouble*) ora_value->value));
		break;
	case GDA_STYPE_LONG:
		TO_IMPLEMENT;
		break;
	case GDA_STYPE_ULONG:
		TO_IMPLEMENT;
		break;
	case GDA_STYPE_NUMERIC: {
		GdaNumeric *numeric;
		gchar *tmp;
		g_assert (!ora_value->use_callback);
		
		tmp = g_malloc0 (ora_value->defined_size);
		memcpy (tmp, ora_value->value, ora_value->defined_size);
		tmp [ora_value->rlen] = '\0';
		g_strchomp (tmp);

		numeric = gda_numeric_new ();
		gda_numeric_set_from_string (numeric, tmp);
		g_free (tmp);
		gda_numeric_set_precision (numeric, ora_value->precision);
		gda_numeric_set_width (numeric, ora_value->scale);
		g_value_take_boxed (value, numeric);
		break;
	}
	case GDA_STYPE_BINARY: {
		GdaBinary *bin;

		bin = g_new0 (GdaBinary, 1);
		if (ora_value->use_callback) {		
			bin->data = ora_value->value;
			ora_value->value = NULL;
		}
		else {
			bin->data = g_new (guchar, ora_value->rlen);
			memcpy (bin->data, ora_value->value, ora_value->rlen);
		}
		bin->binary_length = ora_value->rlen;
		gda_value_take_binary (value, bin);
		break;
	}
	case GDA_STYPE_BLOB: {
		GdaBlob *blob;
		GdaBlobOp *op;
		OCILobLocator *lobloc;
		OracleConnectionData *cdata;
		gint result;

		/* REM: we need to make a "copy" of the lob locator to give to the GdaOracleblobOp object */
		cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, NULL);
		if (!cdata) {
			gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
			gda_value_set_null (value);
			return;
		}

		result = OCIDescriptorAlloc ((dvoid *) cdata->henv, (dvoid **) &lobloc, 
					     (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"))) {
			gda_value_set_null (value);
			return;
		}

		result = OCILobAssign ((dvoid *) cdata->henv, (dvoid *) cdata->herr, ora_value->value, &lobloc);
		if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
					     _("Could not copy Lob locator"))) {
			gda_value_set_null (value);
			return;
		}

		blob = g_new0 (GdaBlob, 1);
		op = gda_oracle_blob_op_new (cnc, lobloc);
		gda_blob_set_op (blob, op);
		g_object_unref (op);

		gda_value_take_blob (value, blob);
		break;
	}
	case GDA_STYPE_CHAR: {
		TO_IMPLEMENT; /* test that value fits in */
		g_value_set_schar (value, *((gint8*) ora_value->value));
		break;
	}
	case GDA_STYPE_SHORT: {
		TO_IMPLEMENT; /* test that value fits in */
		gda_value_set_short (value, *((gint*) ora_value->value));
		break;
	}
	case GDA_STYPE_GTYPE:
		TO_IMPLEMENT;
		break;
	case GDA_STYPE_GEOMETRIC_POINT:
		TO_IMPLEMENT;
		break;
	case GDA_STYPE_NULL:
		gda_value_set_null (value);
		break;
	default:
		g_assert_not_reached ();
	}
}
示例#2
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;
		}
示例#3
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;
}