From b6158cf2a2a872b94e1c8e76e7db5c5872008ed7 Mon Sep 17 00:00:00 2001 From: Howon Lee <hlee.howon@gmail.com> Date: Fri, 8 Jul 2022 22:56:38 -0700 Subject: [PATCH] 22732 rework (#23722) Pursuant to reopening of #22732. Proximate cause is occasional Java bigints getting in where the types assume it'll only be Clojure bigints. On the current reproduction I have it fixes the bug but I am still determining ultimate cause and if there are other phenomena. There was also differential behavior of backport vs. on-master implementation which I still don't understand. This one needs some sync to have gone through, or else it will prehistoric empetuses towards decelization --- .../driver/sql_jdbc/sync/describe_table.clj | 15 +++++++++++++-- .../driver/sql_jdbc/sync/describe_table_test.clj | 13 ++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/metabase/driver/sql_jdbc/sync/describe_table.clj b/src/metabase/driver/sql_jdbc/sync/describe_table.clj index 4caef482a12..00c2330fdae 100644 --- a/src/metabase/driver/sql_jdbc/sync/describe_table.clj +++ b/src/metabase/driver/sql_jdbc/sync/describe_table.clj @@ -298,14 +298,17 @@ ;; JSON itself has the single number type, but Java serde of JSON is stricter java.lang.Long :type/Integer clojure.lang.BigInt :type/BigInteger + java.math.BigInteger :type/BigInteger java.lang.Integer :type/Integer java.lang.Double :type/Float + java.lang.Float :type/Float java.math.BigDecimal :type/Decimal java.lang.Number :type/Number java.lang.Boolean :type/Boolean java.time.LocalDateTime :type/DateTime clojure.lang.PersistentVector :type/Array - clojure.lang.PersistentArrayMap :type/Structured}) + clojure.lang.PersistentArrayMap :type/Structured + clojure.lang.PersistentHashMap :type/Structured}) (def db-type-map "Map from MBQL types to database types. @@ -314,7 +317,15 @@ although as of writing this is just geared towards Postgres types" {:type/Text "text" :type/Integer "integer" - :type/BigInteger "bigint" + ;; You might think that the ordinary 'bigint' type in Postgres and MySQL should be this. + ;; However, Bigint in those DB's maxes out at 2 ^ 64. + ;; JSON, like Javascript itself, will happily represent 1.8 * (10^308), + ;; Losing digits merrily along the way. + ;; We can't really trust anyone to use MAX_SAFE_INTEGER, in JSON-land.. + ;; So really without forcing arbitrary precision ('decimal' type), + ;; we have too many numerical regimes to test. + ;; (#22732) was basically the consequence of missing one. + :type/BigInteger "decimal" :type/Float "double precision" :type/Number "double precision" :type/Decimal "decimal" diff --git a/test/metabase/driver/sql_jdbc/sync/describe_table_test.clj b/test/metabase/driver/sql_jdbc/sync/describe_table_test.clj index dcc1c291633..81c9ca9b0ad 100644 --- a/test/metabase/driver/sql_jdbc/sync/describe_table_test.clj +++ b/test/metabase/driver/sql_jdbc/sync/describe_table_test.clj @@ -114,4 +114,15 @@ (let [row {:bob {:dobbs {:robbs 123} :cobbs [1 2 3]}} types {[:bob :cobbs] clojure.lang.PersistentVector [:bob :dobbs :robbs] java.lang.Long}] - (is (= types (#'sql-jdbc.describe-table/row->types row)))))) + (is (= types (#'sql-jdbc.describe-table/row->types row))))) + (testing "JSON row->types handles bigint that comes in and gets interpreted as Java bigint OK (#22732)" + (let [int-row {:zlob {"blob" (java.math.BigInteger. "123124124312134235234235345344324352")}}] + (is (= #{{:name "zlob → blob", + :database-type "decimal", + :base-type :type/BigInteger, + :database-position 0, + :visibility-type :normal, + :nfc-path [:zlob "blob"]}} + (-> int-row + (#'sql-jdbc.describe-table/row->types) + (#'sql-jdbc.describe-table/field-types->fields))))))) -- GitLab