Skip to content
Snippets Groups Projects
Unverified Commit 4dd50562 authored by Ngoc Khuat's avatar Ngoc Khuat Committed by GitHub
Browse files

fix mongo not able to filter by UUID (#26367)

parent e2939bf6
No related branches found
No related tags found
No related merge requests found
......@@ -25,7 +25,8 @@
$multiply $ne $not $or $project $regex $second $size $skip $sort $strcasecmp $subtract
$sum $toLower $year]]
[schema.core :as s])
(:import org.bson.types.ObjectId))
(:import [org.bson.types ObjectId Binary]
org.bson.BsonBinarySubType))
;;; +----------------------------------------------------------------------------------------------------------------+
;;; | Schema |
......@@ -289,15 +290,32 @@
(defmethod ->rvalue nil [_] nil)
(defn- uuid->bsonbinary
[u]
(let [lo (.getLeastSignificantBits ^java.util.UUID u)
hi (.getMostSignificantBits ^java.util.UUID u)
ba (-> (java.nio.ByteBuffer/allocate 16) ; UUID is 128 bits-long
(.putLong hi)
(.putLong lo)
(.array))]
(Binary. BsonBinarySubType/UUID_STANDARD ba)))
(defmethod ->rvalue :value
[[_ value {base-type :base_type}]]
(if (and (isa? base-type :type/MongoBSONID)
(some? value))
;; Passing nil or "" to the ObjectId constructor throws an exception
;; "invalid hexadecimal representation of an ObjectId: []" so, just treat it as nil
(when (not= value "")
(ObjectId. (str value)))
value))
(cond
;; Passing nil or "" to the ObjectId or Binary constructor throws an exception
(or (nil? value) (= value ""))
value
(isa? base-type :type/MongoBSONID)
(ObjectId. (str value))
(isa? base-type :type/UUID)
(-> (str value)
java.util.UUID/fromString
uuid->bsonbinary)
:else value))
(defn- $date-from-string [s]
{:$dateFromString {:dateString (str s)}})
......
......@@ -91,7 +91,7 @@
:dbname "metabase-test"
:version "2.2134234.lol"}
:expected false}]
:let [ssl-details (tdm/conn-details details)]]
:let [ssl-details (tdm/conn-details details)]]
(testing (str "connect with " details)
(is (= expected
(let [db (db/insert! Database {:name "dummy", :engine "mongo", :details ssl-details})]
......@@ -264,42 +264,71 @@
{:order-by [:name]})]
(into {} field))))))))))
(tx/defdataset with-bson-ids
[["birds"
[{:field-name "name", :base-type :type/Text}
{:field-name "bird_id", :base-type :type/MongoBSONID}]
[["Rasta Toucan" (ObjectId. "012345678901234567890123")]
["Lucky Pigeon" (ObjectId. "abcdefabcdefabcdefabcdef")]
{:field-name "bird_id", :base-type :type/MongoBSONID}
{:field-name "bird_uuid", :base-type :type/UUID}]
[["Rasta Toucan" (ObjectId. "012345678901234567890123") "11111111-1111-1111-1111-111111111111"]
["Lucky Pigeon" (ObjectId. "abcdefabcdefabcdefabcdef") "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"]
["Unlucky Raven" nil]]]])
(deftest bson-ids-test
(mt/test-driver :mongo
(testing "BSON IDs"
(is (= [[2 "Lucky Pigeon" (ObjectId. "abcdefabcdefabcdefabcdef")]]
(rows (mt/dataset with-bson-ids
(mt/run-mbql-query birds
{:filter [:= $bird_id "abcdefabcdefabcdefabcdef"]}))))
"Check that we support Mongo BSON ID and can filter by it (#1367)")
(is (= [[3 "Unlucky Raven" nil]]
(rows (mt/dataset with-bson-ids
(mt/run-mbql-query birds
{:filter [:is-null $bird_id]}))))
"handle null ObjectId queries properly (#11134)")
(is (= [[3 "Unlucky Raven" nil]]
(rows (mt/dataset with-bson-ids
(mt/run-mbql-query birds
{:filter [:is-empty $bird_id]}))))
"treat null ObjectId as empty (#15801)")
(is (= [[1 "Rasta Toucan" (ObjectId. "012345678901234567890123")]
[2 "Lucky Pigeon" (ObjectId. "abcdefabcdefabcdefabcdef")]]
(rows (mt/dataset with-bson-ids
(mt/run-mbql-query birds
{:filter [:not-empty $bird_id]}))))
"treat non-null ObjectId as not-empty (#15801)"))))
(mt/dataset with-bson-ids
(testing "BSON IDs"
(testing "Check that we support Mongo BSON ID and can filter by it (#1367)"
(is (= [[2 "Lucky Pigeon" (ObjectId. "abcdefabcdefabcdefabcdef")]]
(rows (mt/run-mbql-query birds
{:filter [:= $bird_id "abcdefabcdefabcdefabcdef"]
:fields [$id $name $bird_id]})))))
(testing "handle null ObjectId queries properly (#11134)"
(is (= [[3 "Unlucky Raven" nil]]
(rows (mt/run-mbql-query birds
{:filter [:is-null $bird_id]
:fields [$id $name $bird_id]})))))
(testing "treat null ObjectId as empty (#15801)"
(is (= [[3 "Unlucky Raven" nil]]
(rows (mt/run-mbql-query birds
{:filter [:is-empty $bird_id]
:fields [$id $name $bird_id]})))))
(testing "treat non-null ObjectId as not-empty (#15801)"
(is (= [[1 "Rasta Toucan" (ObjectId. "012345678901234567890123")]
[2 "Lucky Pigeon" (ObjectId. "abcdefabcdefabcdefabcdef")]]
(rows (mt/run-mbql-query birds
{:filter [:not-empty $bird_id]
:fields [$id $name $bird_id]}))))))
(testing "BSON UUIDs"
(testing "Check that we support Mongo BSON UUID and can filter by it"
(is (= [[2 "Lucky Pigeon" "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"]]
(rows (mt/run-mbql-query birds
{:filter [:= $bird_uuid "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"]
:fields [$id $name $bird_uuid]})))))
(testing "handle null UUID queries properly"
(is (= [[3 "Unlucky Raven" nil]]
(rows (mt/run-mbql-query birds
{:filter [:is-null $bird_uuid]
:fields [$id $name $bird_uuid]})))))
(testing "treat null UUID as empty"
(is (= [[3 "Unlucky Raven" nil]]
(rows (mt/run-mbql-query birds
{:filter [:is-empty $bird_uuid]
:fields [$id $name $bird_uuid]}))))))
(testing "treat non-null UUID as not-empty"
(is (= [[1 "Rasta Toucan" "11111111-1111-1111-1111-111111111111"]
[2 "Lucky Pigeon" "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"]]
(rows (mt/run-mbql-query birds
{:filter [:not-empty $bird_uuid]
:fields [$id $name $bird_uuid]}))))))))
(deftest bson-fn-call-forms-test
(mt/test-driver :mongo
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment