postgres-pr-encoding 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,174 @@
1
+ # This is a compatibility layer for using the pure Ruby postgres-pr instead of
2
+ # the C interface of postgres.
3
+
4
+ require 'rexml/syncenumerator'
5
+ require 'postgres-pr/connection'
6
+
7
+ class PGconn
8
+ PQTRANS_IDLE = 0 #(connection idle)
9
+ PQTRANS_INTRANS = 2 #(idle, within transaction block)
10
+ PQTRANS_INERROR = 3 #(idle, within failed transaction)
11
+ PQTRANS_UNKNOWN = 4 #(cannot determine status)
12
+
13
+ class << self
14
+ alias connect new
15
+ end
16
+
17
+ def initialize(host, port, options, tty, database, user, auth)
18
+ uri =
19
+ if host.nil?
20
+ nil
21
+ elsif host[0] != ?/
22
+ "tcp://#{ host }:#{ port }"
23
+ else
24
+ "unix:#{ host }/.s.PGSQL.#{ port }"
25
+ end
26
+ @host = host
27
+ @db = database
28
+ @user = user
29
+ @conn = PostgresPR::Connection.new(database, user, auth, uri)
30
+ end
31
+
32
+ def close
33
+ @conn.close
34
+ end
35
+
36
+ attr_reader :host, :db, :user
37
+
38
+ def query(sql)
39
+ PGresult.new(@conn.query(sql))
40
+ end
41
+
42
+ alias exec query
43
+
44
+ def transaction_status
45
+ @conn.transaction_status
46
+ end
47
+
48
+ def self.escape(str)
49
+ str.gsub("'","''").gsub("\\", "\\\\\\\\")
50
+ end
51
+
52
+ def escape(str)
53
+ self.class.escape(str)
54
+ end
55
+
56
+ def notice_processor
57
+ @conn.notice_processor
58
+ end
59
+
60
+ def notice_processor=(np)
61
+ @conn.notice_processor = np
62
+ end
63
+
64
+ def self.quote_ident(name)
65
+ %("#{name}")
66
+ end
67
+
68
+ end
69
+
70
+ class PGresult
71
+ include Enumerable
72
+
73
+ EMPTY_QUERY = 0
74
+ COMMAND_OK = 1
75
+ TUPLES_OK = 2
76
+ COPY_OUT = 3
77
+ COPY_IN = 4
78
+ BAD_RESPONSE = 5
79
+ NONFATAL_ERROR = 6
80
+ FATAL_ERROR = 7
81
+
82
+ def each(&block)
83
+ @result.each(&block)
84
+ end
85
+
86
+ def [](index)
87
+ @result[index]
88
+ end
89
+
90
+ def initialize(res)
91
+ @res = res
92
+ @fields = @res.fields.map {|f| f.name}
93
+ @result = []
94
+ @res.rows.each do |row|
95
+ @result << REXML::SyncEnumerator.new(fields, row).map {|name, value| [name, value]}
96
+ end
97
+ end
98
+
99
+ # TODO: status, getlength, cmdstatus
100
+
101
+ attr_reader :result, :fields
102
+
103
+ def num_tuples
104
+ @result.size
105
+ end
106
+
107
+ alias :ntuples :num_tuples
108
+
109
+ def num_fields
110
+ @fields.size
111
+ end
112
+
113
+ alias :nfields :num_fields
114
+
115
+ def fieldname(index)
116
+ @fields[index]
117
+ end
118
+
119
+ def fieldnum(name)
120
+ @fields.index(name)
121
+ end
122
+
123
+ def type(index)
124
+ # TODO: correct?
125
+ @res.fields[index].type_oid
126
+ end
127
+
128
+ alias :ftype :type
129
+
130
+ def size(index)
131
+ raise
132
+ # TODO: correct?
133
+ @res.fields[index].typlen
134
+ end
135
+
136
+ def getvalue(tup_num, field_num)
137
+ @result[tup_num][field_num]
138
+ end
139
+
140
+ def status
141
+ if num_tuples > 0
142
+ TUPLES_OK
143
+ else
144
+ COMMAND_OK
145
+ end
146
+ end
147
+
148
+ def cmdstatus
149
+ @res.cmd_tag || ''
150
+ end
151
+
152
+ # free the result set
153
+ def clear
154
+ @res = @fields = @result = nil
155
+ end
156
+
157
+ # Returns the number of rows affected by the SQL command
158
+ def cmdtuples
159
+ case @res.cmd_tag
160
+ when nil
161
+ return nil
162
+ when /^INSERT\s+(\d+)\s+(\d+)$/, /^(DELETE|UPDATE|MOVE|FETCH)\s+(\d+)$/
163
+ $2.to_i
164
+ else
165
+ nil
166
+ end
167
+ end
168
+
169
+ alias :cmd_tuples :cmdtuples
170
+
171
+ end
172
+
173
+ class PGError < Exception
174
+ end
@@ -0,0 +1,170 @@
1
+ # This is a compatibility layer for using the pure Ruby postgres-pr instead of
2
+ # the C interface of postgres.
3
+
4
+ require 'postgres-pr/connection'
5
+
6
+ class PGconn
7
+ PQTRANS_IDLE = 0 #(connection idle)
8
+ PQTRANS_INTRANS = 2 #(idle, within transaction block)
9
+ PQTRANS_INERROR = 3 #(idle, within failed transaction)
10
+ PQTRANS_UNKNOWN = 4 #(cannot determine status)
11
+
12
+ class << self
13
+ alias connect new
14
+ end
15
+
16
+ def initialize(host, port, options, tty, database, user, auth)
17
+ uri =
18
+ if host.nil?
19
+ nil
20
+ elsif host[0] != ?/
21
+ "tcp://#{ host }:#{ port }"
22
+ else
23
+ "unix:#{ host }/.s.PGSQL.#{ port }"
24
+ end
25
+ @host = host
26
+ @db = database
27
+ @user = user
28
+ @conn = PostgresPR::Connection.new(database, user, auth, uri)
29
+ end
30
+
31
+ def close
32
+ @conn.close
33
+ end
34
+
35
+ attr_reader :host, :db, :user
36
+
37
+ def query(sql)
38
+ PGresult.new(@conn.query(sql))
39
+ end
40
+
41
+ alias exec query
42
+
43
+ def transaction_status
44
+ @conn.transaction_status
45
+ end
46
+
47
+ def self.escape(str)
48
+ str.gsub("'","''").gsub("\\", "\\\\\\\\")
49
+ end
50
+
51
+ def escape(str)
52
+ self.class.escape(str)
53
+ end
54
+
55
+ def notice_processor
56
+ @conn.notice_processor
57
+ end
58
+
59
+ def notice_processor=(np)
60
+ @conn.notice_processor = np
61
+ end
62
+
63
+ def self.quote_ident(name)
64
+ %("#{name}")
65
+ end
66
+
67
+ end
68
+
69
+ class PGresult
70
+ include Enumerable
71
+
72
+ EMPTY_QUERY = 0
73
+ COMMAND_OK = 1
74
+ TUPLES_OK = 2
75
+ COPY_OUT = 3
76
+ COPY_IN = 4
77
+ BAD_RESPONSE = 5
78
+ NONFATAL_ERROR = 6
79
+ FATAL_ERROR = 7
80
+
81
+ def each(&block)
82
+ @result.each(&block)
83
+ end
84
+
85
+ def [](index)
86
+ @result[index]
87
+ end
88
+
89
+ def initialize(res)
90
+ @res = res
91
+ @fields = @res.fields.map {|f| f.name}
92
+ @result = @res.rows
93
+ end
94
+
95
+ # TODO: status, getlength, cmdstatus
96
+
97
+ attr_reader :result, :fields
98
+
99
+ def num_tuples
100
+ @result.size
101
+ end
102
+
103
+ alias :ntuples :num_tuples
104
+
105
+ def num_fields
106
+ @fields.size
107
+ end
108
+
109
+ alias :nfields :num_fields
110
+
111
+ def fieldname(index)
112
+ @fields[index]
113
+ end
114
+
115
+ def fieldnum(name)
116
+ @fields.index(name)
117
+ end
118
+
119
+ def type(index)
120
+ # TODO: correct?
121
+ @res.fields[index].type_oid
122
+ end
123
+
124
+ alias :ftype :type
125
+
126
+ def size(index)
127
+ raise
128
+ # TODO: correct?
129
+ @res.fields[index].typlen
130
+ end
131
+
132
+ def getvalue(tup_num, field_num)
133
+ @result[tup_num][field_num]
134
+ end
135
+
136
+ def status
137
+ if num_tuples > 0
138
+ TUPLES_OK
139
+ else
140
+ COMMAND_OK
141
+ end
142
+ end
143
+
144
+ def cmdstatus
145
+ @res.cmd_tag || ''
146
+ end
147
+
148
+ # free the result set
149
+ def clear
150
+ @res = @fields = @result = nil
151
+ end
152
+
153
+ # Returns the number of rows affected by the SQL command
154
+ def cmdtuples
155
+ case @res.cmd_tag
156
+ when nil
157
+ return nil
158
+ when /^INSERT\s+(\d+)\s+(\d+)$/, /^(DELETE|UPDATE|MOVE|FETCH)\s+(\d+)$/
159
+ $2.to_i
160
+ else
161
+ nil
162
+ end
163
+ end
164
+
165
+ alias :cmd_tuples :cmdtuples
166
+
167
+ end
168
+
169
+ class PGError < Exception
170
+ end
@@ -0,0 +1,18 @@
1
+ require 'test/unit'
2
+ require 'conv'
3
+ require 'array'
4
+ require 'bytea'
5
+
6
+ class TC_Conversion < Test::Unit::TestCase
7
+ def test_decode_array
8
+ assert_equal ["abcdef ", "hallo", ["1", "2"]], decode_array("{ abcdef , hallo, { 1, 2} }")
9
+ assert_equal [""], decode_array("{ }") # TODO: Correct?
10
+ assert_equal [], decode_array("{}")
11
+ assert_equal ["hallo", ""], decode_array("{hallo,}")
12
+ end
13
+
14
+ def test_bytea
15
+ end
16
+
17
+ include Postgres::Conversion
18
+ end
@@ -0,0 +1,46 @@
1
+ require 'strscan'
2
+
3
+ module Postgres::Conversion
4
+
5
+ def decode_array(str, delim=',', &conv_proc)
6
+ delim = Regexp.escape(delim)
7
+ buf = StringScanner.new(str)
8
+ return parse_arr(buf, delim, &conv_proc)
9
+ ensure
10
+ raise ConversionError, "end of string expected (#{buf.rest})" unless buf.empty?
11
+ end
12
+
13
+ private
14
+
15
+ def parse_arr(buf, delim, &conv_proc)
16
+ # skip whitespace
17
+ buf.skip(/\s*/)
18
+
19
+ raise ConversionError, "'{' expected" unless buf.get_byte == '{'
20
+
21
+ elems = []
22
+ unless buf.scan(/\}/) # array is not empty
23
+ loop do
24
+ # skip whitespace
25
+ buf.skip(/\s+/)
26
+
27
+ elems <<
28
+ if buf.check(/\{/)
29
+ parse_arr(buf, delim, &conv_proc)
30
+ else
31
+ e = buf.scan(/("((\\.)|[^"])*"|\\.|[^\}#{ delim }])*/) || raise(ConversionError)
32
+ if conv_proc then conv_proc.call(e) else e end
33
+ end
34
+
35
+ break if buf.scan(/\}/)
36
+ break unless buf.scan(/#{ delim }/)
37
+ end
38
+ end
39
+
40
+ # skip whitespace
41
+ buf.skip(/\s*/)
42
+
43
+ elems
44
+ end
45
+
46
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: US-ASCII
2
+
3
+ module Postgres::Conversion
4
+
5
+ #
6
+ # Encodes a string as bytea value.
7
+ #
8
+ # for encoding rules see:
9
+ # http://www.postgresql.org/docs/7.4/static/datatype-binary.html
10
+ #
11
+
12
+ def encode_bytea(str)
13
+ str.gsub(/[\000-\037\047\134\177-\377]/) {|b| "\\#{ b[0].to_s(8).rjust(3, '0') }" }
14
+ end
15
+
16
+ #
17
+ # Decodes a bytea encoded string.
18
+ #
19
+ # for decoding rules see:
20
+ # http://www.postgresql.org/docs/7.4/static/datatype-binary.html
21
+ #
22
+ def decode_bytea(str)
23
+ str.gsub(/\\(\\|'|[0-3][0-7][0-7])/) {|s|
24
+ if s.size == 2 then s[1,1] else s[1,3].oct.chr end
25
+ }
26
+ end
27
+
28
+ end
@@ -0,0 +1,5 @@
1
+ module Postgres
2
+ module Conversion
3
+ class ConversionError < Exception; end
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module PostgresPR
2
+ Version = "0.7.0"
3
+ end