momomoto 0.1.15 → 0.1.16
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/momomoto/base.rb +20 -7
- data/lib/momomoto/database.rb +20 -0
- data/lib/momomoto/datatype/array.rb +15 -68
- data/lib/momomoto/datatype/array/base.rb +96 -0
- data/lib/momomoto/datatype/array/integer.rb +27 -0
- data/lib/momomoto/datatype/array/text.rb +16 -0
- data/lib/momomoto/datatype/base.rb +3 -2
- data/lib/momomoto/datatype/bytea.rb +2 -2
- data/lib/momomoto/datatype/date.rb +2 -2
- data/lib/momomoto/datatype/inet.rb +1 -1
- data/lib/momomoto/datatype/interval.rb +5 -5
- data/lib/momomoto/datatype/real.rb +2 -2
- data/lib/momomoto/datatype/smallint.rb +1 -1
- data/lib/momomoto/datatype/text.rb +4 -4
- data/lib/momomoto/datatype/time_without_time_zone.rb +3 -3
- data/lib/momomoto/datatype/timestamp_without_time_zone.rb +2 -2
- data/lib/momomoto/procedure.rb +2 -2
- data/lib/momomoto/table.rb +14 -4
- data/test/test_array.rb +35 -2
- data/test/test_base.rb +1 -1
- data/test/test_bytea.rb +3 -4
- data/test/test_datatype.rb +8 -7
- data/test/test_procedure.rb +10 -6
- data/test/test_table.rb +27 -11
- metadata +7 -4
data/lib/momomoto/base.rb
CHANGED
@@ -83,9 +83,7 @@ module Momomoto
|
|
83
83
|
varname = "@#{name}"
|
84
84
|
# define getter method
|
85
85
|
singleton.send(:define_method, name) do | *values |
|
86
|
-
if not
|
87
|
-
initialize
|
88
|
-
end
|
86
|
+
initialize if not initialized
|
89
87
|
instance_variable_get( varname )
|
90
88
|
end
|
91
89
|
end
|
@@ -99,9 +97,7 @@ module Momomoto
|
|
99
97
|
if values[0]
|
100
98
|
send( settername, values[0] )
|
101
99
|
else
|
102
|
-
if not
|
103
|
-
initialize
|
104
|
-
end
|
100
|
+
initialize if not initialized
|
105
101
|
instance_variable_get( varname )
|
106
102
|
end
|
107
103
|
end
|
@@ -147,7 +143,24 @@ module Momomoto
|
|
147
143
|
protected
|
148
144
|
|
149
145
|
# Getter and setter used for marking tables as initialized.
|
150
|
-
|
146
|
+
attr_writer :initialized
|
147
|
+
|
148
|
+
# overwrite initialized with a normal reader once it has been initialized
|
149
|
+
# to get rid of ruby warnings about @initialized not being initialized
|
150
|
+
# this also works for ruby 1.8.5 where instance_variable_defined? is not
|
151
|
+
# available
|
152
|
+
def initialized
|
153
|
+
@initialized ||= false
|
154
|
+
instance_eval do
|
155
|
+
undef :initialized
|
156
|
+
class << self
|
157
|
+
class_eval do
|
158
|
+
attr_reader :initialized
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
@initialized
|
163
|
+
end
|
151
164
|
|
152
165
|
# Guesses the schema name of the table this class works on.
|
153
166
|
def construct_schema_name( classname )
|
data/lib/momomoto/database.rb
CHANGED
@@ -182,6 +182,26 @@ module Momomoto
|
|
182
182
|
@transaction_active = false
|
183
183
|
end
|
184
184
|
|
185
|
+
# quotes and escapes the given string +input+
|
186
|
+
def self.quote( input )
|
187
|
+
PGconn.quote( input )
|
188
|
+
end
|
189
|
+
|
190
|
+
# quotes and escapes the given string +input+
|
191
|
+
def self.quote_string( input )
|
192
|
+
"E" + PGconn.quote( input )
|
193
|
+
end
|
194
|
+
|
195
|
+
# escapes the given identifier +input+
|
196
|
+
def self.quote_ident( input )
|
197
|
+
PGconn.quote_ident( input.to_s )
|
198
|
+
end
|
199
|
+
|
200
|
+
# quotes and escapes the given string +input+
|
201
|
+
def self.quote_bytea( input )
|
202
|
+
"E'#{PGconn.escape_bytea(input)}'"
|
203
|
+
end
|
204
|
+
|
185
205
|
# escapes the given string +input+
|
186
206
|
def self.escape_string( input )
|
187
207
|
PGconn.escape( input )
|
@@ -1,76 +1,23 @@
|
|
1
|
+
|
2
|
+
require 'momomoto/datatype/array/base'
|
3
|
+
require 'momomoto/datatype/array/integer'
|
4
|
+
require 'momomoto/datatype/array/text'
|
5
|
+
|
1
6
|
module Momomoto
|
2
7
|
module Datatype
|
3
8
|
|
4
9
|
# Represents the data type Array.
|
5
|
-
class Array
|
6
|
-
|
7
|
-
#
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
if
|
12
|
-
"
|
13
|
-
elsif input.instance_of?( ::Array )
|
14
|
-
"ARRAY[" + input.map{|m| "'" + Database.escape_string(m) + "'"}.join(',') + "]"
|
15
|
-
else
|
16
|
-
"'" + Database.escape_string(m) + "'"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# Values are filtered by this function when being set. See the
|
21
|
-
# method in the appropriate derived data type class for allowed
|
22
|
-
# values.
|
23
|
-
def filter_get( value ) # :nodoc:
|
24
|
-
case value
|
25
|
-
when ::Array then value
|
26
|
-
when nil,"" then nil
|
27
|
-
when "{}" then []
|
28
|
-
when /^\{[^"]+(,[^"]+)*\}$/
|
29
|
-
m = v.match(/^\{()\}$/)
|
30
|
-
m[1].split(',')
|
31
|
-
when /^\{"[^"]+"(,"[^"]+")*\}$/
|
32
|
-
m = v.match(/^\{()\}$/)
|
33
|
-
m[1].split(',').map{|e| e.gsub(/^"(.*)"$/, "\\1")}
|
34
|
-
else
|
35
|
-
raise Error, "Error parsing array value"
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
# Values are filtered by this function when being set. See the
|
41
|
-
# method in the appropriate derived data type class for allowed
|
42
|
-
# values.
|
43
|
-
def filter_set( value ) # :nodoc:
|
44
|
-
value = [value] unless value.instance_of?( ::Array )
|
45
|
-
value
|
46
|
-
end
|
47
|
-
|
48
|
-
# Get the default value for this Datatype.
|
49
|
-
def default_operator
|
50
|
-
"@>"
|
51
|
-
end
|
52
|
-
|
53
|
-
# This method is used when compiling the where clause. No need
|
54
|
-
# for direct use.
|
55
|
-
def compile_rule( field_name, value ) # :nodoc:
|
56
|
-
case value
|
57
|
-
when ::Array then
|
58
|
-
raise Error, "empty or nil array conditions are not allowed for #{field_name}" if value.empty? or value.member?( nil )
|
59
|
-
field_name.to_s + ' @> ' + escape(filter_set(value))
|
60
|
-
else
|
61
|
-
super
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
# Additional operators for instances of Array.
|
66
|
-
# See Base#operator_sign
|
67
|
-
def self.operator_sign( op )
|
68
|
-
case op
|
69
|
-
when :contains then '@>'
|
70
|
-
when :contained then '<@'
|
71
|
-
else
|
72
|
-
super( op )
|
10
|
+
class Array
|
11
|
+
|
12
|
+
# Creates a new instance of the special data type, setting +not_null+
|
13
|
+
# and +default+ according to the values from Information Schema.
|
14
|
+
def self.new( row = nil )
|
15
|
+
subtype = nil
|
16
|
+
if row.respond_to?( :udt_name ) && row.udt_name
|
17
|
+
subtype = row.udt_name.gsub(/^_/,"")
|
73
18
|
end
|
19
|
+
subtype ||= 'text'
|
20
|
+
Momomoto::Datatype::Array.const_get(subtype.capitalize).new( row )
|
74
21
|
end
|
75
22
|
|
76
23
|
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Momomoto
|
2
|
+
module Datatype
|
3
|
+
class Array
|
4
|
+
|
5
|
+
# base datatype for array types
|
6
|
+
class Base < Momomoto::Datatype::Base
|
7
|
+
|
8
|
+
# Creates a new instance of the special data type, setting +not_null+
|
9
|
+
# and +default+ according to the values from Information Schema.
|
10
|
+
def initialize( row = nil )
|
11
|
+
@not_null = row.respond_to?(:is_nullable) && row.is_nullable == "NO" ? true : false
|
12
|
+
@default = row.respond_to?(:column_default) ? row.column_default : nil
|
13
|
+
end
|
14
|
+
|
15
|
+
# Escape and quote +input+ to be saved in database.
|
16
|
+
# Returns 'NULL' if +input+ is nil or empty. Otherwise uses
|
17
|
+
# Database#quote
|
18
|
+
def escape( input )
|
19
|
+
if input.nil?
|
20
|
+
"NULL"
|
21
|
+
elsif input.instance_of?( ::Array )
|
22
|
+
if input.empty?
|
23
|
+
"'{}'::#{array_type}[]"
|
24
|
+
else
|
25
|
+
"ARRAY[" + input.map{|m| Database.quote(m)}.join(',') + "]::#{array_type}[]"
|
26
|
+
end
|
27
|
+
else
|
28
|
+
Database.quote( input )
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Values are filtered by this function when being set. See the
|
33
|
+
# method in the appropriate derived data type class for allowed
|
34
|
+
# values.
|
35
|
+
def filter_get( value ) # :nodoc:
|
36
|
+
case value
|
37
|
+
when ::Array then value
|
38
|
+
when nil,"" then nil
|
39
|
+
when "{}" then []
|
40
|
+
when /^\{("[^"]+"|[^",]+)(,("[^"]+"|[^",]+))*\}$/
|
41
|
+
m = value.match(/^\{(.*)\}$/)
|
42
|
+
values = []
|
43
|
+
m[1].gsub( /("[^"]+"|[^",]+)/ ) do | element |
|
44
|
+
if m = element.match(/^"(.*)"$/)
|
45
|
+
values << m[1]
|
46
|
+
else
|
47
|
+
values << element
|
48
|
+
end
|
49
|
+
end
|
50
|
+
values
|
51
|
+
else
|
52
|
+
raise Error, "Error parsing array value"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Values are filtered by this function when being set. See the
|
57
|
+
# method in the appropriate derived data type class for allowed
|
58
|
+
# values.
|
59
|
+
def filter_set( value ) # :nodoc:
|
60
|
+
value = [value] if value && !value.instance_of?( ::Array )
|
61
|
+
value
|
62
|
+
end
|
63
|
+
|
64
|
+
# Get the default value for this Datatype.
|
65
|
+
def default_operator
|
66
|
+
"@>"
|
67
|
+
end
|
68
|
+
|
69
|
+
# This method is used when compiling the where clause. No need
|
70
|
+
# for direct use.
|
71
|
+
def compile_rule( field_name, value ) # :nodoc:
|
72
|
+
case value
|
73
|
+
when ::Array then
|
74
|
+
raise Error, "empty or nil array conditions are not allowed for #{field_name}" if value.empty? or value.member?( nil )
|
75
|
+
field_name.to_s + ' @> ' + escape(filter_set(value))
|
76
|
+
else
|
77
|
+
super
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Additional operators for instances of Array.
|
82
|
+
# See Base#operator_sign
|
83
|
+
def self.operator_sign( op )
|
84
|
+
case op
|
85
|
+
when :contains then '@>'
|
86
|
+
when :contained then '<@'
|
87
|
+
else
|
88
|
+
super( op )
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Momomoto
|
2
|
+
module Datatype
|
3
|
+
class Array
|
4
|
+
|
5
|
+
# datatype for text arrays
|
6
|
+
class Integer < Base
|
7
|
+
|
8
|
+
def array_type
|
9
|
+
"int"
|
10
|
+
end
|
11
|
+
|
12
|
+
def filter_get( value )
|
13
|
+
value = super( value )
|
14
|
+
if value.instance_of?( ::Array )
|
15
|
+
value = value.map{|v| Integer(v)}
|
16
|
+
end
|
17
|
+
value
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
Int4 = Integer
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -52,11 +52,11 @@ module Momomoto
|
|
52
52
|
end
|
53
53
|
|
54
54
|
# Escapes +input+ to be saved in database.
|
55
|
-
# If +input+ equals nil, NULL is returned, otherwise Database#
|
55
|
+
# If +input+ equals nil, NULL is returned, otherwise Database#quote
|
56
56
|
# is called.
|
57
57
|
# This method is overwritten to get data type-specific escaping rules.
|
58
58
|
def escape( input )
|
59
|
-
input.nil? ? "NULL" :
|
59
|
+
input.nil? ? "NULL" : Database.quote( input.to_s )
|
60
60
|
end
|
61
61
|
|
62
62
|
# This method is used when compiling the where clause. No need
|
@@ -70,6 +70,7 @@ module Momomoto
|
|
70
70
|
when :NOT_NULL then
|
71
71
|
field_name.to_s + ' IS NOT NULL'
|
72
72
|
when ::Array then
|
73
|
+
return compile_rule( field_name, value[0] ) if value.length == 1
|
73
74
|
raise Error, "empty array conditions are not allowed for #{field_name}" if value.empty?
|
74
75
|
raise Error, "nil values not allowed in compile_rule for #{field_name}" if value.member?( nil )
|
75
76
|
field_name.to_s + ' IN (' + value.map{ | v | escape(filter_set(v)) }.join(',') + ')'
|
@@ -5,10 +5,10 @@ module Momomoto
|
|
5
5
|
# This class is used for Binary Data (Byte Array).
|
6
6
|
class Bytea < Base
|
7
7
|
|
8
|
-
# Escapes +input+ using Database#
|
8
|
+
# Escapes +input+ using Database#quote_bytea or returns NULL if
|
9
9
|
# +input+ is nil.
|
10
10
|
def escape( input )
|
11
|
-
input.nil? ? "NULL" :
|
11
|
+
input.nil? ? "NULL" : Database.quote_bytea( input )
|
12
12
|
end
|
13
13
|
|
14
14
|
end
|
@@ -5,18 +5,18 @@ module Momomoto
|
|
5
5
|
class Interval < Time_without_time_zone
|
6
6
|
|
7
7
|
# Escapes +value+ before storing to database.
|
8
|
-
# +value+ can be either
|
8
|
+
# +value+ can be either
|
9
9
|
# nil, resulting in 'NULL',
|
10
|
-
# String, which is escaped using Database#
|
10
|
+
# String, which is escaped using Database#quote,
|
11
11
|
# or some Date-like format
|
12
12
|
def escape( value )
|
13
13
|
case value
|
14
14
|
when nil then 'NULL'
|
15
|
-
when String then
|
16
|
-
else
|
15
|
+
when String then Database.quote(value)
|
16
|
+
else Database.quote(value.strftime('%H:%M:%S'))
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
# Values are filtered by this method when getting them from database.
|
21
21
|
# Returns an instance of TimeInterval or nil if +value+ is nil or
|
22
22
|
# empty.
|
@@ -6,26 +6,26 @@ module Momomoto
|
|
6
6
|
|
7
7
|
# Compares two values and returns true if equal or false otherwise.
|
8
8
|
# It is used to check if a row field has been changed so that only
|
9
|
-
# changed fields are written to database.
|
9
|
+
# changed fields are written to database.
|
10
10
|
def equal( a, b )
|
11
11
|
a.to_s == b.to_s
|
12
12
|
end
|
13
13
|
|
14
14
|
# Escapes +input+ to be saved in database.
|
15
15
|
# Returns 'NULL' if +input+ is nil or empty. Otherwise escapes
|
16
|
-
# using Database#
|
16
|
+
# using Database#quote
|
17
17
|
def escape( input )
|
18
18
|
if input.nil? || input.to_s.empty?
|
19
19
|
"NULL"
|
20
20
|
else
|
21
|
-
|
21
|
+
Database.quote_string( input.to_s )
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
# Additional operators for instances of Text.
|
26
26
|
# See Base#operator_sign
|
27
27
|
#
|
28
|
-
# # Selects all posts having "surveillance" in their content field
|
28
|
+
# # Selects all posts having "surveillance" in their content field
|
29
29
|
# # while ignoring case.
|
30
30
|
# Posts.select( :content => {:ilike => 'surveillance'} )
|
31
31
|
def self.operator_sign( op )
|
@@ -9,7 +9,7 @@ module Momomoto
|
|
9
9
|
|
10
10
|
# Compares two values and returns true if equal or false otherwise.
|
11
11
|
# It is used to check if a row field has been changed so that only
|
12
|
-
# changed fields are written to database.
|
12
|
+
# changed fields are written to database.
|
13
13
|
# Escapes before comparing.
|
14
14
|
def equal( a, b )
|
15
15
|
escape(a) == escape(b)
|
@@ -20,8 +20,8 @@ module Momomoto
|
|
20
20
|
def escape( value )
|
21
21
|
case value
|
22
22
|
when nil then 'NULL'
|
23
|
-
when String then
|
24
|
-
else
|
23
|
+
when String then Database.quote(value)
|
24
|
+
else Database.quote(value.strftime('%H:%M:%S'))
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -11,8 +11,8 @@ module Momomoto
|
|
11
11
|
def escape( value )
|
12
12
|
case value
|
13
13
|
when nil then 'NULL'
|
14
|
-
when String then
|
15
|
-
else
|
14
|
+
when String then Database.quote(value)
|
15
|
+
else Database.quote(value.strftime('%Y-%m-%d %H:%M:%S'))
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
data/lib/momomoto/procedure.rb
CHANGED
@@ -29,7 +29,7 @@ module Momomoto
|
|
29
29
|
|
30
30
|
# guesses the procedure name of the procedure this class works on
|
31
31
|
def construct_procedure_name( classname ) # :nodoc:
|
32
|
-
classname.split('::').last.downcase.gsub(/[^a-z_0-9]/, '')
|
32
|
+
classname.to_s.split('::').last.downcase.gsub(/[^a-z_0-9]/, '')
|
33
33
|
end
|
34
34
|
|
35
35
|
# gets the full name of the procedure including schema if set
|
@@ -48,7 +48,7 @@ module Momomoto
|
|
48
48
|
# returns an array of hashes with the field names as keys and the datatype as values
|
49
49
|
def parameters( *p )
|
50
50
|
return self.send( :parameters=, *p ) if not p.empty?
|
51
|
-
initialize if not
|
51
|
+
initialize if not initialized
|
52
52
|
@parameters
|
53
53
|
end
|
54
54
|
|
data/lib/momomoto/table.rb
CHANGED
@@ -339,16 +339,26 @@ module Momomoto
|
|
339
339
|
else
|
340
340
|
cols = columns
|
341
341
|
end
|
342
|
-
sql = "SELECT " + cols.keys.map{ | field |
|
342
|
+
sql = "SELECT " + cols.keys.map{ | field | Database.quote_ident( field ) }.join( "," ) + " FROM "
|
343
343
|
sql += full_name
|
344
344
|
sql += compile_where( conditions )
|
345
345
|
sql += compile_order( options[:order] ) if options[:order] || default_order
|
346
|
+
sql = compile_distinct( sql, cols, options[:distinct] ) if options[:distinct]
|
346
347
|
sql += compile_limit( options[:limit] ) if options[:limit]
|
347
348
|
sql += compile_offset( options[:offset] ) if options[:offset]
|
348
|
-
|
349
|
-
|
350
|
-
|
349
|
+
sql
|
350
|
+
end
|
351
|
+
|
352
|
+
def compile_distinct( inner_sql, cols, distinct )
|
353
|
+
distinct = [distinct] unless distinct.instance_of?( Array )
|
354
|
+
distinct.each do | field |
|
355
|
+
raise CriticalError, "condition key '#{field}' not a column in table '#{table_name}'" unless columns.keys.member?( field.to_sym )
|
351
356
|
end
|
357
|
+
sql = "SELECT DISTINCT ON("
|
358
|
+
sql += distinct.map{|f| Database.quote_ident(f)}.join(',')
|
359
|
+
sql += ") "
|
360
|
+
sql += cols.keys.map{ | field | Database.quote_ident( field ) }.join(',')
|
361
|
+
sql += " FROM (#{inner_sql}) AS t1"
|
352
362
|
sql
|
353
363
|
end
|
354
364
|
|
data/test/test_array.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
|
2
2
|
class TestArray < Test::Unit::TestCase
|
3
3
|
|
4
|
-
def
|
4
|
+
def test_int_samples
|
5
5
|
c = Class.new( Momomoto::Table )
|
6
6
|
c.table_name = 'test_int_array'
|
7
|
-
[[
|
7
|
+
[[1,2,3],nil,[],[1]].each do | value |
|
8
8
|
r = c.new( :data => value )
|
9
9
|
assert_equal( value, r.data )
|
10
10
|
r.write
|
@@ -14,5 +14,38 @@ class TestArray < Test::Unit::TestCase
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
def test_text_samples
|
18
|
+
c = Class.new( Momomoto::Table )
|
19
|
+
c.table_name = 'test_text_array'
|
20
|
+
[['chunky','bacon'],nil,[],['foo']].each do | value |
|
21
|
+
r = c.new( :data => value )
|
22
|
+
assert_equal( value, r.data )
|
23
|
+
r.write
|
24
|
+
r2 = c.select(:id=>r.id).first
|
25
|
+
assert_equal( value, r2.data )
|
26
|
+
r.delete
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_escape
|
31
|
+
a = Momomoto::Datatype::Array.new
|
32
|
+
assert_equal( a.escape( '{1,2,3}' ), "'{1,2,3}'" )
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_filter_get_text
|
36
|
+
a = Momomoto::Datatype::Array::Text.new
|
37
|
+
assert_equal( a.filter_get( '{1,2,3}' ), ['1','2','3'] )
|
38
|
+
assert_equal( a.filter_get( "{',bacon,chunky}" ), ["'","bacon","chunky"] )
|
39
|
+
assert_equal( a.filter_get( '{",",bacon,chunky}' ), [",","bacon","chunky"] )
|
40
|
+
assert_raise( Momomoto::Error ) do
|
41
|
+
a.filter_get( "{\"}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_filter_get_integer
|
46
|
+
a = Momomoto::Datatype::Array::Integer.new
|
47
|
+
assert_equal( a.filter_get( '{1,2,3}' ), [1,2,3] )
|
48
|
+
end
|
49
|
+
|
17
50
|
end
|
18
51
|
|
data/test/test_base.rb
CHANGED
@@ -28,7 +28,7 @@ class TestBase < Test::Unit::TestCase
|
|
28
28
|
t.table_name = 'person'
|
29
29
|
t.send( :initialize )
|
30
30
|
assert_equal( " WHERE person_id = '1'" , t.instance_eval do compile_where( :person_id => '1' ) end )
|
31
|
-
assert_equal( " WHERE person_id
|
31
|
+
assert_equal( " WHERE person_id = '1'" , t.instance_eval do compile_where( :person_id => ['1'] ) end )
|
32
32
|
assert_equal( " WHERE person_id IN ('1','2')" , t.instance_eval do compile_where( :person_id => ['1',2] ) end )
|
33
33
|
assert_equal( " WHERE first_name = E'1'" , t.instance_eval do compile_where( :first_name => '1' ) end )
|
34
34
|
assert_equal( " WHERE first_name = E'chu''nky'" , t.instance_eval do compile_where( :first_name => "chu'nky" ) end )
|
data/test/test_bytea.rb
CHANGED
@@ -24,10 +24,9 @@ class TestBytea < Test::Unit::TestCase
|
|
24
24
|
assert_equal( data.length, r.data.length )
|
25
25
|
assert_equal( data, r.data )
|
26
26
|
r.write
|
27
|
-
r2 = c.
|
28
|
-
assert_equal(
|
29
|
-
assert_equal( data
|
30
|
-
assert_equal( data, r2[0].data )
|
27
|
+
r2 = c.select_single(:id=>r.id)
|
28
|
+
assert_equal( data.length , r2.data.length )
|
29
|
+
assert_equal( data, r2.data )
|
31
30
|
end
|
32
31
|
|
33
32
|
end
|
data/test/test_datatype.rb
CHANGED
@@ -39,13 +39,14 @@ class TestDatatype < Test::Unit::TestCase
|
|
39
39
|
end
|
40
40
|
|
41
41
|
define_method( "test_operator_sign_#{type_name}" ) do
|
42
|
-
|
43
|
-
assert_equal( '
|
44
|
-
assert_equal( '
|
45
|
-
assert_equal( '
|
46
|
-
assert_equal( '
|
47
|
-
assert_equal( '
|
48
|
-
|
42
|
+
t = type.new
|
43
|
+
assert_equal( '<=', t.class.operator_sign( :le ) )
|
44
|
+
assert_equal( '<', t.class.operator_sign( :lt ) )
|
45
|
+
assert_equal( '>=', t.class.operator_sign( :ge ) )
|
46
|
+
assert_equal( '>', t.class.operator_sign( :gt ) )
|
47
|
+
assert_equal( '=', t.class.operator_sign( :eq ) )
|
48
|
+
assert_equal( '<>', t.class.operator_sign( :ne ) )
|
49
|
+
assert_raise( Momomoto::CriticalError ) { t.class.operator_sign( :foo ) }
|
49
50
|
end
|
50
51
|
|
51
52
|
define_method( "test_escape_#{type_name}" ) do
|
data/test/test_procedure.rb
CHANGED
@@ -39,20 +39,24 @@ class TestProcedure < Test::Unit::TestCase
|
|
39
39
|
|
40
40
|
def test_columns
|
41
41
|
p = Class.new( Momomoto::Procedure )
|
42
|
+
p.procedure_name("test_parameter_plpgsql")
|
42
43
|
p2 = Class.new( Momomoto::Procedure )
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
p2.procedure_name("test_parameter_plpgsql")
|
45
|
+
p.columns = { :chunky => :bacon }
|
46
|
+
p2.columns = { :bacon => :chunky }
|
47
|
+
assert_equal( {:chunky=>:bacon}, p.columns )
|
46
48
|
p.columns = :bacon
|
47
49
|
assert_equal( :bacon, p.columns )
|
48
|
-
p.columns
|
49
|
-
assert_equal( :chunky, p.columns )
|
50
|
-
assert_equal( :
|
50
|
+
p.columns = { :chunky => :bacon }
|
51
|
+
assert_equal( {:chunky=>:bacon}, p.columns )
|
52
|
+
assert_equal( {:bacon=>:chunky}, p2.columns )
|
51
53
|
end
|
52
54
|
|
53
55
|
def test_parameters
|
54
56
|
p = Class.new( Momomoto::Procedure )
|
57
|
+
p.procedure_name("test_parameter_plpgsql")
|
55
58
|
p2 = Class.new( Momomoto::Procedure )
|
59
|
+
p2.procedure_name("test_parameter_plpgsql")
|
56
60
|
p.parameters = { :chunky => :bacon }
|
57
61
|
p2.parameters = { :bacon => :chunky }
|
58
62
|
assert_equal( [{:chunky=>:bacon}], p.parameters )
|
data/test/test_table.rb
CHANGED
@@ -14,12 +14,14 @@ class TestTable < Test::Unit::TestCase
|
|
14
14
|
|
15
15
|
def test_default_order_getter
|
16
16
|
c1 = Class.new( Momomoto::Table )
|
17
|
+
c1.table_name('person')
|
17
18
|
c1.default_order = [:a,:b]
|
18
19
|
assert_equal( [:a,:b], c1.default_order )
|
19
20
|
end
|
20
21
|
|
21
22
|
def test_default_order_setter
|
22
23
|
c1 = Class.new( Momomoto::Table )
|
24
|
+
c1.table_name('person')
|
23
25
|
c1.default_order = :a
|
24
26
|
assert_equal( :a, c1.default_order )
|
25
27
|
c1.default_order = :b
|
@@ -30,12 +32,14 @@ class TestTable < Test::Unit::TestCase
|
|
30
32
|
|
31
33
|
def test_columns_getter
|
32
34
|
c1 = Class.new( Momomoto::Table )
|
35
|
+
c1.table_name('person')
|
33
36
|
c1.columns = {:a=>Momomoto::Datatype::Text}
|
34
37
|
assert_equal( {:a=>Momomoto::Datatype::Text}, c1.columns )
|
35
38
|
end
|
36
39
|
|
37
40
|
def test_columns_setter
|
38
41
|
c1 = Class.new( Momomoto::Table )
|
42
|
+
c1.table_name('person')
|
39
43
|
c1.columns = {:a=>Momomoto::Datatype::Text}
|
40
44
|
assert_equal( {:a=>Momomoto::Datatype::Text}, c1.columns )
|
41
45
|
c1.columns = {:b=>Momomoto::Datatype::Text}
|
@@ -46,6 +50,7 @@ class TestTable < Test::Unit::TestCase
|
|
46
50
|
|
47
51
|
def test_primary_key_getter
|
48
52
|
a = Class.new( Momomoto::Table )
|
53
|
+
a.table_name('person')
|
49
54
|
a.primary_keys( [:pk] )
|
50
55
|
assert_equal( [:pk], a.primary_keys )
|
51
56
|
p = Class.new( Momomoto::Table )
|
@@ -56,6 +61,7 @@ class TestTable < Test::Unit::TestCase
|
|
56
61
|
|
57
62
|
def test_primary_key_setter
|
58
63
|
a = Class.new( Momomoto::Table )
|
64
|
+
a.table_name('person')
|
59
65
|
a.primary_keys( [:pk] )
|
60
66
|
assert_equal( [:pk], a.primary_keys )
|
61
67
|
a.primary_keys= [:pk2]
|
@@ -72,26 +78,28 @@ class TestTable < Test::Unit::TestCase
|
|
72
78
|
|
73
79
|
def test_schema_name_setter
|
74
80
|
a = Class.new( Momomoto::Table )
|
81
|
+
a.table_name("person")
|
75
82
|
b = Class.new( Momomoto::Table )
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
assert_equal( :
|
83
|
+
b.table_name("person")
|
84
|
+
a.schema_name = :public
|
85
|
+
b.schema_name = :public
|
86
|
+
assert_equal( :public, a.schema_name )
|
87
|
+
assert_equal( :public, b.schema_name )
|
80
88
|
a.schema_name( :ratbert )
|
81
89
|
assert_equal( :ratbert, a.schema_name )
|
82
|
-
assert_equal( :
|
90
|
+
assert_equal( :public, b.schema_name )
|
83
91
|
end
|
84
92
|
|
85
93
|
def test_table_name_getter
|
86
94
|
t = Class.new( Momomoto::Table )
|
87
|
-
t.table_name = "
|
88
|
-
assert_equal( "
|
95
|
+
t.table_name = "person"
|
96
|
+
assert_equal( "person", t.table_name )
|
89
97
|
end
|
90
98
|
|
91
99
|
def test_table_name_setter
|
92
100
|
t = Class.new( Momomoto::Table )
|
93
|
-
t.table_name = "
|
94
|
-
assert_equal( "
|
101
|
+
t.table_name = "person"
|
102
|
+
assert_equal( "person", t.table_name )
|
95
103
|
t.table_name = "bacon"
|
96
104
|
assert_equal( "bacon", t.table_name )
|
97
105
|
t.table_name( "fox" )
|
@@ -127,7 +135,7 @@ class TestTable < Test::Unit::TestCase
|
|
127
135
|
def test_offset
|
128
136
|
p = Person.select( {}, {:limit => 1, :order => :person_id,:offset=>2})
|
129
137
|
assert_operator( 2, :<, p[0].person_id )
|
130
|
-
assert_raise( Momomoto::Error ) do
|
138
|
+
assert_raise( Momomoto::Error ) do
|
131
139
|
Person.select( {}, {:limit => 1, :order => :person_id,:offset=>'bacon'})
|
132
140
|
end
|
133
141
|
end
|
@@ -145,8 +153,16 @@ class TestTable < Test::Unit::TestCase
|
|
145
153
|
end
|
146
154
|
end
|
147
155
|
|
156
|
+
def test_distinct
|
157
|
+
p = Person.select({},{:distinct=>[:first_name,:nick_name]})
|
158
|
+
end
|
159
|
+
|
148
160
|
def test_write_columns
|
149
|
-
|
161
|
+
t = Class.new( Momomoto::Table )
|
162
|
+
t.table_name( 'person' )
|
163
|
+
p = t.select({},{:columns=>[:first_name],:limit=>1})[0]
|
164
|
+
assert( p.class.columns.member?(:first_name))
|
165
|
+
assert( p.class.columns.member?(:person_id))
|
150
166
|
p.first_name = 'test_write_columns'
|
151
167
|
p.write
|
152
168
|
p2 = Person.select_single(:person_id=>p.person_id)
|
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: 2008-01-
|
6
|
+
version: 0.1.16
|
7
|
+
date: 2008-01-21 00:00:00 +01:00
|
8
8
|
summary: Momomoto is an object relational mapper for PostgreSQL.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -60,10 +60,13 @@ files:
|
|
60
60
|
- lib/momomoto/datatype/numeric.rb
|
61
61
|
- lib/momomoto/datatype/bytea.rb
|
62
62
|
- lib/momomoto/datatype/timestamp_without_time_zone.rb
|
63
|
+
- lib/momomoto/datatype/timestamp_with_time_zone.rb
|
63
64
|
- lib/momomoto/datatype/time_with_time_zone.rb
|
64
65
|
- lib/momomoto/datatype/base.rb
|
65
66
|
- lib/momomoto/datatype/bigint.rb
|
66
|
-
- lib/momomoto/datatype/
|
67
|
+
- lib/momomoto/datatype/array/integer.rb
|
68
|
+
- lib/momomoto/datatype/array/text.rb
|
69
|
+
- lib/momomoto/datatype/array/base.rb
|
67
70
|
- sql/procedures.sql
|
68
71
|
- sql/types.sql
|
69
72
|
- sql/install.sql
|
@@ -117,5 +120,5 @@ dependencies:
|
|
117
120
|
requirements:
|
118
121
|
- - ">="
|
119
122
|
- !ruby/object:Gem::Version
|
120
|
-
version: 0.7.9.
|
123
|
+
version: 0.7.9.2008.01.09
|
121
124
|
version:
|