Re: Insert VARCHAR int TEXT field
Posted in 1997
On Fri, 14 Nov 1997, Christian Hernoux wrote: } At the FTP archive of Informix-related files I find the file : blob_char } with the function blob_to_char. Here is the code : } } [...snip...] } } 4GL Code : } DEFINE MyVar CHAR(200) } DEFINE MyText TEXT } } SELECT MyTable.FText INTO MyText FROM MyTable } CALL blob_to_char(200, MyText) RETURNING MyVAR } } I want to make char to blob. This is my code. Is it correct? No, for a variety of reasons. I'm reorganizing the message somewhat to put the I4GL code first... } 4GL Code : } DEFINE MyVar CHAR(200) } DEFINE MyText TEXT } } LET MyVar = "The IIUG mailing list is a technical list about Informix } products" } ** a) solution } CALL char_to_blob(200, MyVar) RETURNING MyText } ** b) solution } CALL char_to_blob(200, MyVar) } SELECT MyTable.FText INTO MyText FROM MyTable } ** c) solution You need solution c: LOCATE MyText IN MEMORY CALL char_to_blob(200, MyCar, Mytext) -- !Yes! You can only pass blob variables into subroutines; you cannot return them. Further, when you do pass them, they are passed by reference, not by value. When you think about it, that's a good idea -- copying a 30 MB blob in memory would be a trifle expensive. That means you are going to fiddle with MyText inside the char_to_blob() routine. Since we are going to overwrite the existing contents of the blob (if there is any), we're going to need to do some major surgery on the C code. } #include <locator.h> } #include <string.h> } } char_to_blob(arg) } int arg; } { } loc_t *blobp; } short charsize, n; } char s1[513]; } } if (arg != 2) if (arg != 3) } fgl_fatal("char_to_blob.c", 18, -1318); fgl_fatal(__FILE__, __LINE__, -1318); /* Not mandatory, but more flexible! */ } } popshort(&charsize); } popquote(s1); /* I4GL arguments are pushed in left-to-right order, */ /* so the arguments must be popped right-to-left */ poplocator(&blobp); /* Using popquote would yield a string with 512 characters followed by '\\0' */ /* Do we want those trailing blanks? Probably not. Use popvchar()! */ /* If popvchar() is not available, then use popquote() and strip the */ /* blanks using the idiom: s1[stleng(s1, sizeof(s1)-1)] = '\\0'; */ /* The more traditional (because safer) idiom uses strlen(s1) in */ /* place of sizeof(s1)-1, but I think this is safe. */ popvchar(s1, sizeof(s1)); popshort(&charsize); } if (charsize > 512) } charsize = 512; How much are we going to assume about the blob? For example, do we know that the blob is always going to be in memory? Or could it be a blob located anywhere? We'll assume it is a blob in memory, but we won't assume that it has not yet been used, so there may be some old data to get rid of. assert(blobp->loc_loctype == LOCMEMORY); if (blobp->loc_buffer != 0) free(blobp->loc_buffer); blobp->loc_buffer = (char *)malloc(charsize+1); assert(blobp->loc_buffer != (char *)0); blobp->loc_bufsize = charsize + 1; blobp->loc_size = charsize; /* Do not want to store that '\\0'! */ blobp->loc_mflags = 0; strncpy(blobp->loc_buffer, s1, charsize); blobp->loc_buffer[charsize] = '\\0'; } n = (charsize < blobp->loc_size) ? charsize : blobp->loc_size; } } strncpy(blobp->loc_buffer, s1, n); } blobp->loc_buffer[n] = '\\0'; } } ** a) solution } pushlocator(blobp, n); /* Does this function exists ? */ } return(1); } ** b) solution } $INSERT INTO MyTable VALUES(No, FText) = (0, blobp) } return(0); } ** c) another solution ? Solution c: we've been modifying the blob in the calling function. return(0); } } I've not test-compiled the code, and I may have forgotten something, but I believe that it is a bit closer to what you need. You could test to see whether there is enough space in the original buffer instead of disarding it unconditionally. It is tempting to reverse the order of the first two parameters to the function, so that you can pop the size before you pop the string; you can then do away with the local variable s1 and just ensure that the blob has enough space and then pop the string directly into that space, thus saving a copy operation. Some of the information you need is in I4GL Ref Vol 1 at the end of Chapter 2; the rest is in the header locator.h under $INFORMIXDIR. } I can test it because my database is producting. } I'm afraid of breaking the database. You shouldn't be able to break the database; you would crash your program (if you got it to compile!), but it shouldn't crash the database. } I use Informix On-Line 5.01 and I4GL 4.11 UC4. Maybe you should think about upgrading. } The schema of MyTable is : } CREATE TABLE MyTable ( } No SERIAL, } Ftext TEXT IN TABLE } } There's a 56-byte overhead in the table, plus a second network transmission when you use blobs. Make sure the data you are adding is big enough to warrant the space and time overhead. Yours, Jonathan Leffler (johnl@informix.com) #include <witticism.h>