*
*
* 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
database_name access_method_clause access_method attr_name
index_name name function_name file_name
-%type <list> func_name handler_name qual_Op qual_all_Op
+%type <list> func_name handler_name qual_Op qual_all_Op subquery_Op
opt_class opt_validator
%type <range> qualified_name OptConstrFromTable
/* 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);
n->subselect = $4;
$$ = (Node *)n;
}
- | row qual_all_Op select_with_parens
+ | row subquery_Op select_with_parens
%prec Op
{
SubLink *n = makeNode(SubLink);
n->subselect = $3;
$$ = (Node *)n;
}
- | row qual_all_Op row
+ | row subquery_Op row
%prec Op
{
$$ = makeRowExpr($2, $1, $3);
| 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.
$$ = 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;
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);
-- 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)
+
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