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 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 instance_variable_defined?( varname )
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 instance_variable_defined?( varname )
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
- attr_accessor :initialized
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 )
@@ -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 < Base
6
-
7
- # Escapes +input+ to be saved in database.
8
- # Returns 'NULL' if +input+ is nil or empty. Otherwise escapes
9
- # using Database#escape_string
10
- def escape( input )
11
- if input.nil?
12
- "NULL"
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
+
@@ -0,0 +1,16 @@
1
+ module Momomoto
2
+ module Datatype
3
+ class Array
4
+
5
+ # datatype for text arrays
6
+ class Text < Base
7
+
8
+ def array_type
9
+ "text"
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end
16
+
@@ -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#escape_string
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" : "'" + Database.escape_string( input.to_s ) + "'"
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#escape_bytea or returns NULL if
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" : "E'" + Database.escape_bytea( input ) + "'"
11
+ input.nil? ? "NULL" : Database.quote_bytea( input )
12
12
  end
13
13
 
14
14
  end
@@ -17,10 +17,10 @@ module Momomoto
17
17
  when String then ::Date.parse( value, '%Y-%m-%d' )
18
18
  else raise Error
19
19
  end
20
- rescue => e
20
+ rescue => e
21
21
  raise ConversionError, "parse Error in Date #{e}"
22
22
  end
23
-
23
+
24
24
  end
25
25
  end
26
26
  end
@@ -12,7 +12,7 @@ module Momomoto
12
12
  else value
13
13
  end
14
14
  end
15
-
15
+
16
16
  end
17
17
  end
18
18
  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#escape_string,
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 "'#{Database.escape_string(value)}'"
16
- else "'#{Database.escape_string(value.strftime('%H:%M:%S'))}'"
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.
@@ -1,9 +1,9 @@
1
1
  module Momomoto
2
2
  module Datatype
3
-
3
+
4
4
  # Represents the data type Real
5
5
  class Real < Numeric
6
-
6
+
7
7
  end
8
8
  end
9
9
  end
@@ -3,7 +3,7 @@ module Momomoto
3
3
 
4
4
  # Represents the data type Smallint
5
5
  class Smallint < Integer
6
-
6
+
7
7
  end
8
8
  end
9
9
  end
@@ -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#escape_string
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
- "E'" + Database.escape_string( input.to_s ) + "'"
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 "'#{Database.escape_string(value)}'"
24
- else "'#{Database.escape_string(value.strftime('%H:%M:%S'))}'"
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 "'#{Database.escape_string(value)}'"
15
- else "'#{Database.escape_string(value.strftime('%Y-%m-%d %H:%M:%S'))}'"
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
 
@@ -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 instance_variable_defined?( :@parameters )
51
+ initialize if not initialized
52
52
  @parameters
53
53
  end
54
54
 
@@ -339,16 +339,26 @@ module Momomoto
339
339
  else
340
340
  cols = columns
341
341
  end
342
- sql = "SELECT " + cols.keys.map{ | field | '"' + field.to_s + '"' }.join( "," ) + " FROM "
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
- if options[:distinct]
349
- raise CriticalError, "condition key '#{options[:distinct]}' not a column in table '#{table_name}'" unless columns.keys.member?( options[:distinct])
350
- sql = "SELECT DISTINCT ON(\"#{options[:distinct]}\") " + cols.keys.map{ | field | '"' + field.to_s + '"' }.join( "," ) + " FROM (#{sql}) AS t1"
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 test_samples
4
+ def test_int_samples
5
5
  c = Class.new( Momomoto::Table )
6
6
  c.table_name = 'test_int_array'
7
- [["1","2","3"],nil].each do | value |
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 IN ('1')" , t.instance_eval do compile_where( :person_id => ['1'] ) end )
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.select(:id=>r.id)
28
- assert_equal( 1, r2.length )
29
- assert_equal( data.length , r2[0].data.length )
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
@@ -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
- assert_equal( '<=', type.operator_sign( :le ) )
43
- assert_equal( '<', type.operator_sign( :lt ) )
44
- assert_equal( '>=', type.operator_sign( :ge ) )
45
- assert_equal( '>', type.operator_sign( :gt ) )
46
- assert_equal( '=', type.operator_sign( :eq ) )
47
- assert_equal( '<>', type.operator_sign( :ne ) )
48
- assert_raise( Momomoto::CriticalError ) { type.operator_sign( :foo ) }
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
@@ -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
- p.columns = :chunky
44
- p2.columns = :alice
45
- assert_equal( :chunky, p.columns )
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( :chunky )
49
- assert_equal( :chunky, p.columns )
50
- assert_equal( :alice, p2.columns )
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
- a.schema_name = :chunky
77
- b.schema_name = :bacon
78
- assert_equal( :chunky, a.schema_name )
79
- assert_equal( :bacon, b.schema_name )
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( :bacon, b.schema_name )
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 = "chunky"
88
- assert_equal( "chunky", t.table_name )
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 = "chunky"
94
- assert_equal( "chunky", t.table_name )
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
- p = Person.select({},{:columns=>[:first_name],:limit=>1})[0]
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.15
7
- date: 2008-01-13 00:00:00 +01:00
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/timestamp_with_time_zone.rb
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.2007.12.12
123
+ version: 0.7.9.2008.01.09
121
124
  version: