sqlpostgres 1.2.6 → 1.3.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.
- data/Changelog.md +18 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +12 -0
- data/README.rdoc +5 -2
- data/Rakefile +5 -24
- data/VERSION +1 -1
- data/lib/sqlpostgres/Connection.rb +8 -3
- data/lib/sqlpostgres/Cursor.rb +2 -2
- data/lib/sqlpostgres/Insert.rb +1 -1
- data/lib/sqlpostgres/PgBit.rb +1 -1
- data/lib/sqlpostgres/PgBox.rb +1 -1
- data/lib/sqlpostgres/PgCidr.rb +1 -1
- data/lib/sqlpostgres/PgCircle.rb +1 -1
- data/lib/sqlpostgres/PgInet.rb +1 -1
- data/lib/sqlpostgres/PgInterval.rb +1 -1
- data/lib/sqlpostgres/PgLineSegment.rb +1 -1
- data/lib/sqlpostgres/PgMacAddr.rb +1 -1
- data/lib/sqlpostgres/PgPath.rb +1 -1
- data/lib/sqlpostgres/PgPoint.rb +1 -1
- data/lib/sqlpostgres/PgPolygon.rb +1 -1
- data/lib/sqlpostgres/PgTime.rb +1 -1
- data/lib/sqlpostgres/PgTimeWithTimeZone.rb +1 -1
- data/lib/sqlpostgres/PgTimestamp.rb +1 -1
- data/lib/sqlpostgres/PgTwoPoints.rb +1 -1
- data/lib/sqlpostgres/PgWrapper.rb +1 -1
- data/lib/sqlpostgres/Select.rb +25 -25
- data/lib/sqlpostgres/Translate.rb +7 -29
- data/lib/sqlpostgres/Update.rb +1 -1
- data/rake_tasks/db.rake +17 -0
- data/rake_tasks/default.rake +1 -0
- data/rake_tasks/jeweler.rake +18 -0
- data/rake_tasks/test.rake +2 -0
- data/rake_tasks/test_spec.rake +3 -0
- data/rake_tasks/test_unit.rake +4 -0
- data/spec/Translate_spec.rb +533 -0
- data/spec/config/.gitignore +1 -0
- data/spec/config/config.yml +10 -0
- data/spec/config/database.yml.template +6 -0
- data/spec/connection_spec.rb +515 -0
- data/spec/cursor_spec.rb +288 -0
- data/spec/lib/database_config.rb +33 -0
- data/spec/lib/database_server.rb +42 -0
- data/spec/lib/postgres_template.rb +60 -0
- data/spec/lib/target_database_servers.rb +55 -0
- data/spec/lib/temporary_table.rb +45 -0
- data/spec/lib/test_config.rb +24 -0
- data/spec/lib/test_connection.rb +29 -0
- data/spec/lib/test_database.rb +57 -0
- data/spec/roundtrip_spec.rb +582 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/all_characters.rb +18 -0
- data/spec/support/clear_default_connection.rb +5 -0
- data/spec/support/temporary_table.rb +24 -0
- data/spec/support/test_connections.rb +10 -0
- data/sqlpostgres.gemspec +35 -4
- data/test/Connection.test.rb +7 -5
- data/test/Select.test.rb +1 -1
- data/test/TestConfig.rb +9 -0
- data/test/TestUtil.rb +17 -3
- metadata +66 -9
- data/test/Translate.test.rb +0 -354
- data/test/roundtrip.test.rb +0 -565
data/Changelog.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
### 1.3.0
|
2
|
+
|
3
|
+
Enhancements
|
4
|
+
|
5
|
+
* Support Postgresql 9
|
6
|
+
* Some tests converted to rspec
|
7
|
+
* Connection can set client encoding
|
8
|
+
* More adaptable configuration for databases to run tests against
|
9
|
+
|
10
|
+
### 1.2.6
|
11
|
+
|
12
|
+
Bug fixes
|
13
|
+
|
14
|
+
* DateTime objects store their full precision
|
15
|
+
|
16
|
+
### 1.2.4
|
17
|
+
|
18
|
+
* First public release
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
+
diff-lcs (1.1.3)
|
4
5
|
git (1.2.5)
|
5
6
|
jeweler (1.8.4)
|
6
7
|
bundler (~> 1.0)
|
@@ -8,15 +9,26 @@ GEM
|
|
8
9
|
rake
|
9
10
|
rdoc
|
10
11
|
json (1.7.6)
|
12
|
+
memoizer (1.0.1)
|
11
13
|
pg (0.13.2)
|
12
14
|
rake (10.0.3)
|
13
15
|
rdoc (3.12)
|
14
16
|
json (~> 1.4)
|
17
|
+
rspec (2.12.0)
|
18
|
+
rspec-core (~> 2.12.0)
|
19
|
+
rspec-expectations (~> 2.12.0)
|
20
|
+
rspec-mocks (~> 2.12.0)
|
21
|
+
rspec-core (2.12.2)
|
22
|
+
rspec-expectations (2.12.1)
|
23
|
+
diff-lcs (~> 1.1.3)
|
24
|
+
rspec-mocks (2.12.1)
|
15
25
|
|
16
26
|
PLATFORMS
|
17
27
|
ruby
|
18
28
|
|
19
29
|
DEPENDENCIES
|
20
30
|
jeweler (~> 1.8.4)
|
31
|
+
memoizer (~> 1.0.1)
|
21
32
|
pg (~> 0.13.2)
|
22
33
|
rake (~> 10.0.3)
|
34
|
+
rspec (~> 2.12.0)
|
data/README.rdoc
CHANGED
@@ -47,8 +47,7 @@ The tests are known to pass in MRI 1.8.7 and MRI 1.9.3
|
|
47
47
|
|
48
48
|
== POSTGRES VERSIONS
|
49
49
|
|
50
|
-
This library works with Postgres 1.8
|
51
|
-
Postgres 1.9.
|
50
|
+
This library works with Postgres 1.8 and Postgres 1.9.
|
52
51
|
|
53
52
|
== ENCODINGS
|
54
53
|
|
@@ -57,3 +56,7 @@ This library only works properly with the SQL-ASCII encoding.
|
|
57
56
|
== WHOAMI
|
58
57
|
|
59
58
|
Wayne Conrad <wconrad@yagni.com>
|
59
|
+
|
60
|
+
== CONTRIBUTORS
|
61
|
+
|
62
|
+
Sam Kellogg <sam@nickstoys.com>
|
data/Rakefile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
-
|
5
4
|
require 'bundler'
|
5
|
+
|
6
6
|
begin
|
7
7
|
Bundler.setup(:default, :development)
|
8
8
|
rescue Bundler::BundlerError => e
|
@@ -10,28 +10,9 @@ rescue Bundler::BundlerError => e
|
|
10
10
|
$stderr.puts 'Run `bundle install` to install missing gems'
|
11
11
|
exit e.status_code
|
12
12
|
end
|
13
|
-
require 'rake'
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
# gem is a Gem::Specification... see
|
18
|
-
# http://docs.rubygems.org/read/chapter/20 for more options
|
19
|
-
gem.name = 'sqlpostgres'
|
20
|
-
gem.homepage = 'http://github.com/wconrad/sqlpostgres'
|
21
|
-
gem.license = 'MIT'
|
22
|
-
gem.summary = %Q{library for postgresql queries}
|
23
|
-
gem.description =
|
24
|
-
('A mini-language for building and executing SQL statements '\
|
25
|
-
'against a postgresql database. This is a very old library, '\
|
26
|
-
'pre-dating active record and lacking many of its refinments. '\
|
27
|
-
'New projects will probably not want to use it.')
|
28
|
-
gem.email = 'wconrad@yagni.com'
|
29
|
-
gem.authors = ['Wayne Conrad']
|
30
|
-
# dependencies defined in Gemfile
|
31
|
-
end
|
32
|
-
Jeweler::RubygemsDotOrgTasks.new
|
14
|
+
$:.unshift(File.dirname(__FILE__) + '/lib')
|
15
|
+
Dir['rake_tasks/**/*.rake'].sort.each { |path| load path }
|
33
16
|
|
34
|
-
|
35
|
-
|
36
|
-
system 'test/test'
|
37
|
-
end
|
17
|
+
require File.expand_path('spec/lib/target_database_servers',
|
18
|
+
File.dirname(__FILE__))
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.3.0
|
@@ -83,6 +83,8 @@ module SqlPostgres
|
|
83
83
|
# to nil.
|
84
84
|
# 'password'::
|
85
85
|
# Password. nil, the default, means no password.
|
86
|
+
# 'encoding'::
|
87
|
+
# Client encoding.
|
86
88
|
#
|
87
89
|
# To wrap an existing connection, pass this argument:
|
88
90
|
#
|
@@ -107,12 +109,15 @@ module SqlPostgres
|
|
107
109
|
tty = args['tty'] || ""
|
108
110
|
login = args['login']
|
109
111
|
password = args['password']
|
112
|
+
client_encoding = args['encoding']
|
110
113
|
@pgconn = @@pgClass.connect(hostName, port, options, tty, dbName,
|
111
114
|
login, password)
|
115
|
+
if client_encoding
|
116
|
+
@pgconn.set_client_encoding(client_encoding)
|
117
|
+
end
|
112
118
|
end
|
113
119
|
@statement_in_exception = args['statement_in_exception']
|
114
120
|
@statement_in_exception = true if @statement_in_exception.nil?
|
115
|
-
@pgconn.set_client_encoding("unicode")
|
116
121
|
end
|
117
122
|
|
118
123
|
# close the connection. If it's already closed, do nothing.
|
@@ -177,8 +182,8 @@ module SqlPostgres
|
|
177
182
|
unless column.converter.nil?
|
178
183
|
typeCode = pgresult.ftype(i)
|
179
184
|
value = row[i]
|
180
|
-
args = [value]
|
181
|
-
args << typeCode if column.converter.arity ==
|
185
|
+
args = [value, @pgconn]
|
186
|
+
args << typeCode if column.converter.arity == 3
|
182
187
|
hash[column.as || column.value] =
|
183
188
|
value && column.converter.call(*args)
|
184
189
|
end
|
data/lib/sqlpostgres/Cursor.rb
CHANGED
@@ -101,8 +101,8 @@ module SqlPostgres
|
|
101
101
|
@connection.exec(statement)
|
102
102
|
end
|
103
103
|
|
104
|
-
# Close the cursor. Once closed, it may closed or fetched
|
105
|
-
# again.
|
104
|
+
# Close the cursor. Once closed, it may not be closed or fetched
|
105
|
+
# from again.
|
106
106
|
|
107
107
|
def close
|
108
108
|
statement = "close #{@name}"
|
data/lib/sqlpostgres/Insert.rb
CHANGED
@@ -140,7 +140,7 @@ module SqlPostgres
|
|
140
140
|
|
141
141
|
def insert_bytea(column, value = :no_value)
|
142
142
|
@columns << column
|
143
|
-
@values << Translate.escape_bytea(value) unless value == :no_value
|
143
|
+
@values << Translate.escape_bytea(value, @connection.pgconn) unless value == :no_value
|
144
144
|
end
|
145
145
|
|
146
146
|
# Insert into a bytea[] (bytea array) column. You must use this
|
data/lib/sqlpostgres/PgBit.rb
CHANGED
data/lib/sqlpostgres/PgBox.rb
CHANGED
data/lib/sqlpostgres/PgCidr.rb
CHANGED
data/lib/sqlpostgres/PgCircle.rb
CHANGED
data/lib/sqlpostgres/PgInet.rb
CHANGED
data/lib/sqlpostgres/PgPath.rb
CHANGED
data/lib/sqlpostgres/PgPoint.rb
CHANGED
data/lib/sqlpostgres/PgTime.rb
CHANGED
data/lib/sqlpostgres/Select.rb
CHANGED
@@ -609,29 +609,29 @@ module SqlPostgres
|
|
609
609
|
|
610
610
|
# Converters used to translate strings into Ruby types.
|
611
611
|
|
612
|
-
BitConverter = proc { |s| PgBit.from_sql(s) }
|
613
|
-
BooleanConverter = proc { |s| s == 't' }
|
614
|
-
BoxConverter = proc { |s| PgBox.from_sql(s) }
|
615
|
-
ByteaConverter = proc { |s| Translate.unescape_bytea(s) }
|
616
|
-
CidrConverter = proc { |s| PgCidr.from_sql(s) }
|
617
|
-
CircleConverter = proc { |s| PgCircle.from_sql(s) }
|
618
|
-
DateConverter = proc { |s| Translate.sql_to_date(s) }
|
619
|
-
FloatConverter = proc { |s| s.to_f }
|
620
|
-
InetConverter = proc { |s| PgInet.from_sql(s) }
|
621
|
-
IntegerConverter = proc { |s| s.to_i }
|
622
|
-
IntervalConverter = proc { |s| PgInterval.from_sql(s) }
|
623
|
-
LsegConverter = proc { |s| PgLineSegment.from_sql(s) }
|
624
|
-
MacAddrConverter = proc { |s| PgMacAddr.from_sql(s) }
|
625
|
-
PathConverter = proc { |s| PgPath.from_sql(s) }
|
626
|
-
PointConverter = proc { |s| PgPoint.from_sql(s) }
|
627
|
-
PolygonConverter = proc { |s| PgPolygon.from_sql(s) }
|
628
|
-
QCharConverter = proc { |s| Translate.unescape_qchar(s) }
|
629
|
-
StringConverter = proc { |s| s }
|
630
|
-
TimeConverter = proc { |s| PgTime.from_sql(s) }
|
631
|
-
TimeStringConverter = proc { |s| Time.local(*s.split(/:/)) }
|
632
|
-
TimeWithTimeZoneConverter = proc { |s| PgTimeWithTimeZone.from_sql(s) }
|
633
|
-
TimestampConverter = proc { |s| PgTimestamp.from_sql(s) }
|
634
|
-
TimestampTzConverter = proc { |s| Translate.sql_to_datetime(s) }
|
612
|
+
BitConverter = proc { |s, server_version| PgBit.from_sql(s) }
|
613
|
+
BooleanConverter = proc { |s, server_version| s == 't' }
|
614
|
+
BoxConverter = proc { |s, server_version| PgBox.from_sql(s) }
|
615
|
+
ByteaConverter = proc { |s, server_version| Translate.unescape_bytea(s, server_version) }
|
616
|
+
CidrConverter = proc { |s, server_version| PgCidr.from_sql(s) }
|
617
|
+
CircleConverter = proc { |s, server_version| PgCircle.from_sql(s) }
|
618
|
+
DateConverter = proc { |s, server_version| Translate.sql_to_date(s) }
|
619
|
+
FloatConverter = proc { |s, server_version| s.to_f }
|
620
|
+
InetConverter = proc { |s, server_version| PgInet.from_sql(s) }
|
621
|
+
IntegerConverter = proc { |s, server_version| s.to_i }
|
622
|
+
IntervalConverter = proc { |s, server_version| PgInterval.from_sql(s) }
|
623
|
+
LsegConverter = proc { |s, server_version| PgLineSegment.from_sql(s) }
|
624
|
+
MacAddrConverter = proc { |s, server_version| PgMacAddr.from_sql(s) }
|
625
|
+
PathConverter = proc { |s, server_version| PgPath.from_sql(s) }
|
626
|
+
PointConverter = proc { |s, server_version| PgPoint.from_sql(s) }
|
627
|
+
PolygonConverter = proc { |s, server_version| PgPolygon.from_sql(s) }
|
628
|
+
QCharConverter = proc { |s, server_version| Translate.unescape_qchar(s) }
|
629
|
+
StringConverter = proc { |s, server_version| s }
|
630
|
+
TimeConverter = proc { |s, server_version| PgTime.from_sql(s) }
|
631
|
+
TimeStringConverter = proc { |s, server_version| Time.local(*s.split(/:/)) }
|
632
|
+
TimeWithTimeZoneConverter = proc { |s, server_version| PgTimeWithTimeZone.from_sql(s) }
|
633
|
+
TimestampConverter = proc { |s, server_version| PgTimestamp.from_sql(s) }
|
634
|
+
TimestampTzConverter = proc { |s, server_version| Translate.sql_to_datetime(s) }
|
635
635
|
|
636
636
|
# Map each base (non-array) type to a converter.
|
637
637
|
|
@@ -705,7 +705,7 @@ module SqlPostgres
|
|
705
705
|
Types::ARRAY_VARCHAR => Types::VARCHAR,
|
706
706
|
}
|
707
707
|
|
708
|
-
AutoConverter = proc { |s, type_code|
|
708
|
+
AutoConverter = proc { |s, pgconn, type_code|
|
709
709
|
array_element_type = ARRAY_ELEMENT_TYPES[type_code]
|
710
710
|
if !array_element_type.nil?
|
711
711
|
s = Translate.sql_to_array(s)
|
@@ -713,7 +713,7 @@ module SqlPostgres
|
|
713
713
|
end
|
714
714
|
converter = CONVERTERS[type_code] || StringConverter
|
715
715
|
Translate.deep_collect(s) do |e|
|
716
|
-
converter.call(e)
|
716
|
+
converter.call(e, pgconn)
|
717
717
|
end
|
718
718
|
}
|
719
719
|
|
@@ -270,45 +270,23 @@ module SqlPostgres
|
|
270
270
|
# \
|
271
271
|
# \x7f-\xff
|
272
272
|
|
273
|
-
def escape_bytea(s)
|
273
|
+
def escape_bytea(s, pgconn)
|
274
274
|
return "null" if s.nil?
|
275
275
|
return "default" if s == :default
|
276
|
-
|
276
|
+
raise s.inspect if s.is_a?(Array) #DEBUG
|
277
|
+
value = "'" + pgconn.escape_bytea(s) + "'"
|
278
|
+
value = "E" + value if pgconn.server_version < 9_01_00
|
279
|
+
value
|
277
280
|
end
|
278
281
|
module_function :escape_bytea
|
279
282
|
|
280
|
-
# Unescape octal escape sequences, turning them back into bytes.
|
281
|
-
|
282
|
-
def unescape_octal_escapes(s)
|
283
|
-
s.gsub(/\\(\d{3})/) do
|
284
|
-
$1.oct.chr
|
285
|
-
end.gsub(/\\\\/, '\\')
|
286
|
-
end
|
287
|
-
module_function :unescape_octal_escapes
|
288
|
-
|
289
283
|
# Unescape a bytea string read from postgres.
|
290
284
|
|
291
|
-
def unescape_bytea(s)
|
292
|
-
|
293
|
-
s = s.force_encoding("ASCII-8BIT")
|
294
|
-
end
|
295
|
-
s.gsub(/\\(\\|[0-3][0-7][0-7])/) do
|
296
|
-
if $1 == "\\"
|
297
|
-
"\\"
|
298
|
-
else
|
299
|
-
$1.oct.chr
|
300
|
-
end
|
301
|
-
end
|
285
|
+
def unescape_bytea(s, pgconn)
|
286
|
+
pgconn.unescape_bytea(s)
|
302
287
|
end
|
303
288
|
module_function :unescape_bytea
|
304
289
|
|
305
|
-
# Unescape a text string read from postges.
|
306
|
-
|
307
|
-
def unescape_text(s)
|
308
|
-
unescape_bytea(s)
|
309
|
-
end
|
310
|
-
module_function :unescape_text
|
311
|
-
|
312
290
|
# Convert a time to SQL format, including microseconds:
|
313
291
|
# (YYYY-mm-dd HH:MM:SS.uuuuuu)
|
314
292
|
|
data/lib/sqlpostgres/Update.rb
CHANGED
@@ -99,7 +99,7 @@ module SqlPostgres
|
|
99
99
|
#**
|
100
100
|
|
101
101
|
def set_bytea(column, value)
|
102
|
-
@set_clauses << [column, Translate.escape_bytea(value)].join(' = ')
|
102
|
+
@set_clauses << [column, Translate.escape_bytea(value, @connection.pgconn)].join(' = ')
|
103
103
|
end
|
104
104
|
|
105
105
|
# Set a column to an array.
|
data/rake_tasks/db.rake
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
namespace 'test:db' do
|
2
|
+
|
3
|
+
def target_database_servers
|
4
|
+
TestSupport::TargetDatabaseServers.instance
|
5
|
+
end
|
6
|
+
|
7
|
+
desc 'Create test databases'
|
8
|
+
task 'create' do
|
9
|
+
target_database_servers.create_databases
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'Drop test databases'
|
13
|
+
task 'drop' do
|
14
|
+
target_database_servers.drop_databases
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|