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.
- data/Rakefile +15 -0
- data/lib/momomoto/base.rb +77 -12
- data/lib/momomoto/database.rb +16 -4
- data/lib/momomoto/datatype/base.rb +49 -8
- data/lib/momomoto/datatype/bigint.rb +2 -1
- data/lib/momomoto/datatype/boolean.rb +9 -0
- data/lib/momomoto/datatype/bytea.rb +4 -0
- data/lib/momomoto/datatype/character.rb +2 -0
- data/lib/momomoto/datatype/character_varying.rb +2 -0
- data/lib/momomoto/datatype/date.rb +5 -0
- data/lib/momomoto/datatype/inet.rb +4 -0
- data/lib/momomoto/datatype/integer.rb +5 -0
- data/lib/momomoto/datatype/interval.rb +14 -1
- data/lib/momomoto/datatype/numeric.rb +5 -0
- data/lib/momomoto/datatype/real.rb +2 -0
- data/lib/momomoto/datatype/smallint.rb +2 -0
- data/lib/momomoto/datatype/text.rb +14 -0
- data/lib/momomoto/datatype/time_with_time_zone.rb +3 -1
- data/lib/momomoto/datatype/time_without_time_zone.rb +10 -0
- data/lib/momomoto/datatype/timestamp_with_time_zone.rb +2 -0
- data/lib/momomoto/datatype/timestamp_without_time_zone.rb +5 -0
- data/lib/momomoto/information_schema/columns.rb +8 -0
- data/lib/momomoto/information_schema/fetch_procedure_columns.rb +2 -0
- data/lib/momomoto/information_schema/fetch_procedure_parameters.rb +2 -0
- data/lib/momomoto/information_schema/key_column_usage.rb +5 -0
- data/lib/momomoto/information_schema/routines.rb +4 -0
- data/lib/momomoto/information_schema/table_constraints.rb +5 -0
- data/lib/momomoto/order.rb +61 -0
- data/lib/momomoto/procedure.rb +14 -14
- data/lib/momomoto/row.rb +41 -4
- data/lib/momomoto/table.rb +106 -20
- data/lib/timeinterval.rb +90 -16
- data/test/test_datatype.rb +1 -1
- 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,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,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
|
@@ -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,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" )
|
data/lib/momomoto/order.rb
CHANGED
@@ -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
|
data/lib/momomoto/procedure.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
|
2
2
|
module Momomoto
|
3
3
|
|
4
|
-
#
|
5
|
-
#
|
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
|
-
#
|
31
|
+
# sets the procedure name
|
32
32
|
def procedure_name=( procedure_name )
|
33
33
|
@procedure_name = procedure_name
|
34
34
|
end
|
35
35
|
|
36
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
58
|
-
# returns an array of hashes with the
|
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
|
-
#
|
66
|
-
# expects a hash with the
|
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
|
-
#
|
72
|
-
# returns a hash with the
|
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 #{
|
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
|
-
#
|
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 "
|