diff options
author | Bob Lail <bob.lailfamily@gmail.com> | 2019-03-05 13:16:44 -0600 |
---|---|---|
committer | David Heinemeier Hansson <david@loudthinking.com> | 2019-03-05 11:16:44 -0800 |
commit | 91ed21b304c468db8ce9fd830312c151432935d0 (patch) | |
tree | 354a329c8b7308a8762ef39a73e2ed1c30c51baa /activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb | |
parent | db94f492c099db89746f945a522aa7e59ede97cb (diff) | |
download | rails-91ed21b304c468db8ce9fd830312c151432935d0.tar.gz rails-91ed21b304c468db8ce9fd830312c151432935d0.tar.bz2 rails-91ed21b304c468db8ce9fd830312c151432935d0.zip |
Add insert_all to ActiveRecord models (#35077)
Adds a method to ActiveRecord allowing records to be inserted in bulk without instantiating ActiveRecord models. This method supports options for handling uniqueness violations by skipping duplicate records or overwriting them in an UPSERT operation.
ActiveRecord already supports bulk-update and bulk-destroy actions that execute SQL UPDATE and DELETE commands directly. It also supports bulk-read actions through `pluck`. It makes sense for it also to support bulk-creation.
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb')
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 95beeb4cae..5919801519 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -196,6 +196,17 @@ module ActiveRecord true end + def supports_insert_returning? + true + end + + def supports_insert_on_conflict? + postgresql_version >= 90500 + end + alias supports_insert_on_duplicate_skip? supports_insert_on_conflict? + alias supports_insert_on_duplicate_update? supports_insert_on_conflict? + alias supports_insert_conflict_target? supports_insert_on_conflict? + def index_algorithms { concurrently: "CONCURRENTLY" } end @@ -425,6 +436,20 @@ module ActiveRecord index.using == :btree || super end + def build_insert_sql(insert) # :nodoc: + sql = +"INSERT #{insert.into} #{insert.values_list}" + + if insert.skip_duplicates? + sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING" + elsif insert.update_duplicates? + sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET " + sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",") + end + + sql << " RETURNING #{insert.returning}" if insert.returning + sql + end + private def check_version if postgresql_version < 90300 |