From: Tom Lane Date: Fri, 23 Mar 2001 22:07:50 +0000 (+0000) Subject: Doc update from Roberto Mello: improved versions of instr() examples. X-Git-Tag: REL9_0_0~20902 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=3311e250cdcc1b8f566b9f255b8705ff9f2c3450;p=pg-rex%2Fsyncrep.git Doc update from Roberto Mello: improved versions of instr() examples. --- diff --git a/doc/src/sgml/plsql.sgml b/doc/src/sgml/plsql.sgml index 3f162f6f50..87202b6445 100644 --- a/doc/src/sgml/plsql.sgml +++ b/doc/src/sgml/plsql.sgml @@ -1,5 +1,5 @@ @@ -2407,13 +2407,6 @@ WITH (isstrict, iscachable); This function should probably be integrated into the core. - - The third function (that takes 4 parameters) is implemented in - PL/Tcl but I plan on porting it to PL/pgSQL so in case we want to - include it in OpenACS we don't need to require PL/Tcl. Plus - PL/pgSQL should be more efficient. - - -- -- instr functions that mimic Oracle's counterpart @@ -2424,127 +2417,128 @@ WITH (isstrict, iscachable); -- not passed, assume 1 (search starts at first character). -- -- by Roberto Mello (rmello@fslc.usu.edu) +-- modified by Robert Gaszewski (graszew@poland.com) -- Licensed under the GPL v2 or later. -- -DROP FUNCTION instr(varchar, varchar); -CREATE FUNCTION instr(varchar, varchar) RETURNS integer AS ' +DROP FUNCTION instr(varchar,varchar); +CREATE FUNCTION instr(varchar,varchar) RETURNS integer AS ' DECLARE pos integer; BEGIN - pos:= instr($1, $2, 1); + pos:= instr($1,$2,1); RETURN pos; END; -' LANGUAGE 'plpgsql'; +' language 'plpgsql'; + + +DROP FUNCTION instr(varchar,varchar,integer); +CREATE FUNCTION instr(varchar,varchar,integer) RETURNS integer AS ' +DECLARE + string ALIAS FOR $1; + string_to_search ALIAS FOR $2; + beg_index ALIAS FOR $3; + pos integer NOT NULL DEFAULT 0; + temp_str varchar; + beg integer; + length integer; + ss_length integer; +BEGIN + IF beg_index > 0 THEN + + temp_str := substring(string FROM beg_index); + pos := position(string_to_search IN temp_str); + + IF pos = 0 THEN + RETURN 0; + ELSE + RETURN pos + beg_index - 1; + END IF; + ELSE + ss_length := char_length(string_to_search); + length := char_length(string); + beg := length + beg_index - ss_length + 2; + + WHILE beg > 0 LOOP + + temp_str := substring(string FROM beg FOR ss_length); + pos := position(string_to_search IN temp_str); + + IF pos > 0 THEN + RETURN beg; + END IF; + + beg := beg - 1; + END LOOP; + RETURN 0; + END IF; +END; +' language 'plpgsql'; -DROP FUNCTION instr(varchar, varchar, integer); -CREATE FUNCTION instr(varchar, varchar, integer) RETURNS integer AS ' +-- +-- Written by Robert Gaszewski (graszew@poland.com) +-- Licensed under the GPL v2 or later. +-- +DROP FUNCTION instr(varchar,varchar,integer,integer); +CREATE FUNCTION instr(varchar,varchar,integer,integer) RETURNS integer AS ' DECLARE string ALIAS FOR $1; string_to_search ALIAS FOR $2; beg_index ALIAS FOR $3; + occur_index ALIAS FOR $4; pos integer NOT NULL DEFAULT 0; - ending integer; + occur_number integer NOT NULL DEFAULT 0; temp_str varchar; beg integer; + i integer; length integer; - temp_int integer; + ss_length integer; BEGIN IF beg_index > 0 THEN - -- Get substring from 1 to beg_index + beg := beg_index; + temp_str := substring(string FROM beg_index); - temp_str := substring(string FROM beg_index); - pos := position(string_to_search IN temp_str); + FOR i IN 1..occur_index LOOP + pos := position(string_to_search IN temp_str); + + IF i = 1 THEN + beg := beg + pos - 1; + ELSE + beg := beg + pos; + END IF; + + temp_str := substring(string FROM beg + 1); + END LOOP; IF pos = 0 THEN RETURN 0; ELSE - RETURN pos + beg_index - 1; + RETURN beg; END IF; - ELSE + ss_length := char_length(string_to_search); length := char_length(string); + beg := length + beg_index - ss_length + 2; - IF beg_index = -1 THEN - ending := length; - beg := ending; - temp_int := 1; - ELSE - ending := length - abs(beg_index); - beg := ending; - temp_int := ending - beg; - END IF; - - WHILE pos = 0 AND beg <> 1 LOOP - - temp_str := substring(string FROM beg FOR temp_int); + WHILE beg > 0 LOOP + temp_str := substring(string FROM beg FOR ss_length); pos := position(string_to_search IN temp_str); - -- Keep moving left + IF pos > 0 THEN + occur_number := occur_number + 1; + + IF occur_number = occur_index THEN + RETURN beg; + END IF; + END IF; beg := beg - 1; - temp_int := (ending - beg) + 1; END LOOP; - END IF; - IF pos = 0 THEN RETURN 0; - ELSE - RETURN beg + 1; END IF; END; -' LANGUAGE 'plpgsql'; - --- --- The next one (where all four params are passed) is in PL/Tcl --- because I had no more patience to do it in PL/pgSQL. --- It'd probably be faster in PL/pgSQL (that being the reason why --- I implemented the first two functions in PL/pgSQL) so someday I'll do it. --- - -DROP FUNCTION instr(varchar, varchar, integer, integer); -CREATE FUNCTION instr(varchar, varchar, integer, integer) RETURNS integer AS ' - set string1 $1 - set string2 $2 - set n $3 - set m $4 - - if { $n > 0 } { - set pos [string first $string2 $string1 [expr $n -1]] - if { $pos < 0 } { - return 0 - } else { - for { set i 1 } { $i < $m } { incr i } { - set pos [string first $string2 $string1 [expr $pos + 1]] - if { $pos < 0 } { - return 0 - } - } - } - } - - if { $n < 0 } { - set pos [string last $string2 $string1 [expr [string length $string1] + $n]] - - if { $pos < 0 } { - return 0 - } else { - for { set i 1 } { $i < $m } { incr i } { - # n is negative so we add - set pos [string last $string2 $string1 [expr $pos - 1]] - if { $pos < 0 } { - return 0 - } - } - } - } - - if { $pos < 0 } { - return 0 - } else { - return [expr $pos + 1] - } -' LANGUAGE 'pltcl'; +' language 'plpgsql';