Skip to content

Commit 45bfef7

Browse files
committed
Fix sample INSTR() functions in the plpgsql documentation.
These functions are stated to be Oracle-compatible, but they weren't. Yugo Nagata noticed that while our code returns zero for a zero or negative fourth parameter (occur_index), Oracle throws an error. Further testing by me showed that there was also a discrepancy in the interpretation of a negative third parameter (beg_index): Oracle thinks that a negative beg_index indicates the last place where the target substring can *begin*, whereas our code thinks it is the last place where the target can *end*. Adjust the sample code to behave like Oracle in both these respects. Also change it to be a CDATA[] section, simplifying copying-and-pasting out of the documentation source file. And fix minor problems in the introductory comment, which wasn't very complete or accurate. Back-patch to all supported branches. Although this patch only touches documentation, we should probably call it out as a bug fix in the next minor release notes, since users who have adopted the functions will likely want to update their versions. Yugo Nagata and Tom Lane Discussion: https://postgr.es/m/20171229191705.c0b43a8c.nagata@sraoss.co.jp
1 parent 469fa9a commit 45bfef7

File tree

1 file changed

+42
-44
lines changed

1 file changed

+42
-44
lines changed

doc/src/sgml/plpgsql.sgml

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5268,27 +5268,33 @@ $$ LANGUAGE plpgsql STRICT IMMUTABLE;
52685268
your porting efforts.
52695269
</para>
52705270

5271-
<programlisting>
5271+
<indexterm>
5272+
<primary><function>instr</> function</primary>
5273+
</indexterm>
5274+
5275+
<programlisting><![CDATA[
52725276
--
52735277
-- instr functions that mimic Oracle's counterpart
5274-
-- Syntax: instr(string1, string2, [n], [m]) where [] denotes optional parameters.
5278+
-- Syntax: instr(string1, string2 [, n [, m]])
5279+
-- where [] denotes optional parameters.
52755280
--
5276-
-- Searches string1 beginning at the nth character for the mth occurrence
5277-
-- of string2. If n is negative, search backwards. If m is not passed,
5278-
-- assume 1 (search starts at first character).
5281+
-- Search string1, beginning at the nth character, for the mth occurrence
5282+
-- of string2. If n is negative, search backwards, starting at the abs(n)'th
5283+
-- character from the end of string1.
5284+
-- If n is not passed, assume 1 (search starts at first character).
5285+
-- If m is not passed, assume 1 (find first occurrence).
5286+
-- Returns starting index of string2 in string1, or 0 if string2 is not found.
52795287
--
52805288

52815289
CREATE FUNCTION instr(varchar, varchar) RETURNS integer AS $$
5282-
DECLARE
5283-
pos integer;
52845290
BEGIN
5285-
pos:= instr($1, $2, 1);
5286-
RETURN pos;
5291+
RETURN instr($1, $2, 1);
52875292
END;
52885293
$$ LANGUAGE plpgsql STRICT IMMUTABLE;
52895294

52905295

5291-
CREATE FUNCTION instr(string varchar, string_to_search varchar, beg_index integer)
5296+
CREATE FUNCTION instr(string varchar, string_to_search_for varchar,
5297+
beg_index integer)
52925298
RETURNS integer AS $$
52935299
DECLARE
52945300
pos integer NOT NULL DEFAULT 0;
@@ -5297,25 +5303,23 @@ DECLARE
52975303
length integer;
52985304
ss_length integer;
52995305
BEGIN
5300-
IF beg_index &gt; 0 THEN
5306+
IF beg_index > 0 THEN
53015307
temp_str := substring(string FROM beg_index);
5302-
pos := position(string_to_search IN temp_str);
5308+
pos := position(string_to_search_for IN temp_str);
53035309

53045310
IF pos = 0 THEN
53055311
RETURN 0;
53065312
ELSE
53075313
RETURN pos + beg_index - 1;
53085314
END IF;
5309-
ELSIF beg_index &lt; 0 THEN
5310-
ss_length := char_length(string_to_search);
5315+
ELSIF beg_index < 0 THEN
5316+
ss_length := char_length(string_to_search_for);
53115317
length := char_length(string);
5312-
beg := length + beg_index - ss_length + 2;
5318+
beg := length + 1 + beg_index;
53135319

5314-
WHILE beg &gt; 0 LOOP
5320+
WHILE beg > 0 LOOP
53155321
temp_str := substring(string FROM beg FOR ss_length);
5316-
pos := position(string_to_search IN temp_str);
5317-
5318-
IF pos &gt; 0 THEN
5322+
IF string_to_search_for = temp_str THEN
53195323
RETURN beg;
53205324
END IF;
53215325

@@ -5330,7 +5334,7 @@ END;
53305334
$$ LANGUAGE plpgsql STRICT IMMUTABLE;
53315335

53325336

5333-
CREATE FUNCTION instr(string varchar, string_to_search varchar,
5337+
CREATE FUNCTION instr(string varchar, string_to_search_for varchar,
53345338
beg_index integer, occur_index integer)
53355339
RETURNS integer AS $$
53365340
DECLARE
@@ -5342,39 +5346,32 @@ DECLARE
53425346
length integer;
53435347
ss_length integer;
53445348
BEGIN
5345-
IF beg_index &gt; 0 THEN
5346-
beg := beg_index;
5347-
temp_str := substring(string FROM beg_index);
5349+
IF occur_index <= 0 THEN
5350+
RAISE 'argument ''%'' is out of range', occur_index
5351+
USING ERRCODE = '22003';
5352+
END IF;
53485353

5354+
IF beg_index > 0 THEN
5355+
beg := beg_index - 1;
53495356
FOR i IN 1..occur_index LOOP
5350-
pos := position(string_to_search IN temp_str);
5351-
5352-
IF i = 1 THEN
5353-
beg := beg + pos - 1;
5354-
ELSE
5355-
beg := beg + pos;
5356-
END IF;
5357-
53585357
temp_str := substring(string FROM beg + 1);
5358+
pos := position(string_to_search_for IN temp_str);
5359+
IF pos = 0 THEN
5360+
RETURN 0;
5361+
END IF;
5362+
beg := beg + pos;
53595363
END LOOP;
53605364

5361-
IF pos = 0 THEN
5362-
RETURN 0;
5363-
ELSE
5364-
RETURN beg;
5365-
END IF;
5366-
ELSIF beg_index &lt; 0 THEN
5367-
ss_length := char_length(string_to_search);
5365+
RETURN beg;
5366+
ELSIF beg_index < 0 THEN
5367+
ss_length := char_length(string_to_search_for);
53685368
length := char_length(string);
5369-
beg := length + beg_index - ss_length + 2;
5369+
beg := length + 1 + beg_index;
53705370

5371-
WHILE beg &gt; 0 LOOP
5371+
WHILE beg > 0 LOOP
53725372
temp_str := substring(string FROM beg FOR ss_length);
5373-
pos := position(string_to_search IN temp_str);
5374-
5375-
IF pos &gt; 0 THEN
5373+
IF string_to_search_for = temp_str THEN
53765374
occur_number := occur_number + 1;
5377-
53785375
IF occur_number = occur_index THEN
53795376
RETURN beg;
53805377
END IF;
@@ -5389,6 +5386,7 @@ BEGIN
53895386
END IF;
53905387
END;
53915388
$$ LANGUAGE plpgsql STRICT IMMUTABLE;
5389+
]]>
53925390
</programlisting>
53935391
</sect2>
53945392

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy