postgres-pr-opt 0.6.9
Sign up to get free protection for your applications and to get access to all the features.
- data/README +25 -0
- data/Rakefile +2 -0
- data/examples/client.rb +34 -0
- data/examples/og/test.rb +50 -0
- data/examples/server.rb +12 -0
- data/examples/test_connection.rb +18 -0
- data/ext/postgres-pr/utils/extconf.rb +8 -0
- data/ext/postgres-pr/utils/string_unpack_single.c +73 -0
- data/lib/pg.rb +8 -0
- data/lib/postgres-pr/connection.rb +175 -0
- data/lib/postgres-pr/message.rb +589 -0
- data/lib/postgres-pr/pg-compat.rb +225 -0
- data/lib/postgres-pr/postgres-compat.rb +169 -0
- data/lib/postgres-pr/typeconv/TC_conv.rb +18 -0
- data/lib/postgres-pr/typeconv/array.rb +46 -0
- data/lib/postgres-pr/typeconv/bytea.rb +32 -0
- data/lib/postgres-pr/typeconv/conv.rb +5 -0
- data/lib/postgres-pr/utils/buffer.rb +252 -0
- data/lib/postgres-pr/utils/byteorder.rb +45 -0
- data/lib/postgres-pr/version.rb +3 -0
- data/lib/postgres.rb +8 -0
- metadata +102 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
module Postgres::Conversion
|
2
|
+
# Encodes a string as bytea value.
|
3
|
+
#
|
4
|
+
# For encoding rules see:
|
5
|
+
# http://www.postgresql.org/docs/7.4/static/datatype-binary.html
|
6
|
+
#
|
7
|
+
# The historical bytea escape format is always used, for maximum compatibility.
|
8
|
+
def encode_bytea(str)
|
9
|
+
# each_byte used instead of [] for 1.9 compatibility
|
10
|
+
str.gsub(/[\000-\037\047\134\177-\377]/){|b| "\\#{sprintf('%o', b.each_byte{|x| break x}).rjust(3, '0')}"}
|
11
|
+
end
|
12
|
+
|
13
|
+
# Decodes a bytea encoded string.
|
14
|
+
#
|
15
|
+
# For decoding rules see:
|
16
|
+
# http://www.postgresql.org/docs/7.4/static/datatype-binary.html
|
17
|
+
#
|
18
|
+
# Supports both the historical escape format and the new 9.0+ hex format.
|
19
|
+
def decode_bytea(str)
|
20
|
+
if str =~ /\A\\x/
|
21
|
+
# PostgreSQL 9.0+ bytea hex format
|
22
|
+
str[2..-1].gsub(/(..)/){|s| s.to_i(16).chr}
|
23
|
+
else
|
24
|
+
# Historical PostgreSQL bytea escape format
|
25
|
+
str.gsub(/\\(\\|'|[0-3][0-7][0-7])/) {|s|
|
26
|
+
if s.size == 2 then s[1,1] else s[1,3].oct.chr end
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
alias unescape_bytea decode_bytea
|
32
|
+
end
|
@@ -0,0 +1,252 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
unless "".respond_to?(:getbyte)
|
3
|
+
class String
|
4
|
+
alias :getbyte :[]
|
5
|
+
end
|
6
|
+
end
|
7
|
+
unless "".respond_to?(:setbyte)
|
8
|
+
class String
|
9
|
+
alias :setbyte :[]=
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
if RUBY_ENGINE == 'ruby'
|
14
|
+
begin
|
15
|
+
require 'postgres-pr/utils/unpack_single'
|
16
|
+
rescue LoadError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module PostgresPR
|
21
|
+
module Utils
|
22
|
+
STRING_NATIVE_UNPACK_SINGLE = "".respond_to?(:get_int16_network)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
unless PostgresPR::Utils::STRING_NATIVE_UNPACK_SINGLE
|
27
|
+
class String
|
28
|
+
def get_int16_network(pos)
|
29
|
+
byte1, byte2 = getbyte(pos), getbyte(pos+1)
|
30
|
+
(byte1 < 128 ? byte1 : byte1 - 256) * 256 + byte2
|
31
|
+
end
|
32
|
+
def get_int32_network(pos)
|
33
|
+
byte1, byte2 = getbyte(pos), getbyte(pos+1)
|
34
|
+
byte3, byte4 = getbyte(pos+2), getbyte(pos+3)
|
35
|
+
((((byte1 < 128 ? byte1 : byte1 - 256) * 256 + byte2) * 256) + byte3) * 256 + byte4
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module PostgresPR
|
41
|
+
module Utils
|
42
|
+
class NativeBuffer < StringIO
|
43
|
+
def self.of_size(size)
|
44
|
+
new('#'*size, 'r+')
|
45
|
+
end
|
46
|
+
alias position pos
|
47
|
+
alias position= pos=
|
48
|
+
alias read_byte readbyte
|
49
|
+
alias at_end? eof?
|
50
|
+
alias content string
|
51
|
+
alias init_buffer initialize
|
52
|
+
public :init_buffer
|
53
|
+
if STRING_NATIVE_UNPACK_SINGLE
|
54
|
+
include ReadUnpack
|
55
|
+
else
|
56
|
+
def read_int16_network
|
57
|
+
byte1, byte2 = readbyte, readbyte
|
58
|
+
(byte1 < 128 ? byte1 : byte1 - 256) * 256 + byte2
|
59
|
+
end
|
60
|
+
def read_int32_network
|
61
|
+
byte1, byte2 = readbyte, readbyte
|
62
|
+
byte3, byte4 = readbyte, readbyte
|
63
|
+
((((byte1 < 128 ? byte1 : byte1 - 256) * 256 + byte2) * 256) + byte3) * 256 + byte4
|
64
|
+
end
|
65
|
+
end
|
66
|
+
def write_byte(byte)
|
67
|
+
write(byte.chr)
|
68
|
+
end
|
69
|
+
def write_int32_network(int32)
|
70
|
+
write([int32].pack('N'))
|
71
|
+
end
|
72
|
+
def write_int16_network(int16)
|
73
|
+
write([int16].pack('n'))
|
74
|
+
end
|
75
|
+
|
76
|
+
def copy_from_stream(stream, n)
|
77
|
+
raise ArgumentError if n < 0
|
78
|
+
while n > 0
|
79
|
+
str = stream.read(n)
|
80
|
+
write(str)
|
81
|
+
n -= str.size
|
82
|
+
end
|
83
|
+
raise if n < 0
|
84
|
+
end
|
85
|
+
|
86
|
+
NUL = "\000"
|
87
|
+
def write_cstring(cstr)
|
88
|
+
raise ArgumentError, "Invalid Ruby/cstring" if cstr.include?(NUL)
|
89
|
+
write(cstr)
|
90
|
+
write(NUL)
|
91
|
+
end
|
92
|
+
|
93
|
+
# returns a Ruby string without the trailing NUL character
|
94
|
+
def read_cstring
|
95
|
+
s = readline(NUL)
|
96
|
+
s.chop!
|
97
|
+
s
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
class CustomBuffer
|
103
|
+
|
104
|
+
class Error < RuntimeError; end
|
105
|
+
class EOF < Error; end
|
106
|
+
|
107
|
+
def self.from_string(str)
|
108
|
+
new(str)
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.of_size(size)
|
112
|
+
raise ArgumentError if size < 0
|
113
|
+
new('#' * size)
|
114
|
+
end
|
115
|
+
|
116
|
+
def initialize(content)
|
117
|
+
self.init_buffer content
|
118
|
+
end
|
119
|
+
|
120
|
+
def init_buffer(content)
|
121
|
+
@size = content.size
|
122
|
+
@content = content
|
123
|
+
@position = 0
|
124
|
+
end
|
125
|
+
|
126
|
+
def close
|
127
|
+
end
|
128
|
+
|
129
|
+
def size
|
130
|
+
@size
|
131
|
+
end
|
132
|
+
|
133
|
+
def position
|
134
|
+
@position
|
135
|
+
end
|
136
|
+
|
137
|
+
def position=(new_pos)
|
138
|
+
raise ArgumentError if new_pos < 0 or new_pos > @size
|
139
|
+
@position = new_pos
|
140
|
+
end
|
141
|
+
|
142
|
+
def at_end?
|
143
|
+
@position == @size
|
144
|
+
end
|
145
|
+
|
146
|
+
def content
|
147
|
+
@content
|
148
|
+
end
|
149
|
+
|
150
|
+
def read(n)
|
151
|
+
raise EOF, 'cannot read beyond the end of buffer' if @position + n > @size
|
152
|
+
str = @content[@position, n]
|
153
|
+
@position += n
|
154
|
+
str
|
155
|
+
end
|
156
|
+
|
157
|
+
def write(str)
|
158
|
+
sz = str.size
|
159
|
+
raise EOF, 'cannot write beyond the end of buffer' if @position + sz > @size
|
160
|
+
@content[@position, sz] = str
|
161
|
+
@position += sz
|
162
|
+
self
|
163
|
+
end
|
164
|
+
|
165
|
+
def readbyte
|
166
|
+
raise EOF, 'cannot read beyond the end of buffer' if @position >= @size
|
167
|
+
byte = @content.getbyte(@position)
|
168
|
+
@position += 1
|
169
|
+
byte
|
170
|
+
end
|
171
|
+
alias read_byte readbyte
|
172
|
+
|
173
|
+
def read_int16_network
|
174
|
+
pos = @position
|
175
|
+
raise EOF, 'cannot read beyond the end of buffer' if pos + 2 > @size
|
176
|
+
@position += 2
|
177
|
+
@content.get_int16_network(pos)
|
178
|
+
end
|
179
|
+
|
180
|
+
def read_int32_network
|
181
|
+
pos = @position
|
182
|
+
raise EOF, 'cannot read beyond the end of buffer' if pos + 4 > @size
|
183
|
+
@position += 4
|
184
|
+
@content.get_int32_network(pos)
|
185
|
+
end
|
186
|
+
|
187
|
+
def copy_from_stream(stream, n)
|
188
|
+
raise ArgumentError if n < 0
|
189
|
+
while n > 0
|
190
|
+
str = stream.read(n)
|
191
|
+
write(str)
|
192
|
+
n -= str.size
|
193
|
+
end
|
194
|
+
raise if n < 0
|
195
|
+
end
|
196
|
+
|
197
|
+
def writebyte(byte)
|
198
|
+
raise EOF, 'cannot write beyond the end of buffer' if @position >= @size
|
199
|
+
@content.setbyte(@position, byte)
|
200
|
+
@position += 1
|
201
|
+
self
|
202
|
+
end
|
203
|
+
alias write_byte writebyte
|
204
|
+
|
205
|
+
def write_int16_network(int16)
|
206
|
+
raise EOF, 'cannot write beyond the end of buffer' if @position + 2 > @size
|
207
|
+
@content[@position, 2] = [int16].pack('n')
|
208
|
+
@position += 2
|
209
|
+
self
|
210
|
+
end
|
211
|
+
|
212
|
+
def write_int32_network(int32)
|
213
|
+
raise EOF, 'cannot write beyond the end of buffer' if @position + 4 > @size
|
214
|
+
@content[@position, 4] = [int32].pack('N')
|
215
|
+
@position += 4
|
216
|
+
self
|
217
|
+
end
|
218
|
+
|
219
|
+
NUL = "\000"
|
220
|
+
|
221
|
+
def write_cstring(cstr)
|
222
|
+
raise ArgumentError, "Invalid Ruby/cstring" if cstr.include?(NUL)
|
223
|
+
write(cstr)
|
224
|
+
write(NUL)
|
225
|
+
end
|
226
|
+
|
227
|
+
# returns a Ruby string without the trailing NUL character
|
228
|
+
def read_cstring
|
229
|
+
nul_pos = @content.index(NUL, @position)
|
230
|
+
raise Error, "no cstring found!" unless nul_pos
|
231
|
+
|
232
|
+
sz = nul_pos - @position
|
233
|
+
str = @content[@position, sz]
|
234
|
+
@position += sz + 1
|
235
|
+
return str
|
236
|
+
end
|
237
|
+
|
238
|
+
# read till the end of the buffer
|
239
|
+
def read_rest
|
240
|
+
read(self.size-@position)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
if RUBY_ENGINE == 'jruby' || (RUBY_ENGINE == 'ruby' && RUBY_VERSION < '1.9')
|
245
|
+
ReadBuffer = NativeBuffer
|
246
|
+
WriteBuffer = NativeBuffer
|
247
|
+
else
|
248
|
+
ReadBuffer = CustomBuffer
|
249
|
+
WriteBuffer = CustomBuffer
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module PostgresPR
|
2
|
+
module Utils
|
3
|
+
module ByteOrder
|
4
|
+
Native = :Native
|
5
|
+
BigEndian = Big = Network = :BigEndian
|
6
|
+
LittleEndian = Little = :LittleEndian
|
7
|
+
|
8
|
+
# examines the byte order of the underlying machine
|
9
|
+
if [0x12345678].pack("L") == "\x12\x34\x56\x78"
|
10
|
+
def byte_order
|
11
|
+
BigEndian
|
12
|
+
end
|
13
|
+
|
14
|
+
def little_endian?
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
def big_endian?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
else
|
22
|
+
def byte_order
|
23
|
+
LittleEndian
|
24
|
+
end
|
25
|
+
|
26
|
+
def little_endian?
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def big_endian?
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
alias byteorder byte_order
|
36
|
+
alias little? little_endian?
|
37
|
+
alias big? big_endian?
|
38
|
+
alias network? big_endian?
|
39
|
+
|
40
|
+
module_function :byte_order, :byteorder
|
41
|
+
module_function :little_endian?, :little?
|
42
|
+
module_function :big_endian?, :big?, :network?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/postgres.rb
ADDED
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: postgres-pr-opt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 6
|
9
|
+
- 9
|
10
|
+
version: 0.6.9
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Michael Neumann
|
14
|
+
- Jeremy Evans
|
15
|
+
- Alexander E. Fischer
|
16
|
+
- Aaron Hamid
|
17
|
+
- Rahim Packir Saibo
|
18
|
+
- Lars Christensen
|
19
|
+
- Kashif Rasul
|
20
|
+
- Sokolov Yura aka funny_falcon
|
21
|
+
autorequire:
|
22
|
+
bindir: bin
|
23
|
+
cert_chain: []
|
24
|
+
|
25
|
+
date: 2011-11-25 00:00:00 +04:00
|
26
|
+
default_executable:
|
27
|
+
dependencies: []
|
28
|
+
|
29
|
+
description:
|
30
|
+
email:
|
31
|
+
- mneumann@ntecs.de
|
32
|
+
- code@jeremyevans.net
|
33
|
+
- aef@raxys.net
|
34
|
+
- larsch@belunktum.dk
|
35
|
+
- kashif@nomad-labs.com
|
36
|
+
- funny.falcon@gmail.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions:
|
40
|
+
- ext/postgres-pr/utils/extconf.rb
|
41
|
+
extra_rdoc_files: []
|
42
|
+
|
43
|
+
files:
|
44
|
+
- README
|
45
|
+
- Rakefile
|
46
|
+
- lib/postgres-pr/version.rb
|
47
|
+
- lib/postgres-pr/pg-compat.rb
|
48
|
+
- lib/postgres-pr/postgres-compat.rb
|
49
|
+
- lib/postgres-pr/typeconv/TC_conv.rb
|
50
|
+
- lib/postgres-pr/typeconv/array.rb
|
51
|
+
- lib/postgres-pr/typeconv/conv.rb
|
52
|
+
- lib/postgres-pr/typeconv/bytea.rb
|
53
|
+
- lib/postgres-pr/utils/buffer.rb
|
54
|
+
- lib/postgres-pr/utils/byteorder.rb
|
55
|
+
- lib/postgres-pr/connection.rb
|
56
|
+
- lib/postgres-pr/message.rb
|
57
|
+
- lib/pg.rb
|
58
|
+
- lib/postgres.rb
|
59
|
+
- examples/test_connection.rb
|
60
|
+
- examples/server.rb
|
61
|
+
- examples/client.rb
|
62
|
+
- examples/og/test.rb
|
63
|
+
- ext/postgres-pr/utils/extconf.rb
|
64
|
+
- ext/postgres-pr/utils/string_unpack_single.c
|
65
|
+
has_rdoc: true
|
66
|
+
homepage: https://github.com/funny-falcon/postgres-pr
|
67
|
+
licenses:
|
68
|
+
- Ruby
|
69
|
+
- GPL
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
- ext
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
version: "0"
|
94
|
+
requirements: []
|
95
|
+
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 1.6.2
|
98
|
+
signing_key:
|
99
|
+
specification_version: 3
|
100
|
+
summary: A pure Ruby interface to the PostgreSQL (>= 7.4) database.
|
101
|
+
test_files: []
|
102
|
+
|