momomoto 0.1.13 → 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/Rakefile +15 -0
  2. data/lib/momomoto/base.rb +77 -12
  3. data/lib/momomoto/database.rb +16 -4
  4. data/lib/momomoto/datatype/base.rb +49 -8
  5. data/lib/momomoto/datatype/bigint.rb +2 -1
  6. data/lib/momomoto/datatype/boolean.rb +9 -0
  7. data/lib/momomoto/datatype/bytea.rb +4 -0
  8. data/lib/momomoto/datatype/character.rb +2 -0
  9. data/lib/momomoto/datatype/character_varying.rb +2 -0
  10. data/lib/momomoto/datatype/date.rb +5 -0
  11. data/lib/momomoto/datatype/inet.rb +4 -0
  12. data/lib/momomoto/datatype/integer.rb +5 -0
  13. data/lib/momomoto/datatype/interval.rb +14 -1
  14. data/lib/momomoto/datatype/numeric.rb +5 -0
  15. data/lib/momomoto/datatype/real.rb +2 -0
  16. data/lib/momomoto/datatype/smallint.rb +2 -0
  17. data/lib/momomoto/datatype/text.rb +14 -0
  18. data/lib/momomoto/datatype/time_with_time_zone.rb +3 -1
  19. data/lib/momomoto/datatype/time_without_time_zone.rb +10 -0
  20. data/lib/momomoto/datatype/timestamp_with_time_zone.rb +2 -0
  21. data/lib/momomoto/datatype/timestamp_without_time_zone.rb +5 -0
  22. data/lib/momomoto/information_schema/columns.rb +8 -0
  23. data/lib/momomoto/information_schema/fetch_procedure_columns.rb +2 -0
  24. data/lib/momomoto/information_schema/fetch_procedure_parameters.rb +2 -0
  25. data/lib/momomoto/information_schema/key_column_usage.rb +5 -0
  26. data/lib/momomoto/information_schema/routines.rb +4 -0
  27. data/lib/momomoto/information_schema/table_constraints.rb +5 -0
  28. data/lib/momomoto/order.rb +61 -0
  29. data/lib/momomoto/procedure.rb +14 -14
  30. data/lib/momomoto/row.rb +41 -4
  31. data/lib/momomoto/table.rb +106 -20
  32. data/lib/timeinterval.rb +90 -16
  33. data/test/test_datatype.rb +1 -1
  34. metadata +2 -2
@@ -1,7 +1,11 @@
1
1
  module Momomoto
2
2
  module Datatype
3
+
4
+ # This class represents data type Inet which is an IPv4 or IPv6 host or address.
3
5
  class Inet < Text
4
6
 
7
+ # Values are filtered by this method when being set.
8
+ # Returns nil if +value+ is empty or nil.
5
9
  def filter_set( value )
6
10
  case value
7
11
  when nil, '' then nil
@@ -1,7 +1,12 @@
1
1
  module Momomoto
2
2
  module Datatype
3
+
4
+ # This class represents data type Integer.
3
5
  class Integer < Base
4
6
 
7
+ # Values are filtered by this method when being set.
8
+ # Converts +value+ to Integer or return +nil+ if +value+ is nil or empty.
9
+ # Raises ConversionError if converting fails.
5
10
  def filter_set( value )
6
11
  case value
7
12
  when nil, '' then nil
@@ -1,7 +1,14 @@
1
1
  module Momomoto
2
2
  module Datatype
3
+
4
+ # This class represents the data type Interval.
3
5
  class Interval < Time_without_time_zone
4
6
 
7
+ # Escapes +value+ before storing to database.
8
+ # +value+ can be either
9
+ # nil, resulting in 'NULL',
10
+ # String, which is escaped using Database#escape_string,
11
+ # or some Date-like format
5
12
  def escape( value )
6
13
  case value
7
14
  when nil then 'NULL'
@@ -9,7 +16,11 @@ module Momomoto
9
16
  else "'#{Database.escape_string(value.strftime('%H:%M:%S'))}'"
10
17
  end
11
18
  end
12
-
19
+
20
+ # Values are filtered by this method when getting them from database.
21
+ # Returns an instance of TimeInterval or nil if +value+ is nil or
22
+ # empty.
23
+ # Raises ConversionError if the given +value+ cannot be parsed.
13
24
  def filter_get( value )
14
25
  case value
15
26
  when nil, '' then nil
@@ -21,6 +32,8 @@ module Momomoto
21
32
  raise ConversionError, "Error while parsing interval (#{e.message})"
22
33
  end
23
34
 
35
+ # Values are filtered by this function when being set.
36
+ # See Interval#filter_get
24
37
  def filter_set( value )
25
38
  filter_get( value )
26
39
  end
@@ -1,8 +1,13 @@
1
1
 
2
2
  module Momomoto
3
3
  module Datatype
4
+
5
+ # This class represents data type Numeric.
4
6
  class Numeric < Base
5
7
 
8
+ # Values are filtered by this method when being set.
9
+ # Converts +value+ to Float or returns nil if +value+ is nil or
10
+ # empty.
6
11
  def filter_set( value )
7
12
  case value
8
13
  when nil, '' then nil
@@ -1,5 +1,7 @@
1
1
  module Momomoto
2
2
  module Datatype
3
+
4
+ # Represents the data type Real
3
5
  class Real < Numeric
4
6
 
5
7
  end
@@ -1,5 +1,7 @@
1
1
  module Momomoto
2
2
  module Datatype
3
+
4
+ # Represents the data type Smallint
3
5
  class Smallint < Integer
4
6
 
5
7
  end
@@ -1,11 +1,19 @@
1
1
  module Momomoto
2
2
  module Datatype
3
+
4
+ # Represents the data type Text.
3
5
  class Text < Base
4
6
 
7
+ # Compares two values and returns true if equal or false otherwise.
8
+ # It is used to check if a row field has been changed so that only
9
+ # changed fields are written to database.
5
10
  def equal( a, b )
6
11
  a.to_s == b.to_s
7
12
  end
8
13
 
14
+ # Escapes +input+ to be saved in database.
15
+ # Returns 'NULL' if +input+ is nil or empty. Otherwise escapes
16
+ # using Database#escape_string
9
17
  def escape( input )
10
18
  if input.nil? || input.to_s.empty?
11
19
  "NULL"
@@ -14,6 +22,12 @@ module Momomoto
14
22
  end
15
23
  end
16
24
 
25
+ # Additional operators for instances of Text.
26
+ # See Base#operator_sign
27
+ #
28
+ # # Selects all posts having "surveillance" in their content field
29
+ # # while ignoring case.
30
+ # Posts.select( :content => {:ilike => 'surveillance'} )
17
31
  def self.operator_sign( op )
18
32
  case op
19
33
  when :like then 'LIKE'
@@ -3,8 +3,10 @@ require 'date'
3
3
 
4
4
  module Momomoto
5
5
  module Datatype
6
+
7
+ # Represents the data type Time with time zone.
6
8
  class Time_with_time_zone < Time_without_time_zone
7
-
9
+
8
10
  end
9
11
  end
10
12
  end
@@ -3,12 +3,20 @@ require 'time'
3
3
 
4
4
  module Momomoto
5
5
  module Datatype
6
+
7
+ # Represents the data type Time without time zone.
6
8
  class Time_without_time_zone < Base
7
9
 
10
+ # Compares two values and returns true if equal or false otherwise.
11
+ # It is used to check if a row field has been changed so that only
12
+ # changed fields are written to database.
13
+ # Escapes before comparing.
8
14
  def equal( a, b )
9
15
  escape(a) == escape(b)
10
16
  end
11
17
 
18
+ # Escapes +value+ to be saved in database.
19
+ # Returns 'NULL' if +value+ is nil.
12
20
  def escape( value )
13
21
  case value
14
22
  when nil then 'NULL'
@@ -17,6 +25,8 @@ module Momomoto
17
25
  end
18
26
  end
19
27
 
28
+ # Values are filtered by this function when being set.
29
+ # Returns an instance of Time or nil if +value+ is nil or empty.
20
30
  def filter_set( value )
21
31
  case value
22
32
  when nil, '' then nil
@@ -1,5 +1,7 @@
1
1
  module Momomoto
2
2
  module Datatype
3
+
4
+ # Represents the data type Timestamp with time zone.
3
5
  class Timestamp_with_time_zone < Timestamp_without_time_zone
4
6
 
5
7
  end
@@ -3,8 +3,11 @@ require 'date'
3
3
 
4
4
  module Momomoto
5
5
  module Datatype
6
+
7
+ # Represents the data type Timestamp without time zone.
6
8
  class Timestamp_without_time_zone < Base
7
9
 
10
+ # Escapes +value+ to be saved in database.
8
11
  def escape( value )
9
12
  case value
10
13
  when nil then 'NULL'
@@ -13,6 +16,8 @@ module Momomoto
13
16
  end
14
17
  end
15
18
 
19
+ # Values are filtered by this function when being set.
20
+ # Returns an instance of Time or nil if +value+ is nil or empty.
16
21
  def filter_set( value )
17
22
  case value
18
23
  when nil, '' then nil
@@ -1,6 +1,14 @@
1
1
 
2
2
  module Momomoto
3
+
4
+ # This module is used by Momomoto to access the database's meta
5
+ # information on the current active database.
3
6
  module Information_schema
7
+
8
+ # internal use only
9
+ #
10
+ # Represents the corresponding view from Information Schema and is
11
+ # used when getting the data type of a column.
4
12
  class Columns < Momomoto::Table
5
13
  primary_keys( [] )
6
14
  schema_name( "information_schema" )
@@ -1,6 +1,8 @@
1
1
 
2
2
  module Momomoto
3
3
  module Information_schema
4
+
5
+ # internal use only
4
6
  class Fetch_procedure_columns < Momomoto::Procedure
5
7
  schema_name( "momomoto" )
6
8
  parameters( :procedure_name => Momomoto::Datatype::Text.new )
@@ -1,6 +1,8 @@
1
1
 
2
2
  module Momomoto
3
3
  module Information_schema
4
+
5
+ # internal use only
4
6
  class Fetch_procedure_parameters < Momomoto::Procedure
5
7
  schema_name( "momomoto" )
6
8
  parameters( :procedure_name => Momomoto::Datatype::Text.new )
@@ -1,6 +1,11 @@
1
1
 
2
2
  module Momomoto
3
3
  module Information_schema
4
+
5
+ # internal use only
6
+ #
7
+ # Represents the corresponding view from Information Schema and is
8
+ # used for getting the column names of primary keys of a table.
4
9
  class Key_column_usage < Momomoto::Table
5
10
  schema_name( "information_schema" )
6
11
  end
@@ -3,6 +3,10 @@ module Momomoto
3
3
 
4
4
  module Information_schema
5
5
 
6
+ # internal use only
7
+ #
8
+ # Represents the corresponding view from Information Schema and is
9
+ # used for getting all defined functions within a database.
6
10
  class Routines < Momomoto::Table
7
11
  schema_name( "information_schema" )
8
12
  end
@@ -1,6 +1,11 @@
1
1
 
2
2
  module Momomoto
3
3
  module Information_schema
4
+
5
+ # internal use only
6
+ #
7
+ # Represents the corresponding view from Information Schema and is
8
+ # used when fetching primary keys.
4
9
  class Table_constraints < Momomoto::Table
5
10
  primary_keys( [] )
6
11
  schema_name( "information_schema" )
@@ -1,14 +1,55 @@
1
1
 
2
2
  module Momomoto
3
3
 
4
+ # This class is used to specify the order of returned +Row+s.
5
+ # Whenever selecting rows you can use plain +Symbol+s for column names
6
+ # or the builtin classes for having the result automatically sorted +asc+
7
+ # ending, +desc+ending or case-insensitive with +lower+.
8
+ #
9
+ # When executing SELECT on tables the method Base#compile_order is
10
+ # invoked, which compiles the order statement according to Table#default_order
11
+ # if defined. This can be overwritten with options[:order] set as parameter
12
+ # for the select method.
13
+ #
14
+ # class Feeds < Momomoto::Table
15
+ # default_order Momomoto.desc( :last_changed )
16
+ # #equals default_order Momomoto::Order::Desc.new( :last_changed )
17
+ # end
18
+ #
19
+ # newest_five_feeds = Feeds.select( {}, { :limit => 5} )
20
+ # => Returns the five rows from Feeds with the newest column last_changed
21
+ #
22
+ # Now, if you want to get all feeds sorted by column title instead of
23
+ # last_changed and also want to ignore case, do the following:
24
+ #
25
+ # feeds_by_title = Feeds.select( {}, {:order => Momomoto::lower(:title)} )
26
+ #
27
+ # This overwrites the default value for order.
28
+ #
29
+ # You can also define multiple order statements at once, which are then
30
+ # joined together.
31
+ #
32
+ # class Feeds < Momomoto::Table
33
+ # default_order [Momomoto::desc(:last_changed), Momomoto::lower(:title)]
34
+ # end
4
35
  class Order
5
36
 
37
+ # Getter and setter methods for +fields+. +fields+ are +Symbol+s
38
+ # representing the columns the Order class operates on.
6
39
  attr_accessor :fields
7
40
 
41
+ # Creates a new instance of Order and flattens the given parameter
42
+ # +fields+.
43
+ #
44
+ # Usage:
45
+ # Momomoto::Order.new(:url_class, [:url, :title])
8
46
  def initialize( *fields )
9
47
  @fields = fields.flatten
10
48
  end
11
49
 
50
+ # This method is used to build the SQL statement from the given
51
+ # +columns+ and their class. This method is only invoked from
52
+ # Base#compile_order.
12
53
  def to_sql( columns )
13
54
  sql = []
14
55
  fields.each do | field |
@@ -22,7 +63,17 @@ module Momomoto
22
63
  sql.join(',')
23
64
  end
24
65
 
66
+ # This class is used for case-insensitive orders. It is derived from
67
+ # the Order class where you can find more information on usage.
25
68
  class Lower < Order
69
+
70
+ # Creates a new instance of Lower and flattens the given parameter
71
+ # +fields+.
72
+ # Raises Error if presented with fields that are either instances of
73
+ # Order::Asc or Order::Desc.
74
+ #
75
+ # Usage:
76
+ # Momomoto::Order::Lower.new(:author, [:title, :publisher])
26
77
  def initialize( *fields )
27
78
  fields = fields.flatten
28
79
  fields.each do | field |
@@ -31,6 +82,8 @@ module Momomoto
31
82
  @fields = fields
32
83
  end
33
84
 
85
+ # Translates all +argument+s to the SQL statement.
86
+ # Returns the joined arguments.
34
87
  def function( argument )
35
88
  argument = [ argument ] if not argument.kind_of?( Array )
36
89
  argument = argument.map{|a| "lower(#{a})"}
@@ -38,13 +91,21 @@ module Momomoto
38
91
  end
39
92
  end
40
93
 
94
+ # This class is used for ascending orders. It is derived from the
95
+ # Order class where you can find more information on usage.
41
96
  class Asc < Order
97
+
98
+ # translates +argument+ to SQL statement for ascending.
42
99
  def function( argument )
43
100
  "#{argument} asc"
44
101
  end
45
102
  end
46
103
 
104
+ # This class is used for descending orders. It is derived from the
105
+ # Order class where you can find more information on usage.
47
106
  class Desc < Order
107
+
108
+ # translates +argument+ to SQL statement for descending.
48
109
  def function( argument )
49
110
  "#{argument} desc"
50
111
  end
@@ -1,8 +1,8 @@
1
1
 
2
2
  module Momomoto
3
3
 
4
- # this class implements access to stored procedures
5
- # it must not be used directly but you should inherit from this class
4
+ # This class implements access to stored procedures.
5
+ # It must not be used directly but you should inherit from this class.
6
6
  class Procedure < Base
7
7
 
8
8
  class << self
@@ -28,12 +28,12 @@ module Momomoto
28
28
  classname.split('::').last.downcase.gsub(/[^a-z_0-9]/, '')
29
29
  end
30
30
 
31
- # set the procedure name
31
+ # sets the procedure name
32
32
  def procedure_name=( procedure_name )
33
33
  @procedure_name = procedure_name
34
34
  end
35
35
 
36
- # get the procedure name
36
+ # gets the procedure name
37
37
  def procedure_name( procedure_name = nil )
38
38
  return self.procedure_name=( procedure_name ) if procedure_name
39
39
  if not instance_variable_defined?( :@procedure_name )
@@ -42,34 +42,34 @@ module Momomoto
42
42
  @procedure_name
43
43
  end
44
44
 
45
- # get the full name of the procedure including schema if set
45
+ # gets the full name of the procedure including schema if set
46
46
  def full_name # :nodoc:
47
47
  "#{ schema_name ? schema_name + '.' : ''}#{procedure_name}"
48
48
  end
49
49
 
50
- # set the parameters this procedures accepts
50
+ # sets the parameters this procedures accepts
51
51
  # example: parameters = {:param1=>Momomoto::Datatype::Text.new}
52
52
  def parameters=( *p )
53
53
  p = p.flatten
54
54
  @parameters = p
55
55
  end
56
56
 
57
- # get the parameters this procedure accepts
58
- # returns an array of hashes with the fieldnames as key and the datatype as value
57
+ # gets the parameters this procedure accepts
58
+ # returns an array of hashes with the field names as keys and the datatype as values
59
59
  def parameters( *p )
60
60
  return self.send( :parameters=, *p ) if not p.empty?
61
61
  initialize_procedure if not instance_variable_defined?( :@parameters )
62
62
  @parameters
63
63
  end
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
+ # sets the columns of the result set this procedure returns
66
+ # expects a hash with the field names as keys and the datatype as values
67
67
  def columns=( columns )
68
68
  @columns = columns
69
69
  end
70
70
 
71
- # get the columns of the resultset this procedure returns
72
- # returns a hash with the fieldnames as key and the datatype as value
71
+ # gets the columns of the result set this procedure returns
72
+ # returns a hash with the field names as keys and the datatype as values
73
73
  def columns( c = nil )
74
74
  return self.columns=( c ) if c
75
75
  initialize_procedure if not instance_variable_defined?( :@columns )
@@ -81,13 +81,13 @@ module Momomoto
81
81
  parameters.each do | parameter |
82
82
  field_name, datatype = parameter.to_a.first
83
83
  raise Error, "parameter #{field_name} not specified" if not params.member?( field_name )
84
- raise Error, "Not null fields(#{field_name}) need to be set in #{procedure_name}" if !params[field_name] && datatype.not_null?
84
+ raise Error, "Not null fields(#{field_name}) need to be set in #{full_name}" if !params[field_name] && datatype.not_null?
85
85
  args << datatype.escape( params[field_name] )
86
86
  end
87
87
  args.join(',')
88
88
  end
89
89
 
90
- # execute the stored procedure
90
+ # executes the stored procedure
91
91
  def call( params = {}, conditions = {}, options = {} )
92
92
  initialize_procedure unless initialized
93
93
  sql = "SELECT #{columns.keys.join(',')} FROM "