momomoto 0.1.13 → 0.1.14

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.
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 "