perpetuity-postgres 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/perpetuity/postgres/date_value.rb +29 -0
- data/lib/perpetuity/postgres/query_expression.rb +6 -1
- data/lib/perpetuity/postgres/serializer.rb +1 -1
- data/lib/perpetuity/postgres/sql_value.rb +3 -0
- data/lib/perpetuity/postgres/table/attribute.rb +6 -1
- data/lib/perpetuity/postgres/version.rb +1 -1
- data/spec/perpetuity/postgres/connection_pool_spec.rb +4 -4
- data/spec/perpetuity/postgres/date_value_spec.rb +24 -0
- data/spec/perpetuity/postgres/query_attribute_spec.rb +3 -2
- data/spec/perpetuity/postgres/query_expression_spec.rb +6 -0
- data/spec/perpetuity/postgres/serialized_data_spec.rb +2 -2
- data/spec/perpetuity/postgres/serializer_spec.rb +10 -5
- data/spec/perpetuity/postgres/sql_select_spec.rb +11 -3
- data/spec/perpetuity/postgres/sql_value_spec.rb +5 -0
- data/spec/perpetuity/postgres/table/attribute_spec.rb +8 -0
- data/spec/perpetuity/postgres/table_spec.rb +8 -0
- data/spec/perpetuity/postgres_spec.rb +27 -16
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 131881bc7b24a361b04326b0fac2699ca1ca2c22
|
4
|
+
data.tar.gz: 57dc7bd53e485500524439604ceaa517f5990215
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1c978801cc9d1a5c4bc888c899ce27ff15166bb396ad4eb5b95212664b408e76f13afb57175220072b532b6beaeb598794c67c0f1de809cb893bad71de49e8a
|
7
|
+
data.tar.gz: 5645ce0e3ebca3602b789515db6762ca0713c958dd915502dea87d8137df67f1c55b8b53bd9a632e081c55ce8ee767a12984a294a74db2992150ef48c8b32a68
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Perpetuity
|
4
|
+
class Postgres
|
5
|
+
class DateValue
|
6
|
+
attr_reader :date
|
7
|
+
|
8
|
+
def initialize date
|
9
|
+
@date = date
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.from_sql date_string
|
13
|
+
new(Date.parse(date_string))
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_date
|
17
|
+
date
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
"'#{date.to_s}'::date"
|
22
|
+
end
|
23
|
+
|
24
|
+
def value
|
25
|
+
date
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -66,7 +66,12 @@ module Perpetuity
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def in
|
69
|
-
|
69
|
+
case sql_value
|
70
|
+
when Range
|
71
|
+
"#{attribute} BETWEEN #{SQLValue.new(sql_value.min)} AND #{SQLValue.new(sql_value.max)}"
|
72
|
+
else
|
73
|
+
"#{attribute} IN #{sql_value}"
|
74
|
+
end
|
70
75
|
end
|
71
76
|
|
72
77
|
def =~
|
@@ -12,7 +12,7 @@ module Perpetuity
|
|
12
12
|
class Serializer
|
13
13
|
include DataInjectable
|
14
14
|
|
15
|
-
SERIALIZABLE_CLASSES = Set[Fixnum, Float, String, Time, TrueClass, FalseClass, NilClass]
|
15
|
+
SERIALIZABLE_CLASSES = Set[Fixnum, Float, String, Time, Date, TrueClass, FalseClass, NilClass]
|
16
16
|
attr_reader :mapper, :mapper_registry
|
17
17
|
|
18
18
|
def initialize mapper
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'perpetuity/postgres/text_value'
|
2
2
|
require 'perpetuity/postgres/timestamp_value'
|
3
|
+
require 'perpetuity/postgres/date_value'
|
3
4
|
require 'perpetuity/postgres/numeric_value'
|
4
5
|
require 'perpetuity/postgres/null_value'
|
5
6
|
require 'perpetuity/postgres/boolean_value'
|
@@ -17,6 +18,8 @@ module Perpetuity
|
|
17
18
|
TextValue.new(value)
|
18
19
|
when Time
|
19
20
|
TimestampValue.new(value)
|
21
|
+
when Date
|
22
|
+
DateValue.new(value)
|
20
23
|
when Fixnum, Float
|
21
24
|
NumericValue.new(value)
|
22
25
|
when Hash, JSONHash
|
@@ -18,6 +18,7 @@ module Perpetuity
|
|
18
18
|
Float => 'FLOAT',
|
19
19
|
UUID => 'UUID',
|
20
20
|
Time => 'TIMESTAMPTZ',
|
21
|
+
Date => 'DATE',
|
21
22
|
TrueClass => 'BOOLEAN',
|
22
23
|
FalseClass => 'BOOLEAN'
|
23
24
|
}.tap{|m| m.default = 'JSON' }
|
@@ -26,7 +27,11 @@ module Perpetuity
|
|
26
27
|
@name = name
|
27
28
|
@type = type
|
28
29
|
@max_length = options[:max_length]
|
29
|
-
@primary_key =
|
30
|
+
@primary_key = if @name.to_s == 'id'
|
31
|
+
true
|
32
|
+
else
|
33
|
+
options.fetch(:primary_key) { false }
|
34
|
+
end
|
30
35
|
@default = options.fetch(:default) { NoDefaultValue }
|
31
36
|
end
|
32
37
|
|
@@ -6,7 +6,7 @@ module Perpetuity
|
|
6
6
|
let(:pool) { ConnectionPool.new }
|
7
7
|
|
8
8
|
it 'defaults to 5 connections' do
|
9
|
-
pool.
|
9
|
+
expect(pool.connections.size).to eq 5
|
10
10
|
end
|
11
11
|
|
12
12
|
describe 'lending a connection' do
|
@@ -20,9 +20,9 @@ module Perpetuity
|
|
20
20
|
|
21
21
|
it 'lends a connection for the duration of a block' do
|
22
22
|
pool.lend_connection do |connection|
|
23
|
-
pool.
|
23
|
+
expect(pool.connections.size).to eq 4
|
24
24
|
end
|
25
|
-
pool.
|
25
|
+
expect(pool.connections.size).to eq 5
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'returns the value of the block' do
|
@@ -48,7 +48,7 @@ module Perpetuity
|
|
48
48
|
pool.lend_connection { |c| connections << c }
|
49
49
|
end
|
50
50
|
|
51
|
-
connections.uniq.
|
51
|
+
expect(connections.uniq.size).to eq pool.size
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'perpetuity/postgres/date_value'
|
2
|
+
|
3
|
+
module Perpetuity
|
4
|
+
class Postgres
|
5
|
+
describe DateValue do
|
6
|
+
it 'converts to a SQL string' do
|
7
|
+
date = Date.new(2014, 8, 25)
|
8
|
+
DateValue.new(date).to_s.should == "'2014-08-25'::date"
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'conversion from a SQL value string' do
|
12
|
+
it 'converts GMT-X times' do
|
13
|
+
actual = DateValue.from_sql('2013-12-01')
|
14
|
+
expected = Date.new(2013, 12, 1)
|
15
|
+
actual.to_date.should == expected
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns its wrapped value' do
|
20
|
+
DateValue.new(:foo).value.should == :foo
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -4,9 +4,10 @@ module Perpetuity
|
|
4
4
|
class Postgres
|
5
5
|
describe QueryAttribute do
|
6
6
|
let(:attribute) { QueryAttribute.new :attribute_name }
|
7
|
-
subject { attribute }
|
8
7
|
|
9
|
-
|
8
|
+
it 'returns its name' do
|
9
|
+
attribute.name.should == :attribute_name
|
10
|
+
end
|
10
11
|
|
11
12
|
it 'checks for equality' do
|
12
13
|
(attribute == 1).should be_a QueryExpression
|
@@ -57,6 +57,12 @@ module Perpetuity
|
|
57
57
|
expression.to_db.should == "attribute IN (1,2,3)"
|
58
58
|
end
|
59
59
|
|
60
|
+
it 'checks for inclusion in a range' do
|
61
|
+
expression.comparator = :in
|
62
|
+
expression.value = (1..3)
|
63
|
+
expression.to_db.should == "attribute BETWEEN 1 AND 3"
|
64
|
+
end
|
65
|
+
|
60
66
|
it 'checks for inclusion of strings' do
|
61
67
|
expression.comparator = :in
|
62
68
|
expression.value = ['abc', '123']
|
@@ -45,9 +45,9 @@ module Perpetuity
|
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'checks whether there are any objects' do
|
48
|
-
serialized.any?.should
|
48
|
+
serialized.any?.should be_truthy
|
49
49
|
serialized.values.clear << []
|
50
|
-
serialized.any?.should
|
50
|
+
serialized.any?.should be_falsey
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'iterates like a hash' do
|
@@ -81,6 +81,11 @@ module Perpetuity
|
|
81
81
|
serializer.serialize_attribute(time).should == "'2000-01-02 03:04:05.123456-0400'::timestamptz"
|
82
82
|
end
|
83
83
|
|
84
|
+
it 'serializes Date objects' do
|
85
|
+
date = Date.new(2014, 8, 25)
|
86
|
+
serializer.serialize_attribute(date).should == "'2014-08-25'::date"
|
87
|
+
end
|
88
|
+
|
84
89
|
it 'serializes an array as JSON' do
|
85
90
|
serializer.serialize_attribute([1, 'foo']).should == %q{'[1,"foo"]'}
|
86
91
|
end
|
@@ -181,25 +186,25 @@ module Perpetuity
|
|
181
186
|
|
182
187
|
describe 'identifying embedded/referenced objects as foreign' do
|
183
188
|
it 'sees hashes with metadata keys as foreign objects' do
|
184
|
-
serializer.foreign_object?({'__metadata__' => 'lol'}).should
|
189
|
+
serializer.foreign_object?({'__metadata__' => 'lol'}).should be_truthy
|
185
190
|
end
|
186
191
|
|
187
192
|
it 'sees hashes without metadata keys as simple hashes' do
|
188
|
-
serializer.foreign_object?({ 'name' => 'foo' }).should
|
193
|
+
serializer.foreign_object?({ 'name' => 'foo' }).should be_falsey
|
189
194
|
end
|
190
195
|
end
|
191
196
|
|
192
197
|
describe 'identifying possible JSON strings' do
|
193
198
|
it 'identifies JSON objects' do
|
194
|
-
serializer.possible_json_value?('{"name":"foo"}').should
|
199
|
+
serializer.possible_json_value?('{"name":"foo"}').should be_truthy
|
195
200
|
end
|
196
201
|
|
197
202
|
it 'identifies JSON arrays' do
|
198
|
-
serializer.possible_json_value?('[{"name":"foo"}]').should
|
203
|
+
serializer.possible_json_value?('[{"name":"foo"}]').should be_truthy
|
199
204
|
end
|
200
205
|
|
201
206
|
it 'rejects things it does not detect as either of the above' do
|
202
|
-
serializer.possible_json_value?('foo is my name').should
|
207
|
+
serializer.possible_json_value?('foo is my name').should be_falsey
|
203
208
|
end
|
204
209
|
end
|
205
210
|
|
@@ -8,9 +8,17 @@ module Perpetuity
|
|
8
8
|
limit: 4) }
|
9
9
|
subject { query }
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
it 'returns its table name' do
|
12
|
+
query.table.should == 'foo'
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'returns its WHERE clause' do
|
16
|
+
query.where.should == "name = 'foo'"
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns its limit' do
|
20
|
+
query.limit.should == 4
|
21
|
+
end
|
14
22
|
|
15
23
|
it 'generates a SQL query' do
|
16
24
|
query.to_s.should == %Q{SELECT * FROM "foo" WHERE name = 'foo' LIMIT 4}
|
@@ -50,6 +50,11 @@ module Perpetuity
|
|
50
50
|
time = Time.new(2013, 1, 2, 3, 4, 5.1234567, '+05:30')
|
51
51
|
SQLValue.new(time).should == "'2013-01-02 03:04:05.123456+0530'::timestamptz"
|
52
52
|
end
|
53
|
+
|
54
|
+
it 'converts Date objects' do
|
55
|
+
date = Date.new(2014, 8, 25)
|
56
|
+
SQLValue.new(date).should == "'2014-08-25'::date"
|
57
|
+
end
|
53
58
|
end
|
54
59
|
end
|
55
60
|
end
|
@@ -80,6 +80,14 @@ module Perpetuity
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
+
describe 'dates' do
|
84
|
+
let(:date) { Attribute.new('anniversary_date', Date) }
|
85
|
+
|
86
|
+
it 'converts to the SQL DATE type' do
|
87
|
+
date.sql_type.should == 'DATE'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
83
91
|
describe 'booleans' do
|
84
92
|
it 'is stored in a BOOLEAN column' do
|
85
93
|
Attribute.new(:true, TrueClass).sql_type.should == 'BOOLEAN'
|
@@ -29,6 +29,14 @@ module Perpetuity
|
|
29
29
|
'CREATE TABLE IF NOT EXISTS "Article" (id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), title TEXT, body TEXT, author JSON, published_at TIMESTAMPTZ, views BIGINT)'
|
30
30
|
end
|
31
31
|
|
32
|
+
it 'sets the id as PRIMARY KEY even if specified in attributes' do
|
33
|
+
attributes = self.attributes.dup
|
34
|
+
attributes.unshift Table::Attribute.new(:id, String)
|
35
|
+
table = Table.new('Article', attributes)
|
36
|
+
table.create_table_sql.should ==
|
37
|
+
'CREATE TABLE IF NOT EXISTS "Article" (id TEXT PRIMARY KEY, title TEXT, body TEXT, author JSON, published_at TIMESTAMPTZ, views BIGINT)'
|
38
|
+
end
|
39
|
+
|
32
40
|
describe 'id column' do
|
33
41
|
context 'when there is an id attribute' do
|
34
42
|
it 'uses the attribute type for the column type' do
|
@@ -25,25 +25,36 @@ module Perpetuity
|
|
25
25
|
password: password
|
26
26
|
)
|
27
27
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
its(:username) { should == username }
|
35
|
-
its(:password) { should == password }
|
28
|
+
|
29
|
+
[:host, :port, :db, :pool_size, :username, :password].each do |attribute|
|
30
|
+
it "returns its #{attribute}" do
|
31
|
+
postgres.public_send(attribute).should == send(attribute)
|
32
|
+
end
|
33
|
+
end
|
36
34
|
end
|
37
35
|
|
38
36
|
context 'default values' do
|
39
37
|
let(:postgres) { Postgres.new(db: 'my_db') }
|
40
|
-
subject { postgres }
|
41
38
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
39
|
+
it 'defaults to host = localhost' do
|
40
|
+
postgres.host.should == 'localhost'
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'defaults to port = 5432 (Postgres default)' do
|
44
|
+
postgres.port.should == 5432
|
45
|
+
end
|
46
|
+
|
47
|
+
it "defaults to username = #{ENV['USER']}" do
|
48
|
+
postgres.username.should == ENV['USER']
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'defaults to a blank password' do
|
52
|
+
postgres.password.should be nil
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'defaults to pool_size = 5' do
|
56
|
+
postgres.pool_size.should == 5
|
57
|
+
end
|
47
58
|
end
|
48
59
|
end
|
49
60
|
|
@@ -108,7 +119,7 @@ module Perpetuity
|
|
108
119
|
Postgres::SerializedData.new([:name], ["'Kevin'"])
|
109
120
|
ids = postgres.insert('User', data, attributes)
|
110
121
|
ids.should be_a Array
|
111
|
-
ids.
|
122
|
+
expect(ids.count).to eq 3
|
112
123
|
end
|
113
124
|
|
114
125
|
it 'returns numeric ids when numeric ids are specified' do
|
@@ -128,7 +139,7 @@ module Perpetuity
|
|
128
139
|
it 'counts objects with a string query' do
|
129
140
|
insert = proc { postgres.insert 'User', data, attributes }
|
130
141
|
expect(&insert).to change { postgres.count('User', "name = 'Jamie'") }.by 1
|
131
|
-
expect(&insert).not_to change { postgres.count('User', "name = 'Jessica'") }
|
142
|
+
expect(&insert).not_to change { postgres.count('User', "name = 'Jessica'") }
|
132
143
|
end
|
133
144
|
|
134
145
|
it 'returns a count of 0 when the table does not exist' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perpetuity-postgres
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jamie Gaskins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-08-
|
11
|
+
date: 2014-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -98,6 +98,7 @@ files:
|
|
98
98
|
- lib/perpetuity/postgres/boolean_value.rb
|
99
99
|
- lib/perpetuity/postgres/connection.rb
|
100
100
|
- lib/perpetuity/postgres/connection_pool.rb
|
101
|
+
- lib/perpetuity/postgres/date_value.rb
|
101
102
|
- lib/perpetuity/postgres/expression.rb
|
102
103
|
- lib/perpetuity/postgres/index.rb
|
103
104
|
- lib/perpetuity/postgres/index_collection.rb
|
@@ -130,6 +131,7 @@ files:
|
|
130
131
|
- spec/perpetuity/postgres/boolean_value_spec.rb
|
131
132
|
- spec/perpetuity/postgres/connection_pool_spec.rb
|
132
133
|
- spec/perpetuity/postgres/connection_spec.rb
|
134
|
+
- spec/perpetuity/postgres/date_value_spec.rb
|
133
135
|
- spec/perpetuity/postgres/expression_spec.rb
|
134
136
|
- spec/perpetuity/postgres/index_collection_spec.rb
|
135
137
|
- spec/perpetuity/postgres/index_spec.rb
|
@@ -187,6 +189,7 @@ test_files:
|
|
187
189
|
- spec/perpetuity/postgres/boolean_value_spec.rb
|
188
190
|
- spec/perpetuity/postgres/connection_pool_spec.rb
|
189
191
|
- spec/perpetuity/postgres/connection_spec.rb
|
192
|
+
- spec/perpetuity/postgres/date_value_spec.rb
|
190
193
|
- spec/perpetuity/postgres/expression_spec.rb
|
191
194
|
- spec/perpetuity/postgres/index_collection_spec.rb
|
192
195
|
- spec/perpetuity/postgres/index_spec.rb
|