 src/backend/parser/parse_oper.c      | 18 ++++++++++
 src/test/regress/expected/arrays.out | 64 ++++++++++++++++++++++++++++++++++++
 src/test/regress/sql/arrays.sql      | 20 +++++++++++
 3 files changed, 102 insertions(+)

diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index e9bf502..f6c3caf 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -877,6 +877,7 @@ make_scalar_array_op(ParseState *pstate, List *opname,
 	List	   *args;
 	Oid			rettype;
 	ScalarArrayOpExpr *result;
+	Node	   *riexpr;
 
 	ltypeId = exprType(ltree);
 	atypeId = exprType(rtree);
@@ -971,6 +972,23 @@ make_scalar_array_op(ParseState *pstate, List *opname,
 	/* perform the necessary typecasting of arguments */
 	make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
 
+	/*
+	* If rtree is an array with only one item, we escape from using ANY and
+	* ARRAY and transform expr to more simple form. It allows to use index
+	* search by ltree column with sorted result.
+	*/
+	if (IsA(rtree, ArrayExpr) &&
+		list_length(((ArrayExpr *)rtree)->elements) == 1)
+	{
+		ReleaseSysCache(tup);
+		riexpr = (Node *)linitial(((ArrayExpr *)rtree)->elements);
+		return (Node *)make_op(pstate,
+							   opname,
+							   ltree,
+							   riexpr,
+							   location);
+	}
+
 	/* and build the expression node */
 	result = makeNode(ScalarArrayOpExpr);
 	result->opno = oprid(tup);
diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out
index c730563..3d5c8e6 100644
--- a/src/test/regress/expected/arrays.out
+++ b/src/test/regress/expected/arrays.out
@@ -1173,6 +1173,70 @@ SELECT NULL::text[]::int[] AS "NULL";
  
 (1 row)
 
+-- Optimizing for single-element arrays
+CREATE TEMP TABLE arr_single (i1 int, i2 int);
+CREATE INDEX arr_single_right ON arr_single (i1, i2);
+CREATE INDEX arr_single_wrong ON arr_single (i2);
+EXPLAIN (COSTS OFF)
+  SELECT * FROM arr_single WHERE i1 = ANY(ARRAY[23]) ORDER BY i2 LIMIT 1;
+                         QUERY PLAN
+------------------------------------------------------------
+ Limit
+   ->  Index Only Scan using arr_single_right on arr_single
+         Index Cond: (i1 = 23)
+(3 rows)
+
+DROP TABLE arr_single;
+-- scalar op any/all (array)
+SELECT 33 = ANY(ARRAY[23]);
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT 33 = ALL(ARRAY[23]);
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT 33 >= ALL(ARRAY[23]);
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT 33 = ANY(ARRAY[NULL]::int[]);
+ ?column?
+----------
+
+(1 row)
+
+SELECT 33 >= ALL(ARRAY[NULL]::int[]);
+ ?column?
+----------
+
+(1 row)
+
+-- cross-datatype
+select 33.4 = ANY(ARRAY[23]);
+ ?column?
+----------
+ f
+(1 row)
+
+select 33.4 > ALL(ARRAY[23]);
+ ?column?
+----------
+ t
+(1 row)
+
+-- errors
+SELECT 33 * ANY(ARRAY[23]);
+ERROR:  op ANY/ALL (array) requires operator to yield boolean
+LINE 1: SELECT 33 * ANY(ARRAY[23]);
+                  ^
+--
 -- scalar op any/all (array)
 select 33 = any ('{1,2,3}');
  ?column? 
diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql
index 25dd4e2..1aa5c72 100644
--- a/src/test/regress/sql/arrays.sql
+++ b/src/test/regress/sql/arrays.sql
@@ -348,6 +348,26 @@ SELECT ARRAY[['a','bc'],['def','hijk']]::text[]::varchar[] is of (varchar[]) as
 SELECT CAST(ARRAY[[[[[['a','bb','ccc']]]]]] as text[]) as "{{{{{{a,bb,ccc}}}}}}";
 SELECT NULL::text[]::int[] AS "NULL";
 
+-- Optimizing for single-element arrays
+CREATE TEMP TABLE arr_single (i1 int, i2 int);
+CREATE INDEX arr_single_right ON arr_single (i1, i2);
+CREATE INDEX arr_single_wrong ON arr_single (i2);
+EXPLAIN (COSTS OFF)
+  SELECT * FROM arr_single WHERE i1 = ANY(ARRAY[23]) ORDER BY i2 LIMIT 1;
+DROP TABLE arr_single;
+-- scalar op any/all (array)
+SELECT 33 = ANY(ARRAY[23]);
+SELECT 33 = ALL(ARRAY[23]);
+SELECT 33 >= ALL(ARRAY[23]);
+SELECT 33 = ANY(ARRAY[NULL]::int[]);
+SELECT 33 >= ALL(ARRAY[NULL]::int[]);
+-- cross-datatype
+select 33.4 = ANY(ARRAY[23]);
+select 33.4 > ALL(ARRAY[23]);
+-- errors
+SELECT 33 * ANY(ARRAY[23]);
+--
+
 -- scalar op any/all (array)
 select 33 = any ('{1,2,3}');
 select 33 = any ('{1,2,33}');
