momomoto 0.1.13 → 0.1.14
Sign up to get free protection for your applications and to get access to all the features.
- 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 "
|