[gnome-db] [PATCH] libgda Firebird patch - 090204-0



 This patch adds blob read support to Firebird provider.

 Attached a patch file and 2 new files that should be posted (copied) in
libgda/providers/firebird/ before aplying the patch.

Attachment: libgda_firebird_090204-0.diff.gz
Description: GNU Zip compressed data

/* GDA Firebird Blob
 * Copyright (C) 1998-2004 The GNOME Foundation
 *
 * AUTHORS:
 *         Albi Jeronimo <jeronimoalbi yahoo com ar>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "gda-firebird-blob.h"
#include "gda-firebird-provider.h"
#include "gda-firebird-recordset.h"
#include <libgda/gda-intl.h>

typedef struct _FirebirdBlobPrivate FirebirdBlobPrivate;

/* FirebirdBlob private structure */
struct _FirebirdBlobPrivate {
	isc_blob_handle blob_handle;
	isc_tr_handle ftr;
	GdaBlobMode mode;
	ISC_QUAD blob_id;
	GdaConnection *cnc;
};

static void	gda_firebird_blob_free_data (GdaBlob *blob);
static gint	gda_firebird_blob_open (GdaBlob *blob, GdaBlobMode mode);
static gint	gda_firebird_blob_read (GdaBlob *blob, gpointer buf, gint size, gint *bytes_read);
static gint	gda_firebird_blob_close (GdaBlob *blob);


/********************************
 * FirebirdBlob public methods *
 ********************************/

GdaBlob *
gda_firebird_blob_new (GdaConnection *cnc)
{
	FirebirdBlobPrivate *priv;
	GdaBlob *blob;
	
	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
	
	blob = g_new0 (GdaBlob, 1);
	blob->priv_data = g_new0 (FirebirdBlobPrivate, 1);
		
	priv = blob->priv_data;
	priv->mode = -1;
	priv->blob_handle = NULL;
	priv->cnc = cnc;
	priv->ftr = NULL;
		
	blob->free_data = gda_firebird_blob_free_data;
	blob->open = gda_firebird_blob_open;
	blob->read = gda_firebird_blob_read;
	blob->close = gda_firebird_blob_close;
	blob->write = NULL;
	blob->lseek = NULL;
	blob->remove = NULL;

	return blob;
}

void
gda_firebird_blob_set_id (GdaBlob *blob,
			  const ISC_QUAD *blob_id)
{
	FirebirdBlobPrivate *priv;

	g_return_if_fail (blob != NULL);

	priv = blob->priv_data;
	
	priv->blob_id.gds_quad_high = blob_id->gds_quad_high;
	priv->blob_id.gds_quad_low = blob_id->gds_quad_low;
}


/********************************
 * FirebirdBlob private methods *
 ********************************/

static void
gda_firebird_blob_free_data (GdaBlob *blob)
{
	FirebirdBlobPrivate *priv;
	ISC_STATUS status[20];

	g_return_if_fail (blob != NULL);
	
	priv = blob->priv_data;

	/* Rollback transaction if active */
	if (priv->ftr)
		isc_rollback_transaction (status, priv->ftr);
	
	g_free (priv);
	
	blob->priv_data = NULL;
}

static gint
gda_firebird_blob_open (GdaBlob *blob, 
			GdaBlobMode mode)
{
	FirebirdBlobPrivate *priv;
	GdaFirebirdConnection *fcnc;
	
	g_return_val_if_fail (blob != NULL, -1);

	priv = blob->priv_data;
	/* Process Blob only if is not oppened */
	if (!priv->blob_handle) {
		
		fcnc = g_object_get_data (G_OBJECT (priv->cnc), CONNECTION_DATA);
		if (!fcnc) {
			gda_connection_add_error_string (priv->cnc, _("Invalid Firebird handle"));
			return -1;
		}
		
		if (isc_start_transaction (fcnc->status, &(priv->ftr), 1, &(fcnc->handle), 0, NULL)) {
			gda_connection_add_error_string (priv->cnc, _("Unable to start transaction"));
			return -1;
		}
		
		priv->mode = mode;
		if (!isc_open_blob2 (fcnc->status, &(fcnc->handle), &(priv->ftr),
				     &(priv->blob_handle), &(priv->blob_id), 0, NULL)) {
			return 0;
		}
	}
	
	gda_connection_add_error_string (priv->cnc, _("Blob already open"));
	
	return -1;
}

static gint 
gda_firebird_blob_read (GdaBlob *blob,
			gpointer buf,
			gint size,
			gint *bytes_read)
{
	GdaFirebirdConnection *fcnc;
	FirebirdBlobPrivate *priv;
	gushort actual_segment_length;
	gint fetch_stat;
	
	g_return_val_if_fail (blob != NULL, -1);
	g_return_val_if_fail (blob->priv_data != NULL, -1);
	g_return_val_if_fail (bytes_read != NULL, -1);

	priv = blob->priv_data;

	/* Process Blob only if is oppened */
	if (priv->blob_handle) {
	
		/* I don't know if buffer comes initialized, so I initialize */
		if (!buf)
			buf = g_malloc0 (size);
	
		fcnc = g_object_get_data (G_OBJECT (priv->cnc), CONNECTION_DATA);
		if (!fcnc) {
			gda_connection_add_error_string (priv->cnc, _("Invalid Firebird handle"));
			return -1;
		}
	
		fetch_stat = isc_get_segment (
					fcnc->status,
					&(priv->blob_handle),
					&actual_segment_length,
					(gushort) size,
					(gchar *) buf);

		/* If we reach blob EOF */
		if (fetch_stat == isc_segstr_eof) {
			*(bytes_read) = (gint) actual_segment_length;
			return -1;
		}
	
		/* Fetched OK or partially */
		if ((fetch_stat == 0) || (fetch_stat == isc_segment)) {
			*(bytes_read) = (gint) actual_segment_length;
			return 0;
		}
		else
			gda_connection_add_error_string (priv->cnc, _("Error getting blob segment."));

	}
		
	gda_connection_add_error_string (priv->cnc, _("Can't read a closed Blob"));
	
	return -1;
}

static gint 
gda_firebird_blob_close (GdaBlob *blob)
{
	FirebirdBlobPrivate *priv;
	GdaFirebirdConnection *fcnc;

	g_return_val_if_fail (blob != NULL, -1);
	g_return_val_if_fail (blob->priv_data != NULL, -1);

	priv = blob->priv_data;

	/* Close Blob if is opened */
	if (priv->blob_handle) {
	
		fcnc = g_object_get_data (G_OBJECT (priv->cnc), CONNECTION_DATA);
		if (!fcnc) {
			gda_connection_add_error_string (priv->cnc, _("Invalid Firebird handle"));
			return -1;
		}
		
		if (!isc_close_blob (fcnc->status, &(priv->blob_handle))) {
			
			/* Rollback transaction if active */
			if (priv->ftr)
				isc_rollback_transaction (fcnc->status, &(priv->ftr));
			
			priv->blob_handle = NULL;
			priv->ftr = NULL;

			return 0;
		}
		else
			gda_connection_add_error_string (priv->cnc, _("Unable to close blob."));
	}

	gda_connection_add_error_string (priv->cnc, _("Blob is closed"));

	return -1;
}



/* GDA Firebird Blob
 * Copyright (C) 1998-2004 The GNOME Foundation
 *
 * AUTHORS:
 *         Albi Jeronimo <jeronimoalbi yahoo com ar>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef _GDA_FIREBIRD_BLOB_H_
#define _GDA_FIREBIRD_BLOB_H

#include <libgda/gda-blob.h>
#include <libgda/gda-connection.h>
#include <ibase.h>

/* Firebird Blob public interface */

GdaBlob		*gda_firebird_blob_new (GdaConnection *cnc);
void		 gda_firebird_blob_set_id (GdaBlob *self, const ISC_QUAD *blob_id);

#endif /* _GDA_FIREBIRD_BLOB_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]