momomoto 0.1.12 → 0.1.13
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/lib/momomoto/base.rb +5 -3
- data/lib/momomoto/procedure.rb +4 -1
- data/lib/momomoto/table.rb +83 -75
- data/lib/timeinterval.rb +9 -1
- data/sql/procedures.sql +39 -11
- data/test/test_base.rb +8 -5
- data/test/test_functions.sql +35 -2
- data/test/test_procedure.rb +61 -0
- metadata +2 -2
data/lib/momomoto/base.rb
CHANGED
@@ -90,14 +90,16 @@ module Momomoto
|
|
90
90
|
case conditions
|
91
91
|
when Array then
|
92
92
|
conditions.each do | value |
|
93
|
-
|
93
|
+
expr = compile_expression( value, operator )
|
94
|
+
where << expr if expr.length > 0
|
94
95
|
end
|
95
96
|
when Hash then
|
96
97
|
conditions.each do | key , value |
|
97
98
|
key = key.to_sym if key.kind_of?( String )
|
98
99
|
case key
|
99
|
-
when :OR then
|
100
|
-
|
100
|
+
when :OR,:AND then
|
101
|
+
expr = compile_expression( value, key.to_s )
|
102
|
+
where << "(#{expr})" if expr.length > 0
|
101
103
|
else
|
102
104
|
raise CriticalError, "condition key '#{key}' not a column in table '#{table_name}'" unless columns.keys.member?( key )
|
103
105
|
where << columns[key].compile_rule( key, value )
|
data/lib/momomoto/procedure.rb
CHANGED
@@ -55,18 +55,21 @@ module Momomoto
|
|
55
55
|
end
|
56
56
|
|
57
57
|
# get the parameters this procedure accepts
|
58
|
+
# returns an array of hashes with the fieldnames as key and the datatype as value
|
58
59
|
def parameters( *p )
|
59
60
|
return self.send( :parameters=, *p ) if not p.empty?
|
60
61
|
initialize_procedure if not instance_variable_defined?( :@parameters )
|
61
62
|
@parameters
|
62
63
|
end
|
63
64
|
|
64
|
-
#
|
65
|
+
# set the columns of the resultset this procedure returns
|
66
|
+
# expects a hash with the fieldnames as key and the datatype as value
|
65
67
|
def columns=( columns )
|
66
68
|
@columns = columns
|
67
69
|
end
|
68
70
|
|
69
71
|
# get the columns of the resultset this procedure returns
|
72
|
+
# returns a hash with the fieldnames as key and the datatype as value
|
70
73
|
def columns( c = nil )
|
71
74
|
return self.columns=( c ) if c
|
72
75
|
initialize_procedure if not instance_variable_defined?( :@columns )
|
data/lib/momomoto/table.rb
CHANGED
@@ -32,34 +32,6 @@ module Momomoto
|
|
32
32
|
@columns
|
33
33
|
end
|
34
34
|
|
35
|
-
def initialize_table # :nodoc:
|
36
|
-
|
37
|
-
@table_name ||= construct_table_name( self.name )
|
38
|
-
@schema_name ||= construct_schema_name( self.name )
|
39
|
-
|
40
|
-
@columns ||= database.fetch_table_columns( table_name(), schema_name() )
|
41
|
-
raise CriticalError, "No fields in table #{table_name}" if columns.keys.empty?
|
42
|
-
|
43
|
-
@primary_keys ||= database.fetch_primary_keys( table_name(), schema_name() )
|
44
|
-
@column_order = @columns.keys
|
45
|
-
@default_order ||= nil
|
46
|
-
|
47
|
-
@logical_operator ||= "AND"
|
48
|
-
|
49
|
-
const_set( :Row, Class.new( Momomoto::Row ) ) if not const_defined?( :Row )
|
50
|
-
initialize_row( const_get( :Row ), self )
|
51
|
-
@row_cache = {}
|
52
|
-
|
53
|
-
# mark class as initialized
|
54
|
-
self.initialized = true
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
# guesses the table name of the table this class works on
|
59
|
-
def construct_table_name( classname ) # :nodoc:
|
60
|
-
classname.split('::').last.downcase.gsub(/[^a-z_0-9]/, '')
|
61
|
-
end
|
62
|
-
|
63
35
|
# set the table_name of the table this class operates on
|
64
36
|
def table_name=( table_name )
|
65
37
|
@table_name = table_name
|
@@ -77,7 +49,7 @@ module Momomoto
|
|
77
49
|
end
|
78
50
|
|
79
51
|
# set the primary key fields of the table
|
80
|
-
def primary_keys=( keys )
|
52
|
+
def primary_keys=( keys )
|
81
53
|
@primary_keys = keys
|
82
54
|
end
|
83
55
|
|
@@ -90,23 +62,6 @@ module Momomoto
|
|
90
62
|
@primary_keys
|
91
63
|
end
|
92
64
|
|
93
|
-
# compile the select clause
|
94
|
-
def compile_select( conditions, options ) # :nodoc:
|
95
|
-
if options[:columns]
|
96
|
-
cols = {}
|
97
|
-
options[:columns].each do | name | cols[name] = columns[name] end
|
98
|
-
else
|
99
|
-
cols = columns
|
100
|
-
end
|
101
|
-
sql = "SELECT " + cols.keys.map{ | field | '"' + field.to_s + '"' }.join( "," ) + " FROM "
|
102
|
-
sql += full_name
|
103
|
-
sql += compile_where( conditions )
|
104
|
-
sql += compile_order( options[:order] ) if options[:order] || default_order
|
105
|
-
sql += compile_limit( options[:limit] ) if options[:limit]
|
106
|
-
sql += compile_offset( options[:offset] ) if options[:offset]
|
107
|
-
sql
|
108
|
-
end
|
109
|
-
|
110
65
|
# Searches for records and returns an array containing the records
|
111
66
|
def select( conditions = {}, options = {} )
|
112
67
|
initialize_table unless initialized
|
@@ -119,25 +74,6 @@ module Momomoto
|
|
119
74
|
data
|
120
75
|
end
|
121
76
|
|
122
|
-
def build_row_class( options )
|
123
|
-
if options[:columns]
|
124
|
-
options[:columns] += primary_keys
|
125
|
-
options[:columns].uniq!
|
126
|
-
if not @row_cache[options[:columns]]
|
127
|
-
row_class = Class.new( Momomoto::Row )
|
128
|
-
cols = {}
|
129
|
-
columns.each do | key, value |
|
130
|
-
cols[key] = value if options[:columns].member?( key )
|
131
|
-
end
|
132
|
-
initialize_row( row_class, self, cols )
|
133
|
-
@row_cache[options[:columns]] = row_class
|
134
|
-
end
|
135
|
-
return @row_cache[options[:columns]]
|
136
|
-
else
|
137
|
-
return const_get(:Row)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
77
|
# Searches for records and returns an array containing the records
|
142
78
|
def select_outer_join( conditions = {}, options = {} )
|
143
79
|
initialize_table unless initialized
|
@@ -169,11 +105,6 @@ module Momomoto
|
|
169
105
|
result
|
170
106
|
end
|
171
107
|
|
172
|
-
# returns the columns to be used for joining
|
173
|
-
def join_columns( join_table ) # :nodoc:
|
174
|
-
join_table.primary_keys.select{|f| columns.key?(f)}
|
175
|
-
end
|
176
|
-
|
177
108
|
# constructor for a record in this table accepts a hash with presets for the fields of the record
|
178
109
|
def new( fields = {} )
|
179
110
|
initialize_table unless initialized
|
@@ -225,8 +156,9 @@ module Momomoto
|
|
225
156
|
end
|
226
157
|
end
|
227
158
|
|
228
|
-
# Select a single row from the database
|
229
|
-
#
|
159
|
+
# Select a single row from the database
|
160
|
+
# raises Momomoto::Nothing_found if nothing was found, raises
|
161
|
+
# Momomoto::Too_many_records if more than one record was found.
|
230
162
|
def select_single( conditions = {}, options = {} )
|
231
163
|
data = select( conditions, options )
|
232
164
|
case data.length
|
@@ -237,6 +169,7 @@ module Momomoto
|
|
237
169
|
end
|
238
170
|
|
239
171
|
# write row back to database
|
172
|
+
# this function is called by Momomoto::Row#write
|
240
173
|
def write( row ) # :nodoc:
|
241
174
|
if row.new_record?
|
242
175
|
insert( row )
|
@@ -249,7 +182,8 @@ module Momomoto
|
|
249
182
|
end
|
250
183
|
|
251
184
|
# create an insert statement for a row
|
252
|
-
|
185
|
+
# do not call insert directly use row.write or Table.write( row ) instead
|
186
|
+
def insert( row )
|
253
187
|
fields, values = [], []
|
254
188
|
columns.each do | field_name, datatype |
|
255
189
|
# check for set primary key fields or fetch respective default values
|
@@ -272,7 +206,8 @@ module Momomoto
|
|
272
206
|
end
|
273
207
|
|
274
208
|
# create an update statement for a row
|
275
|
-
|
209
|
+
# do not call update directly use row.write or Table.write( row ) instead
|
210
|
+
def update( row )
|
276
211
|
raise CriticalError, 'Updating is only allowed for tables with primary keys' if primary_keys.empty?
|
277
212
|
setter, conditions = [], {}
|
278
213
|
row.class.columns.each do | field_name, data_type |
|
@@ -287,7 +222,8 @@ module Momomoto
|
|
287
222
|
database.execute( sql )
|
288
223
|
end
|
289
224
|
|
290
|
-
|
225
|
+
# delete _row_ from the database
|
226
|
+
def delete( row )
|
291
227
|
raise CriticalError, 'Deleting is only allowed for tables with primary keys' if primary_keys.empty?
|
292
228
|
raise Error, "this is a new record" if row.new_record?
|
293
229
|
conditions = {}
|
@@ -300,6 +236,78 @@ module Momomoto
|
|
300
236
|
database.execute( sql )
|
301
237
|
end
|
302
238
|
|
239
|
+
protected
|
240
|
+
|
241
|
+
# guesses the table name of the table this class works on
|
242
|
+
def construct_table_name( classname )
|
243
|
+
classname.split('::').last.downcase.gsub(/[^a-z_0-9]/, '')
|
244
|
+
end
|
245
|
+
|
246
|
+
# initialie a table class
|
247
|
+
def initialize_table
|
248
|
+
|
249
|
+
@table_name ||= construct_table_name( self.name )
|
250
|
+
@schema_name ||= construct_schema_name( self.name )
|
251
|
+
|
252
|
+
@columns ||= database.fetch_table_columns( table_name(), schema_name() )
|
253
|
+
raise CriticalError, "No fields in table #{table_name}" if columns.keys.empty?
|
254
|
+
|
255
|
+
@primary_keys ||= database.fetch_primary_keys( table_name(), schema_name() )
|
256
|
+
@column_order = @columns.keys
|
257
|
+
@default_order ||= nil
|
258
|
+
|
259
|
+
@logical_operator ||= "AND"
|
260
|
+
|
261
|
+
const_set( :Row, Class.new( Momomoto::Row ) ) if not const_defined?( :Row )
|
262
|
+
initialize_row( const_get( :Row ), self )
|
263
|
+
@row_cache = {}
|
264
|
+
|
265
|
+
self.initialized = true
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
# builds the row class for this table
|
270
|
+
def build_row_class( options )
|
271
|
+
if options[:columns]
|
272
|
+
options[:columns] += primary_keys
|
273
|
+
options[:columns].uniq!
|
274
|
+
if not @row_cache[options[:columns]]
|
275
|
+
row_class = Class.new( Momomoto::Row )
|
276
|
+
cols = {}
|
277
|
+
columns.each do | key, value |
|
278
|
+
cols[key] = value if options[:columns].member?( key )
|
279
|
+
end
|
280
|
+
initialize_row( row_class, self, cols )
|
281
|
+
@row_cache[options[:columns]] = row_class
|
282
|
+
end
|
283
|
+
return @row_cache[options[:columns]]
|
284
|
+
else
|
285
|
+
return const_get(:Row)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
# compile the select clause
|
290
|
+
def compile_select( conditions, options )
|
291
|
+
if options[:columns]
|
292
|
+
cols = {}
|
293
|
+
options[:columns].each do | name | cols[name] = columns[name] end
|
294
|
+
else
|
295
|
+
cols = columns
|
296
|
+
end
|
297
|
+
sql = "SELECT " + cols.keys.map{ | field | '"' + field.to_s + '"' }.join( "," ) + " FROM "
|
298
|
+
sql += full_name
|
299
|
+
sql += compile_where( conditions )
|
300
|
+
sql += compile_order( options[:order] ) if options[:order] || default_order
|
301
|
+
sql += compile_limit( options[:limit] ) if options[:limit]
|
302
|
+
sql += compile_offset( options[:offset] ) if options[:offset]
|
303
|
+
sql
|
304
|
+
end
|
305
|
+
|
306
|
+
# returns the columns to be used for joining
|
307
|
+
def join_columns( join_table ) # :nodoc:
|
308
|
+
join_table.primary_keys.select{|f| columns.key?(f)}
|
309
|
+
end
|
310
|
+
|
303
311
|
end
|
304
312
|
|
305
313
|
end
|
data/lib/timeinterval.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
|
2
2
|
require 'date'
|
3
3
|
|
4
|
+
# the class is used in Momomoto to represent the SQL interval datatype
|
4
5
|
class TimeInterval
|
5
6
|
|
6
7
|
include Comparable
|
@@ -17,10 +18,14 @@ class TimeInterval
|
|
17
18
|
|
18
19
|
end
|
19
20
|
|
21
|
+
# compare two TimeInterval instances
|
22
|
+
# the comparison is done by calling to_i on other
|
20
23
|
def <=>( other )
|
21
24
|
self.to_i <=> other.to_i
|
22
25
|
end
|
23
26
|
|
27
|
+
# formats timeinterval according to the directives in the give format
|
28
|
+
# string
|
24
29
|
def strftime( fmt = "%H:%M:%S" )
|
25
30
|
fmt.gsub( /%(.)/ ) do | match |
|
26
31
|
case match[1,1]
|
@@ -33,14 +38,17 @@ class TimeInterval
|
|
33
38
|
end
|
34
39
|
end
|
35
40
|
|
41
|
+
# returns the value of timeinterval as number of seconds
|
36
42
|
def to_i
|
37
43
|
@hour * 3600 + @min * 60 + @sec
|
38
44
|
end
|
39
45
|
|
40
46
|
alias_method :to_int, :to_i
|
41
47
|
|
48
|
+
# Returns a string representing timeinterval. Equivalent to calling
|
49
|
+
# Time#strftime with a format string of '%H:%M:%S'.
|
42
50
|
def to_s
|
43
|
-
strftime
|
51
|
+
strftime( '%H:%M:%S' )
|
44
52
|
end
|
45
53
|
|
46
54
|
def initialize( d = {} )
|
data/sql/procedures.sql
CHANGED
@@ -4,6 +4,7 @@ DECLARE
|
|
4
4
|
proc RECORD;
|
5
5
|
typ RECORD;
|
6
6
|
att RECORD;
|
7
|
+
i INTEGER;
|
7
8
|
col momomoto.procedure_column%rowtype;
|
8
9
|
BEGIN
|
9
10
|
SELECT INTO proc * FROM pg_proc WHERE proname = procedure_name;
|
@@ -11,15 +12,42 @@ BEGIN
|
|
11
12
|
SELECT INTO typ * FROM pg_type WHERE oid = proc.prorettype;
|
12
13
|
|
13
14
|
IF typ.typtype = 'b' THEN
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
-- base type
|
16
|
+
IF proc.proallargtypes IS NULL THEN
|
17
|
+
-- we only got IN arguments
|
18
|
+
col.column_name = procedure_name;
|
19
|
+
SELECT INTO col.data_type format_type( proc.prorettype, NULL::integer );
|
20
|
+
RETURN NEXT col;
|
21
|
+
ELSE
|
22
|
+
-- we got a named out arguments
|
23
|
+
FOR i IN array_lower(proc.proallargtypes, 1) .. array_upper(proc.proallargtypes, 1)
|
24
|
+
LOOP
|
25
|
+
CONTINUE WHEN proc.proargmodes[ i ] = 'i';
|
26
|
+
IF COALESCE( proc.proargnames[ i ], '' ) = '' THEN
|
27
|
+
col.column_name = procedure_name;
|
28
|
+
ELSE
|
29
|
+
col.column_name = proc.proargnames[ i ];
|
30
|
+
END IF;
|
31
|
+
col.data_type = format_type( proc.proallargtypes[ i ], NULL );
|
32
|
+
RETURN NEXT col;
|
33
|
+
END LOOP;
|
34
|
+
END IF;
|
17
35
|
ELSIF typ.typtype = 'c' THEN
|
36
|
+
-- composite type
|
18
37
|
FOR col IN
|
19
38
|
SELECT attname AS column_name, format_type(atttypid, NULL) FROM pg_attribute WHERE attrelid = typ.typrelid AND attnum > 0 ORDER BY attnum
|
20
39
|
LOOP
|
21
40
|
RETURN NEXT col;
|
22
41
|
END LOOP;
|
42
|
+
ELSIF typ.typtype = 'p' THEN
|
43
|
+
-- pseudo type
|
44
|
+
FOR i IN array_lower(proc.proallargtypes, 1) .. array_upper(proc.proallargtypes, 1)
|
45
|
+
LOOP
|
46
|
+
CONTINUE WHEN proc.proargmodes[ i ] = 'i';
|
47
|
+
col.column_name = proc.proargnames[ i ];
|
48
|
+
col.data_type = format_type( proc.proallargtypes[ i ], NULL );
|
49
|
+
RETURN NEXT col;
|
50
|
+
END LOOP;
|
23
51
|
ELSE
|
24
52
|
RAISE EXCEPTION 'Not yet implemented';
|
25
53
|
END IF;
|
@@ -34,17 +62,17 @@ DECLARE
|
|
34
62
|
typ RECORD;
|
35
63
|
col momomoto.procedure_parameter%rowtype;
|
36
64
|
i INTEGER;
|
37
|
-
j INTEGER;
|
38
|
-
k INTEGER;
|
39
65
|
BEGIN
|
40
|
-
SELECT INTO proc proargnames,
|
66
|
+
SELECT INTO proc proargnames, proargtypes, proargmodes, proargtypes FROM pg_proc WHERE proname = procedure_name;
|
41
67
|
IF FOUND THEN
|
42
|
-
|
43
|
-
k = array_upper(proc.proargtypes, 1);
|
44
|
-
FOR i IN j .. k
|
68
|
+
FOR i IN array_lower(proc.proargtypes, 1) .. array_upper(proc.proargtypes, 1)
|
45
69
|
LOOP
|
46
|
-
|
47
|
-
|
70
|
+
IF COALESCE( proc.proargnames[ i + array_lower( proc.proargnames, 1 ) ], '' ) = '' THEN
|
71
|
+
col.parameter_name = procedure_name;
|
72
|
+
ELSE
|
73
|
+
col.parameter_name = proc.proargnames[ i + array_lower( proc.proargnames, 1 )];
|
74
|
+
END IF;
|
75
|
+
col.data_type = format_type( proc.proargtypes[ i ], NULL );
|
48
76
|
RETURN NEXT col;
|
49
77
|
END LOOP;
|
50
78
|
END IF;
|
data/test/test_base.rb
CHANGED
@@ -4,10 +4,10 @@ class TestBase < Test::Unit::TestCase
|
|
4
4
|
def test_logical_operator
|
5
5
|
t1 = Class.new( Momomoto::Table )
|
6
6
|
t1.table_name = 'person'
|
7
|
-
t1.initialize_table
|
7
|
+
t1.send( :initialize_table )
|
8
8
|
t2 = Class.new( Momomoto::Table )
|
9
9
|
t2.table_name = 'person'
|
10
|
-
t2.initialize_table
|
10
|
+
t2.send( :initialize_table )
|
11
11
|
assert_equal( "AND", t1.logical_operator )
|
12
12
|
assert_equal( "AND", t2.logical_operator )
|
13
13
|
t1.logical_operator = "OR"
|
@@ -25,7 +25,7 @@ class TestBase < Test::Unit::TestCase
|
|
25
25
|
def test_compile_where
|
26
26
|
t = Class.new( Momomoto::Table )
|
27
27
|
t.table_name = 'person'
|
28
|
-
t.initialize_table
|
28
|
+
t.send( :initialize_table )
|
29
29
|
assert_equal( " WHERE person_id = '1'" , t.instance_eval do compile_where( :person_id => '1' ) end )
|
30
30
|
assert_equal( " WHERE person_id IN ('1')" , t.instance_eval do compile_where( :person_id => ['1'] ) end )
|
31
31
|
assert_equal( " WHERE person_id IN ('1','2')" , t.instance_eval do compile_where( :person_id => ['1',2] ) end )
|
@@ -34,10 +34,13 @@ class TestBase < Test::Unit::TestCase
|
|
34
34
|
assert_equal( " WHERE first_name IN (E'chu''nky',E'bac''n')" , t.instance_eval do compile_where( :first_name => ["chu'nky","bac'n"] ) end )
|
35
35
|
assert_equal( " WHERE (person_id = '1')" , t.instance_eval do compile_where( :OR => { :person_id => '1' } ) end )
|
36
36
|
assert_equal( " WHERE (person_id = '1')" , t.instance_eval do compile_where( :AND => { :person_id => '1' } ) end )
|
37
|
-
|
38
|
-
|
37
|
+
assert( [" WHERE (person_id = '1' OR first_name = E's')"," WHERE (first_name = E's' OR person_id = '1')"].member?( t.instance_eval do compile_where( :OR => { :person_id => '1',:first_name=>'s' } ) end ) )
|
38
|
+
assert( [" WHERE (person_id = '1' AND first_name = E's')"," WHERE (first_name = E's' AND person_id = '1')"].member?( t.instance_eval do compile_where( :AND => { :person_id => '1',:first_name=>'s' } ) end ) )
|
39
39
|
assert_equal( " WHERE (person_id = '1' AND person_id = '2')" , t.instance_eval do compile_where( :AND =>[{:person_id=>1},{:person_id=>2}] ) end )
|
40
40
|
assert_equal( " WHERE (person_id = '1' OR person_id = '2')" , t.instance_eval do compile_where( :OR =>[{:person_id=>1},{:person_id=>2}] ) end )
|
41
|
+
assert_equal( "" , t.instance_eval do compile_where( :OR =>[] ) end )
|
42
|
+
assert_equal( "" , t.instance_eval do compile_where( :OR =>[{}] ) end )
|
43
|
+
assert_equal( "" , t.instance_eval do compile_where( :AND =>[{},{}] ) end )
|
41
44
|
end
|
42
45
|
|
43
46
|
end
|
data/test/test_functions.sql
CHANGED
@@ -8,14 +8,12 @@ CREATE OR REPLACE FUNCTION test_parameter_sql_strict( param1 INTEGER ) RETURNS I
|
|
8
8
|
$$ LANGUAGE sql STRICT;
|
9
9
|
|
10
10
|
CREATE OR REPLACE FUNCTION test_parameter_plpgsql( param1 INTEGER, param2 TEXT ) RETURNS INTEGER AS $$
|
11
|
-
DECLARE
|
12
11
|
BEGIN
|
13
12
|
RETURN param1;
|
14
13
|
END;
|
15
14
|
$$ LANGUAGE plpgsql;
|
16
15
|
|
17
16
|
CREATE OR REPLACE FUNCTION test_parameter_plpgsql_strict( param1 INTEGER, param2 TEXT ) RETURNS INTEGER AS $$
|
18
|
-
DECLARE
|
19
17
|
BEGIN
|
20
18
|
RETURN param1;
|
21
19
|
END;
|
@@ -34,3 +32,38 @@ CREATE OR REPLACE FUNCTION test_set_returning( person_id INTEGER ) RETURNS SETOF
|
|
34
32
|
END;
|
35
33
|
$$ LANGUAGE plpgsql;
|
36
34
|
|
35
|
+
CREATE OR REPLACE FUNCTION test_parameter_inout_sql( IN param1 INTEGER, OUT ret1 INTEGER ) AS $$
|
36
|
+
SELECT $1;
|
37
|
+
$$ LANGUAGE sql;
|
38
|
+
|
39
|
+
CREATE OR REPLACE FUNCTION test_parameter_inout_plpgsql( IN param1 INTEGER, IN param2 TEXT, OUT ret1 INTEGER ) AS $$
|
40
|
+
BEGIN
|
41
|
+
ret1 := param1;
|
42
|
+
RETURN;
|
43
|
+
END;
|
44
|
+
$$ LANGUAGE plpgsql;
|
45
|
+
|
46
|
+
CREATE OR REPLACE FUNCTION test_set_returning_inout( IN param1 INTEGER, OUT ret1 INTEGER, OUT ret2 TEXT ) RETURNS SETOF RECORD AS $$
|
47
|
+
BEGIN
|
48
|
+
ret1 := param1;
|
49
|
+
ret2 := 'chunky';
|
50
|
+
RETURN NEXT;
|
51
|
+
ret2 := 'bacon';
|
52
|
+
RETURN NEXT;
|
53
|
+
RETURN;
|
54
|
+
END;
|
55
|
+
$$ LANGUAGE plpgsql;
|
56
|
+
|
57
|
+
CREATE OR REPLACE FUNCTION test_parameter_inout_unnamed( IN INTEGER, OUT INTEGER ) AS $$
|
58
|
+
SELECT $1;
|
59
|
+
$$ LANGUAGE sql;
|
60
|
+
|
61
|
+
CREATE OR REPLACE FUNCTION test_parameter_inout_unnamed2( IN param1 INTEGER, OUT INTEGER ) AS $$
|
62
|
+
SELECT $1;
|
63
|
+
$$ LANGUAGE sql;
|
64
|
+
|
65
|
+
CREATE OR REPLACE FUNCTION test_parameter_inout_unnamed3( IN INTEGER, OUT ret1 INTEGER ) AS $$
|
66
|
+
SELECT $1;
|
67
|
+
$$ LANGUAGE sql;
|
68
|
+
|
69
|
+
|
data/test/test_procedure.rb
CHANGED
@@ -85,7 +85,68 @@ class TestProcedure < Test::Unit::TestCase
|
|
85
85
|
assert_raise( Momomoto::Error ) { b.call }
|
86
86
|
assert_raise( Momomoto::Error ) { b.call({:param1=>nil})}
|
87
87
|
assert_nothing_raised { b.call({:param1=>1})}
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_inout_sql
|
91
|
+
a = Class.new(Momomoto::Procedure)
|
92
|
+
a.procedure_name("test_parameter_inout_sql")
|
93
|
+
assert_equal( 1, a.columns.keys.length )
|
94
|
+
assert_instance_of( Momomoto::Datatype::Integer, a.columns[:ret1] )
|
95
|
+
assert_equal( 1, a.parameters.length )
|
96
|
+
assert_instance_of( Momomoto::Datatype::Integer, a.parameters.first[:param1] )
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_inout_plpgsql
|
100
|
+
a = Class.new(Momomoto::Procedure)
|
101
|
+
a.procedure_name("test_parameter_inout_plpgsql")
|
102
|
+
assert_equal( 1, a.columns.keys.length )
|
103
|
+
assert_instance_of( Momomoto::Datatype::Integer, a.columns[:ret1] )
|
104
|
+
assert_equal( 2, a.parameters.length )
|
105
|
+
assert_instance_of( Momomoto::Datatype::Integer, a.parameters[0][:param1] )
|
106
|
+
assert_instance_of( Momomoto::Datatype::Text, a.parameters[1][:param2] )
|
107
|
+
end
|
88
108
|
|
109
|
+
def test_set_returning_inout
|
110
|
+
a = Class.new(Momomoto::Procedure)
|
111
|
+
a.procedure_name("test_set_returning_inout")
|
112
|
+
assert_equal( 2, a.columns.keys.length )
|
113
|
+
assert_instance_of( Momomoto::Datatype::Integer, a.columns[:ret1] )
|
114
|
+
assert_instance_of( Momomoto::Datatype::Text, a.columns[:ret2] )
|
115
|
+
assert_equal( 1, a.parameters.length )
|
116
|
+
assert_instance_of( Momomoto::Datatype::Integer, a.parameters[0][:param1] )
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_parameter_inout_unnamed
|
120
|
+
a = Class.new(Momomoto::Procedure)
|
121
|
+
a.procedure_name("test_parameter_inout_unnamed")
|
122
|
+
assert_equal( 1, a.columns.keys.length )
|
123
|
+
assert_equal( :test_parameter_inout_unnamed, a.columns.keys.first )
|
124
|
+
assert_instance_of( Momomoto::Datatype::Integer, a.columns[:test_parameter_inout_unnamed] )
|
125
|
+
assert_equal( 1, a.parameters.length )
|
126
|
+
assert_equal( :test_parameter_inout_unnamed, a.parameters.first.keys.first )
|
127
|
+
assert_instance_of( Momomoto::Datatype::Integer, a.parameters[0][:test_parameter_inout_unnamed] )
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_parameter_inout_unnamed2
|
131
|
+
a = Class.new(Momomoto::Procedure)
|
132
|
+
a.procedure_name("test_parameter_inout_unnamed2")
|
133
|
+
assert_equal( 1, a.columns.keys.length )
|
134
|
+
assert_equal( :test_parameter_inout_unnamed2, a.columns.keys.first )
|
135
|
+
assert_instance_of( Momomoto::Datatype::Integer, a.columns[:test_parameter_inout_unnamed2] )
|
136
|
+
assert_equal( 1, a.parameters.length )
|
137
|
+
assert_equal( :param1, a.parameters.first.keys.first )
|
138
|
+
assert_instance_of( Momomoto::Datatype::Integer, a.parameters[0][:param1] )
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_parameter_inout_unnamed3
|
142
|
+
a = Class.new(Momomoto::Procedure)
|
143
|
+
a.procedure_name("test_parameter_inout_unnamed3")
|
144
|
+
assert_equal( 1, a.columns.keys.length )
|
145
|
+
assert_equal( :ret1, a.columns.keys.first )
|
146
|
+
assert_instance_of( Momomoto::Datatype::Integer, a.columns[:ret1] )
|
147
|
+
assert_equal( 1, a.parameters.length )
|
148
|
+
assert_equal( :test_parameter_inout_unnamed3, a.parameters.first.keys.first )
|
149
|
+
assert_instance_of( Momomoto::Datatype::Integer, a.parameters[0][:test_parameter_inout_unnamed3] )
|
89
150
|
end
|
90
151
|
|
91
152
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: momomoto
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
7
|
-
date: 2007-11-
|
6
|
+
version: 0.1.13
|
7
|
+
date: 2007-11-22 00:00:00 +01:00
|
8
8
|
summary: Momomoto is an object relational mapper for PostgreSQL.
|
9
9
|
require_paths:
|
10
10
|
- lib
|