Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"ERROR: null value in column" when trying to insert into the database #8

Open
AndreaCrotti opened this issue Jun 13, 2024 · 6 comments

Comments

@AndreaCrotti
Copy link

So I'm just trying to insert data into the database using postgres and next.jdbc, but when it actually tries to write the data the values in the foreign key fields are always NULLS.

I thought it was related to my model but I get the same behaviour with the sample code from the README, it works fine for the mock db but not for a real Postgres db.
If I look at the output from generate I see that it's all correct, but not when I try to insert data, any idea why it could be wrong?

(def id-atom (atom 0))
(def monotonic-id-gen
  (gen/fmap (fn [_] (swap! id-atom inc)) (gen/return nil)))

(def ID
  [:and {:gen/gen monotonic-id-gen} pos-int?])

(def User
  [:map
   [:user/id ID]
   [:user/username string?]])

(def Post
  [:map
   [:post/id ID]
   [:post/created_by_id pos-int?]
   [:post/content string?]])

(def potato-schema
  {:user {:prefix   :u
          :generate {:schema User}
          :fixtures {:table-name "metagross.users"}}

   :post {:prefix    :p
          :generate  {:schema Post}
          :fixtures  {:table-name "metagross.posts"}
          :relations {:post/created_by_id [:user :user/id]}}})


(defn unwrap-connection
  [& _args]
  (.unwrap (postgres/connection) Connection))

(def potato-pg
  {:schema   potato-schema
   :generate {:generator mg/generate}
   :fixtures (merge dnj/config
                    {:get-connection unwrap-connection
                     :close-connection (fn close-connection [& _args]
                                         (.close (unwrap-connection)))})})

The code is pretty much just this, I had to redefine get-connection, but I don't think that's the problem, it connects just fine it just seems to lose the data when trying to write out.

@AndreaCrotti
Copy link
Author

As you can see from this image, I just tapped visit-data in the insert-fixtures* function, and created_by_id is not nil in :generate, but it's nil in visit-val, any idea why?
image

@AndreaCrotti
Copy link
Author

I wonder if it could be related with https://github.com/donut-party/datapotato/wiki/database-integration#optional-define-a-get-inserted-method
even though in the docs it says that if I use postgres I should not need to worry about, I don't that defmethod defined for Postgres.

@raszi
Copy link

raszi commented Aug 13, 2024

I also ran into this, because it seems that the documentation is a bit inaccurate here.

What was working for me if I set the relations as namespace-qualified keywords.

(def potato-schema
  {:company {:prefix :c
             :fixtures {:table-name "companies"}
             :generate {:schema ::spec.company/complete}}

   :user {:prefix :u
          :fixtures {:table-name "users"}
          :generate {:schema ::spec.user/complete}
          :relations {:company_id [:company :companies/id]}}})

(defn potato-db [db]
  {:schema potato-schema
   :generate {:generator generator}
   :fixtures (assoc dnj/config :dbspec db)})

(defn insert [db]
  (dc/with-fixtures (potato-db db)
    (dc/insert-fixtures {:user [{:count 3}]})))

I believe the reason is that next.jdbc.sql/insert! returns with namespace-qualified keywords at least with Postgres.

@raszi
Copy link

raszi commented Aug 13, 2024

I can verify that is the problem there.

If you set a custom insert function that uses the next.jdbc.result-set/as-unqualified-maps as the builder-fn, then you don't need to use namespace-qualified keywords.

@raszi
Copy link

raszi commented Aug 13, 2024

Because you are using a separate schema, I guess it would be :metagross.users/id.

@raszi
Copy link

raszi commented Sep 2, 2024

I just realized that the easiest option is to override the :fixtures :get-inserted option with a custom get-inserted function that strips the namespace-qualified keywords. This get-inserted function receives the insert-result and the table-name as well.

(get-inserted_ {:dbspec dbspec
:dbtype dbtype
:connection connection
:table-name table-name
:insert-result insert-result}))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants