multi_insert 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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