/****************************************************************************** * ExtractSubString(Haystack,, First Marker, Default, startindex, numberofchar) DROP FUNCTION ExtractSubString(VARCHAR, VARCHAR, VARCHAR, INT, INT); CREATE FUNCTION ExtractSubString(VARCHAR, VARCHAR, VARCHAR, INT, INT) RETURNS text AS '/usr/lib/pgsql/SecomSQLib.so', 'ExtractSubString' LANGUAGE 'C'; ******************************************************************************/ PG_FUNCTION_INFO_V1(ExtractSubString); Datum ExtractSubString(PG_FUNCTION_ARGS) { text *t1 = PG_GETARG_TEXT_P(0); text *t2 = PG_GETARG_TEXT_P(1); text *t3 = PG_GETARG_TEXT_P(2); int startindex = PG_GETARG_INT32(3); int numberofchar = PG_GETARG_INT32(4); text *resulttext; int len,i, foundstartmarker=0, // Indicates field found foundendmarker=0; // Indicates end of field found char haystack[256], // temp storage of source string workstring[256], *startmarker, // Requested field header (For example 'D1') *searchpointer, // Working pointer *startmarkerpos, //this contains the location of the startmarker in the string of data *endmarkerpos; //this contains the location of the endmarker in the string of data memcpy(haystack, VARDATA(t1),VARSIZE(t1)-VARHDRSZ); //copy in the old data, No terminator VARDATA(t1) points to start of string len=(VARSIZE(t1)-VARHDRSZ); //get string length haystack[len]='\0'; //put in terminator startmarker = VARDATA(t2); if ((VARSIZE(t2)-VARHDRSZ) > 0) //Default marker supplied - start scanning for marker { for (searchpointer=haystack; (searchpointer<(haystack+len)) && (foundendmarker==0); searchpointer=searchpointer+2) { if ((foundstartmarker==0) && (*searchpointer==*startmarker)) { //Check First character of startmarker if (*(searchpointer+1)==*(startmarker+1)) { //Check Second character of startmarker startmarkerpos=searchpointer; foundstartmarker=1; continue; } } if ((foundstartmarker==1) && ((*searchpointer >= 0x41) && (*searchpointer <= 0x46))) { //Check For A, B, C, D, E or F if (((*(searchpointer+1) >= 0x30) && (*(searchpointer+1) <= 0x39)) || (*(searchpointer+1) = 0x46 )) { //Check for integer or F (for FF) endmarkerpos=searchpointer; foundendmarker=1; // fprintf(stderr, "Endmarker Found at Iteration: %d", i); } } } if ((foundstartmarker==1) && (foundendmarker==0)) //This could happen when we want the last field in the string { endmarkerpos=haystack+len; //we pick up from the Startpointer and include the rest of the string foundendmarker=1; // fprintf(stderr, "Startmarker found, but no Endmarker"); } if (foundendmarker==1) //Ok, everything went smooth, go on and return the string between the markers { startmarkerpos=startmarkerpos+2; //advance by two to skip the startmarker len=endmarkerpos-startmarkerpos; //find the length of the string if (len>0) { //if no data is found in the field, return Default memcpy(workstring, startmarkerpos, len); workstring[len]='\0'; /* resulttext = (text *) palloc(VARHDRSZ + len); //allocate memory VARATT_SIZEP(resulttext) = (VARHDRSZ + len); //sizes the result ? memcpy(VARDATA(resulttext), startmarkerpos, len); //copy in our result to the result-memory address PG_RETURN_TEXT_P(resulttext); */ } } else //startmarker was supplied but not found in string -- return default { PG_RETURN_TEXT_P(t3); //return default } } else //Startmarker not supplied -- copy in the whole string to workstring and do the substring { strcpy(workstring, haystack); } //now we need to do the substring-operation if (strlen(workstring) < startindex) //does the start index point outside the workstring ? { PG_RETURN_TEXT_P(t3); //return default } if (strlen(workstring) < (startindex + numberofchar) -1) //does the start index + number of chars point outside the workstring ? { numberofchar = strlen(workstring) - startindex+1; //reduce number of chars } strcpy(workstring, workstring + startindex -1); workstring[numberofchar]='\0'; len = strlen(workstring); if (len==0) PG_RETURN_TEXT_P(t3); //return default //Now we need to scan threw and see if we got nothing but spaces. if we did return default for (i=0; i < len; i++) { if (workstring[i] != 0x20) break; //Non space found, return result if (i==len - 1) PG_RETURN_TEXT_P(t3); //Only spaces found,return default } resulttext = (text *) palloc(VARHDRSZ + len); //allocate memory VARATT_SIZEP(resulttext) = (VARHDRSZ + len); //sizes the result ? memcpy(VARDATA(resulttext), workstring, len); //copy in our result to the result-memory address PG_RETURN_TEXT_P(resulttext); } /*****************************************************************************/