Re: Blobs (JPEG images) and Pro*C/C++ (Oracle 8)

From: Mark Tomlinson <marktoml_at_gdi.net>
Date: 1998/09/14
Message-ID: <35fe67b1.83374245_at_newshost.us.oracle.com>#1/1


here is a way to access the LOB data from any of the recent precompilers. This demos insert/update, you could turn it around for a read...[Tom Kyte had the original Idea for this BTW]

Name: proc_blob.PC
Category: Pro*C
Port: Generic
Description: Example of Using Pro*C to insert/update a BLOB column, (piecewise). This would work with a V7 precopiler. Uses DBMS_LOB.WRITE to do the work... [could be further extended to store the filename in the table and even use the DBMS_LOB.READ to read it back]


/*
create table test_o8blob ( the_blob blob );

and the package:

create package test_o8blob_pkg
as

   g_blob blob;
end;
*/

/*
I use the package to maintain my Lob Locator instead of trying to muck around with it in pro*c
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sqlproto.h>
#include <sqlca.h>

#define BUF_SIZE 15000
#define min(a, b) (((a) < (b)) ? (a) : (b))

void sqlerror(void); /* handles unrecoverable errors */

typedef struct { short len; char arr[32000]; } my_blob;

EXEC SQL BEGIN DECLARE SECTION;
EXEC SQL TYPE my_blob is VARRAW(32000);

	my_blob blob_piece;
	char    * data;
	int     data_size;
	int     amt_to_write;
	int     amt_written;
	VARCHAR         username[20];
	VARCHAR         password[20];
	VARCHAR         connect[20];

EXEC SQL END DECLARE SECTION; int main(int argc, char *argv[ ], char *envp[ ]) {
	FILE* input;
	char    Infile[128];
	int       fsize, chunk;
	char   *buff;
	int      count = 0;

	if(argc < 5)	{
		printf("Not enough arguments\nUsage: progname.exe user
password connect filename\n");
		return 1;
	}

	strcpy((char *)username.arr, argv[1]);          /* copy the
username */
	username.len = (short) strlen((char *)username.arr);
	strcpy((char *)password.arr, argv[2]);          /* copy the
password */
	password.len = (short) strlen((char *)password.arr);
	strcpy((char *)connect.arr, argv[3]);          /* copy the
connect string */
	connect.len = (short) strlen((char *)connect.arr);
	strcpy(Infile,argv[4]);

	input = fopen( Infile, "rb" );
 	if ( input == NULL ) 	{ 
		printf( "unable to open input file %s\n",argv[4]);

		return 1; 	
	} 
	
	printf( "Input file %s opened\n",Infile); 
	buff = (char *) malloc(BUF_SIZE);
	if (buff == NULL)	{
		printf("unable to allocate %d bytes for temp
buffer\n", BUF_SIZE);
		return 1;
	}
	fseek(input,0,SEEK_END);
	fsize = ftell(input);
	rewind(input);
	printf( "Input File length: %d\n", fsize); 
    	data_size = fsize;
    	data = (char *)malloc( data_size );
    	memset( data, 0, data_size );
	if (data == NULL)	{
		printf("unable to allocate %d bytes for data
buffer\n", fsize);
		return 1;
	}
	while ((chunk = fread(buff, 1, BUF_SIZE, input )) == BUF_SIZE
)	{
		memcpy(data+(count * chunk),buff,chunk);
		count += 1;
	}
	printf("memory buffers allocated\n");
	free(buff); 	

	EXEC SQL WHENEVER SQLERROR DO sqlerror();
	EXEC SQL CONNECT :username IDENTIFIED BY :password USING
:connect;
	printf("\nConnected to ORACLE as user: %s\n", username.arr);

    	EXEC SQL EXECUTE
    		BEGIN
        		insert into test_o8blob values ( empty_blob()
)
        		return the_blob into test_o8blob_pkg.g_blob;
    		END;
    	END-EXEC;


    	for( amt_to_write = min(data_size,32000), amt_written = 0;
         	       amt_written < data_size;
         	       amt_written += amt_to_write,
                        amt_to_write =
min(32000,data_size-amt_written) )
    	{
        		memmove( blob_piece.arr, data+amt_written,
amt_to_write );
        		blob_piece.len = (short)amt_to_write;
        		printf( "Writing blob from offset %d, for %d
bytes\n", amt_written+1, amt_to_write );
        		EXEC SQL EXECUTE
        			BEGIN
            			dbms_lob.write( lob_loc =>
test_o8blob_pkg.g_blob,amount => :amt_to_write,offset => :amt_written+1,buffer => :blob_piece );
        			END;
        		END-EXEC;
    	}
	printf("done\n");
	free(data);
	EXEC SQL COMMIT WORK RELEASE;
	return 0;

}

void sqlerror()
{

        EXEC SQL WHENEVER SQLERROR CONTINUE;

	printf("\nORACLE error detected:\n");
	printf("\n% .70s \n", sqlca.sqlerrm.sqlerrmc);

	EXEC SQL ROLLBACK RELEASE;
	exit(1);

} Received on Mon Sep 14 1998 - 00:00:00 CEST

Original text of this message