Custom column ordering - Mailing list pgsql-general

From Steven Xu
Subject Custom column ordering
Date
Msg-id OF4914D9AC.730EB9E5-ON85257F69.0072D4B1-85257F69.0072D4B3@yorku.ca
Whole thread Raw
Responses Re: Custom column ordering
List pgsql-general
<font face=3D"Default Sans Serif,Verdana,Arial,Helvetica,sans-serif" size=
=3D"2">Hi all,I'm trying to order some rows based on port names, a =
text column, using some domain-specific knowledge for Netdisco, an open-sou=
rce application. In particular, I'm trying to do this without havin=
g to redo the entire design for the database. Note that in this database, t=
here are no foreign key constraints, mostly because they weren't considered=
 in the original inception of the software. The rough idea of the s=
olution I've come up with is to create a new composite data type called "<f=
ont face=3D"Default Monospace,Courier New,Courier,monospace">port" w=
ith a single text column. Then I created the relevant comparison functions,=
 operators and operator classes under the "<font face=3D"Default Monospace,=
Courier New,Courier,monospace">port=5Fops" operator family. Then, I =
created a function "<font face=3D"Default Monospace,Courier New,Courier,mon=
ospace">cast=5Fto=5Fport(text)" that casts "<font face=3D"Default Mo=
nospace,Courier New,Courier,monospace">text" data types to "<font fa=
ce=3D"Default Monospace,Courier New,Courier,monospace">port" (which =
simply creates a tuple with the single text value, see the code for details=
). Finally, I created an index on the "<font face=3D"Default Monospace,Cour=
ier New,Courier,monospace">device=5Fport" table with "<font face=3D"=
Default Monospace,Courier New,Courier,monospace">cast=5Fto=5Fport(port)</fo=
nt>" as the indexed column using  "port=5Fops". However, when I run "<font =
face=3D"Default Monospace,Courier New,Courier,monospace">select port from d=
evice=5Fport order by cast=5Fto=5Fport(port)", it doesn't use the in=
dex I created and doesn't even order using the operators I created. Instead=
, it orders by the lexicographical ordering of the original text column.<br=
>Questions:  - Why is PostgreSQL not using the functional inde=
x I created and why is it not being ordered correctly?  - Is creat=
ing a separate data type and using a functional index on the casts to this =
data type the right approach to a custom ordering?Steven<br=
>Details:Creating the "<font face=3D"Default Monospace,Courier New,Cour=
ier,monospace">port" type:<font face=3D"Default Monospace,Courie=
r New,Courier,monospace">  create type port as (f1 text);<b=
r>Creating the comparator function, substituted with much shorter code as a=
n example. I can include the original code, but it's much shorter to provid=
e this.It returns -1 if the first argument is "less than" the second ar=
gument, 0 if they are equal and 1 otherwise. In this example, "less than" m=
eans lexicographically greater, because of the negation.<font face=3D"D=
efault Monospace,Courier New,Courier,monospace">  create or replace fu=
nction port=5Fcmp(port,port)      RETURNS integer as=
  $$    my ($a, $b) =3D @=5F;    retu=
rn -( $a cmp $b ); // comparison function does the opposite of cmp =
; $$ language plperl;Creating the "<font face=3D"Default Mon=
ospace,Courier New,Courier,monospace">port=5Fops" operators and oper=
ator classes for the "<font face=3D"Default Monospace,Courier New,Courier,m=
onospace">port" type:<font face=3D"Default Monospace,Courier New=
,Courier,monospace">CREATE OR REPLACE FUNCTION port=5Flt(port, port)&nb=
sp;   RETURNS boolean AS$$    BEGIN&nb=
sp;       RETURN port=5Fcmp($1, $2) < 0;&nb=
sp;   END;$$ LANGUAGE plpgsql;CREATE OR REPLACE FUNCT=
ION port=5Fgt(port, port)    RETURNS boolean AS$$<br=
>    BEGIN        RETURN p=
ort=5Fcmp($1, $2) > 0;    END;$$ LANGUAGE plpgsql=
;CREATE OR REPLACE FUNCTION port=5Flte(port, port)  &=
nbsp; RETURNS boolean AS$$    BEGIN  &=
nbsp;     RETURN port=5Fcmp($1, $2) <=3D 0; &nbs=
p;  END;$$ LANGUAGE plpgsql;CREATE OR REPLACE FUNCTION por=
t=5Fgte(port, port)    RETURNS boolean AS$$ =
;   BEGIN        RETURN port=5F=
cmp($1, $2) >=3D 0;    END;$$ LANGUAGE plpgsql;<b=
r>CREATE OR REPLACE FUNCTION port=5Feq(port, port)   =
; RETURNS boolean AS$$    BEGIN   =
;     RETURN port=5Fcmp($1, $2) =3D 0;   =
 END;$$ LANGUAGE plpgsql;CREATE OPERATOR < ( PROCEDURE=3Dpor=
t=5Flt, LEFTARG=3Dport, RIGHTARG=3Dport);CREATE OPERATOR <=3D ( PROC=
EDURE=3Dport=5Flte, LEFTARG=3Dport, RIGHTARG=3Dport);CREATE OPERATOR &g=
t;=3D ( PROCEDURE=3Dport=5Fgte, LEFTARG=3Dport,  RIGHTARG=3Dport);=
CREATE OPERATOR > ( PROCEDURE=3Dport=5Fgte, LEFTARG=3Dport, RIGHTARG=3Dp=
ort);<font face=3D"Default Monospace,Courier New,Courier,monospa=
ce">CREATE OPERATOR =3D ( PROCEDURE=3Dport=5Feq, LEFTARG=3Dport, RIGHTARG=
=3Dport);CREATE OPERATOR CLASS port=5Fops DEFAULTFOR TYPE port =
USING btreeASOPERATOR        1&n=
bsp;      <  ,OPERATOR  &nbs=
p;     2       <=3D ,<=
br>OPERATOR        3   &n=
bsp;   =3D  ,OPERATOR      =
;  4       >=3D ,OPERATOR &n=
bsp;      5       &g=
t;  ,FUNCTION        1 &nb=
sp;     port=5Fcmp(port, port);Creat=
ing the function to cast "<font face=3D"Default Monospace,Courier New,Couri=
er,monospace">text" data to "<font face=3D"Default Monospace,Courier=
 New,Courier,monospace">port" data:<font face=3D"Default Monospa=
ce,Courier New,Courier,monospace">CREATE OR REPLACE FUNCTION cast=5Fto=5Fpo=
rt(text) RETURNS port LANGUAGE sqlAS $function$&n=
bsp; SELECT ($1);$function$ IMMUTABLE;Creating the index=
:CREATE =
INDEX idx=5Fdevice=5Fport=5Fport=5Fproper on device=5Fport (cast=5Fto=5Fpor=
t(port) port=5Fops desc);Sample table structure, shortened f=
or brevity:<font face=3D"Default Monospace,Courier New,Courier,monospac=
e">            =
         Table "public.device=5Fpor=
t"    Column    |    =
        Type    &nbs=
p;        |     =
;  Modifiers--------------+-----------------------------+---------=
--------------- ip        =
   | inet         &n=
bsp;            =
;  | not null port       &=
nbsp; | text          &nb=
sp;            =
 | not null

pgsql-general by date:

Previous
From: Pavel Stehule
Date:
Subject: Re: Does RAISE EXCEPTION rollback previous commands in a stored function?
Next
From: Artur Zakirov
Date:
Subject: Re: commit time in logical decoding