Class: Qreport::Connection
- Inherits:
-
Object
- Object
- Qreport::Connection
show all
- Defined in:
- lib/qreport/connection.rb
Defined Under Namespace
Modules: TypeName
Classes: Query, SQL
Constant Summary
collapse
- NULL =
'NULL'.freeze
- QUOTE =
"'".freeze
- T_ =
"'t'::boolean".freeze
- F_ =
"'f'::boolean".freeze
- T =
't'.freeze
- IDENTITY =
lambda { | val, type | val }
- @@require_pg =
true
Class Attribute Summary collapse
Instance Attribute Summary collapse
Instance Method Summary
collapse
Constructor Details
#initialize(args = nil) ⇒ Connection
Returns a new instance of Connection.
17
18
19
20
21
22
23
|
# File 'lib/qreport/connection.rb', line 17
def initialize args = nil
@arguments = args
initialize_copy nil
if conn = @arguments && @arguments.delete(:conn)
self.conn = conn
end
end
|
Class Attribute Details
.current ⇒ Object
Returns the value of attribute current.
14
15
16
|
# File 'lib/qreport/connection.rb', line 14
def current
@current
end
|
Instance Attribute Details
#arguments ⇒ Object
Returns the value of attribute arguments.
7
8
9
|
# File 'lib/qreport/connection.rb', line 7
def arguments
@arguments
end
|
#conn ⇒ Object
Returns the PG connection object. Create a new connection from #arguments. New connection will be closed by #close.
49
50
51
|
# File 'lib/qreport/connection.rb', line 49
def conn
@conn
end
|
#conn_owned ⇒ Object
Returns the value of attribute conn_owned.
10
11
12
|
# File 'lib/qreport/connection.rb', line 10
def conn_owned
@conn_owned
end
|
#env ⇒ Object
Returns the value of attribute env.
7
8
9
|
# File 'lib/qreport/connection.rb', line 7
def env
@env
end
|
#schemaname ⇒ Object
Returns the value of attribute schemaname.
9
10
11
|
# File 'lib/qreport/connection.rb', line 9
def schemaname
@schemaname
end
|
#unescape_value_funcs ⇒ Object
Returns the value of attribute unescape_value_funcs.
11
12
13
|
# File 'lib/qreport/connection.rb', line 11
def unescape_value_funcs
@unescape_value_funcs
end
|
#verbose ⇒ Object
Returns the value of attribute verbose.
8
9
10
|
# File 'lib/qreport/connection.rb', line 8
def verbose
@verbose
end
|
#verbose_result ⇒ Object
Returns the value of attribute verbose_result.
8
9
10
|
# File 'lib/qreport/connection.rb', line 8
def verbose_result
@verbose_result
end
|
#verbose_stream ⇒ Object
Returns the value of attribute verbose_stream.
8
9
10
|
# File 'lib/qreport/connection.rb', line 8
def verbose_stream
@verbose_stream
end
|
Instance Method Details
#_transaction_abort ⇒ Object
137
138
139
|
# File 'lib/qreport/connection.rb', line 137
def _transaction_abort
run "ABORT"; self
end
|
#_transaction_begin ⇒ Object
129
130
131
|
# File 'lib/qreport/connection.rb', line 129
def _transaction_begin
run "BEGIN"; self
end
|
#_transaction_commit ⇒ Object
133
134
135
|
# File 'lib/qreport/connection.rb', line 133
def _transaction_commit
run "COMMIT"; self
end
|
#_type_name(args) ⇒ Object
264
265
266
267
268
269
270
271
272
|
# File 'lib/qreport/connection.rb', line 264
def _type_name args
x = conn.exec("SELECT pg_catalog.format_type($1,$2)", args).
getvalue(0, 0).to_s.dup
x.extend(TypeName)
x.pg_ftype, x.pg_fmod = args
x.freeze
x
end
|
#close ⇒ Object
75
76
77
78
79
80
81
82
83
84
85
86
|
# File 'lib/qreport/connection.rb', line 75
def close
raise Error, "close during transaction" if in_transaction?
if @conn
conn = @conn
@conn = nil
conn.close if @conn_owned
end
ensure
@invalid = false
@transaction_nesting = 0
@conn_owned = false
end
|
#dump_result!(result, stream = nil) ⇒ Object
248
249
250
251
|
# File 'lib/qreport/connection.rb', line 248
def dump_result! result, stream = nil
PP.pp(result, stream || verbose_stream) if result
result
end
|
#escape_identifier(name) ⇒ Object
180
181
182
|
# File 'lib/qreport/connection.rb', line 180
def escape_identifier name
conn.escape_identifier name.to_s
end
|
#escape_value(val) ⇒ Object
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
# File 'lib/qreport/connection.rb', line 184
def escape_value val
case val
when SQL
val.to_s
when nil
NULL
when true
T_
when false
F_
when Integer, Float
val
when String, Symbol
"'" << conn.escape_string(val.to_s) << QUOTE
when Time
escape_value(val.iso8601(6)) << "::timestamp"
when Range
"BETWEEN #{escape_value(val.first)} AND #{escape_value(val.last)}"
when Hash, Array
escape_value(val.to_json)
else
raise TypeError, "cannot escape_value on #{val.class.name}"
end.to_s
end
|
#fd ⇒ Object
71
72
73
|
# File 'lib/qreport/connection.rb', line 71
def fd
@conn && @conn.socket
end
|
#in_transaction? ⇒ Boolean
88
|
# File 'lib/qreport/connection.rb', line 88
def in_transaction?; @transaction_nesting > 0; end
|
#initialize_copy(src) ⇒ Object
25
26
27
28
29
30
|
# File 'lib/qreport/connection.rb', line 25
def initialize_copy src
@conn = @conn_owned = nil
@abort_transaction = @invalid = nil
@unescape_value_funcs_cache = nil
@transaction_nesting = 0
end
|
#run(sql, options = nil) ⇒ Object
options:
:arguments => { :key => value, ... }
:limit => size
:limit => [ size, offset ]
157
158
159
160
161
162
163
164
165
166
167
|
# File 'lib/qreport/connection.rb', line 157
def run sql, options = nil
options ||= { }
conn = options[:connection] || self.conn
result = Query.new
result.sql = sql
result.options = options
result.conn = self
result.run!
dump_result! result if @verbose_result || options[:verbose_result]
result
end
|
#run_query!(sql, query, options = nil) ⇒ Object
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
|
# File 'lib/qreport/connection.rb', line 288
def run_query! sql, query, options = nil
options ||= EMPTY_Hash
result = nil
begin
result = conn.async_exec(sql)
rescue ::PG::Error => exc
query.error = exc.inspect
raise exc unless options[:capture_error]
rescue ::StandardError => exc
@invalid = true
query.error = exc.inspect
raise exc unless options[:capture_error]
end
result
end
|
#safe_sql(x) ⇒ Object
176
177
178
|
# File 'lib/qreport/connection.rb', line 176
def safe_sql x
SQL.new(x)
end
|
#table_exists?(name, schemaname = nil) ⇒ Boolean
141
142
143
144
145
146
147
148
149
150
151
|
# File 'lib/qreport/connection.rb', line 141
def table_exists? name, schemaname = nil
schema_name = name.split('.', 2)
schema = schema_name.shift if schema_name.size > 1
name = schema_name.first
schema ||= schemaname || self.schemaname || 'public'
result =
run "SELECT EXISTS(SELECT * FROM pg_catalog.pg_tables WHERE tablename = :tablename AND schemaname = :schemaname) as \"exists\"",
:arguments => { :tablename => name, :schemaname => schema }
result.rows[0]["exists"]
end
|
#transaction ⇒ Object
90
91
92
93
94
95
96
97
98
99
100
101
102
|
# File 'lib/qreport/connection.rb', line 90
def transaction
raise Error, "no block" unless block_given?
abort = false
begin
transaction_begin
yield
rescue ::StandardError => exc
abort = @abort_transaction = exc
raise exc
ensure
transaction_end abort
end
end
|
#transaction_begin ⇒ Object
104
105
106
107
108
109
110
|
# File 'lib/qreport/connection.rb', line 104
def transaction_begin
if @transaction_nesting == 0
_transaction_begin
end
@transaction_nesting += 1
self
end
|
#transaction_end(abort = nil) ⇒ Object
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
# File 'lib/qreport/connection.rb', line 112
def transaction_end abort = nil
if (@transaction_nesting -= 1) == 0
begin
if abort
_transaction_abort
else
_transaction_commit
end
ensure
if @invalid
close
end
end
end
self
end
|
#type_name(*args) ⇒ Object
Returns a frozen String representing a column type. The String also responds to #pg_ftype and #pg_fmod.
255
256
257
258
|
# File 'lib/qreport/connection.rb', line 255
def type_name *args
(@type_names ||= { })[args] ||=
_type_name(args)
end
|
#unescape_value(val, type) ⇒ Object
214
215
216
217
218
219
220
221
222
223
|
# File 'lib/qreport/connection.rb', line 214
def unescape_value val, type
case val
when nil
when String
return nil if val == NULL
func = (@unescape_value_funcs_cache ||= { })[type] ||= unescape_value_func(type)
val = func.call(val, type)
end
val
end
|
#unescape_value_func(type) ⇒ Object
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
|
# File 'lib/qreport/connection.rb', line 225
def unescape_value_func type
if @unescape_value_funcs and func = @unescape_value_funcs[type]
return func
end
case type
when /^bool/
lambda { | val, type | val == T }
when /^(int|smallint|bigint|oid|tid|xid|cid)/
lambda { | val, type | val.to_i }
when /^(float|real|double|numeric)/
lambda { | val, type | val.to_f }
when /^timestamp/
lambda { | val, type | Time.parse(val) }
else
IDENTITY
end
end
|
#with_limit(sql, limit = nil) ⇒ Object
274
275
276
277
278
279
280
281
282
283
284
285
286
|
# File 'lib/qreport/connection.rb', line 274
def with_limit sql, limit = nil
sql = sql.dup
case limit
when Integer
limit = "LIMIT #{limit}"
when Array
limit = "OFFSET #{limit[1].to_i}\nLIMIT #{limit[0].to_i}"
end
unless sql.sub!(/:LIMIT\b|\bLIMIT\s+\S+\s*|\Z/im, "\n#{limit}")
sql << "\n" << limit
end
sql
end
|