11<!--
2- $Header: /cvsroot/pgsql/doc/src/sgml/Attic/plsql.sgml,v 2.24 2001/03/17 18:08:14 petere Exp $
2+ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/plsql.sgml,v 2.25 2001/03/23 22:07:50 tgl Exp $
33-->
44
55<chapter id="plpgsql">
@@ -2407,13 +2407,6 @@ WITH (isstrict, iscachable);
24072407 This function should probably be integrated into the core.
24082408 </comment>
24092409
2410- <para>
2411- The third function (that takes 4 parameters) is implemented in
2412- PL/Tcl but I plan on porting it to PL/pgSQL so in case we want to
2413- include it in OpenACS we don't need to require PL/Tcl. Plus
2414- PL/pgSQL should be more efficient.
2415- </para>
2416-
24172410<programlisting>
24182411--
24192412-- instr functions that mimic Oracle's counterpart
@@ -2424,127 +2417,128 @@ WITH (isstrict, iscachable);
24242417-- not passed, assume 1 (search starts at first character).
24252418--
24262419-- by Roberto Mello (rmello@fslc.usu.edu)
2420+ -- modified by Robert Gaszewski (graszew@poland.com)
24272421-- Licensed under the GPL v2 or later.
24282422--
24292423
2430- DROP FUNCTION instr(varchar, varchar);
2431- CREATE FUNCTION instr(varchar, varchar) RETURNS integer AS '
2424+ DROP FUNCTION instr(varchar,varchar);
2425+ CREATE FUNCTION instr(varchar,varchar) RETURNS integer AS '
24322426DECLARE
24332427 pos integer;
24342428BEGIN
2435- pos:= instr($1, $2, 1);
2429+ pos:= instr($1,$2,1);
24362430 RETURN pos;
24372431END;
2438- ' LANGUAGE 'plpgsql';
2432+ ' language 'plpgsql';
2433+
2434+
2435+ DROP FUNCTION instr(varchar,varchar,integer);
2436+ CREATE FUNCTION instr(varchar,varchar,integer) RETURNS integer AS '
2437+ DECLARE
2438+ string ALIAS FOR $1;
2439+ string_to_search ALIAS FOR $2;
2440+ beg_index ALIAS FOR $3;
2441+ pos integer NOT NULL DEFAULT 0;
2442+ temp_str varchar;
2443+ beg integer;
2444+ length integer;
2445+ ss_length integer;
2446+ BEGIN
2447+ IF beg_index > 0 THEN
2448+
2449+ temp_str := substring(string FROM beg_index);
2450+ pos := position(string_to_search IN temp_str);
2451+
2452+ IF pos = 0 THEN
2453+ RETURN 0;
2454+ ELSE
2455+ RETURN pos + beg_index - 1;
2456+ END IF;
2457+ ELSE
2458+ ss_length := char_length(string_to_search);
2459+ length := char_length(string);
2460+ beg := length + beg_index - ss_length + 2;
2461+
2462+ WHILE beg > 0 LOOP
2463+
2464+ temp_str := substring(string FROM beg FOR ss_length);
2465+ pos := position(string_to_search IN temp_str);
2466+
2467+ IF pos > 0 THEN
2468+ RETURN beg;
2469+ END IF;
2470+
2471+ beg := beg - 1;
2472+ END LOOP;
2473+ RETURN 0;
2474+ END IF;
2475+ END;
2476+ ' language 'plpgsql';
24392477
2440- DROP FUNCTION instr(varchar, varchar, integer);
2441- CREATE FUNCTION instr(varchar, varchar, integer) RETURNS integer AS '
2478+ --
2479+ -- Written by Robert Gaszewski (graszew@poland.com)
2480+ -- Licensed under the GPL v2 or later.
2481+ --
2482+ DROP FUNCTION instr(varchar,varchar,integer,integer);
2483+ CREATE FUNCTION instr(varchar,varchar,integer,integer) RETURNS integer AS '
24422484DECLARE
24432485 string ALIAS FOR $1;
24442486 string_to_search ALIAS FOR $2;
24452487 beg_index ALIAS FOR $3;
2488+ occur_index ALIAS FOR $4;
24462489 pos integer NOT NULL DEFAULT 0;
2447- ending integer;
2490+ occur_number integer NOT NULL DEFAULT 0 ;
24482491 temp_str varchar;
24492492 beg integer;
2493+ i integer;
24502494 length integer;
2451- temp_int integer;
2495+ ss_length integer;
24522496BEGIN
24532497 IF beg_index > 0 THEN
2454- -- Get substring from 1 to beg_index
2498+ beg := beg_index;
2499+ temp_str := substring(string FROM beg_index);
24552500
2456- temp_str := substring(string FROM beg_index);
2457- pos := position(string_to_search IN temp_str);
2501+ FOR i IN 1..occur_index LOOP
2502+ pos := position(string_to_search IN temp_str);
2503+
2504+ IF i = 1 THEN
2505+ beg := beg + pos - 1;
2506+ ELSE
2507+ beg := beg + pos;
2508+ END IF;
2509+
2510+ temp_str := substring(string FROM beg + 1);
2511+ END LOOP;
24582512
24592513 IF pos = 0 THEN
24602514 RETURN 0;
24612515 ELSE
2462- RETURN pos + beg_index - 1 ;
2516+ RETURN beg ;
24632517 END IF;
2464-
24652518 ELSE
2519+ ss_length := char_length(string_to_search);
24662520 length := char_length(string);
2521+ beg := length + beg_index - ss_length + 2;
24672522
2468- IF beg_index = -1 THEN
2469- ending := length;
2470- beg := ending;
2471- temp_int := 1;
2472- ELSE
2473- ending := length - abs(beg_index);
2474- beg := ending;
2475- temp_int := ending - beg;
2476- END IF;
2477-
2478- WHILE pos = 0 AND beg <> 1 LOOP
2479-
2480- temp_str := substring(string FROM beg FOR temp_int);
2523+ WHILE beg > 0 LOOP
2524+ temp_str := substring(string FROM beg FOR ss_length);
24812525 pos := position(string_to_search IN temp_str);
24822526
2483- -- Keep moving left
2527+ IF pos > 0 THEN
2528+ occur_number := occur_number + 1;
2529+
2530+ IF occur_number = occur_index THEN
2531+ RETURN beg;
2532+ END IF;
2533+ END IF;
24842534
24852535 beg := beg - 1;
2486- temp_int := (ending - beg) + 1;
24872536 END LOOP;
2488- END IF;
24892537
2490- IF pos = 0 THEN
24912538 RETURN 0;
2492- ELSE
2493- RETURN beg + 1;
24942539 END IF;
24952540END;
2496- ' LANGUAGE 'plpgsql';
2497-
2498- --
2499- -- The next one (where all four params are passed) is in PL/Tcl
2500- -- because I had no more patience to do it in PL/pgSQL.
2501- -- It'd probably be faster in PL/pgSQL (that being the reason why
2502- -- I implemented the first two functions in PL/pgSQL) so someday I'll do it.
2503- --
2504-
2505- DROP FUNCTION instr(varchar, varchar, integer, integer);
2506- CREATE FUNCTION instr(varchar, varchar, integer, integer) RETURNS integer AS '
2507- set string1 $1
2508- set string2 $2
2509- set n $3
2510- set m $4
2511-
2512- if { $n > 0 } {
2513- set pos [string first $string2 $string1 [expr $n -1]]
2514- if { $pos < 0 } {
2515- return 0
2516- } else {
2517- for { set i 1 } { $i < $m } { incr i } {
2518- set pos [string first $string2 $string1 [expr $pos + 1]]
2519- if { $pos < 0 } {
2520- return 0
2521- }
2522- }
2523- }
2524- }
2525-
2526- if { $n < 0 } {
2527- set pos [string last $string2 $string1 [expr [string length $string1] + $n]]
2528-
2529- if { $pos < 0 } {
2530- return 0
2531- } else {
2532- for { set i 1 } { $i < $m } { incr i } {
2533- # n is negative so we add
2534- set pos [string last $string2 $string1 [expr $pos - 1]]
2535- if { $pos < 0 } {
2536- return 0
2537- }
2538- }
2539- }
2540- }
2541-
2542- if { $pos < 0 } {
2543- return 0
2544- } else {
2545- return [expr $pos + 1]
2546- }
2547- ' LANGUAGE 'pltcl';
2541+ ' language 'plpgsql';
25482542</programlisting>
25492543 </sect3>
25502544 </sect2>
0 commit comments