From f71a752148b0063b60162094e7c3ddceaf6d7eb5 Mon Sep 17 00:00:00 2001 From: FiVo Date: Mon, 28 Aug 2023 11:56:26 +0200 Subject: [PATCH] Add iid-fast path for non sequential in args --- core/src/main/clojure/xtdb/operator/scan.clj | 23 +++++++++++------- src/test/clojure/xtdb/operator/scan_test.clj | 25 ++++++++++++++++---- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/core/src/main/clojure/xtdb/operator/scan.clj b/core/src/main/clojure/xtdb/operator/scan.clj index 9232c11aa8..8f0236523c 100644 --- a/core/src/main/clojure/xtdb/operator/scan.clj +++ b/core/src/main/clojure/xtdb/operator/scan.clj @@ -623,11 +623,18 @@ :current-iid-ptr (ArrowBufPointer.)} (at-point-point? scan-opts) (assoc :point-point? true)))))) -(defn selects->iid-byte-buffer ^ByteBuffer [selects] +(defn selects->iid-byte-buffer ^ByteBuffer [selects ^RelationReader params-rel] (when-let [eid-select (or (get selects 'xt/id) (get selects 'xt$id))] (let [eid (nth eid-select 2)] - (when (and (= '= (first eid-select)) (s/valid? ::lp/value eid)) - (trie/->iid eid))))) + (when (= '= (first eid-select)) + (cond + (s/valid? ::lp/value eid) + (trie/->iid eid) + + (s/valid? ::lp/param eid) + (let [eid-rdr (.readerForName params-rel (name eid))] + (when (= 1 (.valueCount eid-rdr)) + (trie/->iid (.getObject eid-rdr 0))))))))) (defmethod ig/prep-key ::scan-emitter [_ opts] (merge opts @@ -693,17 +700,12 @@ (first arg)) (into {})) - iid-bb (selects->iid-byte-buffer selects) - col-preds (->> (for [[col-name select-form] selects] ;; for temporal preds, we may not need to re-apply these if they can be represented as a temporal range. (MapEntry/create (str col-name) (expr/->expression-relation-selector select-form {:col-types col-types, :param-types param-types}))) (into {})) - col-preds (cond-> col-preds - iid-bb - (assoc "xt$iid" (iid-selector iid-bb))) metadata-args (vec (for [[col-name select] selects :when (not (types/temporal-column? (util/str->normal-form-str (str col-name))))] @@ -718,7 +720,10 @@ {:col-types col-types :stats {:row-count row-count} :->cursor (fn [{:keys [allocator, ^IWatermark watermark, basis, params default-all-valid-time?]}] - (let [metadata-pred (expr.meta/->metadata-selector (cons 'and metadata-args) col-types params) + (let [iid-bb (selects->iid-byte-buffer selects params) + col-preds (cond-> col-preds + iid-bb (assoc "xt$iid" (iid-selector iid-bb))) + metadata-pred (expr.meta/->metadata-selector (cons 'and metadata-args) col-types params) scan-opts (-> scan-opts (update :for-valid-time (fn [fvt] diff --git a/src/test/clojure/xtdb/operator/scan_test.clj b/src/test/clojure/xtdb/operator/scan_test.clj index d2f7237074..4382816ea3 100644 --- a/src/test/clojure/xtdb/operator/scan_test.clj +++ b/src/test/clojure/xtdb/operator/scan_test.clj @@ -6,11 +6,13 @@ [xtdb.operator.scan :as scan] [xtdb.test-util :as tu] [xtdb.util :as util] + [xtdb.vector.reader :as vr] [xtdb.vector.writer :as vw]) (:import (java.util LinkedList) xtdb.operator.IRaQuerySource xtdb.operator.IRelationSelector - (xtdb.operator.scan RowConsumer))) + (xtdb.operator.scan RowConsumer) + xtdb.vector.RelationReader)) (t/use-fixtures :each tu/with-mock-clock tu/with-allocator) @@ -446,17 +448,32 @@ [:put :xt-docs {:xt/id after-uuid :version 1}]]) (xt/submit-tx node [[:put :xt-docs {:xt/id search-uuid :version 2}]]) - (t/is (nil? (scan/selects->iid-byte-buffer {}))) + (t/is (nil? (scan/selects->iid-byte-buffer {} vw/empty-params))) (t/is (= (util/uuid->byte-buffer search-uuid) - (scan/selects->iid-byte-buffer {'xt/id (list '= 'xt/id search-uuid)}))) + (scan/selects->iid-byte-buffer {'xt/id (list '= 'xt/id search-uuid)} vw/empty-params))) - (t/is (nil? (scan/selects->iid-byte-buffer {'xt/id (list '< 'xt/id search-uuid)}))) + (t/is (nil? (scan/selects->iid-byte-buffer {'xt/id (list '< 'xt/id search-uuid)} vw/empty-params))) + + (with-open [^RelationReader params-rel (vw/open-params tu/*allocator* {'?search-uuid #uuid "80000000-0000-0000-0000-000000000000"})] + (t/is (= (util/uuid->byte-buffer search-uuid) + (scan/selects->iid-byte-buffer '{xt/id (= xt/id ?search-uuid)} + params-rel)))) + + (with-open [search-uuid-vec (vw/open-vec tu/*allocator* (name '?search-uuid) [#uuid "00000000-0000-0000-0000-000000000000" + #uuid "80000000-0000-0000-0000-000000000000"]) + ^RelationReader params-rel (vw/open-rel [search-uuid-vec])] + (t/is (nil? (scan/selects->iid-byte-buffer '{xt/id (= xt/id ?search-uuid)} + params-rel)))) (t/is (= [{:version 2, :xt/id search-uuid}] (tu/query-ra [:scan {:table 'xt_docs} ['version {'xt/id (list '= 'xt/id search-uuid)}]] {:node node}))) + (t/is (= [{:version 2, :xt/id search-uuid}] + (tu/query-ra '[:scan {:table xt_docs} [version {xt/id (= xt/id ?search-uuid)}]] + {:node node :params {'?search-uuid #uuid "80000000-0000-0000-0000-000000000000"}}))) + (t/is (= [{:version 2, :xt/id search-uuid} {:version 1, :xt/id search-uuid}] (tu/query-ra [:scan {:table 'xt_docs