Thread: functional indexes

functional indexes

From
Daniel Kalchev
Date:
With the current snapshot, there seems to be problem with functional indexes.
Example:

CREATE TABLE timelog (loginname text, site varchar(16), start_time datetime,
elapsed timespan);
CREATE FUNCTION datetime_day (datetime ) RETURNS float8 AS 'select
date_part(''day'', $1)' LANGUAGE 'SQL';
INSERT INTO timelog values ('abc','varna','Thu 01 Jan 23:23:34 1998 EET','@ 10
mins');
INSERT INTO timelog values ('abc','sofia','Thu 01 Jan 23:23:34 1998 EET','@ 2
hours 10 mins');

$ psql test
Welcome to the POSTGRESQL interactive sql monitor:
  Please read the file COPYRIGHT for copyright terms of POSTGRESQL

   type \? for help on slash commands
   type \q to quit
   type \g or terminate with semicolon to execute query
 You are currently connected to the database: test

test=> create index timelog_date_idx on timelog (datetime_day(start_time));
ERROR:  DefineIndex: (null) class not found
test=>

Also, using date_part() directly in the index definition:

test=> create index timelog_date_idx on timelog (datetime_part('day',
start_time));
ERROR:  parser: parse error at or near "'"


Can something be done about this before 6.4 is released?

Daniel



Re: [HACKERS] functional indexes

From
Bruce Momjian
Date:
Added to open 6.4 bugs list.


> With the current snapshot, there seems to be problem with functional indexes.
> Example:
>
> CREATE TABLE timelog (loginname text, site varchar(16), start_time datetime,
> elapsed timespan);
> CREATE FUNCTION datetime_day (datetime ) RETURNS float8 AS 'select
> date_part(''day'', $1)' LANGUAGE 'SQL';
> INSERT INTO timelog values ('abc','varna','Thu 01 Jan 23:23:34 1998 EET','@ 10
> mins');
> INSERT INTO timelog values ('abc','sofia','Thu 01 Jan 23:23:34 1998 EET','@ 2
> hours 10 mins');
>
> $ psql test
> Welcome to the POSTGRESQL interactive sql monitor:
>   Please read the file COPYRIGHT for copyright terms of POSTGRESQL
>
>    type \? for help on slash commands
>    type \q to quit
>    type \g or terminate with semicolon to execute query
>  You are currently connected to the database: test
>
> test=> create index timelog_date_idx on timelog (datetime_day(start_time));
> ERROR:  DefineIndex: (null) class not found
> test=>
>
> Also, using date_part() directly in the index definition:
>
> test=> create index timelog_date_idx on timelog (datetime_part('day',
> start_time));
> ERROR:  parser: parse error at or near "'"
>
>
> Can something be done about this before 6.4 is released?
>
> Daniel
>
>
>
>


--
  Bruce Momjian                        |  http://www.op.net/~candle
  maillist@candle.pha.pa.us            |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026


Re: [HACKERS] functional indexes

From
jwieck@debis.com (Jan Wieck)
Date:
>
> Added to open 6.4 bugs list.

    Can be removed from the list.

>
>
> > With the current snapshot, there seems to be problem with functional indexes.
> > Example:
> >
> > CREATE TABLE timelog (loginname text, site varchar(16), start_time datetime,
> > elapsed timespan);
> > CREATE FUNCTION datetime_day (datetime ) RETURNS float8 AS 'select
> > date_part(''day'', $1)' LANGUAGE 'SQL';
> > INSERT INTO timelog values ('abc','varna','Thu 01 Jan 23:23:34 1998 EET','@ 10
> > mins');
> > INSERT INTO timelog values ('abc','sofia','Thu 01 Jan 23:23:34 1998 EET','@ 2
> > hours 10 mins');
> >
> > $ psql test
> > Welcome to the POSTGRESQL interactive sql monitor:
> >   Please read the file COPYRIGHT for copyright terms of POSTGRESQL
> >
> >    type \? for help on slash commands
> >    type \q to quit
> >    type \g or terminate with semicolon to execute query
> >  You are currently connected to the database: test
> >
> > test=> create index timelog_date_idx on timelog (datetime_day(start_time));
> > ERROR:  DefineIndex: (null) class not found
> > test=>
> >
> > Also, using date_part() directly in the index definition:
> >
> > test=> create index timelog_date_idx on timelog (datetime_part('day',
> > start_time));
> > ERROR:  parser: parse error at or near "'"
> >
> >
> > Can something be done about this before 6.4 is released?
> >
> > Daniel
> >
> >
> >
> >

    Problem 1:
        You must specify an operator class for the index.

    Solution:
        CREATE INDEX timelog_date_idx ON timelog
            (datetime_day(start_time) float8_ops);

        in the above case.

    Problem 2:
        Only  tuple  attributes  can  be  given  to  a functional
        indexes proc. This is  why  date_part('day',  start_time)
        cannot be used directly. There is no place in pg_index to
        store constant values.

    Solution:
        As you did with a wrapper function. But...

    Problem 3:
        You cannot use  SQL  language  functions  for  functional
        index    procs.     The   index   access   methods   call
        fmgr_array_args() to compute the functional index  value.
    And this cannot execute SQL language functions.

    Solution:
        Write  a  C  language function for it or use the PL/pgSQL
        function

        CREATE FUNCTION datetime_day(datetime) RETURNS float8 AS '
            BEGIN
                RETURN date_part(''day'', $1);
            END;'
            LANGUAGE 'plpgsql';

        after  installing  the  procedural   language   in   your
        database.  Did I tell that I like PL/pgSQL more and more?
    Think it was really time for it.

    Problem 4:
        The  isNull  flag used in access/index/indexam.c function
        GetIndexValue() is not initialized correctly.

    Solution:
        Apply the patch at the end.


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#======================================== jwieck@debis.com (Jan Wieck) #


*** indexam.c.orig    Fri Oct  2 15:16:49 1998
--- indexam.c    Fri Oct  2 15:17:24 1998
***************
*** 362,368 ****
                bool *attNull)
  {
      Datum        returnVal;
!     bool        isNull;

      if (PointerIsValid(fInfo) && FIgetProcOid(fInfo) != InvalidOid)
      {
--- 362,368 ----
                bool *attNull)
  {
      Datum        returnVal;
!     bool        isNull = FALSE;

      if (PointerIsValid(fInfo) && FIgetProcOid(fInfo) != InvalidOid)
      {
***************
*** 375,387 ****
                                        attrNums[i],
                                        hTupDesc,
                                        attNull);
          }
          returnVal = (Datum) fmgr_array_args(FIgetProcOid(fInfo),
                                              FIgetnArgs(fInfo),
                                              (char **) attData,
                                              &isNull);
          pfree(attData);
!         *attNull = FALSE;
      }
      else
          returnVal = heap_getattr(tuple, attrNums[attOff], hTupDesc, attNull);
--- 375,389 ----
                                        attrNums[i],
                                        hTupDesc,
                                        attNull);
+             if (*attNull)
+                 isNull = TRUE;
          }
          returnVal = (Datum) fmgr_array_args(FIgetProcOid(fInfo),
                                              FIgetnArgs(fInfo),
                                              (char **) attData,
                                              &isNull);
          pfree(attData);
!         *attNull = isNull;
      }
      else
          returnVal = heap_getattr(tuple, attrNums[attOff], hTupDesc, attNull);