diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index e8abfe039f0..84efc2875ee 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.449 2004/03/17 20:48:42 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.450 2004/04/05 03:07:26 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -194,7 +194,7 @@ static void doNegateFloat(Value *v); database_name access_method_clause access_method attr_name index_name name function_name file_name -%type func_name handler_name qual_Op qual_all_Op +%type func_name handler_name qual_Op qual_all_Op subquery_Op opt_class opt_validator %type qualified_name OptConstrFromTable @@ -5692,7 +5692,7 @@ r_expr: row IN_P select_with_parens /* Stick a NOT on top */ $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, (Node *) n); } - | row qual_all_Op sub_type select_with_parens + | row subquery_Op sub_type select_with_parens %prec Op { SubLink *n = makeNode(SubLink); @@ -5702,7 +5702,7 @@ r_expr: row IN_P select_with_parens n->subselect = $4; $$ = (Node *)n; } - | row qual_all_Op select_with_parens + | row subquery_Op select_with_parens %prec Op { SubLink *n = makeNode(SubLink); @@ -5712,7 +5712,7 @@ r_expr: row IN_P select_with_parens n->subselect = $3; $$ = (Node *)n; } - | row qual_all_Op row + | row subquery_Op row %prec Op { $$ = makeRowExpr($2, $1, $3); @@ -5807,6 +5807,23 @@ qual_all_Op: | OPERATOR '(' any_operator ')' { $$ = $3; } ; +subquery_Op: + all_Op { $$ = makeList1(makeString($1)); } + | OPERATOR '(' any_operator ')' { $$ = $3; } + | LIKE { $$ = makeList1(makeString("~~")); } + | NOT LIKE { $$ = makeList1(makeString("!~~")); } + | ILIKE { $$ = makeList1(makeString("~~*")); } + | NOT ILIKE { $$ = makeList1(makeString("!~~*")); } +/* cannot put SIMILAR TO here, because SIMILAR TO is a hack. + * the regular expression is preprocessed by a function (similar_escape), + * and the ~ operator for posix regular expressions is used. + * x SIMILAR TO y -> x ~ similar_escape(y) + * this transformation is made on the fly by the parser upwards. + * however the SubLink structure which handles any/some/all stuff + * is not ready for such a thing. + */ + ; + /* * General expressions * This is the heart of the expression syntax. @@ -6132,7 +6149,7 @@ a_expr: c_expr { $$ = $1; } $$ = n; } } - | a_expr qual_all_Op sub_type select_with_parens %prec Op + | a_expr subquery_Op sub_type select_with_parens %prec Op { SubLink *n = makeNode(SubLink); n->subLinkType = $3; @@ -6141,7 +6158,7 @@ a_expr: c_expr { $$ = $1; } n->subselect = $4; $$ = (Node *)n; } - | a_expr qual_all_Op sub_type '(' a_expr ')' %prec Op + | a_expr subquery_Op sub_type '(' a_expr ')' %prec Op { if ($3 == ANY_SUBLINK) $$ = (Node *) makeA_Expr(AEXPR_OP_ANY, $2, $1, $5); diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out index 6f3c07cfb3f..6e82a7d0a6c 100644 --- a/src/test/regress/expected/arrays.out +++ b/src/test/regress/expected/arrays.out @@ -377,3 +377,52 @@ select * from arr_tbl where f1 > '{1,2,3}' and f1 <= '{1,5,3}'; -- note: if above select doesn't produce the expected tuple order, -- then you didn't get an indexscan plan, and something is busted. +-- test [not] (like|ilike) (any|all) (...) +select 'foo' like any (array['%a', '%o']); -- t + ?column? +---------- + t +(1 row) + +select 'foo' like any (array['%a', '%b']); -- f + ?column? +---------- + f +(1 row) + +select 'foo' like all (array['f%', '%o']); -- t + ?column? +---------- + t +(1 row) + +select 'foo' like all (array['f%', '%b']); -- f + ?column? +---------- + f +(1 row) + +select 'foo' not like any (array['%a', '%b']); -- t + ?column? +---------- + t +(1 row) + +select 'foo' not like all (array['%a', '%o']); -- f + ?column? +---------- + f +(1 row) + +select 'foo' ilike any (array['%A', '%O']); -- t + ?column? +---------- + t +(1 row) + +select 'foo' ilike all (array['F%', '%O']); -- t + ?column? +---------- + t +(1 row) + diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql index 3bc800cef21..629ca15fb1c 100644 --- a/src/test/regress/sql/arrays.sql +++ b/src/test/regress/sql/arrays.sql @@ -183,3 +183,13 @@ set enable_seqscan to off; select * from arr_tbl where f1 > '{1,2,3}' and f1 <= '{1,5,3}'; -- note: if above select doesn't produce the expected tuple order, -- then you didn't get an indexscan plan, and something is busted. + +-- test [not] (like|ilike) (any|all) (...) +select 'foo' like any (array['%a', '%o']); -- t +select 'foo' like any (array['%a', '%b']); -- f +select 'foo' like all (array['f%', '%o']); -- t +select 'foo' like all (array['f%', '%b']); -- f +select 'foo' not like any (array['%a', '%b']); -- t +select 'foo' not like all (array['%a', '%o']); -- f +select 'foo' ilike any (array['%A', '%O']); -- t +select 'foo' ilike all (array['F%', '%O']); -- t