Implement LIKE/ESCAPE. Change parser to use like()/notlike()
authorThomas G. Lockhart <lockhart@fourpalms.org>
Sun, 6 Aug 2000 18:06:44 +0000 (18:06 +0000)
committerThomas G. Lockhart <lockhart@fourpalms.org>
Sun, 6 Aug 2000 18:06:44 +0000 (18:06 +0000)
 rather than the "~~" operator; this made it easy to add ESCAPE features.
Implement ILIKE, NOT ILIKE, and the ESCAPE clause for them.
 afaict this is not MultiByte clean, but lots of other stuff isn't either.
Fix up underlying support code for LIKE/NOT LIKE.
 Things should be faster and does not require internal string copying.
Update regression test to add explicit checks for
 LIKE/NOT LIKE/ILIKE/NOT ILIKE.
Remove colon and semi-colon operators as threatened in 7.0.
Implement SQL99 COMMIT/AND NO CHAIN.
 Throw elog(ERROR) on COMMIT/AND CHAIN per spec
 since we don't yet support it.
Implement SQL99 CREATE/DROP SCHEMA as equivalent to CREATE DATABASE.
 This is only a stopgap or demo since schemas will have another
 implementation soon.
Remove a few unused production rules to get rid of warnings
 which crept in on the last commit.
Fix up tabbing in some places by removing embedded spaces.

src/backend/parser/gram.y
src/backend/parser/keywords.c
src/backend/utils/adt/like.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/utils/builtins.h

index ba2b8d3b8982acf384e935c745b42567f4301f7a..89bda3d82df73fe639038555dd07d9066535dfcf 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.181 2000/07/30 22:13:50 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.182 2000/08/06 18:05:21 thomas Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -123,7 +123,7 @@ static void doNegateFloat(Value *v);
                AlterSchemaStmt, AlterTableStmt, ClosePortalStmt,
                CopyStmt, CreateStmt, CreateAsStmt, CreateSchemaStmt, CreateSeqStmt, DefineStmt, DropStmt,
                TruncateStmt, CommentStmt,
-               ExtendStmt, FetchStmt,  GrantStmt, CreateTrigStmt, DropTrigStmt,
+               ExtendStmt, FetchStmt,  GrantStmt, CreateTrigStmt, DropSchemaStmt, DropTrigStmt,
                CreatePLangStmt, DropPLangStmt,
                IndexStmt, ListenStmt, UnlistenStmt, LockStmt, OptimizableStmt,
                ProcedureStmt, ReindexStmt, RemoveAggrStmt, RemoveOperStmt,
@@ -191,7 +191,7 @@ static void doNegateFloat(Value *v);
 %type <list>   for_update_clause, update_list
 %type <boolean>        opt_all
 %type <boolean>        opt_table
-%type <boolean>        opt_trans
+%type <boolean>        opt_chain, opt_trans
 
 %type <jexpr>  from_expr, join_clause, join_expr
 %type <jexpr>  join_clause_with_union, join_expr_with_union
@@ -252,7 +252,7 @@ static void doNegateFloat(Value *v);
 
 %type <typnam> Typename, SimpleTypename, ConstTypename
                                Generic, Numeric, Geometric, Character, ConstDatetime, ConstInterval, Bit
-%type <str>            typename, generic, numeric, geometric, character, datetime, bit
+%type <str>            generic, character, datetime, bit
 %type <str>            extract_arg
 %type <str>            opt_charset, opt_collate
 %type <str>            opt_float
@@ -302,7 +302,7 @@ static void doNegateFloat(Value *v);
                CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
                DAY_P, DEC, DECIMAL, DECLARE, DEFAULT, DELETE, DESC,
                DISTINCT, DOUBLE, DROP,
-               ELSE, END_TRANS, EXCEPT, EXECUTE, EXISTS, EXTRACT,
+               ELSE, END_TRANS, ESCAPE, EXCEPT, EXECUTE, EXISTS, EXTRACT,
                FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
                GLOBAL, GRANT, GROUP, HAVING, HOUR_P,
                IN, INNER_P, INSENSITIVE, INSERT, INTERSECT, INTERVAL, INTO, IS,
@@ -320,7 +320,7 @@ static void doNegateFloat(Value *v);
                WHEN, WHERE, WITH, WORK, YEAR_P, ZONE
 
 /* Keywords (in SQL3 reserved words) */
-%token CHARACTERISTICS,
+%token CHAIN, CHARACTERISTICS,
                DEFERRABLE, DEFERRED,
                IMMEDIATE, INITIALLY, INOUT,
                OFF, OUT,
@@ -345,7 +345,7 @@ static void doNegateFloat(Value *v);
                DATABASE, DELIMITERS, DO,
                EACH, ENCODING, EXCLUSIVE, EXPLAIN, EXTEND,
                FORCE, FORWARD, FUNCTION, HANDLER,
-               INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
+               ILIKE, INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
                LANCOMPILER, LIMIT, LISTEN, LOAD, LOCATION, LOCK_P,
                MAXVALUE, MINVALUE, MODE, MOVE,
                NEW, NOCREATEDB, NOCREATEUSER, NONE, NOTHING, NOTIFY, NOTNULL,
@@ -368,7 +368,7 @@ static void doNegateFloat(Value *v);
 %right         NOT
 %right         '='
 %nonassoc      '<' '>'
-%nonassoc      LIKE
+%nonassoc      LIKE ILIKE
 %nonassoc      OVERLAPS
 %nonassoc      BETWEEN
 %nonassoc      IN
@@ -382,13 +382,14 @@ static void doNegateFloat(Value *v);
 %left          '^'
 %left          '|'                             /* this is the relation union op, not logical or */
 /* Unary Operators */
-%right         ':'
-%left          ';'                             /* end of statement or natural log */
+%right         ':'                             /* delimiter for array ranges */
+%left          ';'                             /* end of statement */
 %right         UMINUS
 %left          '.'
 %left          '[' ']'
 %left          TYPECAST
 %left          UNION INTERSECT EXCEPT
+%left          ESCAPE
 %%
 
 /*
@@ -432,6 +433,7 @@ stmt :      AlterSchemaStmt
                | ClusterStmt
                | DefineStmt
                | DropStmt              
+               | DropSchemaStmt
                | TruncateStmt
                | CommentStmt
                | DropGroupStmt
@@ -678,7 +680,16 @@ DropGroupStmt: DROP GROUP UserId
 
 CreateSchemaStmt:  CREATE SCHEMA UserId
                                {
-                                       elog(ERROR, "CREATE SCHEMA not yet supported");
+                                       /* for now, just make this the same as CREATE DATABASE */
+                                       CreatedbStmt *n = makeNode(CreatedbStmt);
+                                       n->dbname = $3;
+                                       n->dbpath = NULL;
+#ifdef MULTIBYTE
+                                       n->encoding = GetTemplateEncoding();
+#else
+                                       n->encoding = 0;
+#endif
+                                       $$ = (Node *)n;
                                }
                ;
 
@@ -688,6 +699,13 @@ AlterSchemaStmt:  ALTER SCHEMA UserId
                                }
                ;
 
+DropSchemaStmt:  DROP SCHEMA UserId
+                               {
+                                       DropdbStmt *n = makeNode(DropdbStmt);
+                                       n->dbname = $3;
+                                       $$ = (Node *)n;
+                               }
+
 
 /*****************************************************************************
  *
@@ -2648,7 +2666,7 @@ opt_force:        FORCE                                                                   {  $$ = TRUE; }
  *****************************************************************************/
 
 RenameStmt:  ALTER TABLE relation_name opt_inh_star
-        /* "*" deprecated */
+                               /* "*" deprecated */
                                  RENAME opt_column opt_name TO name
                                {
                                        RenameStmt *n = makeNode(RenameStmt);
@@ -2823,6 +2841,12 @@ TransactionStmt: ABORT_TRANS opt_trans
                                        n->command = COMMIT;
                                        $$ = (Node *)n;
                                }
+               | COMMIT opt_trans opt_chain
+                               {
+                                       TransactionStmt *n = makeNode(TransactionStmt);
+                                       n->command = COMMIT;
+                                       $$ = (Node *)n;
+                               }
                | END_TRANS opt_trans
                                {
                                        TransactionStmt *n = makeNode(TransactionStmt);
@@ -2835,6 +2859,12 @@ TransactionStmt: ABORT_TRANS opt_trans
                                        n->command = ROLLBACK;
                                        $$ = (Node *)n;
                                }
+               | ROLLBACK opt_trans opt_chain
+                               {
+                                       TransactionStmt *n = makeNode(TransactionStmt);
+                                       n->command = ROLLBACK;
+                                       $$ = (Node *)n;
+                               }
                ;
 
 opt_trans: WORK                                                                        { $$ = TRUE; }
@@ -2842,6 +2872,19 @@ opt_trans: WORK                                                                  { $$ = TRUE; }
                | /*EMPTY*/                                                             { $$ = TRUE; }
                ;
 
+opt_chain: AND NO CHAIN
+                               { $$ = FALSE; }
+               | AND CHAIN
+                               {
+                                       /* SQL99 asks that conforming dbs reject AND CHAIN
+                                        * if they don't support it. So we can't just ignore it.
+                                        * - thomas 2000-08-06
+                                        */
+                                       elog(ERROR, "COMMIT/CHAIN not yet supported");
+                                       $$ = TRUE;
+                               }
+               ;
+
 
 /*****************************************************************************
  *
@@ -2891,11 +2934,11 @@ LoadStmt:  LOAD file_name
  *****************************************************************************/
 
 CreatedbStmt:  CREATE DATABASE database_name WITH createdb_opt_location createdb_opt_encoding
-               {
-                   CreatedbStmt *n;
+                               {
+                                       CreatedbStmt *n;
 
-                   if ($5 == NULL && $6 == -1)
-                       elog(ERROR, "CREATE DATABASE WITH requires at least one option.");
+                                       if ($5 == NULL && $6 == -1)
+                                               elog(ERROR, "CREATE DATABASE WITH requires at least one option.");
 
                     n = makeNode(CreatedbStmt);
                                        n->dbname = $3;
@@ -2918,50 +2961,49 @@ CreatedbStmt:  CREATE DATABASE database_name WITH createdb_opt_location createdb
                ;
 
 createdb_opt_location:  LOCATION '=' Sconst            { $$ = $3; }
-        | LOCATION '=' DEFAULT                  { $$ = NULL; }
+               | LOCATION '=' DEFAULT                                  { $$ = NULL; }
                | /*EMPTY*/                                                             { $$ = NULL; }
                ;
 
-createdb_opt_encoding:
-        ENCODING '=' Sconst
-        {
+createdb_opt_encoding:  ENCODING '=' Sconst
+                               {
 #ifdef MULTIBYTE
-            int i;
-            i = pg_char_to_encoding($3);
-            if (i == -1)
-                elog(ERROR, "%s is not a valid encoding name", $3);
-            $$ = i;
+                                       int i;
+                                       i = pg_char_to_encoding($3);
+                                       if (i == -1)
+                                               elog(ERROR, "%s is not a valid encoding name", $3);
+                                       $$ = i;
 #else
-            elog(ERROR, "Multi-byte support is not enabled");
+                                       elog(ERROR, "Multi-byte support is not enabled");
 #endif
-        }
-        | ENCODING '=' Iconst
-        {
+                               }
+               | ENCODING '=' Iconst
+                               {
 #ifdef MULTIBYTE
-            if (!pg_get_encent_by_encoding($3))
-                elog(ERROR, "%d is not a valid encoding code", $3);
-            $$ = $3;
+                                       if (!pg_get_encent_by_encoding($3))
+                                               elog(ERROR, "%d is not a valid encoding code", $3);
+                                       $$ = $3;
 #else
-            elog(ERROR, "Multi-byte support is not enabled");
+                                       elog(ERROR, "Multi-byte support is not enabled");
 #endif
-        }
-        | ENCODING '=' DEFAULT
-        {
+                               }
+               | ENCODING '=' DEFAULT
+                               {
 #ifdef MULTIBYTE
-            $$ = GetTemplateEncoding();
+                                       $$ = GetTemplateEncoding();
 #else
-            $$ = 0;
+                                       $$ = 0;
 #endif
-        }
-        | /*EMPTY*/
-        {
+                               }
+               | /*EMPTY*/
+                               {
 #ifdef MULTIBYTE
-            $$ = GetTemplateEncoding();
+                                       $$ = GetTemplateEncoding();
 #else
-            $$= 0;
+                                       $$= 0;
 #endif
-        }
-        ;
+                               }
+               ;
 
 
 /*****************************************************************************
@@ -3255,7 +3297,7 @@ UpdateStmt:  UPDATE opt_only relation_name
                          where_clause
                                {
                                        UpdateStmt *n = makeNode(UpdateStmt);
-                    n->inh = $2;
+                                       n->inh = $2;
                                        n->relname = $3;
                                        n->targetList = $5;
                                        n->fromClause = $6;
@@ -3353,7 +3395,7 @@ SelectStmt:         select_clause sort_clause for_update_clause opt_select_limit
                                        List *select_list = NIL;
                                        SelectStmt *first_select;
                                        bool    intersect_present = FALSE,
-                                                       unionall_present = FALSE;
+                                               unionall_present = FALSE;
 
                                        /* Take the operator tree as an argument and create a
                                         * list of all SelectStmt Nodes found in the tree.
@@ -3429,21 +3471,21 @@ select_clause: '(' select_clause ')'
                | select_clause EXCEPT select_clause
                        {
                                $$ = (Node *)makeA_Expr(AND,NULL,$1,
-                                                       makeA_Expr(NOT,NULL,NULL,$3));
+                                                                               makeA_Expr(NOT,NULL,NULL,$3));
                        }
                | select_clause UNION opt_all select_clause
                        {       
                                if (IsA($4, SelectStmt))
-                                 {
-                                    SelectStmt *n = (SelectStmt *)$4;
-                                    n->unionall = $3;
-                                        /* NOTE: if UNION ALL appears with a parenthesized set
-                                         * operation to its right, the ALL is silently discarded.
-                                         * Should we generate an error instead?  I think it may
-                                         * be OK since ALL with UNION to its right is ignored
-                                         * anyway...
-                                         */
-                                 }
+                               {
+                                       SelectStmt *n = (SelectStmt *)$4;
+                                       n->unionall = $3;
+                                       /* NOTE: if UNION ALL appears with a parenthesized set
+                                        * operation to its right, the ALL is silently discarded.
+                                        * Should we generate an error instead?  I think it may
+                                        * be OK since ALL with UNION to its right is ignored
+                                        * anyway...
+                                        */
+                               }
                                $$ = (Node *)makeA_Expr(OR,NULL,$1,$4);
                        }
                | select_clause INTERSECT select_clause
@@ -3899,21 +3941,21 @@ relation_expr:  relation_name
                                        $$->relname = $1;
                                        $$->inh = SQL_inheritance;
                                }
-               | relation_name '*'                               %prec '='
+               | relation_name '*'                             %prec '='
                                {
                                        /* inheritance query */
                                        $$ = makeNode(RelExpr);
                                        $$->relname = $1;
                                        $$->inh = TRUE;
                                }
-        | ONLY relation_name               %prec '='
-                {
+               | ONLY relation_name                    %prec '='
+                               {
                                        /* no inheritance */
                                        $$ = makeNode(RelExpr);
                                        $$->relname = $2;
                                        $$->inh = FALSE;
                 }
-         ;
+               ;
 
 opt_array_bounds:      '[' ']' opt_array_bounds
                                {  $$ = lcons(makeInteger(-1), $3); }
@@ -3975,14 +4017,6 @@ ConstTypename:  Generic
                | ConstDatetime
                ;
 
-typename:  generic                                                             { $$ = $1; }
-               | numeric                                                               { $$ = $1; }
-               | geometric                                                             { $$ = $1; }
-               | bit                                                                   { $$ = $1; }
-               | character                                                             { $$ = $1; }
-               | datetime                                                              { $$ = $1; }
-               ;
-
 Generic:  generic
                                {
                                        $$ = makeNode(TypeName);
@@ -4032,13 +4066,6 @@ Numeric:  FLOAT opt_float
                                }
                ;
 
-numeric:  FLOAT                                                        { $$ = xlateSqlType("float"); }
-               | DOUBLE PRECISION                              { $$ = xlateSqlType("float8"); }
-               | DECIMAL                                               { $$ = xlateSqlType("decimal"); }
-               | DEC                                                   { $$ = xlateSqlType("decimal"); }
-               | NUMERIC                                               { $$ = xlateSqlType("numeric"); }
-               ;
-
 Geometric:  PATH_P
                                {
                                        $$ = makeNode(TypeName);
@@ -4047,9 +4074,6 @@ Geometric:  PATH_P
                                }
                ;
 
-geometric:  PATH_P                                             { $$ = xlateSqlType("path"); }
-               ;
-
 opt_float:  '(' Iconst ')'
                                {
                                        if ($2 < 1)
@@ -4435,16 +4459,6 @@ a_expr:  c_expr
                                {       $$ = makeA_Expr(OP, "^", NULL, $2); }
                | '|' a_expr
                                {       $$ = makeA_Expr(OP, "|", NULL, $2); }
-               | ':' a_expr
-                               {       $$ = makeA_Expr(OP, ":", NULL, $2);
-                                       elog(NOTICE, "The ':' operator is deprecated.  Use exp(x) instead."
-                                                "\n\tThis operator will be removed in a future release.");
-                               }
-               | ';' a_expr
-                               {       $$ = makeA_Expr(OP, ";", NULL, $2);
-                                       elog(NOTICE, "The ';' operator is deprecated.  Use ln(x) instead."
-                                                "\n\tThis operator will be removed in a future release.");
-                               }
                | a_expr '%'
                                {       $$ = makeA_Expr(OP, "%", $1, NULL); }
                | a_expr '^'
@@ -4499,9 +4513,77 @@ a_expr:  c_expr
                                {       $$ = makeA_Expr(NOT, NULL, NULL, $2); }
 
                | a_expr LIKE a_expr
-                               {       $$ = makeA_Expr(OP, "~~", $1, $3); }
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "like";
+                                       n->args = makeList($1, $3, -1);
+                                       n->agg_star = FALSE;
+                                       n->agg_distinct = FALSE;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr LIKE a_expr ESCAPE a_expr
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "like";
+                                       n->args = makeList($1, $3, $5, -1);
+                                       n->agg_star = FALSE;
+                                       n->agg_distinct = FALSE;
+                                       $$ = (Node *)n;
+                               }
                | a_expr NOT LIKE a_expr
-                               {       $$ = makeA_Expr(OP, "!~~", $1, $4); }
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "notlike";
+                                       n->args = makeList($1, $4, -1);
+                                       n->agg_star = FALSE;
+                                       n->agg_distinct = FALSE;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr NOT LIKE a_expr ESCAPE a_expr
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "notlike";
+                                       n->args = makeList($1, $4, $6, -1);
+                                       n->agg_star = FALSE;
+                                       n->agg_distinct = FALSE;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr ILIKE a_expr
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "ilike";
+                                       n->args = makeList($1, $3, -1);
+                                       n->agg_star = FALSE;
+                                       n->agg_distinct = FALSE;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr ILIKE a_expr ESCAPE a_expr
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "ilike";
+                                       n->args = makeList($1, $3, $5, -1);
+                                       n->agg_star = FALSE;
+                                       n->agg_distinct = FALSE;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr NOT ILIKE a_expr
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "inotlike";
+                                       n->args = makeList($1, $4, -1);
+                                       n->agg_star = FALSE;
+                                       n->agg_distinct = FALSE;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr NOT ILIKE a_expr ESCAPE a_expr
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "inotlike";
+                                       n->args = makeList($1, $4, $6, -1);
+                                       n->agg_star = FALSE;
+                                       n->agg_distinct = FALSE;
+                                       $$ = (Node *)n;
+                               }
 
                | a_expr ISNULL
                                {       $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
@@ -4659,16 +4741,6 @@ b_expr:  c_expr
                                {       $$ = makeA_Expr(OP, "^", NULL, $2); }
                | '|' b_expr
                                {       $$ = makeA_Expr(OP, "|", NULL, $2); }
-               | ':' b_expr
-                               {       $$ = makeA_Expr(OP, ":", NULL, $2);
-                                       elog(NOTICE, "The ':' operator is deprecated.  Use exp(x) instead."
-                                                "\n\tThis operator will be removed in a future release.");
-                               }
-               | ';' b_expr
-                               {       $$ = makeA_Expr(OP, ";", NULL, $2);
-                                       elog(NOTICE, "The ';' operator is deprecated.  Use ln(x) instead."
-                                                "\n\tThis operator will be removed in a future release.");
-                               }
                | b_expr '%'
                                {       $$ = makeA_Expr(OP, "%", $1, NULL); }
                | b_expr '^'
@@ -5496,6 +5568,7 @@ TokenId:  ABSOLUTE                                                { $$ = "absolute"; }
                | BY                                                    { $$ = "by"; }
                | CACHE                                                 { $$ = "cache"; }
                | CASCADE                                               { $$ = "cascade"; }
+               | CHAIN                                                 { $$ = "chain"; }
                | CLOSE                                                 { $$ = "close"; }
                | COMMENT                                               { $$ = "comment"; }
                | COMMIT                                                { $$ = "commit"; }
@@ -5515,6 +5588,7 @@ TokenId:  ABSOLUTE                                                { $$ = "absolute"; }
                | DROP                                                  { $$ = "drop"; }
                | EACH                                                  { $$ = "each"; }
                | ENCODING                                              { $$ = "encoding"; }
+               | ESCAPE                                                { $$ = "escape"; }
                | EXCLUSIVE                                             { $$ = "exclusive"; }
                | EXECUTE                                               { $$ = "execute"; }
                | FETCH                                                 { $$ = "fetch"; }
@@ -5661,6 +5735,7 @@ ColLabel:  ColId                                          { $$ = $1; }
                | GLOBAL                                                { $$ = "global"; }
                | GROUP                                                 { $$ = "group"; }
                | HAVING                                                { $$ = "having"; }
+               | ILIKE                                                 { $$ = "ilike"; }
                | INITIALLY                                             { $$ = "initially"; }
                | IN                                                    { $$ = "in"; }
                | INNER_P                                               { $$ = "inner"; }
index e173805a79c5149dacbe0f406b5e9f64a65493b4..848f1dc8d6b8d33fa9f658ef5baa241806ee5803 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.79 2000/07/14 15:43:32 thomas Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.80 2000/08/06 18:05:22 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -55,6 +55,7 @@ static ScanKeyword ScanKeywords[] = {
        {"cascade", CASCADE},
        {"case", CASE},
        {"cast", CAST},
+       {"chain", CHAIN},
        {"char", CHAR},
        {"character", CHARACTER},
        {"characteristics", CHARACTERISTICS},
@@ -101,6 +102,7 @@ static ScanKeyword ScanKeywords[] = {
        {"else", ELSE},
        {"encoding", ENCODING},
        {"end", END_TRANS},
+       {"escape", ESCAPE},
        {"except", EXCEPT},
        {"exclusive", EXCLUSIVE},
        {"execute", EXECUTE},
@@ -124,6 +126,7 @@ static ScanKeyword ScanKeywords[] = {
        {"handler", HANDLER},
        {"having", HAVING},
        {"hour", HOUR_P},
+       {"ilike", ILIKE},
        {"immediate", IMMEDIATE},
        {"in", IN},
        {"increment", INCREMENT},
index 5a7b84733924a1ea403c9a255917fa5cf7dd2157..058fb1d9656655983b2a4c18aa15b9859be62286 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *     $Header: /cvsroot/pgsql/src/backend/utils/adt/like.c,v 1.37 2000/07/07 21:12:50 tgl Exp $
+ *     $Header: /cvsroot/pgsql/src/backend/utils/adt/like.c,v 1.38 2000/08/06 18:05:41 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "mb/pg_wchar.h"
 #include "utils/builtins.h"
 
-static bool like(pg_wchar * text, pg_wchar * p);
+
+#define LIKE_TRUE                                              1
+#define LIKE_FALSE                                             0
+#define LIKE_ABORT                                             (-1)
+
+
+static int MatchText(pg_wchar * t, int tlen, pg_wchar * p, int plen, char *e);
+static int MatchTextLower(pg_wchar * t, int tlen, pg_wchar * p, int plen, char *e);
+
 
 /*
  *     interface routines called by the function manager
  */
 
-/*
-   fixedlen_like:
+Datum
+namelike(PG_FUNCTION_ARGS)
+{
+       Name            n = PG_GETARG_NAME(0);
+       text       *p = PG_GETARG_TEXT_P(1);
 
-   a generic fixed length like routine
-                s              - the string to match against  (not necessarily null-terminated)
-                p                 - the pattern (as text*)
-                charlen   - the length of the string
-*/
-static bool
-fixedlen_like(char *s, text *p, int charlen)
-{
-       pg_wchar   *sterm,
-                          *pterm;
-       bool            result;
-       int                     len;
-
-       /* be sure sterm is null-terminated */
-#ifdef MULTIBYTE
-       sterm = (pg_wchar *) palloc((charlen + 1) * sizeof(pg_wchar));
-       (void) pg_mb2wchar_with_len((unsigned char *) s, sterm, charlen);
-#else
-       sterm = (char *) palloc(charlen + 1);
-       memcpy(sterm, s, charlen);
-       sterm[charlen] = '\0';
-#endif
+       PG_RETURN_BOOL(MatchText(NameStr(*n), strlen(NameStr(*n)),
+                                                        VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                        NULL)
+                                  == LIKE_TRUE);
+}
 
-       /*
-        * p is a text, not a string so we have to make a string
-        * from the vl_data field of the struct.
-        */
+Datum
+namenlike(PG_FUNCTION_ARGS)
+{
+       Name            n = PG_GETARG_NAME(0);
+       text       *p = PG_GETARG_TEXT_P(1);
 
-       /* palloc the length of the text + the null character */
-       len = VARSIZE(p) - VARHDRSZ;
-#ifdef MULTIBYTE
-       pterm = (pg_wchar *) palloc((len + 1) * sizeof(pg_wchar));
-       (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(p), pterm, len);
-#else
-       pterm = (char *) palloc(len + 1);
-       memcpy(pterm, VARDATA(p), len);
-       *(pterm + len) = '\0';
-#endif
+       PG_RETURN_BOOL(MatchText(NameStr(*n), strlen(NameStr(*n)),
+                                                        VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                        NULL)
+                                  != LIKE_TRUE);
+}
 
-       /* do the regexp matching */
-       result = like(sterm, pterm);
+Datum
+namelike_escape(PG_FUNCTION_ARGS)
+{
+       Name            n = PG_GETARG_NAME(0);
+       text       *p = PG_GETARG_TEXT_P(1);
+       text       *e = PG_GETARG_TEXT_P(2);
 
-       pfree(sterm);
-       pfree(pterm);
+       PG_RETURN_BOOL(MatchText(NameStr(*n), strlen(NameStr(*n)),
+                                                        VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                        ((VARSIZE(e)-VARHDRSZ) > 0? VARDATA(e): NULL))
+                                  == LIKE_TRUE);
+}
 
-       return result;
+Datum
+namenlike_escape(PG_FUNCTION_ARGS)
+{
+       Name            n = PG_GETARG_NAME(0);
+       text       *p = PG_GETARG_TEXT_P(1);
+       text       *e = PG_GETARG_TEXT_P(2);
+
+       PG_RETURN_BOOL(MatchText(NameStr(*n), strlen(NameStr(*n)),
+                                                        VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                        ((VARSIZE(e)-VARHDRSZ) > 0? VARDATA(e): NULL))
+                                  != LIKE_TRUE);
 }
 
 Datum
-namelike(PG_FUNCTION_ARGS)
+textlike(PG_FUNCTION_ARGS)
+{
+       text       *s = PG_GETARG_TEXT_P(0);
+       text       *p = PG_GETARG_TEXT_P(1);
+
+       PG_RETURN_BOOL(MatchText(VARDATA(s), (VARSIZE(s)-VARHDRSZ),
+                                                        VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                        NULL)
+                                  == LIKE_TRUE);
+}
+
+Datum
+textnlike(PG_FUNCTION_ARGS)
+{
+       text       *s = PG_GETARG_TEXT_P(0);
+       text       *p = PG_GETARG_TEXT_P(1);
+
+       PG_RETURN_BOOL(MatchText(VARDATA(s), (VARSIZE(s)-VARHDRSZ),
+                                                        VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                        NULL)
+                                  != LIKE_TRUE);
+}
+
+Datum
+textlike_escape(PG_FUNCTION_ARGS)
+{
+       text       *s = PG_GETARG_TEXT_P(0);
+       text       *p = PG_GETARG_TEXT_P(1);
+       text       *e = PG_GETARG_TEXT_P(2);
+
+       PG_RETURN_BOOL(MatchText(VARDATA(s), (VARSIZE(s)-VARHDRSZ),
+                                                        VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                        ((VARSIZE(e)-VARHDRSZ) > 0? VARDATA(e): NULL))
+                                  == LIKE_TRUE);
+}
+
+Datum
+textnlike_escape(PG_FUNCTION_ARGS)
+{
+       text       *s = PG_GETARG_TEXT_P(0);
+       text       *p = PG_GETARG_TEXT_P(1);
+       text       *e = PG_GETARG_TEXT_P(2);
+
+       PG_RETURN_BOOL(MatchText(VARDATA(s), (VARSIZE(s)-VARHDRSZ),
+                                                        VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                        ((VARSIZE(e)-VARHDRSZ) > 0? VARDATA(e): NULL))
+                                  != LIKE_TRUE);
+}
+
+/*
+ * Case-insensitive versions
+ */
+
+Datum
+inamelike(PG_FUNCTION_ARGS)
 {
        Name            n = PG_GETARG_NAME(0);
        text       *p = PG_GETARG_TEXT_P(1);
 
-       PG_RETURN_BOOL(fixedlen_like(NameStr(*n), p, strlen(NameStr(*n))));
+       PG_RETURN_BOOL(MatchTextLower(NameStr(*n), strlen(NameStr(*n)),
+                                                                 VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                                 NULL)
+                                  == LIKE_TRUE);
 }
 
 Datum
-namenlike(PG_FUNCTION_ARGS)
+inamenlike(PG_FUNCTION_ARGS)
 {
        Name            n = PG_GETARG_NAME(0);
        text       *p = PG_GETARG_TEXT_P(1);
 
-       PG_RETURN_BOOL(! fixedlen_like(NameStr(*n), p, strlen(NameStr(*n))));
+       PG_RETURN_BOOL(MatchTextLower(NameStr(*n), strlen(NameStr(*n)),
+                                                                 VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                                 NULL)
+                                  != LIKE_TRUE);
 }
 
 Datum
-textlike(PG_FUNCTION_ARGS)
+inamelike_escape(PG_FUNCTION_ARGS)
+{
+       Name            n = PG_GETARG_NAME(0);
+       text       *p = PG_GETARG_TEXT_P(1);
+       text       *e = PG_GETARG_TEXT_P(2);
+
+       PG_RETURN_BOOL(MatchTextLower(NameStr(*n), strlen(NameStr(*n)),
+                                                                 VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                                 ((VARSIZE(e)-VARHDRSZ) > 0? VARDATA(e): NULL))
+                                  == LIKE_TRUE);
+}
+
+Datum
+inamenlike_escape(PG_FUNCTION_ARGS)
+{
+       Name            n = PG_GETARG_NAME(0);
+       text       *p = PG_GETARG_TEXT_P(1);
+       text       *e = PG_GETARG_TEXT_P(2);
+
+       PG_RETURN_BOOL(MatchTextLower(NameStr(*n), strlen(NameStr(*n)),
+                                                                 VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                                 ((VARSIZE(e)-VARHDRSZ) > 0? VARDATA(e): NULL))
+                                  != LIKE_TRUE);
+}
+
+Datum
+itextlike(PG_FUNCTION_ARGS)
 {
        text       *s = PG_GETARG_TEXT_P(0);
        text       *p = PG_GETARG_TEXT_P(1);
 
-       PG_RETURN_BOOL(fixedlen_like(VARDATA(s), p, VARSIZE(s) - VARHDRSZ));
+       PG_RETURN_BOOL(MatchTextLower(VARDATA(s), (VARSIZE(s)-VARHDRSZ),
+                                                                 VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                                 NULL)
+                                  == LIKE_TRUE);
 }
 
 Datum
-textnlike(PG_FUNCTION_ARGS)
+itextnlike(PG_FUNCTION_ARGS)
+{
+       text       *s = PG_GETARG_TEXT_P(0);
+       text       *p = PG_GETARG_TEXT_P(1);
+
+       PG_RETURN_BOOL(MatchTextLower(VARDATA(s), (VARSIZE(s)-VARHDRSZ),
+                                                                 VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                                 NULL)
+                                  != LIKE_TRUE);
+}
+
+Datum
+itextlike_escape(PG_FUNCTION_ARGS)
+{
+       text       *s = PG_GETARG_TEXT_P(0);
+       text       *p = PG_GETARG_TEXT_P(1);
+       text       *e = PG_GETARG_TEXT_P(2);
+
+       PG_RETURN_BOOL(MatchTextLower(VARDATA(s), (VARSIZE(s)-VARHDRSZ),
+                                                                 VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                                 ((VARSIZE(e)-VARHDRSZ) > 0? VARDATA(e): NULL))
+                                  == LIKE_TRUE);
+}
+
+Datum
+itextnlike_escape(PG_FUNCTION_ARGS)
 {
        text       *s = PG_GETARG_TEXT_P(0);
        text       *p = PG_GETARG_TEXT_P(1);
+       text       *e = PG_GETARG_TEXT_P(2);
 
-       PG_RETURN_BOOL(! fixedlen_like(VARDATA(s), p, VARSIZE(s) - VARHDRSZ));
+       PG_RETURN_BOOL(MatchTextLower(VARDATA(s), (VARSIZE(s)-VARHDRSZ),
+                                                                 VARDATA(p), (VARSIZE(p)-VARHDRSZ),
+                                                                 ((VARSIZE(e)-VARHDRSZ) > 0? VARDATA(e): NULL))
+                                  != LIKE_TRUE);
 }
 
 
@@ -136,12 +261,16 @@ textnlike(PG_FUNCTION_ARGS)
 **      LIKE <pattern> ESCAPE <escape character>. We are a small operation
 **      so we force you to use '\'. - ay 7/95]
 **
+** OK, we now support the SQL9x LIKE <pattern> ESCAPE <char> syntax.
+** We should kill the backslash escaping mechanism since it is non-standard
+** and undocumented afaik.
+** The code is rewritten to avoid requiring null-terminated strings,
+** which in turn allows us to leave out some memcpy() operations.
+** This code should be faster and take less memory, but no promises...
+** - thomas 2000-08-06
+**
 */
 
-#define LIKE_TRUE                                              1
-#define LIKE_FALSE                                             0
-#define LIKE_ABORT                                             (-1)
-
 /*--------------------
  *     Match text and p, return LIKE_TRUE, LIKE_FALSE, or LIKE_ABORT.
  *
@@ -153,69 +282,97 @@ textnlike(PG_FUNCTION_ARGS)
  * pattern either, so an upper-level % scan can stop scanning now.
  *--------------------
  */
+
+#define NextChar(p, plen) (p)++, (plen)--
+
 static int
-DoMatch(pg_wchar * text, pg_wchar * p)
+MatchText(pg_wchar * t, int tlen, pg_wchar * p, int plen, char *e)
 {
-       for (; *p && *text; text ++, p++)
+       /* Fast path for match-everything pattern
+        * Include weird case of escape character as a percent sign or underscore,
+        * when presumably that wildcard character becomes a literal.
+        */
+       if ((plen == 1) && (*p == '%')
+               && ! ((e != NULL) && (*e == '%')))
+               return LIKE_TRUE;
+
+       while ((tlen > 0) && (plen > 0))
        {
-               switch (*p)
+               /* If an escape character was specified and we find it here in the pattern,
+                * then we'd better have an exact match for the next character.
+                */
+               if ((e != NULL) && (*p == *e))
                {
-                       case '\\':
-                               /* Literal match with following character. */
-                               p++;
-                               /* FALLTHROUGH */
-                       default:
-                               if (*text !=*p)
-                                       return LIKE_FALSE;
-                               break;
-                       case '_':
-                               /* Match any single character. */
-                               break;
-                       case '%':
-                               /* %% is the same as % according to the SQL standard */
-                               /* Advance past all %'s */
-                               while (*p == '%')
-                                       p++;
-                               /* Trailing percent matches everything. */
-                               if (*p == '\0')
-                                       return LIKE_TRUE;
-
-                               /*
-                                * Otherwise, scan for a text position at which we can
-                                * match the rest of the pattern.
-                                */
-                               for (; *text; text ++)
-                               {
+                       NextChar(p, plen);
+                       if ((plen <= 0) || (*t != *p))
+                               return LIKE_FALSE;
+               }
+               else
+               {
+                       switch (*p)
+                       {
+                               case '\\':
+                                       /* Literal match with following character. */
+                                       NextChar(p, plen);
+                                       /* FALLTHROUGH */
+                               default:
+                                       if (*t != *p)
+                                               return LIKE_FALSE;
+                                       break;
+                               case '_':
+                                       /* Match any single character. */
+                                       break;
+                               case '%':
+                                       /* %% is the same as % according to the SQL standard */
+                                       /* Advance past all %'s */
+                                       while ((plen > 0) && (*p == '%'))
+                                               NextChar(p, plen);
+                                       /* Trailing percent matches everything. */
+                                       if (plen <= 0)
+                                               return LIKE_TRUE;
 
                                        /*
-                                        * Optimization to prevent most recursion: don't
-                                        * recurse unless first pattern char might match this
-                                        * text char.
+                                        * Otherwise, scan for a text position at which we can
+                                        * match the rest of the pattern.
                                         */
-                                       if (*text == *p || *p == '\\' || *p == '_')
+                                       while (tlen > 0)
                                        {
-                                               int                     matched = DoMatch(text, p);
+                                               /*
+                                                * Optimization to prevent most recursion: don't
+                                                * recurse unless first pattern char might match this
+                                                * text char.
+                                                */
+                                               if ((*t == *p) || (*p == '\\') || (*p == '_')
+                                                       || ((e != NULL) && (*p == *e)))
+                                               {
+                                                       int matched = MatchText(t, tlen, p, plen, e);
+
+                                                       if (matched != LIKE_FALSE)
+                                                               return matched;         /* TRUE or ABORT */
+                                               }
 
-                                               if (matched != LIKE_FALSE)
-                                                       return matched;         /* TRUE or ABORT */
+                                               NextChar(t, tlen);
                                        }
-                               }
 
-                               /*
-                                * End of text with no match, so no point in trying later
-                                * places to start matching this pattern.
-                                */
-                               return LIKE_ABORT;
+                                       /*
+                                        * End of text with no match, so no point in trying later
+                                        * places to start matching this pattern.
+                                        */
+                                       return LIKE_ABORT;
+                       }
                }
+
+               NextChar(t, tlen);
+               NextChar(p, plen);
        }
 
-       if (*text !='\0')
+       if (tlen > 0)
                return LIKE_FALSE;              /* end of pattern, but not of text */
 
        /* End of input string.  Do we have matching pattern remaining? */
-       while (*p == '%')                       /* allow multiple %'s at end of pattern */
-               p++;
-       if (*p == '\0')
+       while ((plen > 0) && (*p == '%'))       /* allow multiple %'s at end of pattern */
+               NextChar(p, plen);
+       if (plen <= 0)
                return LIKE_TRUE;
 
        /*
@@ -223,16 +380,101 @@ DoMatch(pg_wchar * text, pg_wchar * p)
         * start matching this pattern.
         */
        return LIKE_ABORT;
-}
+} /* MatchText() */
 
-/*
-**     User-level routine.  Returns TRUE or FALSE.
-*/
-static bool
-like(pg_wchar * text, pg_wchar * p)
+static int
+MatchTextLower(pg_wchar * t, int tlen, pg_wchar * p, int plen, char *e)
 {
-       /* Fast path for match-everything pattern */
-       if (p[0] == '%' && p[1] == '\0')
-               return true;
-       return DoMatch(text, p) == LIKE_TRUE;
-}
+       /* Fast path for match-everything pattern
+        * Include weird case of escape character as a percent sign or underscore,
+        * when presumably that wildcard character becomes a literal.
+        */
+       if ((plen == 1) && (*p == '%')
+               && ! ((e != NULL) && (*e == '%')))
+               return LIKE_TRUE;
+
+       while ((tlen > 0) && (plen > 0))
+       {
+               /* If an escape character was specified and we find it here in the pattern,
+                * then we'd better have an exact match for the next character.
+                */
+               if ((e != NULL) && (tolower(*p) == tolower(*e)))
+               {
+                       NextChar(p, plen);
+                       if ((plen <= 0) || (tolower(*t) != tolower(*p)))
+                               return LIKE_FALSE;
+               }
+               else
+               {
+                       switch (*p)
+                       {
+                               case '\\':
+                                       /* Literal match with following character. */
+                                       NextChar(p, plen);
+                                       /* FALLTHROUGH */
+                               default:
+                                       if (tolower(*t) != tolower(*p))
+                                               return LIKE_FALSE;
+                                       break;
+                               case '_':
+                                       /* Match any single character. */
+                                       break;
+                               case '%':
+                                       /* %% is the same as % according to the SQL standard */
+                                       /* Advance past all %'s */
+                                       while ((plen > 0) && (*p == '%'))
+                                               NextChar(p, plen);
+                                       /* Trailing percent matches everything. */
+                                       if (plen <= 0)
+                                               return LIKE_TRUE;
+
+                                       /*
+                                        * Otherwise, scan for a text position at which we can
+                                        * match the rest of the pattern.
+                                        */
+                                       while (tlen > 0)
+                                       {
+                                               /*
+                                                * Optimization to prevent most recursion: don't
+                                                * recurse unless first pattern char might match this
+                                                * text char.
+                                                */
+                                               if ((tolower(*t) == tolower(*p)) || (*p == '\\') || (*p == '_')
+                                                       || ((e != NULL) && (tolower(*p) == tolower(*e))))
+                                               {
+                                                       int matched = MatchText(t, tlen, p, plen, e);
+
+                                                       if (matched != LIKE_FALSE)
+                                                               return matched;         /* TRUE or ABORT */
+                                               }
+
+                                               NextChar(t, tlen);
+                                       }
+
+                                       /*
+                                        * End of text with no match, so no point in trying later
+                                        * places to start matching this pattern.
+                                        */
+                                       return LIKE_ABORT;
+                       }
+               }
+
+               NextChar(t, tlen);
+               NextChar(p, plen);
+       }
+
+       if (tlen > 0)
+               return LIKE_FALSE;              /* end of pattern, but not of text */
+
+       /* End of input string.  Do we have matching pattern remaining? */
+       while ((plen > 0) && (*p == '%'))       /* allow multiple %'s at end of pattern */
+               NextChar(p, plen);
+       if (plen <= 0)
+               return LIKE_TRUE;
+
+       /*
+        * End of text with no match, so no point in trying later places to
+        * start matching this pattern.
+        */
+       return LIKE_ABORT;
+} /* MatchTextLower() */
index c9ac2c39abae763497dfb1fb8bf8047084232150..d0c0b8e2bf9a01e2c6e2c0ec790e3a00f2af5bc5 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.39 2000/08/04 04:16:17 tgl Exp $
+ * $Id: catversion.h,v 1.40 2000/08/06 18:06:13 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200008031
+#define CATALOG_VERSION_NO     200008061
 
 #endif
index 4bc8609521f26a955a397e437df479057f4474d7..9f616dbc10158110eb12bd36cd5def081952bb26 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.160 2000/08/05 14:59:19 momjian Exp $
+ * $Id: pg_proc.h,v 1.161 2000/08/06 18:06:13 thomas Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -2039,6 +2039,31 @@ DATA(insert OID = 1623 (  varchar                        PGUID 12 f t t t 1 f 1043 "20" 100 0 0 100
 DESCR("convert int8 to varchar");
 DATA(insert OID = 1624 (  mul_d_interval       PGUID 12 f t t t 2 f 1186 "701 1186" 100 0 0 100        mul_d_interval - ));
 
+DATA(insert OID = 1625 (  like                         PGUID 12 f t t t 3 f 16 "19 25 25" 100 0 1 0  namelike_escape - ));
+DESCR("matches LIKE expression");
+DATA(insert OID = 1626 (  notlike                      PGUID 12 f t t t 3 f 16 "19 25 25" 100 0 1 0  namenlike_escape - ));
+DESCR("does not match LIKE expression");
+DATA(insert OID = 1627 (  ilike                                PGUID 12 f t t t 3 f 16 "19 25 25" 100 0 1 0  inamelike_escape - ));
+DESCR("matches case-insensitive LIKE expression");
+DATA(insert OID = 1628 (  inotlike                     PGUID 12 f t t t 3 f 16 "19 25 25" 100 0 1 0  inamenlike_escape - ));
+DESCR("does not match case-insensitive LIKE expression");
+DATA(insert OID = 1629 (  like                         PGUID 12 f t t t 3 f 16 "25 25 25" 100 0 1 0  textlike_escape - ));
+DESCR("matches LIKE expression");
+DATA(insert OID = 1630 (  notlike                      PGUID 12 f t t t 3 f 16 "25 25 25" 100 0 1 0  textnlike_escape - ));
+DESCR("does not match LIKE expression");
+DATA(insert OID = 1631 (  ilike                                PGUID 12 f t t t 3 f 16 "25 25 25" 100 0 1 0  itextlike_escape - ));
+DESCR("matches case-insensitive LIKE expression");
+DATA(insert OID = 1632 (  inotlike                     PGUID 12 f t t t 3 f 16 "25 25 25" 100 0 1 0  itextnlike_escape - ));
+DESCR("does not match case-insensitive LIKE expression");
+DATA(insert OID = 1633 (  ilike                                PGUID 12 f t t t 2 f 16 "25 25" 100 0 1 0  itextlike - ));
+DESCR("matches case-insensitive LIKE expression");
+DATA(insert OID = 1634 (  inotlike                     PGUID 12 f t t t 2 f 16 "25 25" 100 0 1 0  itextnlike - ));
+DESCR("does not match case-insensitive LIKE expression");
+DATA(insert OID = 1635 (  ilike                                PGUID 12 f t t t 2 f 16 "19 25" 100 0 0 100  inamelike - ));
+DESCR("matches case-insensitive LIKE expression");
+DATA(insert OID = 1636 (  inotlike                     PGUID 12 f t t t 2 f 16 "19 25" 100 0 0 100  inamenlike - ));
+DESCR("does not match case-insensitive LIKE expression");
+
 DATA(insert OID = 1689 (  update_pg_pwd       PGUID 12 f t f t 0 f 0  ""  100 0 0 100  update_pg_pwd - ));
 DESCR("update pg_pwd file");
 
@@ -2291,9 +2316,9 @@ DESCR("greater-than");
 DATA(insert OID = 1721 ( numeric_ge                            PGUID 12 f t t t 2 f 16 "1700 1700" 100 0 0 100  numeric_ge - ));
 DESCR("greater-than-or-equal");
 DATA(insert OID = 1722 ( numeric_lt                            PGUID 12 f t t t 2 f 16 "1700 1700" 100 0 0 100  numeric_lt - ));
-DESCR("lower-than");
+DESCR("less-than");
 DATA(insert OID = 1723 ( numeric_le                            PGUID 12 f t t t 2 f 16 "1700 1700" 100 0 0 100  numeric_le - ));
-DESCR("lower-than-or-equal");
+DESCR("less-than-or-equal");
 DATA(insert OID = 1724 ( numeric_add                   PGUID 12 f t t t 2 f 1700 "1700 1700" 100 0 0 100  numeric_add - ));
 DESCR("add");
 DATA(insert OID = 1725 ( numeric_sub                   PGUID 12 f t t t 2 f 1700 "1700 1700" 100 0 0 100  numeric_sub - ));
index 4fa7481f042ec711570b348b7a2f5dcb6f78d67d..f9d3679e27a867ec0d227e98676e43b7a11f0f02 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: builtins.h,v 1.130 2000/08/03 23:07:51 tgl Exp $
+ * $Id: builtins.h,v 1.131 2000/08/06 18:06:44 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -431,8 +431,12 @@ extern Datum pgsql_version(PG_FUNCTION_ARGS);
 /* like.c */
 extern Datum namelike(PG_FUNCTION_ARGS);
 extern Datum namenlike(PG_FUNCTION_ARGS);
+extern Datum namelike_escape(PG_FUNCTION_ARGS);
+extern Datum namenlike_escape(PG_FUNCTION_ARGS);
 extern Datum textlike(PG_FUNCTION_ARGS);
 extern Datum textnlike(PG_FUNCTION_ARGS);
+extern Datum textlike_escape(PG_FUNCTION_ARGS);
+extern Datum textnlike_escape(PG_FUNCTION_ARGS);
 
 /* oracle_compat.c */
 extern Datum lower(PG_FUNCTION_ARGS);