Beispiel #1
0
/*
 * Blob read request
 */
static glong
gda_sqlite_blob_op_read (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size)
{
	GdaSqliteBlobOp *bop;
	GdaBinary *bin;
	gpointer buffer = NULL;
	int rc;

	g_return_val_if_fail (GDA_IS_SQLITE_BLOB_OP (op), -1);
	bop = GDA_SQLITE_BLOB_OP (op);
  GdaSqliteBlobOpPrivate *priv = gda_sqlite_blob_op_get_instance_private (bop);
	g_return_val_if_fail (priv->sblob, -1);
	if (offset >= G_MAXINT)
		return -1;
	g_return_val_if_fail (blob, -1);

	if (offset > G_MAXINT)
		return -1;
	if (size > G_MAXINT)
		return -1;

	GdaSqliteProvider *prov = g_weak_ref_get (&priv->provider);
	g_return_val_if_fail (prov != NULL, -1);

	bin = gda_blob_get_binary (blob);
	gda_binary_set_data (bin, (guchar*) "", 0);

	/* fetch blob data using C API into bin->data, and set bin->binary_length */
	int rsize;
	int len;

	len = SQLITE3_CALL (prov, sqlite3_blob_bytes) (priv->sblob);
	if (len < 0){
		g_object_unref (prov);
		return -1;
	} else if (len == 0) {
		g_object_unref (prov);
		return 0;
	}
		
	rsize = (int) size;
	if (offset >= len) {
		g_object_unref (prov);
		return -1;
	}

	if (len - offset < rsize)
		rsize = len - offset;
  
	rc = SQLITE3_CALL (prov, sqlite3_blob_read) (priv->sblob, buffer, rsize, offset);
	if (rc != SQLITE_OK) {
		gda_binary_reset_data (bin);
		g_object_unref (prov);
		return -1;
	}
	gda_binary_set_data (bin, buffer, rsize);
	g_object_unref (prov);

	return gda_binary_get_size (bin);
}
Beispiel #2
0
/**
 * gda_xa_transaction_register_connection:
 * @xa_trans: a #GdaXaTransaction object
 * @cnc: the connection to add to @xa_trans
 * @branch: the branch qualifier
 * @error: (nullable): a place to store errors, or %NULL
 *
 * Registers @cnc to be used by @xa_trans to create a distributed transaction.
 *
 * Note: any #GdaConnection object can only be registered with at most one #GdaXaTransaction object; also
 * some connections may not be registered at all with a #GdaXaTransaction object because the database
 * provider being used does not support it.
 *
 * Returns: %TRUE if no error occurred
 */
gboolean
gda_xa_transaction_register_connection  (GdaXaTransaction *xa_trans, GdaConnection *cnc, 
					 const gchar *branch, GError **error)
{
	GdaBinary *bin;

	g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE);
	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
	g_return_val_if_fail (branch && *branch, FALSE);
	GdaXaTransactionPrivate *priv = gda_xa_transaction_get_instance_private (xa_trans);
	if (strlen (branch) >= 64) {
		g_set_error (error, GDA_XA_TRANSACTION_ERROR,
			     GDA_XA_TRANSACTION_CONNECTION_BRANCH_LENGTH_ERROR,
			     "%s", _("Connection branch cannot exceed 63 bytes"));
		return FALSE;
	}

	const GdaBinary *ebranch = g_hash_table_lookup (priv->cnc_hash, cnc);
	if (ebranch) {
		bin = gda_binary_new ();
		gda_binary_set_data (bin, (const guchar *)branch, strlen (branch) + 1);
		g_hash_table_insert (priv->cnc_hash, cnc, bin);
		return TRUE;
	}

	/* check that @cnc is not already registered with another GdaXaTransaction object */
	if (g_object_get_data (G_OBJECT (cnc), "_gda_xa_transaction")) {
		g_set_error (error, GDA_XA_TRANSACTION_ERROR,
			     GDA_XA_TRANSACTION_ALREADY_REGISTERED_ERROR,
			     "%s", _("Connection already registered with another GdaXaTransaction object"));
		return FALSE;
	}

	/* check that connection supports distributed transaction, only ONE connection in @xa_trans is allowed
	 * to not support them */
	GdaServerProvider *prov;
	prov = gda_connection_get_provider (cnc);

	if (!gda_server_provider_supports_feature (prov, cnc, GDA_CONNECTION_FEATURE_XA_TRANSACTIONS)) {
		/* if another connection does not support distributed transaction, then there is an error */
		if (priv->non_xa_cnc) {
			g_set_error (error, GDA_XA_TRANSACTION_ERROR,
				     GDA_XA_TRANSACTION_DTP_NOT_SUPPORTED_ERROR,
				     "%s", _("Connection does not support distributed transaction"));
			return FALSE;
		}
		else
			priv->non_xa_cnc = cnc;
	}

	bin = gda_binary_new ();
	gda_binary_set_data (bin, (const guchar *)branch, strlen (branch) + 1);
	priv->cnc_list = g_list_prepend (priv->cnc_list, cnc);
	g_hash_table_insert (priv->cnc_hash, cnc, bin);
	g_object_ref (cnc);
	g_object_set_data (G_OBJECT (cnc), "_gda_xa_transaction", xa_trans);

	return TRUE;
}
Beispiel #3
0
int
main (int argc, char** argv)
{
	gchar *file;
	GdaBinary* bin;
	gchar *bin_data;
	gsize bin_length;
	GError *error = NULL;

	/* load binary data */
	file = g_build_filename (CHECK_FILES, "data", "sales_test.db", NULL);
	if (! g_file_get_contents (file, &bin_data, &bin_length, &error)) {
		g_print ("Error reading binary file: %s\n", error->message);
		return EXIT_FAILURE;
	}		
	g_free (file);
	bin = gda_binary_new ();
	gda_binary_set_data (bin, (guchar*) bin_data, bin_length);

	/* convert to string */
	gchar *conv1;
	conv1 = gda_binary_to_string (bin, 0);
	
	/* convert back to binary */
	GdaBinary *bin2;
	bin2 = gda_string_to_binary (conv1);
	
	/* compare bin */
	if (gda_binary_get_size (bin) != gda_binary_get_size (bin2)) {
		g_print ("Error: binary length differ: from %ld to %ld\n",
			 gda_binary_get_size (bin), gda_binary_get_size (bin2));
		return EXIT_FAILURE;
	}
	gint i;
	for (i = 0; i < gda_binary_get_size (bin); i++) {
	  guchar *buffer = gda_binary_get_data (bin);
	  guchar *buffer2 = gda_binary_get_data (bin2);
		if (buffer[i] != buffer2[i]) {
			g_print ("Error: binary differ orig[%d]=%d and copy[%d]=%d\n",
				 i, buffer[i], i, buffer2[i]);
			return EXIT_FAILURE;
		}
	}
	
	g_free (conv1);
	gda_binary_free (bin);
	gda_binary_free (bin2);

	g_print ("Ok (file size: %d)\n", bin_length);
	return EXIT_SUCCESS;
}
Beispiel #4
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;
}