Re: String manipulation

Lists: pgsql-general
From: pativo(at)arcor(dot)de (pativo)
To: pgsql-general(at)postgresql(dot)org
Subject: String manipulation
Date: 2004-02-17 11:46:53
Message-ID: 58babf1b.0402170346.4a719868@posting.google.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Hello to all,

I have small problem. I have some database fields (VARCHAR)
and these field should hold some ahex coded values. So the
string length must be even and each character can only be
0-9, a-f or A-F.
My idea was that:

====8<-----------------------------------

CREATE TABLE test (
id INT4 PRIMARY KEY NOT NULL DEFAULT nextID(),
text VARCHAR(150) NOT NULL CHECK(isAHex(text))
);

CREATE FUNCTION isAHex(VARCHAR) RETURNS BOOLEAN AS '
DECLARE
text_p ALIAS FOR $1;
BEGIN
IF ((length(text_p) % 2) <> 0) THEN
RETURN FALSE;
END IF;
-- TODO How to check each character
RETURN TRUE;
END;
' LANGUAGE 'plpgsql';

====8<-----------------------------------

Has anybody an idea how could I check each character?
I would prefer a solution in plpgsql!!

Thank!

pativo

--
\\://
(- 0)
---ooO-(_)-Ooo---


From: Bruno Wolff III <bruno(at)wolff(dot)to>
To: pativo <pativo(at)arcor(dot)de>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: String manipulation
Date: 2004-02-17 19:32:46
Message-ID: 20040217193246.GB28099@wolff.to
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

On Tue, Feb 17, 2004 at 03:46:53 -0800,
pativo <pativo(at)arcor(dot)de> wrote:
> Hello to all,
>
> I have small problem. I have some database fields (VARCHAR)
> and these field should hold some ahex coded values. So the
> string length must be even and each character can only be
> 0-9, a-f or A-F.

You can use a constraint that checks the value versus a regular
expression. Something like: ~ '^([0-9a-fA-F][0-9a-fA-F])+$^'
Unless the 150 character limit is a real business rule, you probably
want to use TEXT instead of VARCHAR(150).


From: Pascal Polleunus <ppo(at)beeznest(dot)net>
To: pgsql-general(at)postgresql(dot)org
Cc: pativo <pativo(at)arcor(dot)de>
Subject: Re: String manipulation
Date: 2004-02-17 19:55:54
Message-ID: 403271CA.7080705@beeznest.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

You should be able to do that with a regular expression.

CHECK (text ~ '^([0-9A-F]{2})+$')

Remark: As the column is NOT NULL, I suppose that an empty string is not
valid. If an empty string must be valid, replace the + with * ;-)

pativo wrote:
> Hello to all,
>
> I have small problem. I have some database fields (VARCHAR)
> and these field should hold some ahex coded values. So the
> string length must be even and each character can only be
> 0-9, a-f or A-F.
> My idea was that:
>
> ====8<-----------------------------------
>
> CREATE TABLE test (
> id INT4 PRIMARY KEY NOT NULL DEFAULT nextID(),
> text VARCHAR(150) NOT NULL CHECK(isAHex(text))
> );
>
> CREATE FUNCTION isAHex(VARCHAR) RETURNS BOOLEAN AS '
> DECLARE
> text_p ALIAS FOR $1;
> BEGIN
> IF ((length(text_p) % 2) <> 0) THEN
> RETURN FALSE;
> END IF;
> -- TODO How to check each character
> RETURN TRUE;
> END;
> ' LANGUAGE 'plpgsql';
>
> ====8<-----------------------------------
>
> Has anybody an idea how could I check each character?
> I would prefer a solution in plpgsql!!
>
> Thank!
>
>
> pativo
>


From: Ron St-Pierre <rstpierre(at)syscor(dot)com>
To: pativo <pativo(at)arcor(dot)de>, pgsql-general <pgsql-general(at)postgresql(dot)org>
Subject: Re: String manipulation
Date: 2004-02-17 20:06:38
Message-ID: 4032744E.8040708@syscor.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

pativo wrote:

>Hello to all,
>
>I have small problem. I have some database fields (VARCHAR)
>and these field should hold some ahex coded values. So the
>string length must be even and each character can only be
>0-9, a-f or A-F.
>My idea was that:
>
>====8<-----------------------------------
>
>CREATE TABLE test (
> id INT4 PRIMARY KEY NOT NULL DEFAULT nextID(),
> text VARCHAR(150) NOT NULL CHECK(isAHex(text))
>);
>
>CREATE FUNCTION isAHex(VARCHAR) RETURNS BOOLEAN AS '
> DECLARE
> text_p ALIAS FOR $1;
> BEGIN
> IF ((length(text_p) % 2) <> 0) THEN
> RETURN FALSE;
> END IF;
> -- TODO How to check each character
> RETURN TRUE;
> END;
>' LANGUAGE 'plpgsql';
>
>====8<-----------------------------------
>
>Has anybody an idea how could I check each character?
>I would prefer a solution in plpgsql!!
>
>Thank!
>
>
>pativo
>
>
>
Here's one solution:
CREATE OR REPLACE FUNCTION isAHex(text) RETURNS boolean as '

DECLARE
inputText ALIAS FOR $1;
tempChar text;
isHex boolean;
BEGIN
isHex = true;
IF ((length(inputText) % 2) <> 0) THEN
return FALSE;
END IF;
FOR i IN 1..length(inputText) LOOP
tempChar := substr(inputText, i, 1);
IF tempChar ~ ''[g-z]'' THEN
return FALSE;
ELSE IF tempChar ~ ''[G-Z]'' THEN
return FALSE;
END IF;
END LOOP;

return isHex;
END;
' LANGUAGE 'plpgsql';

You may have to check the IF...ELSE IF... stuff but this should work.
I've used a very similar one to check if a value is numeric.

Ron


From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Pascal Polleunus <ppo(at)beeznest(dot)net>
Cc: pgsql-general(at)postgresql(dot)org, pativo <pativo(at)arcor(dot)de>
Subject: Re: String manipulation
Date: 2004-02-17 21:44:28
Message-ID: 200402172144.i1HLiS609434@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Pascal Polleunus wrote:
> You should be able to do that with a regular expression.
>
> CHECK (text ~ '^([0-9A-F]{2})+$')
>
> Remark: As the column is NOT NULL, I suppose that an empty string is not
> valid. If an empty string must be valid, replace the + with * ;-)

I just noticed an unusual affect. GUC regex_flavor affects CHECK
constraints even after the check constraint has been created:

test=> SET regex_flavor = 'advanced'; -- default
SET
?column?
----------
t
(1 row)

test=> SET regex_flavor = 'basic';
SET
test=> SELECT 'abc' ~ '(a|x).*';
?column?
----------
f
(1 row)

test=> SET regex_flavor = 'advanced';
SET
test=> CREATE TABLE test (x TEXT CHECK (x ~ '(a|x).*'));
CREATE TABLE
test=> INSERT INTO test VALUES ('a');
INSERT 17149 1
test=> SET regex_flavor = 'basic';
SET
test=> INSERT INTO test VALUES ('a');
ERROR: new row for relation "test" violates check constraint "test_x"

--
Bruce Momjian | http://candle.pha.pa.us
pgman(at)candle(dot)pha(dot)pa(dot)us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
Cc: Pascal Polleunus <ppo(at)beeznest(dot)net>, pgsql-general(at)postgresql(dot)org, pativo <pativo(at)arcor(dot)de>
Subject: Re: String manipulation
Date: 2004-02-17 23:35:32
Message-ID: 18817.1077060932@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us> writes:
> I just noticed an unusual affect. GUC regex_flavor affects CHECK
> constraints even after the check constraint has been created:

Why does that surprise you?

regards, tom lane


From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Pascal Polleunus <ppo(at)beeznest(dot)net>, pgsql-general(at)postgresql(dot)org, pativo <pativo(at)arcor(dot)de>
Subject: Re: String manipulation
Date: 2004-02-17 23:42:20
Message-ID: 200402172342.i1HNgKj24508@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

\Tom Lane wrote:
> Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us> writes:
> > I just noticed an unusual affect. GUC regex_flavor affects CHECK
> > constraints even after the check constraint has been created:
>
> Why does that surprise you?

I don't think it is good practice for a CHECK constraint to change its
behavior based on a GUC variable. I am not surprised, but am pointing
out it isn't ideal.

--
Bruce Momjian | http://candle.pha.pa.us
pgman(at)candle(dot)pha(dot)pa(dot)us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
Cc: Pascal Polleunus <ppo(at)beeznest(dot)net>, pgsql-general(at)postgresql(dot)org, pativo <pativo(at)arcor(dot)de>
Subject: Re: String manipulation
Date: 2004-02-18 00:13:05
Message-ID: 19143.1077063185@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us> writes:
> I don't think it is good practice for a CHECK constraint to change its
> behavior based on a GUC variable.

You can develop comparable "failure scenarios" for any of the GUC
variables that affect query semantics --- timezone, sql_inheritance,
you name it. Locking them all down when a check constraint or function
or view is created seems impractical ... and if we did do it then we'd
get complaints about that too. ("What do you mean I can't change the
setting later?")

In practice I think we have to assume that those variables are set
consistently within any one application. If you go frobbing them
on-the-fly then you're going to have issues.

I suppose paranoid sorts might lobby to make any GUC variable that can
change query semantics be a superuser-only setting, but to me that cure
sounds worse than the disease.

regards, tom lane


From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Pascal Polleunus <ppo(at)beeznest(dot)net>, pgsql-general(at)postgresql(dot)org, pativo <pativo(at)arcor(dot)de>
Subject: Re: String manipulation
Date: 2004-02-18 03:43:06
Message-ID: 200402180343.i1I3h6M29146@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Tom Lane wrote:
> Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us> writes:
> > I don't think it is good practice for a CHECK constraint to change its
> > behavior based on a GUC variable.
>
> You can develop comparable "failure scenarios" for any of the GUC
> variables that affect query semantics --- timezone, sql_inheritance,
> you name it. Locking them all down when a check constraint or function
> or view is created seems impractical ... and if we did do it then we'd
> get complaints about that too. ("What do you mean I can't change the
> setting later?")
>
> In practice I think we have to assume that those variables are set
> consistently within any one application. If you go frobbing them
> on-the-fly then you're going to have issues.
>
> I suppose paranoid sorts might lobby to make any GUC variable that can
> change query semantics be a superuser-only setting, but to me that cure
> sounds worse than the disease.

What concerned me is that it would actually make data the passed the
CHECK constraint initially fail later. Look at this:

test=> CREATE TABLE test (x TEXT CHECK (x ~ '(a|x).*'), y INT);
CREATE TABLE
test=> INSERT INTO test VALUES ('a', 1);
INSERT 380556 1
test=> SET regex_flavor = 'basic';
SET
test=> UPDATE test SET y=2;
ERROR: new row for relation "test" violates check constraint "test_x"

The UPDATE fails even when the row isn't changed. Certainly interesting.

--
Bruce Momjian | http://candle.pha.pa.us
pgman(at)candle(dot)pha(dot)pa(dot)us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073


From: pativo(at)arcor(dot)de (pativo)
To: pgsql-general(at)postgresql(dot)org
Subject: Re: String manipulation
Date: 2004-02-18 09:17:01
Message-ID: 58babf1b.0402180117.31e1cc91@posting.google.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

pativo(at)arcor(dot)de (pativo) wrote in message news:<58babf1b(dot)0402170346(dot)4a719868(at)posting(dot)google(dot)com>...

Hello and thanks to all!

I'm amused that I get so many responses.

Ok, at time I use a plpgsql function (isAHex(VARCHAR)) which checks only
if the length is even.
So I think I should implement the following.

=======8<-------------------------------------------------------------------

CREATE FUNCTION isAHex(VARCHAR) RETURNS BOOLEAN AS '
DECLARE
input_text_p ALIAS FOR $1;
tmp_char VARCHAR;
BEGIN
IF ((length(input_text_p) % 2) <> 0) THEN
RETURN FALSE;
END IF;
FOR i IN 1..length(input_text_p) LOOP
tmp_char := substr(input_text_p, i, 1);
IF NOT tmp_char ~ ''[0-9a-fA-F]'' THEN
RETURN FALSE;
END IF;
END LOOP;
RETURN TRUE;
END;
' LANGUAGE 'plpgsql';

CREATE TABLE textsTest (
surrogate VARCHAR(40) PRIMARY KEY,
hex_text VARCHAR(150) NOT NULL CHECK(isAHexTest(hex_text))
);

=======8<-------------------------------------------------------------------

But for next release I will use the following. This is in my eyes
the better solution.

=======8<-------------------------------------------------------------------

CREATE TABLE textsTest (
surrogate VARCHAR(40) PRIMARY KEY,
hex_text TEXT NOT NULL CHECK(text ~ '^([0-9A-Fa-f]{2})+$')
);

=======8<-------------------------------------------------------------------

Thanks to all!!!

oki,

pativo

--
www.pativo.de