From a6c910268df972deba5576dd4904b6b998bab3be Mon Sep 17 00:00:00 2001 From: Chris Nuernberger Date: Tue, 27 Feb 2024 07:35:10 -0700 Subject: [PATCH] Attempting to reproduce #22 --- deps.edn | 3 +-- src/tmducken/duckdb.clj | 17 +++++++++++++++++ src/tmducken/duckdb/ffi.clj | 1 + test/tmducken/duckdb_test.clj | 28 ++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/deps.edn b/deps.edn index e2ab5d7..032768a 100644 --- a/deps.edn +++ b/deps.edn @@ -1,7 +1,6 @@ {:paths ["src" "lib"] - :deps {techascent/tech.ml.dataset {:mvn/version "7.023"} + :deps {techascent/tech.ml.dataset {:mvn/version "7.025"} techascent/tech.ml.dataset.sql {:mvn/version "7.000-beta-52"} - cnuernber/dtype-next {:mvn/version "10.109-SNAPSHOT"} net.java.dev.jna/jna {:mvn/version "5.13.0"}} :aliases {:build diff --git a/src/tmducken/duckdb.clj b/src/tmducken/duckdb.clj index facdfeb..929f33f 100644 --- a/src/tmducken/duckdb.clj +++ b/src/tmducken/duckdb.clj @@ -89,6 +89,22 @@ _unnamed [5 3]: @initialize*) +(defn duckdb-library-version + ^String [] + (dt-ffi/c->string (duckdb-ffi/duckdb_library_version))) + + +(defn- check-lib-version! + [] + (let [lib-version (duckdb-library-version) + parts (.split lib-version "\\.") + mid-part (Integer/parseInt (aget parts 1))] + (when-not (or (not= "v0" (aget parts 0)) + (>= mid-part 10)) + (throw (RuntimeException. (str "Invalid version: " lib-version " - " "this version of tmducken is meant for duckdb version 0.10.0 and up")))) + :ok)) + + (defn initialize! "Initialize the duckdb ffi system. This must be called first should be called only once. It is safe, however, to call this multiple times. @@ -119,6 +135,7 @@ _unnamed [5 3]: (log/info "Attempting to load in-process duckdb")) (duckdb-ffi/define-datatypes!) (dt-ffi/library-singleton-set! duckdb-ffi/lib libpath)))) + (check-lib-version!) true))) ([] (initialize! nil))) diff --git a/src/tmducken/duckdb/ffi.clj b/src/tmducken/duckdb/ffi.clj index 7da8adc..0b10ab1 100644 --- a/src/tmducken/duckdb/ffi.clj +++ b/src/tmducken/duckdb/ffi.clj @@ -115,6 +115,7 @@ associated with the connection. :doc "Closes the specified connection and de-allocates all memory allocated for that connection. * connection: The connection to close."} + :duckdb_library_version {:rettype :pointer} :duckdb_config_count {:rettype :size-t :doc "This returns the total amount of configuration options available for usage with `duckdb_get_config_flag`. diff --git a/test/tmducken/duckdb_test.clj b/test/tmducken/duckdb_test.clj index aeba0e8..9d91f0a 100644 --- a/test/tmducken/duckdb_test.clj +++ b/test/tmducken/duckdb_test.clj @@ -4,6 +4,7 @@ [tmducken.duckdb.ffi :as duckdb-ffi] [tech.v3.dataset :as ds] [tech.v3.datatype.functional :as dfn] + [tech.v3.datatype :as dt] [tech.v3.datatype.datetime :as dtype-dt] [tech.v3.resource :as resource]) (:import [java.util UUID] @@ -94,6 +95,33 @@ (catch Throwable e nil))))) +(deftest filter-stonks-test + (let [stonks (-> @stocks-src* + (ds/row-map (fn [m] + (cond + (< (:price m) 37.) (update m :price (constantly nil)) + :else m))) + (vary-meta assoc :name :stonks))] + (try + (do (duckdb/create-table! @conn* stonks) + (duckdb/insert-dataset! @conn* stonks)) + (let [sql-stocks (duckdb/sql->dataset @conn* "select * from stonks")] + (is (= (ds/row-count stonks) + (ds/row-count sql-stocks))) + (is (= (vec (stonks :symbol)) + (vec (sql-stocks "symbol")))) + (is (= (vec (stonks :date)) + (vec (sql-stocks "date")))) + (is (== (dt/ecount (ds/missing stonks)) + (dt/ecount (ds/missing sql-stocks)))) + (is (dfn/equals (stonks :price) + (sql-stocks "price")))) + (finally + (try + (duckdb/drop-table! @conn* stonks) + (catch Throwable e nil)))))) + + (deftest prepared-statements-test (try (let [stocks @stocks-src*