BLOB Help
Posted in 1999
A 4GL developer on IDS 7.3/SCO UnixWare asked how to build up a TEXT blob in Informix-4GL by appending formatted fields, without using INPUT and without the legacy third-party C functions. Jonathan Leffler replied that there is no way: a located BYTE/TEXT variable can only be populated via INPUT or LOCATE IN a named file, so the C routines are necessary. The poster then hit stray control/null characters at the start of the blob when PRINTing it in a report (the C code stores an integer field count at the front of the buffer) and worked around it by using field_count/pop_field to extract each field and reassemble a fixed-length string. Art Kagel asked for the C source, which was posted, but no fix to the C code is recorded in the thread.
Auto-generated by DrWatson from the posts below — may be imperfect; read the full thread.
Topics: Connectivity: ESQL/C, 4GL & Embedded SQL
Hi I am just starting to use BLOBS for a correspondence system at our site. Previously Blobs were handled via C functions but I want to do it via 4GL without calling those. How do I get data into the Blob without using INPUT ? I basically want to do this CALL push_field_data("C",name) CALL push_field_data("D",date_blah) CALL push_field_data("I",integer_value) The function push field data simply formats it dependent on the type indicated by the 1st parameter , and then adds the text into the global TEXT fied ( and incidentally adds a "|" character ). Basically LET myblob = myblob CLIPPED, "|", field_to_add CLIPPED I know thats not the right way to do it BUT , you get the idea. BTW I understand the use of LOCATE , FREE etc. I just need help with this bit. Everybody is welcome to respond with their 2 bobs worth. Thanks in advance.
This is pretty urgent , I'd appreciate help. BTW , I should probably have mentioned : I'm using 4GL, IDS 7.3 on SCo Unixware 7.
You know those C functions? They're necessary. There is no defined way of populating a located blob (BYTE or TEXT) variable in I4GL other than via an INPUT statement, or via the LOCATE IN "specified filename" (give or take any syntax errors). Robert Taylor wrote: > Hi I am just starting to use BLOBS for a correspondence system at our site. > > Previously Blobs were handled via C functions but I want to do it via 4GL > without calling those. How do I get data into the Blob without using INPUT ? > > I basically want to do this > > CALL push_field_data("C",name) > CALL push_field_data("D",date_blah) > CALL push_field_data("I",integer_value) > > The function push field data simply formats it dependent on the type > indicated by the 1st parameter , and then adds the text into the global > TEXT fied ( and incidentally adds a "|" character ). > > Basically > > LET myblob = myblob CLIPPED, "|", field_to_add CLIPPED > > I know thats not the right way to do it BUT , you get the idea. > BTW I understand the use of LOCATE , FREE etc. -- Jonathan Leffler (jleffler@informix.com, jleffler@earthlink.net) Guardian of DBD::Informix v0.62 -- see http://www.perl.com/CPAN #include <disclaimer.h>
Cheers for the help. I think our C functions were written by a 3rd party called Sherwood many years ago. I am still getting a problem using them though. I get a control character at the start of the BLOB field when I PRINT it in a REPORT. We have other programs that chop off that 1st character using a shell script , I don't want to have to do that and don't think it is the best solution. Have you or anyone else encountered this problem ? The control characters are ^G on the 1st row of the unload and ^K on the second. This happens in two seperate files. I need a fast answer if possible. Otherwise I'm going to use VARCHAR. If you can't get back to me quickly thanks anyway. Regards. Jonathan Leffler <jleffler@earthlink.net> wrote in message news:384F5275.8F246030@earthlink.net... > You know those C functions? They're necessary. There is no defined way of > populating > a located blob (BYTE or TEXT) variable in I4GL other than via an INPUT > statement, or > via the LOCATE IN "specified filename" (give or take any syntax errors). > > Robert Taylor wrote: > > > Hi I am just starting to use BLOBS for a correspondence system at our site. > > > > Previously Blobs were handled via C functions but I want to do it via 4GL > > without calling those. How do I get data into the Blob without using INPUT ? > > > > I basically want to do this > > > > CALL push_field_data("C",name) > > CALL push_field_data("D",date_blah) > > CALL push_field_data("I",integer_value) > > > > The function push field data simply formats it dependent on the type > > indicated by the 1st parameter , and then adds the text into the global > > TEXT fied ( and incidentally adds a "|" character ). > > > > Basically > > > > LET myblob = myblob CLIPPED, "|", field_to_add CLIPPED > > > > I know thats not the right way to do it BUT , you get the idea. > > BTW I understand the use of LOCATE , FREE etc. > > -- > Jonathan Leffler (jleffler@informix.com, jleffler@earthlink.net) > Guardian of DBD::Informix v0.62 -- see http://www.perl.com/CPAN > #include <disclaimer.h> > > >
OK - Control characters are a bummer. To get round the problem I have had to add some extra lines into my REPORT code. Basically I count the number of the fields in the BLOB ( we have a C function ). I use the field count in a FOR loop. I then 'pop' each field out ( C function ) in turn and add it to a big string with pipes between each field, obviously clipping as I go. I then print my accumulated string. Hey presto no control characters. As the fields get pop'd in reverse ( its a stack ) I need to put them in order which isn't difficult. The downside of this method is that I am using fixed length string for the large string and each field item. I can set these up large enough to know that they will always be big enough, but as every programmer knows, always is never always ! If anyone has a better solution to this then let me know. Thanks.
Post the source of the C functions if they are not large and perhaps someone will debug it for you if the changes are not complex. Art S. Kagel Robert Taylor wrote: > > Cheers for the help. I think our C functions were written by a 3rd party > called Sherwood many years ago. > I am still getting a problem using them though. > I get a control character at the start of the BLOB field when I PRINT it in > a REPORT. We have other programs that chop off that 1st character using a > shell script , I don't want to have to do that and don't think it is the > best solution. > > Have you or anyone else encountered this problem ? > The control characters are ^G on the 1st row of the unload and ^K on the > second. > This happens in two seperate files. > > I need a fast answer if possible. Otherwise I'm going to use VARCHAR. If you > can't get back to me quickly thanks anyway. > > Regards. > > Jonathan Leffler <jleffler@earthlink.net> wrote in message > news:384F5275.8F246030@earthlink.net... > > You know those C functions? They're necessary. There is no defined way > of > > populating > > a located blob (BYTE or TEXT) variable in I4GL other than via an INPUT > > statement, or > > via the LOCATE IN "specified filename" (give or take any syntax errors). > > > > Robert Taylor wrote: > > > > > Hi I am just starting to use BLOBS for a correspondence system at our > site. > > > > > > Previously Blobs were handled via C functions but I want to do it via > 4GL > > > without calling those. How do I get data into the Blob without using > INPUT ? > > > > > > I basically want to do this > > > > > > CALL push_field_data("C",name) > > > CALL push_field_data("D",date_blah) > > > CALL push_field_data("I",integer_value) > > > > > > The function push field data simply formats it dependent on the type > > > indicated by the 1st parameter , and then adds the text into the global > > > TEXT fied ( and incidentally adds a "|" character ). > > > > > > Basically > > > > > > LET myblob = myblob CLIPPED, "|", field_to_add CLIPPED > > > > > > I know thats not the right way to do it BUT , you get the idea. > > > BTW I understand the use of LOCATE , FREE etc. > > > > -- > > Jonathan Leffler (jleffler@informix.com, jleffler@earthlink.net) > > Guardian of DBD::Informix v0.62 -- see http://www.perl.com/CPAN > > #include <disclaimer.h> > > > > > >
OK - Here they are. Any help will be greatly appreciated. BYW - In normal circumstances should you be ables to do PRINT myblob In a report and not get some null characters at the start ? WHen you vi my output file the CTRL chars I spoke about are listed as 8 null characters etc by the vi editor. /* ** CREATE_BLOB_FIELD - creates memory space for blob, ** NOTE: calls _locate to locate the blob in memory ** input : the_blob - locator structure of blob */ int create_blob_field(n) int n; { loc_t *the_blob; char *myblob; int *mycount; if (n != 1) { return (0); } /* initialize id of blob space, count, and string field... */ created_flag = "Y"; poplocator(&the_blob); /* call function to locate the blob in memory */ status = _locate(the_blob, 12, 0, (char *)0); if (status < 0) { fgl_fatal(fgl_modname, 23, status); } if ( the_blob->loc_loctype != LOCMEMORY) { my_error(0); return (0); } free(the_blob->loc_buffer); myblob = the_blob->loc_buffer = (char *) malloc(MY_BLOB_SZ); mycount = (int *) myblob; *mycount = 0; myblob += sizeof(int); *myblob = (char) NULL; the_blob->loc_bufsize = the_blob->loc_size = the_blob->loc_xfercount = sizeof(int) + 1; the_blob->loc_indicator = the_blob->loc_status = 0; the_blob->loc_user_env = created_flag; the_blob->loc_currdata_p = the_blob->loc_buffer + sizeof(int) + 1; the_blob->loc_mflags = 1; return (0); } /* create_blob_field */ /* ** PUSH_FIELD - places input string at end of currently held string fields ** input : locator id of blob field, string field ** output: NONE */ int push_field(n) int n; { loc_t *the_blob; char *myblob; int *mycount; char *mystr; int no_flds; int length; int new_blob_sz; switch (n) { case 2: mystr = (char *) malloc(1001); popvchar(mystr, 1000); poplocator(&the_blob); break; default: return (0); break; } if (the_blob->loc_loctype != LOCMEMORY) { my_error(0); return (0); } if (the_blob->loc_user_env != created_flag) { my_error(1); return (0); } mycount = (int *) the_blob->loc_buffer; myblob = the_blob->loc_buffer + sizeof(int); /* process the string here */ new_blob_sz = strip_tail(mystr) + 1 + the_blob->loc_bufsize; if (new_blob_sz > MY_BLOB_SZ) { my_error(2); return (0); } the_blob->loc_xfercount = the_blob->loc_size = the_blob->loc_bufsize = new_blob_sz; the_blob->loc_currdata_p = the_blob->loc_buffer + new_blob_sz; strcat(mystr, "|"); strcat(myblob, mystr); /* increment the string count */ (*mycount)++; free(mystr); return (0); } /* push_field */ /* ** POP_FIELD - removes last currently held string field ** input: locator id of blob field ** ouput: string field */ int pop_field(n) int n; { loc_t *the_blob; char *myblob; int *mycount; char *mystr; int no_flds = 0; int ix; switch (n) { case 1: poplocator(&the_blob); break; default: retquote("", 1); return (1); break; } if (the_blob->loc_loctype != LOCMEMORY) { retquote("", 1); return (1); } if (the_blob->loc_user_env != created_flag) { my_error(1); retquote("", 1); return (1); } mycount = (int *) the_blob->loc_buffer; if ((*mycount == 0) || (the_blob->loc_bufsize <= 0)) { retquote("", 1); return (1); } myblob = the_blob->loc_buffer + sizeof(int); /* process string here */ ix = strlen(myblob) - 1; if (ix < 0) { retquote("", 1); return (1); } myblob[ix] = (char) NULL; while ((ix > 0) && (myblob[ix - 1] != '|')) ix--; (*mycount)--; retquote(&(myblob[ix]), strlen(&(myblob[ix]))); myblob[ix] = (char) NULL; the_blob->loc_xfercount = the_blob->loc_size = the_blob->loc_bufsize = strlen(myblob) + sizeof(int) + 1; the_blob->loc_currdata_p = the_blob->loc_buffer + the_blob->loc_bufsize; return (1); } /* pop_field */ /* ** NULL_FIELD resets the blob to an empty field ** input: locator struct - the blob ** output: NONE */ int null_field(n) int n; { int *mycount; loc_t *the_blob; char *myblob; switch (n) { case 1: poplocator(&the_blob); break; default: my_error( 3, "null_field" ); return (0); break; } if (the_blob->loc_loctype != LOCMEMORY) { my_error(0, ""); return (0); } if ((! the_blob->loc_user_env) || (the_blob->loc_user_env != created_flag)) { my_error(1, ""); return (0); } mycount = (int *) the_blob->loc_buffer; myblob = the_blob->loc_buffer + sizeof( int ); *mycount = 0; *myblob = (char) NULL; the_blob->loc_xfercount = the_blob->loc_size = the_blob->loc_bufsize = sizeof( int ) + 1; the_blob->loc_currdata_p = the_blob->loc_buffer + the_blob->loc_bufsize; return (0); } /* null_field */ /* ** FIELD_COUNT returns the no. of string fields currently held ** input: long int - id of blob ** output: integer - no of fields remaining in blob space */ int field_count(n) int n; { loc_t *the_blob; int *mycount; switch (n) { case 1: poplocator(&the_blob); break; default: retint(-1); return (1); break; } if (the_blob->loc_loctype != LOCMEMORY) { my_error(0); retint(0); return (1); } if (the_blob->loc_user_env != created_flag) { my_error(1); retint(0); return (1); } mycount = (int *) the_blob->loc_buffer; if ((*mycount <= 0) || (the_blob->loc_bufsize <= 0)) { retint(0); return (1); } else { retint(*mycount); return (1); } } /* field_count */ /* ** FREE_BLOB_FIELD ** input: blobid ( id of blob ) ** output: NONE */ int free_blob_field(n) int n; { loc_t *the_blob; char *myblob; if (n != 0) return(0); poplocator(&the_blob); if (the_blob->loc_loctype != LOCMEMORY) { my_error(0); return (0); } if (the_blob->loc_user_env != created_flag) { my_error(1); ret