sequel-select-order-clauses 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4596afa94f19b82c39ae79479131ff6c60643740
4
+ data.tar.gz: 1eb6f016f4d7ea86d33891dc3cb85b1e508b0f16
5
+ SHA512:
6
+ metadata.gz: 0dd46ee1b0e93733b06ba789868d0c0990433bf75cf530e8ea2afb6a33566194d3f62607549ba88827abe0aa9fbafae05561b92b7e72fc9b7b94f356e1fb0ed4
7
+ data.tar.gz: cb3caecd7a4132fb3fd74339b0d8c91d8894960a0b8dd6e5d82080c1385e65e534665a208d7ef69fd4ee6d8dbd35340b72b10806b443c4f3ad0f2f5229bed654
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'minitest', '5.5.1'
7
+ gem 'minitest-rg', '5.1.0'
8
+
9
+ gem 'pry'
10
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016 Chris Hanks
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # Sequel::SelectOrderClauses
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ Dir["./tasks/*.rb"].sort.each &method(:require)
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sequel/extensions/select_order_clauses'
@@ -0,0 +1,237 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sequel'
4
+ require 'sequel/extensions/select_order_clauses/version'
5
+
6
+ module Sequel
7
+ module SelectOrderClauses
8
+ def append_order_as_selection
9
+ return self unless order = @opts[:order]
10
+ return self if @opts[:order_info]
11
+
12
+ # Note that since we're iterating over the order to return a modified
13
+ # version of this dataset, we can't modify the order in this method and
14
+ # remain sensible.
15
+ ds = self
16
+
17
+ selections = extract_selections(ds).map { |s| normalize_selection(s) }
18
+
19
+ order_info =
20
+ order.map.with_index do |o, index|
21
+ exp = normalize_expression(unwrap_order_expression(o))
22
+ dir = extract_direction(o)
23
+
24
+ # Try to figure out which of the select expressions is going to
25
+ # correspond to this order expression. This heuristic may not be
26
+ # perfect, but do our best and raise an error if we find more than one
27
+ # selection.
28
+ expression_selects =
29
+ selections.select do |s|
30
+ selection_satisfies_expression?(s, exp)
31
+ end
32
+
33
+ name =
34
+ case expression_selects.length
35
+ when 0 then nil
36
+ when 1
37
+ expression_select = expression_selects.first
38
+
39
+ # Once we have the SELECT expression that matches our ORDER BY
40
+ # expression, we just extract its name so that we'll be able to
41
+ # figure out how we sorted records later on. The exception is if
42
+ # the matching SELECT expression is "table".* - in that case
43
+ # we'll need to get the name from the ORDER BY expression.
44
+ target_expression =
45
+ if expression_select.is_a?(Sequel::SQL::ColumnAll)
46
+ exp
47
+ else
48
+ expression_select
49
+ end
50
+
51
+ extract_expression_name(target_expression)
52
+ else
53
+ raise "Found more than one selection in #{inspect} that matched the expression #{exp.inspect}: #{expression_selects.inspect}"
54
+ end
55
+
56
+ # After all that, we still might not have been able to get a name.
57
+ # In that case, just append the ORDER BY expression to the SELECT
58
+ # clause with a special alias that we'll use later.
59
+ unless name
60
+ name = "order_#{index}".to_sym
61
+ ds = ds.select_append(Sequel.as(exp, name))
62
+ end
63
+
64
+ {name: name, direction: dir}
65
+ end
66
+
67
+ ds.clone(order_info: order_info)
68
+ end
69
+
70
+ private
71
+
72
+ # Our inputs should have already been simplified and normalized to the
73
+ # extent possible, now the nitty-gritty of defining whatever equality
74
+ # logic we really need to for them.
75
+
76
+ # The question at hand: can we safely assume that this expression in the
77
+ # SELECT clause will always represent this expression in the ORDER BY?
78
+ def selection_satisfies_expression?(s, e)
79
+ case s
80
+ when Sequel::SQL::AliasedExpression
81
+ # Order expressions can be simple references to aliases, which is a
82
+ # pretty simple and useful case to check for. In other words:
83
+ # `SELECT function() AS my_value FROM table ORDER BY my_value`
84
+ if e.is_a?(Symbol) && s.aliaz == e
85
+ true
86
+ else
87
+ # Otherwise, see whether the expression being aliased does what we
88
+ # want. For example:
89
+ # `SELECT function() AS my_value FROM table ORDER BY function()`
90
+ selection_satisfies_expression?(normalize_selection(s.expression), e)
91
+ end
92
+ when Sequel::SQL::QualifiedIdentifier
93
+ # SELECT "table"."column"
94
+ case e
95
+ when Symbol
96
+ # SELECT "table"."column" FROM "table" ORDER BY "column"
97
+ s.column == e
98
+ when Sequel::SQL::QualifiedIdentifier
99
+ # SELECT "table"."column" FROM "table" ORDER BY "table"."column"
100
+ s == e
101
+ end
102
+ when Sequel::SQL::ColumnAll
103
+ # SELECT "table".*
104
+ case e
105
+ when Sequel::SQL::QualifiedIdentifier
106
+ # Satisfies any column anchored on that table...
107
+ s.table == e.table
108
+ when Symbol
109
+ # ...or a plain column reference that we can verify lives on this
110
+ # model. Note that m.columns.include?(e) would leave out
111
+ # lazy-loaded columns.
112
+ respond_to?(:model) &&
113
+ (m = model) &&
114
+ m.table_name == s.table &&
115
+ m.db_schema.has_key?(e)
116
+ end
117
+ else
118
+ # These values could be anything - functions, mathematical operations,
119
+ # literal SQL strings, etc. Just try for simple equality.
120
+ s == e
121
+ end
122
+ end
123
+
124
+ # In addition to the common normalization logic in normalize_expression(),
125
+ # which can be applied to expressions in either the SELECT or ORDER BY
126
+ # clauses, this method encapsulates an assumption that is safe to make
127
+ # about expressions in SELECT but not in ORDER BY, that a simple
128
+ # identifier (a symbol) on a single-source dataset must refer to a column
129
+ # in the table. In an ORDER BY clause it could also refer to an alias in
130
+ # the SELECT clause.
131
+ def normalize_selection(s)
132
+ s = normalize_expression(s)
133
+
134
+ case s
135
+ when Symbol
136
+ if joined_dataset?
137
+ s # Can't make any assumptions about the source table.
138
+ else
139
+ Sequel.qualify(first_source, s)
140
+ end
141
+ else
142
+ s
143
+ end
144
+ end
145
+
146
+ # Move more esoteric Sequel types to the baseline of symbols representing
147
+ # identifiers and QualifiedIdentifiers representing table-column pairs, so
148
+ # that it's easier for us to do comparisons without needing to define
149
+ # equality logic between every combination of classes in the Sequel AST.
150
+ def normalize_expression(expression)
151
+ case expression
152
+ when Symbol
153
+ # Take care of symbol notations like :table__column___alias.
154
+ table, column, aliaz =
155
+ Sequel.split_symbol(expression).map { |part| part&.to_sym }
156
+
157
+ exp = table ? Sequel.qualify(table, column) : column
158
+ exp = Sequel.as(exp, aliaz) if aliaz
159
+ exp
160
+ when Sequel::SQL::Identifier
161
+ # Identifier objects have their uses, but not here, where a symbol is
162
+ # just fine.
163
+ expression.value.to_sym
164
+ when Sequel::SQL::QualifiedIdentifier
165
+ t = expression.table
166
+ c = expression.column
167
+
168
+ if t.is_a?(Symbol) && c.is_a?(Symbol)
169
+ expression
170
+ else
171
+ Sequel::SQL::QualifiedIdentifier.new(
172
+ normalize_expression(t),
173
+ normalize_expression(c),
174
+ )
175
+ end
176
+ else
177
+ # Other arbitrary expressions can just be passed through.
178
+ expression
179
+ end
180
+ end
181
+
182
+ def extract_selections(ds)
183
+ if selections = ds.opts[:select]
184
+ return selections
185
+ end
186
+
187
+ if (froms = ds.opts[:from]) && froms.length == 1
188
+ from = unwrap_alias(froms.first)
189
+ if from.is_a?(Sequel::Dataset)
190
+ extract_selections(from)
191
+ end
192
+ end
193
+ end
194
+
195
+ def extract_expression_name(expression)
196
+ case expression
197
+ when Symbol
198
+ expression
199
+ when Sequel::SQL::AliasedExpression
200
+ expression.aliaz
201
+ when Sequel::SQL::Identifier
202
+ extract_expression_name(expression.value)
203
+ when Sequel::SQL::QualifiedIdentifier
204
+ extract_expression_name(expression.column)
205
+ end
206
+ end
207
+
208
+ def unwrap_order_expression(order)
209
+ case order
210
+ when Sequel::SQL::OrderedExpression
211
+ order.expression
212
+ else
213
+ order
214
+ end
215
+ end
216
+
217
+ def unwrap_alias(expression)
218
+ case expression
219
+ when Sequel::SQL::AliasedExpression
220
+ expression.expression
221
+ else
222
+ expression
223
+ end
224
+ end
225
+
226
+ def extract_direction(order)
227
+ case order
228
+ when Sequel::SQL::OrderedExpression
229
+ order.descending ? :desc : :asc
230
+ else
231
+ :asc
232
+ end
233
+ end
234
+ end
235
+
236
+ Dataset.register_extension(:select_order_clauses, SelectOrderClauses)
237
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sequel
4
+ module SelectOrderClauses
5
+ VERSION = '0.0.1'
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sequel/extensions/select_order_clauses/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'sequel-select-order-clauses'
8
+ spec.version = Sequel::SelectOrderClauses::VERSION
9
+ spec.authors = ["Chris Hanks"]
10
+ spec.email = ['christopher.m.hanks@gmail.com']
11
+ spec.summary = %q{Select the order clauses in a dataset}
12
+ spec.description = %q{Simple support for selecting the order clauses in a dataset}
13
+ spec.homepage = 'https://github.com/chanks/sequel-select-order-clauses'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.6'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'sqlite3'
24
+
25
+ spec.add_dependency 'sequel', '~> 4.0'
26
+ end
@@ -0,0 +1,227 @@
1
+ require 'spec_helper'
2
+
3
+ class SelectOrderClausesSpec < Minitest::Spec
4
+ it "should have a version" do
5
+ assert Sequel::SelectOrderClauses::VERSION.is_a?(String)
6
+ end
7
+
8
+ describe "append_order_as_selection" do
9
+ def assert_order_append(ds:, selects_to_append:, order_names:)
10
+ initial = ds
11
+ final = ds.append_order_as_selection
12
+
13
+ assert_equal (initial.opts[:select] || []) + selects_to_append, final.opts[:select] || []
14
+
15
+ order_info = final.opts.fetch(:order_info)
16
+
17
+ assert_equal order_names, order_info.map { |h| h.fetch(:name) }
18
+ end
19
+
20
+ it "should do nothing to queries without order_by clauses" do
21
+ assert_equal User.dataset, User.dataset.append_order_as_selection
22
+ end
23
+
24
+ describe "for simple symbol columns" do
25
+ it "when they are missing" do
26
+ assert_order_append \
27
+ ds: User.dataset.select(:id).order_by(:description),
28
+ selects_to_append: [Sequel.as(:description, :order_0)],
29
+ order_names: [:order_0]
30
+
31
+ assert_order_append \
32
+ ds: User.dataset.select(:id).order_by(:fake_column),
33
+ selects_to_append: [Sequel.as(:fake_column, :order_0)],
34
+ order_names: [:order_0]
35
+ end
36
+
37
+ it "when they are present" do
38
+ assert_order_append \
39
+ ds: User.dataset.select(:id).order_by(:id),
40
+ selects_to_append: [],
41
+ order_names: [:id]
42
+
43
+ assert_order_append \
44
+ ds: User.dataset.select(:created_at).order_by(:created_at),
45
+ selects_to_append: [],
46
+ order_names: [:created_at]
47
+ end
48
+ end
49
+
50
+ describe "when the dataset has been made via #from_self" do
51
+ it "when they are present" do
52
+ assert_order_append \
53
+ ds: User.dataset.select(:id).from_self.order_by(:id),
54
+ selects_to_append: [],
55
+ order_names: [:id]
56
+
57
+ assert_order_append \
58
+ ds: User.dataset.select(:users__created_at).from_self.order_by(:created_at),
59
+ selects_to_append: [],
60
+ order_names: [:created_at]
61
+ end
62
+ end
63
+
64
+ describe "for qualified columns" do
65
+ it "when they are missing" do
66
+ assert_order_append \
67
+ ds: User.dataset.select(:id).order_by(Sequel.qualify(:other_table, :fake_column)),
68
+ selects_to_append: [Sequel.qualify(:other_table, :fake_column).as(:order_0)],
69
+ order_names: [:order_0]
70
+
71
+ assert_order_append \
72
+ ds: User.dataset.select(:id).order_by(:other_table__fake_column),
73
+ selects_to_append: [Sequel.qualify(:other_table, :fake_column).as(:order_0)],
74
+ order_names: [:order_0]
75
+ end
76
+
77
+ it "when they are present" do
78
+ assert_order_append \
79
+ ds: User.dataset.select(Sequel.qualify(:users, :id)).order_by(:id),
80
+ selects_to_append: [],
81
+ order_names: [:id]
82
+
83
+ assert_order_append \
84
+ ds: User.dataset.select(Sequel.qualify(:users, Sequel::SQL::Identifier.new(:id))).order_by(:id),
85
+ selects_to_append: [],
86
+ order_names: [:id]
87
+
88
+ assert_order_append \
89
+ ds: User.dataset.select(:id).order_by(Sequel.qualify(:users, :id)),
90
+ selects_to_append: [],
91
+ order_names: [:id]
92
+
93
+ assert_order_append \
94
+ ds: User.dataset.select(:created_at).order_by(:users__created_at),
95
+ selects_to_append: [],
96
+ order_names: [:created_at]
97
+ end
98
+ end
99
+
100
+ describe "for columns with aliases" do
101
+ it "should recognize that ORDER BY can take either the column name or its alias" do
102
+ assert_order_append \
103
+ ds: User.dataset.select(Sequel.as(:description, :des)).order_by(:des),
104
+ selects_to_append: [],
105
+ order_names: [:des]
106
+
107
+ assert_order_append \
108
+ ds: User.dataset.select(Sequel.as(:description, :des)).order_by(:description),
109
+ selects_to_append: [],
110
+ order_names: [:des]
111
+ end
112
+
113
+ it "that are also qualified" do
114
+ assert_order_append \
115
+ ds: User.dataset.select(Sequel.qualify(:users, :description).as(:des)).order_by(:description),
116
+ selects_to_append: [],
117
+ order_names: [:des]
118
+
119
+ assert_order_append \
120
+ ds: User.dataset.select(Sequel.qualify(:users, :description).as(:des)).order_by(:des),
121
+ selects_to_append: [],
122
+ order_names: [:des]
123
+
124
+ assert_order_append \
125
+ ds: User.dataset.select(Sequel.as(:description, :des)).order_by(Sequel.qualify(:users, :description)),
126
+ selects_to_append: [],
127
+ order_names: [:des]
128
+
129
+ assert_order_append \
130
+ ds: User.dataset.select(:created_at___c_at).order_by(:users__created_at),
131
+ selects_to_append: [],
132
+ order_names: [:c_at]
133
+
134
+ assert_order_append \
135
+ ds: User.dataset.select(Sequel.qualify(:users, :description).as(:des)).order_by(:description),
136
+ selects_to_append: [],
137
+ order_names: [:des]
138
+ end
139
+ end
140
+
141
+ describe "when ordering by arbitrary expressions" do
142
+ it "when they are missing" do
143
+ assert_order_append \
144
+ ds: User.dataset.select(:id).order_by{function(:column1, 2)},
145
+ selects_to_append: [Sequel.virtual_row{function(:column1, 2)}.as(:order_0)],
146
+ order_names: [:order_0]
147
+
148
+ assert_order_append \
149
+ ds: User.dataset.select(:id).order_by{column - 2},
150
+ selects_to_append: [Sequel.virtual_row{column - 2}.as(:order_0)],
151
+ order_names: [:order_0]
152
+
153
+ assert_order_append \
154
+ ds: User.dataset.select(:id).order_by(Sequel.lit('function(column1, 2)')),
155
+ selects_to_append: [Sequel.lit('function(column1, 2)').as(:order_0)],
156
+ order_names: [:order_0]
157
+ end
158
+
159
+ it "when they are present" do
160
+ assert_order_append \
161
+ ds: User.dataset.select{function(:column1, 2).as(:my_column)}.order_by{function(:column1, 2)},
162
+ selects_to_append: [],
163
+ order_names: [:my_column]
164
+ end
165
+
166
+ it "when they are present but don't have a name we can safely predict" do
167
+ assert_order_append \
168
+ ds: User.dataset.select{function(:column1, 2)}.order_by{function(:column1, 2)},
169
+ selects_to_append: [Sequel.virtual_row{function(:column1, 2)}.as(:order_0)],
170
+ order_names: [:order_0]
171
+ end
172
+ end
173
+
174
+ describe "when a selection includes a ColumnAll" do
175
+ describe "and is not connected to a model" do
176
+ it "when ordering by a column qualified to that table" do
177
+ assert_order_append \
178
+ ds: DB[:users].select_all(:users).order_by(Sequel.qualify(:users, :id)),
179
+ selects_to_append: [],
180
+ order_names: [:id]
181
+ end
182
+
183
+ it "when ordering by a column qualified to a different table" do
184
+ assert_order_append \
185
+ ds: DB[:users].select_all(:users).order_by(Sequel.qualify(:users_2, :id)),
186
+ selects_to_append: [Sequel.qualify(:users_2, :id).as(:order_0)],
187
+ order_names: [:order_0]
188
+ end
189
+
190
+ it "when ordering by an unqualified column" do
191
+ assert_order_append \
192
+ ds: DB[:users].select_all(:users).order_by(:id),
193
+ selects_to_append: [Sequel.as(:id, :order_0)],
194
+ order_names: [:order_0]
195
+ end
196
+
197
+ it "when ordering by an arbitrary expression" do
198
+ assert_order_append \
199
+ ds: DB[:users].select_all(:users).order_by{function(:column, 2)},
200
+ selects_to_append: [Sequel.virtual_row{function(:column, 2)}.as(:order_0)],
201
+ order_names: [:order_0]
202
+ end
203
+ end
204
+
205
+ describe "and is connected to a model so we can look up columns" do
206
+ it "when ordering by an unqualified column that is present in the table" do
207
+ assert_order_append \
208
+ ds: User.dataset.select_all(:users).order_by(:id),
209
+ selects_to_append: [],
210
+ order_names: [:id]
211
+
212
+ assert_order_append \
213
+ ds: User.dataset.select_all(:users).order_by(:description),
214
+ selects_to_append: [],
215
+ order_names: [:description]
216
+ end
217
+
218
+ it "when ordering by an unqualified column that is not present in the table" do
219
+ assert_order_append \
220
+ ds: User.dataset.select_all(:users).order_by(:fake_column),
221
+ selects_to_append: [Sequel.as(:fake_column, :order_0)],
222
+ order_names: [:order_0]
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,19 @@
1
+ require 'sequel'
2
+
3
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ Sequel::Database.extension :select_order_clauses
6
+
7
+ DB = Sequel.sqlite
8
+
9
+ DB.create_table :users do
10
+ primary_key :id
11
+ Time :created_at
12
+ String :description
13
+ end
14
+
15
+ class User < Sequel::Model; end
16
+
17
+ require 'pry'
18
+ require 'minitest/autorun'
19
+ require 'minitest/rg'
data/tasks/specs.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new :default do |t|
5
+ t.libs = ['spec']
6
+ t.pattern = 'spec/**/*_spec.rb'
7
+ end
8
+
9
+ task :spec => :default
10
+ task :test => :default
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sequel-select-order-clauses
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Chris Hanks
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-10-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sequel
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '4.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '4.0'
69
+ description: Simple support for selecting the order clauses in a dataset
70
+ email:
71
+ - christopher.m.hanks@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - Gemfile
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - lib/sequel-select-order-clauses.rb
82
+ - lib/sequel/extensions/select_order_clauses.rb
83
+ - lib/sequel/extensions/select_order_clauses/version.rb
84
+ - sequel-select-order-clauses.gemspec
85
+ - spec/select_order_clauses_spec.rb
86
+ - spec/spec_helper.rb
87
+ - tasks/specs.rb
88
+ homepage: https://github.com/chanks/sequel-select-order-clauses
89
+ licenses:
90
+ - MIT
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 2.5.1
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Select the order clauses in a dataset
112
+ test_files:
113
+ - spec/select_order_clauses_spec.rb
114
+ - spec/spec_helper.rb