Обсуждение: invalid regular expression: invalid backreference number

Поиск
Список
Период
Сортировка

invalid regular expression: invalid backreference number

От
Jeff Ross
Дата:
I've got a function that generates usernames and passwords on insert if
they haven't yet been set.  The code block is:

   -- create a new username for new people
   IF (LENGTH(COALESCE(new_pp_username, '')) = 0) THEN
     LOOP
       gen_pp_username := LOWER(SUBSTRING(new_pp_first_name from 1 for
2)) || LOWER(SUBSTRING(new_pp_last_name from 1 for 8)) ||
round(random()*100);
       gen_pp_username := regexp_replace(gen_pp_username, E'\\W', '', 'g');
       EXIT WHEN ((SELECT COUNT(*) FROM people WHERE pp_username =
gen_pp_username AND pp_provisional_p='f') = 0);
     END LOOP;
   ELSE
     gen_pp_username := new_pp_username;
   END IF;

   -- create a new password if there is none
   IF (LENGTH(COALESCE(new_pp_password, '')) = 0) THEN
     chars :=
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
     FOR i in 1..8 LOOP
       gen_pp_password := gen_pp_password || SUBSTRING(chars,
ceil(random()*LENGTH(chars)), 1);2007-02-15 15:32:57.264727500
     END LOOP;
   ELSE
     gen_pp_password := new_pp_password;
   END IF;

This used to work before my upgrade to 8.2.1.

The error the function now throws is:

<jross%wykids>ERROR:  invalid regular expression: invalid backreference
number
2007-02-15 15:32:57.264729500 <jross%wykids>CONTEXT:  SQL function
"substring" statement 1
2007-02-15 15:32:57.264730500   PL/pgSQL function "set_people" line 58
at assignment

I've futzed around with the various ways I can call substring, but I
don't understand why this is throwing the error.

Any help would be greatly appreciated!

Jeff Ross

Re: invalid regular expression: invalid backreference number

От
Tom Lane
Дата:
Jeff Ross <jross@wykids.org> writes:
> This used to work before my upgrade to 8.2.1.

Which version were you using before?

> The error the function now throws is:

> <jross%wykids>ERROR:  invalid regular expression: invalid backreference
> number
> 2007-02-15 15:32:57.264729500 <jross%wykids>CONTEXT:  SQL function
> "substring" statement 1
> 2007-02-15 15:32:57.264730500   PL/pgSQL function "set_people" line 58
> at assignment

You could have helped us out by mentioning exactly which line was line
58 ... but I'm guessing it's this one:

>        gen_pp_password := gen_pp_password || SUBSTRING(chars,
> ceil(random()*LENGTH(chars)), 1);2007-02-15 15:32:57.264727500

Since ceil() produces float8 which does not implicitly cast to int,
this call has probably never done what you thought --- AFAICS it will
cast all the arguments to text and invoke substring(text,text,text)
which treats its second argument as a SQL99 regular expression.
I doubt that it's useful to figure out exactly what changed to make
it fail more obviously than before --- I think the problem is that
you'd better cast the ceil() result to int.

[ObRant: still another example of why implicit casts to text are evil.]

            regards, tom lane

Re: invalid regular expression: invalid backreference number

От
Jeff Ross
Дата:
Tom Lane wrote:

Thanks for the reply, Tom.
> Jeff Ross <jross@wykids.org> writes:
>
>> This used to work before my upgrade to 8.2.1.
>>
>
> Which version were you using before?
>
>
8.1.x
>> The error the function now throws is:
>>
>
>
>> <jross%wykids>ERROR:  invalid regular expression: invalid backreference
>> number
>> 2007-02-15 15:32:57.264729500 <jross%wykids>CONTEXT:  SQL function
>> "substring" statement 1
>> 2007-02-15 15:32:57.264730500   PL/pgSQL function "set_people" line 58
>> at assignment
>>
>
> You could have helped us out by mentioning exactly which line was line
> 58 ... but I'm guessing it's this one:
>
>
Sorry, my bad, but you guessed right.
>>        gen_pp_password := gen_pp_password || SUBSTRING(chars,
>> ceil(random()*LENGTH(chars)), 1);2007-02-15 15:32:57.264727500
>>
>
> Since ceil() produces float8 which does not implicitly cast to int,
> this call has probably never done what you thought --- AFAICS it will
> cast all the arguments to text and invoke substring(text,text,text)
> which treats its second argument as a SQL99 regular expression.
> I doubt that it's useful to figure out exactly what changed to make
> it fail more obviously than before --- I think the problem is that
> you'd better cast the ceil() result to int.
>
> [ObRant: still another example of why implicit casts to text are evil.]
>
>             regards, tom lane
>
>
To debug this I've extracted the code into its own function:


CREATE FUNCTION gen_password() RETURNS text AS $$
DECLARE
  password text;
  chars := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
BEGIN
  FOR i IN 1..9 LOOP
    password := password || SUBSTRING(chars,
ceil(random()*LENGTH(chars))::int, 1);
  END LOOP;
  return password;
END;
$$
LANGUAGE plpgsql;


when I try to generate the function with this I get the following error:

psql -f create_password.sql wykids
psql:create_password.sql:12: LOG:  statement: CREATE FUNCTION
gen_password() RETURNS text AS $$
DECLARE
        password text;
        chars :=
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
BEGIN
        FOR i IN 1..9 LOOP
                password := password || SUBSTRING(chars,
ceil(random()*LENGTH(chars))::int, 1);
        END LOOP;
        return password;
END;
$$
LANGUAGE plpgsql;
psql:create_password.sql:12: ERROR:  invalid type name ""
CONTEXT:  compile of PL/pgSQL function "gen_password" near line 3

I've not been able to figure out this error message at all, and google
hasn't been any help either.  I'm only now learning functions (I
inherited the one that used to work) so if someone can point me in the
general direction I sure would appreciate it.

Thanks,

Jeff Ross



Re: invalid regular expression: invalid backreference number

От
Stephan Szabo
Дата:
On Sun, 18 Feb 2007, Jeff Ross wrote:

> Tom Lane wrote:
> >
> > Since ceil() produces float8 which does not implicitly cast to int,
> > this call has probably never done what you thought --- AFAICS it will
> > cast all the arguments to text and invoke substring(text,text,text)
> > which treats its second argument as a SQL99 regular expression.
> > I doubt that it's useful to figure out exactly what changed to make
> > it fail more obviously than before --- I think the problem is that
> > you'd better cast the ceil() result to int.
> >
> > [ObRant: still another example of why implicit casts to text are evil.]
> >
> To debug this I've extracted the code into its own function:
>
>
> CREATE FUNCTION gen_password() RETURNS text AS $$
> DECLARE
>   password text;
>   chars := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
> BEGIN
>   FOR i IN 1..9 LOOP
>     password := password || SUBSTRING(chars,
> ceil(random()*LENGTH(chars))::int, 1);
>   END LOOP;
>   return password;
> END;
> $$
> LANGUAGE plpgsql;
>
>
> when I try to generate the function with this I get the following error:
>
> psql -f create_password.sql wykids
> psql:create_password.sql:12: LOG:  statement: CREATE FUNCTION
> gen_password() RETURNS text AS $$
> DECLARE
>         password text;
>         chars :=
[snipped]
> psql:create_password.sql:12: ERROR:  invalid type name ""
> CONTEXT:  compile of PL/pgSQL function "gen_password" near line 3

Given the context and function, I'd say it's complaining because you
didn't put a type after chars and before the := for the initializer.
Changing it to chars text := ... should make that work.
In addition, the default initialized value for password will be a NULL
which probably won't do what you want either, since NULL || something is
NULL, so you probably want password text := '' there.

Re: invalid regular expression: invalid backreference number

От
Tom Lane
Дата:
Jeff Ross <jross@wykids.org> writes:
> To debug this I've extracted the code into its own function:

> CREATE FUNCTION gen_password() RETURNS text AS $$
> DECLARE
>   password text;
>   chars := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
> BEGIN

You forgot to give a type for the "chars" variable.

> psql:create_password.sql:12: ERROR:  invalid type name ""
> CONTEXT:  compile of PL/pgSQL function "gen_password" near line 3

I agree that this is a pretty awful error message :-( ... will take a
look at whether it can be improved.

            regards, tom lane