From 235e56b60d1a392eaa03338184ce9f506345ae9f Mon Sep 17 00:00:00 2001
From: Danis Kirasirov <dbgbbu@gmail.com>
Date: Tue, 6 Feb 2024 09:55:10 +0300
Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?=
 =?UTF-8?q?=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B0?=
 =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=82=D0=B8=D0=BF=20array=20=D0=B4=D0=BB?=
 =?UTF-8?q?=D1=8F=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8=20len?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pkg/expr/mongo.go      | 19 ++++++++++---------
 pkg/expr/mongo_test.go |  6 +++---
 2 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/pkg/expr/mongo.go b/pkg/expr/mongo.go
index f856311d..597180a6 100644
--- a/pkg/expr/mongo.go
+++ b/pkg/expr/mongo.go
@@ -673,27 +673,28 @@ func (c *compiler) handleLenNode(node *ast.BinaryNode) bson.M {
 		panic("len() can only be compared with non-negative number")
 	}
 
+	field := c.identifier(lenNode.Arguments[0])
 	switch op := node.Operator; {
 	case (op == "==" || op == "<=") && length == 0:
-		return bson.M{c.identifier(lenNode.Arguments[0]): bson.M{"$eq": bson.A{}}}
+		return bson.M{field: bson.M{"$eq": bson.A{}}}
 	case (op == "!=" || op == ">") && length == 0:
-		return bson.M{c.identifier(lenNode.Arguments[0]): bson.M{"$exists": true, "$type": "array", "$ne": bson.A{}}}
+		return bson.M{field: bson.M{"$exists": true, "$type": "array", "$ne": bson.A{}}}
 	case op == ">=" && length == 0:
-		return bson.M{c.identifier(lenNode.Arguments[0]): bson.M{"$exists": true, "$type": "array"}}
+		return bson.M{field: bson.M{"$exists": true, "$type": "array"}}
 	case op == "<" && length == 0:
 		panic("invalid comparison: len() cannot be less than 0")
 	case op == "==":
-		return bson.M{c.identifier(lenNode.Arguments[0]): bson.M{"$size": length}}
+		return bson.M{field: bson.M{"$size": length}}
 	case op == "!=":
-		return bson.M{c.identifier(lenNode.Arguments[0]): bson.M{"$not": bson.M{"$size": length}}}
+		return bson.M{field: bson.M{"$not": bson.M{"$size": length}, "$type": "array"}}
 	case op == ">":
-		return bson.M{c.identifier(lenNode.Arguments[0]) + "." + strconv.Itoa(length): bson.M{"$exists": true}}
+		return bson.M{field + "." + strconv.Itoa(length): bson.M{"$exists": true}}
 	case op == ">=":
-		return bson.M{c.identifier(lenNode.Arguments[0]) + "." + strconv.Itoa(length-1): bson.M{"$exists": true}}
+		return bson.M{field + "." + strconv.Itoa(length-1): bson.M{"$exists": true}}
 	case op == "<":
-		return bson.M{c.identifier(lenNode.Arguments[0]) + "." + strconv.Itoa(length-1): bson.M{"$exists": false}}
+		return bson.M{field + "." + strconv.Itoa(length-1): bson.M{"$exists": false}, field: bson.M{"$type": "array"}}
 	case op == "<=":
-		return bson.M{c.identifier(lenNode.Arguments[0]) + "." + strconv.Itoa(length): bson.M{"$exists": false}}
+		return bson.M{field + "." + strconv.Itoa(length): bson.M{"$exists": false}, field: bson.M{"$type": "array"}}
 	default:
 		panic("invalid comparison operator with len()")
 	}
diff --git a/pkg/expr/mongo_test.go b/pkg/expr/mongo_test.go
index 6420579c..dee6e668 100644
--- a/pkg/expr/mongo_test.go
+++ b/pkg/expr/mongo_test.go
@@ -39,15 +39,15 @@ func TestConvertToMongo(t *testing.T) {
 		{"len#5", "len(s) == s", nil, nil, true},
 		{"len eq", "len(s) == 1", nil, bson.M{"s": bson.M{"$size": 1}}, false},
 		{"len eq zero", "len(s) == 0", nil, bson.M{"s": bson.M{"$eq": bson.A{}}}, false},
-		{"len ne", "len(s) != 1", nil, bson.M{"s": bson.M{"$not": bson.M{"$size": 1}}}, false},
+		{"len ne", "len(s) != 1", nil, bson.M{"s": bson.M{"$not": bson.M{"$size": 1}, "$type": "array"}}, false},
 		{"len ne zero", "len(s) != 0", nil, bson.M{"s": bson.M{"$exists": true, "$ne": bson.A{}, "$type": "array"}}, false},
 		{"len gt", "len(s) > 1", nil, bson.M{"s.1": bson.M{"$exists": true}}, false},
 		{"len gt zero", "len(s) > 0", nil, bson.M{"s": bson.M{"$exists": true, "$type": "array", "$ne": bson.A{}}}, false},
 		{"len gte", "len(s) >= 1", nil, bson.M{"s.0": bson.M{"$exists": true}}, false},
 		{"len gte zero", "len(s) >= 0", nil, bson.M{"s": bson.M{"$exists": true, "$type": "array"}}, false},
-		{"len lt", "len(s) < 1", nil, bson.M{"s.0": bson.M{"$exists": false}}, false},
+		{"len lt", "len(s) < 1", nil, bson.M{"s.0": bson.M{"$exists": false}, "s": bson.M{"$type": "array"}}, false},
 		{"len lt zero", "len(s) < 0", nil, nil, true},
-		{"len lte", "len(s) <= 1", nil, bson.M{"s.1": bson.M{"$exists": false}}, false},
+		{"len lte", "len(s) <= 1", nil, bson.M{"s.1": bson.M{"$exists": false}, "s": bson.M{"$type": "array"}}, false},
 		{"len lte zero", "len(s) <= 0", nil, bson.M{"s": bson.M{"$eq": bson.A{}}}, false},
 		{"field#1", "s.test > 3", nil, bson.M{"s.test": bson.M{"$gt": 3}}, false},
 		{"field#2", "s['test'] > 3", nil, bson.M{"s.test": bson.M{"$gt": 3}}, false},
-- 
GitLab