Re: Index use difference betweer LIKE, LIKE ANY?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On Sun, Feb 27, 2011 at 2:43 AM, Josh Berkus <josh@xxxxxxxxxxxx> wrote:
On 2/25/11 5:31 AM, Sam Wong wrote:
> I found that "LIKE", "= ANY (...)", "LIKE .. OR LIKE .." against a text
> field used the index correctly, but not "LIKE ANY (...)". Would that be a
> bug?

No, it would be a TODO.  This is a known limitation; it needs some
clever code to make it work, and nobody's written it.


came up with attached patch without thinking too much.
With this patch, the explain output for the same query is as below:

postgres=# explain select * from shipment_lookup where (UPPER(lookup) LIKE                  
ANY(ARRAY['SD1102228482%', 'ABCDEFGHIJK%']))
;e
                                           QUERY PLAN                                           
-------------------------------------------------------------------------------------------------
 Seq Scan on shipment_lookup  (cost=0.00..254057.36 rows=2000 width=14)
   Filter: ((upper(lookup) ~~ 'SD1102228482%'::text) OR (upper(lookup) ~~ 'ABCDEFGHIJK%'::text))
(2 rows)

postgres-#

The thing to be noted here is that  the where clause "<pred> LIKE ANY ARRAY[..]"
has been converted into
(<pred> LIKE first_array_element) or (<pred> LIKE second_array_element) or ....

Please pass on your inputs.

Regards,
Chetan

--
Chetan Sutrave
Senior Software Engineer
EnterpriseDB Corporation
The Enterprise PostgreSQL Company
Phone: +91.20.30589523

Website: www.enterprisedb.com
EnterpriseDB Blog: http://blogs.enterprisedb.com/
Follow us on Twitter: http://www.twitter.com/enterprisedb

This e-mail message (and any attachment) is intended for the use of the individual or entity to whom it is addressed. This message contains information from EnterpriseDB Corporation that may be privileged, confidential, or exempt from disclosure under applicable law. If you are not the intended recipient or authorized to receive this for the intended recipient, any use, dissemination, distribution, retention, archiving, or copying of this communication is strictly prohibited. If you have received this e-mail in error, please notify the sender immediately by reply e-mail and delete this message.

diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 1633499..a4a7832 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -10068,7 +10068,37 @@ a_expr:		c_expr									{ $$ = $1; }
 			| a_expr subquery_Op sub_type '(' a_expr ')'		%prec Op
 				{
 					if ($3 == ANY_SUBLINK)
-						$$ = (Node *) makeA_Expr(AEXPR_OP_ANY, $2, $1, $5, @2);
+					{
+						bool expandLike = false;
+						/* convert expr of type "a like any(array[1,2])" into
+						 * "a like 1 or a like 2"
+						 */
+						if (strcmp(NameListToString($2),"~~")==0)
+						{
+							ListCell *lc;
+							if (IsA($5, A_ArrayExpr))
+							{
+								Node *res = NULL;
+								A_ArrayExpr *arr_expr = (A_ArrayExpr *)$5;
+								foreach (lc, arr_expr->elements)
+								{
+									Node *tmp = NULL;
+									Node *element = (Node*)lfirst(lc);
+									expandLike = true;
+									tmp = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, element, @2);
+									if (res)
+										res = (Node*) makeA_Expr(AEXPR_OR, NIL, res, tmp, @2);
+									else
+										res = tmp;
+								}
+								$$ = res;
+							}
+
+						}
+						/* also handles array with zero elements */
+						if (!expandLike)
+							$$ = (Node *) makeA_Expr(AEXPR_OP_ANY, $2, $1, $5, @2);
+					}
 					else
 						$$ = (Node *) makeA_Expr(AEXPR_OP_ALL, $2, $1, $5, @2);
 				}
-- 
Sent via pgsql-performance mailing list (pgsql-performance@xxxxxxxxxxxxxx)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance

[Postgresql General]     [Postgresql PHP]     [PHP Users]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Yosemite]

  Powered by Linux