multi_insert 0.2.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc4fbdea86f270f216a65ede4de9f283ad443ea0
4
- data.tar.gz: f1a8f163a22a3b1c1dd261f2e47c3bde55fb549b
3
+ metadata.gz: '09249bbd92253e001ba2eda9b5229ba076f5fa47'
4
+ data.tar.gz: fa5a964166797cce48283e4dfd2dd1baf2426fd3
5
5
  SHA512:
6
- metadata.gz: 25ab114fd113733f6d6eebc55b6a9823dcdbe50a67d8613de9ff8116386acc915dff79197aff2e4925a6dfc1b3b1856e963f03c70f20e2ea46d1b9ec69fb9561
7
- data.tar.gz: ee85021afd8623963c931a16757b577e5f875cf1d711cba08de4fe57a3a30dfac8d3837a94a5849d6683961bd5cfb9d21eddfafbad7e5b9da1a64213106b601c
6
+ metadata.gz: 507b36948e987722d93c623bfa5a743fddd970d03926439f81b5c577f75da3dc5c5aeb2a1d23162e362fe2c8df1f27670a003efd8b6d2e88914f2c85b076e3c2
7
+ data.tar.gz: 2bd855e0af71b62829b7be80d7d3e452fcce4c7de3079299b6b56d8b1ff4d67f48649cb9d5180d136f87b6f282bee8805d3b18784fdece2309150effd9fd4bf2
@@ -2,6 +2,14 @@ require 'active_record'
2
2
  require 'multi_insert/query'
3
3
 
4
4
  class ActiveRecord::Base
5
+ # Start a multi insert.
6
+ #
7
+ # See `Query#new` for a list of options.
8
+ #
9
+ # @param columns [Array<Symbol | String>] The columns to use for insertion.
10
+ # @param values [Array<Array<String | Number | Boolean | nil>>] Values to be inserted.
11
+ # @param opts [Hash<Object>] Options.
12
+ # @return [Query] A query object.
5
13
  def self.multi_insert(columns, values, opts = {})
6
14
  ::MultiInsert::Query.new(self.table_name, columns, values, opts)
7
15
  end
@@ -1,18 +1,43 @@
1
1
  require 'active_record'
2
2
  require 'multi_insert/query_builder'
3
3
 
4
+ # Top level module for MultiInsert.
4
5
  module MultiInsert
6
+ # A MultiInsert query.
7
+ #
8
+ # Most of the time, you do not need to instanciate it yourself.
5
9
  class Query
10
+ # A conflict close inside a query.
11
+ #
12
+ # You never need to instanciate it yourself. Instead, use `Query#on_conflict`.
6
13
  class OnConflict
14
+ # Create an ON CONFLICT clause
15
+ #
16
+ # @param query [Query] the query.
17
+ # @param column [String | Symbol] the column to watch for conflicts.
7
18
  def initialize(query, column)
8
19
  @query = query
9
20
  @column = column.to_sym
10
21
  end
11
22
 
23
+ # Ignore conflicting rows.
24
+ #
25
+ # @return [Query] the original query.
12
26
  def do_nothing
13
27
  @query.on_conflict_sql(::MultiInsert::QueryBuilder.on_conflict_do_nothing(@column))
14
28
  end
15
29
 
30
+ # Update the conflicting rows according to user-supplied rules.
31
+ #
32
+ # The rules can be:
33
+ # - A single symbol or string denoting a column name. In this case, the matching column will be updated.
34
+ # - An array of strings or symbols. In this case, the matching columns will be updated.
35
+ # - An hash of values (Integers or Strings) or the symbol `:excluded`. The matching columns will be updated
36
+ # to the supplied values, except when the value is `:excluded`. In that case, the matching columns will be set
37
+ # to the value to be inserted.
38
+ #
39
+ # @param values [String | Symbol | Array<String | Symbol> | Hash<String | Symbol => String | Number | Boolean>] The user specified rules.
40
+ # @return [Query] The original query.
16
41
  def do_update(values)
17
42
  @query.on_conflict_sql(::MultiInsert::QueryBuilder.on_conflict_do_update(@column, values, @query.opts))
18
43
  end
@@ -20,41 +45,80 @@ module MultiInsert
20
45
 
21
46
  attr_reader :opts
22
47
 
48
+ # Create an insert query against the specified table and columns, with the specified values.
49
+ # The following options are supported:
50
+ # - time (true) Whether to insert created_at and updated_at.
51
+ #
52
+ # @param table [String | Symbol] The table to be used for insertion.
53
+ # @param columns [Array<String | Symbol>] The columns to be inserted.
54
+ # @param values [Array<Array<String | Number | Boolean>>] The values to be inserted.
55
+ # @param opts [Hash<Object>] Options.
23
56
  def initialize(table, columns, values, opts = {})
24
57
  @table = table.to_sym
25
58
  @opts = opts
26
59
  @sql_insert = ::MultiInsert::QueryBuilder.insert(table, columns, values, opts)
27
60
  end
28
61
 
62
+ # Add a returning clause to the query.
63
+ #
64
+ # @param columns [Array<Symbol | String>] The columns to return.
65
+ # @return [Query] self.
29
66
  def returning(columns)
30
67
  @sql_returning = ::MultiInsert::QueryBuilder.returning(columns)
31
68
  @returning_flat = false
32
69
  self
33
70
  end
34
71
 
72
+ # Add a returning clause to the query, returning IDs.
73
+ #
74
+ # The IDs will be returned as a flat array.
75
+ # @return [Query] self
35
76
  def returning_id
36
77
  @sql_returning = ::MultiInsert::QueryBuilder.returning([:id])
37
78
  @returning_flat = true
38
79
  self
39
80
  end
40
81
 
82
+ # Begin a conflict clause.
83
+ #
84
+ # @param column [String | Symbol] The column to watch for conflicts.
85
+ # @return [Query::OnConflict] A conflict clause.
41
86
  def on_conflict(column)
42
87
  ::MultiInsert::Query::OnConflict.new(self, column)
43
88
  end
44
89
 
90
+ # Handle a conflict with raw SQL
91
+ #
92
+ # You should probably use the friendly helper method instead.
93
+ # @param sql [String] An SQL expression starting with "ON CONFLICT".
94
+ # @return [Query] self.
45
95
  def on_conflict_sql(sql)
46
96
  @sql_on_conflict = sql
47
97
  self
48
98
  end
49
99
 
100
+ # Convert the query to raw SQL.
101
+ #
102
+ # @return [String] An SQL query.
50
103
  def to_sql
51
104
  [@sql_insert, @sql_on_conflict, @sql_returning].reject(&:nil?).join(' ')
52
105
  end
53
106
 
107
+ # Equivalent to `to_sql`.
108
+ #
109
+ # @return [String] An SQL query.
54
110
  def to_s
55
111
  to_sql
56
112
  end
57
113
 
114
+ # Execute the query, and return eventual results.
115
+ #
116
+ # Result may be:
117
+ # - Nil if no returning clause was present.
118
+ # - An array of IDs if the returning_id helper was called.
119
+ # - An array of rows otherwise.
120
+ #
121
+ # @return [nil | Array<Integer> | Array<Array<String | Number | Boolean>>]
58
122
  def execute
59
123
  result = ActiveRecord::Base.connection.execute(to_sql)
60
124
  if @sql_returning.nil?
@@ -53,7 +53,8 @@ module MultiInsert
53
53
  now = Time.now.to_s(:db)
54
54
  values[:updated_at] = now
55
55
  end
56
- values.map! do |key, value|
56
+ arr = []
57
+ values.each do |key, value|
57
58
  v = nil
58
59
  key = ActiveRecord::Base.connection.quote_column_name(key.to_s)
59
60
  if value == :excluded
@@ -61,9 +62,9 @@ module MultiInsert
61
62
  else
62
63
  v = ActiveRecord::Base.connection.quote(value)
63
64
  end
64
- "#{key} = #{v}"
65
+ arr << "#{key} = #{v}"
65
66
  end
66
- values = values.join(', ')
67
+ values = arr.join(', ')
67
68
  "#{on_conflict(column)} DO UPDATE SET #{values}"
68
69
  end
69
70
 
@@ -1,3 +1,4 @@
1
1
  module MultiInsert
2
- VERSION = "0.2.1"
2
+ # The version number for MultiInsert.
3
+ VERSION = "1.0.0"
3
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: multi_insert
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nax