sqlyzer 0.1
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.tar.gz.sig +2 -0
- data/COPYING.txt +338 -0
- data/README.txt +86 -0
- data/lib/sqlyzer.rb +31 -0
- data/lib/sqlyzer/associate.rb +184 -0
- data/lib/sqlyzer/container.rb +140 -0
- data/lib/sqlyzer/create.rb +189 -0
- data/lib/sqlyzer/db.rb +141 -0
- data/lib/sqlyzer/errors.rb +75 -0
- data/lib/sqlyzer/handler.rb +88 -0
- data/lib/sqlyzer/parameters.rb +448 -0
- data/lib/sqlyzer/request.rb +151 -0
- data/lib/sqlyzer/serializer.rb +200 -0
- metadata +80 -0
- metadata.gz.sig +0 -0
data/lib/sqlyzer/db.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
# SQLYZER Ruby Object serializer to SQL.
|
2
|
+
# For more information visit http://sqlyzer.rubyforge.org
|
3
|
+
#
|
4
|
+
# This program is free software; you can redistribute it and/or
|
5
|
+
# modify it under the terms of the GNU General Public License
|
6
|
+
# as published by the Free Software Foundation; either version 2
|
7
|
+
# of the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'dbi'
|
20
|
+
|
21
|
+
require 'sqlyzer/errors'
|
22
|
+
|
23
|
+
module Sqlyzer
|
24
|
+
|
25
|
+
#
|
26
|
+
#Static class assuming connectivity and traffic to remote database server.
|
27
|
+
#It's a pure ruby interface to Ruby DBI Api, offering some usage improvements.
|
28
|
+
#
|
29
|
+
class Db
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
#
|
34
|
+
#Class variable storing current DBI connexion to the database.
|
35
|
+
#
|
36
|
+
@@handle = nil
|
37
|
+
|
38
|
+
#
|
39
|
+
#This method is called by do, query_hash and query_array to manage
|
40
|
+
#error handling.
|
41
|
+
#
|
42
|
+
#Throws Sqlyzer::NotConnectedError and Sqlyzer::RequestError.
|
43
|
+
#
|
44
|
+
def Db._safe_request(request)
|
45
|
+
raise Sqlyzer::NotConnectedError unless @@handle
|
46
|
+
begin
|
47
|
+
yield request
|
48
|
+
rescue DBI::Error
|
49
|
+
raise Sqlyzer::RequestError, request
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
public
|
54
|
+
|
55
|
+
#
|
56
|
+
#This method will try to establish the connexion to remote database server from
|
57
|
+
#given _api_, _hostname_, _database_, _username_ and _password_.
|
58
|
+
#Method call will assign _handle_ class attribute.
|
59
|
+
#
|
60
|
+
#Throws Sqlyzer::ConnexionError.
|
61
|
+
#
|
62
|
+
def Db.connect(api, hostname, database, username, password)
|
63
|
+
begin
|
64
|
+
@@handle = DBI.connect("DBI:#{api}:#{database}:#{hostname}", username, password)
|
65
|
+
rescue DBI::Error
|
66
|
+
raise Sqlyzer::ConnexionError, "#{username}@DBI:#{api}:#{database}:#{hostname}"
|
67
|
+
else
|
68
|
+
true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
public
|
73
|
+
|
74
|
+
#
|
75
|
+
#Retreive the Array containing the table list in current database.
|
76
|
+
#
|
77
|
+
#Throws Sqlyzer::NotConnectedError.
|
78
|
+
#
|
79
|
+
def Db.tables
|
80
|
+
raise Sqlyzer::NotConnectedError unless @@handle
|
81
|
+
@@handle.tables
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
#Send given _request_ to the database, doesn't expect any return value.
|
86
|
+
#Mostly used with CREATE, ALTER, INSERT, UPDATE or DELETE Sql commands.
|
87
|
+
#
|
88
|
+
def Db.do(request)
|
89
|
+
Db::_safe_request(request) { |r|
|
90
|
+
@@handle.do r
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
#Send given _request_ to the database and expect a return value as an array
|
96
|
+
#from the remote server. Each tupple will be passed through a yield call, enabling
|
97
|
+
#user to process a request result just like Array#each.
|
98
|
+
#Mostly used with SELECT Sql command.
|
99
|
+
#
|
100
|
+
#If no block is given, return do call value.
|
101
|
+
#
|
102
|
+
def Db.query_array(request)
|
103
|
+
return Db::do(request) unless block_given?
|
104
|
+
Db::_safe_request(request) { |r|
|
105
|
+
sth = @@handle.execute r
|
106
|
+
while row = sth.fetch
|
107
|
+
yield row
|
108
|
+
end
|
109
|
+
sth.finish
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
#Send given _request_ to the database and expect a return value as a Hash
|
115
|
+
#from the remote server. Each tupple will be passed through a yield call, enabling
|
116
|
+
#user to process a request result just like Hash#each.
|
117
|
+
#Mostly used with SELECT Sql command.
|
118
|
+
#
|
119
|
+
#If no block is given, return do call value.
|
120
|
+
#
|
121
|
+
def Db.query_hash(request)
|
122
|
+
return Db::do(request) unless block_given?
|
123
|
+
Db::_safe_request(request) { |r|
|
124
|
+
sth = @@handle.execute r
|
125
|
+
while row = sth.fetch_hash
|
126
|
+
yield row
|
127
|
+
end
|
128
|
+
sth.finish
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
#Alias to query_hash.
|
134
|
+
#
|
135
|
+
def Db.query(request, &block)
|
136
|
+
query_hash(request, &block)
|
137
|
+
end
|
138
|
+
|
139
|
+
end #~ Db
|
140
|
+
|
141
|
+
end #~ Sqlyzer
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# SQLYZER Ruby Object serializer to SQL.
|
2
|
+
# For more information visit http://sqlyzer.rubyforge.org
|
3
|
+
#
|
4
|
+
# This program is free software; you can redistribute it and/or
|
5
|
+
# modify it under the terms of the GNU General Public License
|
6
|
+
# as published by the Free Software Foundation; either version 2
|
7
|
+
# of the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
17
|
+
#
|
18
|
+
|
19
|
+
module Sqlyzer
|
20
|
+
|
21
|
+
#
|
22
|
+
#Sqlyzer main Error class.
|
23
|
+
#
|
24
|
+
#All other errors from this module are inherited from Sqlyzer::Error :
|
25
|
+
#* Sqlyzer::DatabaseError
|
26
|
+
#* Sqlyzer::NotConnectedError
|
27
|
+
#* Sqlyzer::ConnexionError
|
28
|
+
#* Sqlyzer::RequestError
|
29
|
+
#
|
30
|
+
class Error < ::RuntimeError
|
31
|
+
end #~ Error
|
32
|
+
|
33
|
+
#
|
34
|
+
#Database main Error class.
|
35
|
+
#
|
36
|
+
#All other errors relating Database are inherited from Sqlyzer::DatabaseError :
|
37
|
+
#* Sqlyzer::NotConnectedError
|
38
|
+
#* Sqlyzer::ConnexionError
|
39
|
+
#* Sqlyzer::RequestError
|
40
|
+
#
|
41
|
+
class DatabaseError < Error
|
42
|
+
end #~ DatabaseError
|
43
|
+
|
44
|
+
#
|
45
|
+
#Raised when calling an instruction which need a database connectivity before
|
46
|
+
#calling Sqlyzer::Db::connect to establish connexion.
|
47
|
+
#
|
48
|
+
class NotConnectedError < DatabaseError
|
49
|
+
def initialize
|
50
|
+
super "You have to call Sqlyzer::Db::connect at the top of your code before running this command.\nSee RDoc for more instructions."
|
51
|
+
end
|
52
|
+
end #~ NotConnectedError
|
53
|
+
|
54
|
+
#
|
55
|
+
#Raised when an error is caught during connexion to the database.
|
56
|
+
#
|
57
|
+
class ConnexionError < DatabaseError
|
58
|
+
def initialize(connexion_string)
|
59
|
+
super "Received error : #{$!.to_s.chomp}\nfor DBI connexion string : '#{connexion_string}'"
|
60
|
+
end
|
61
|
+
end #~ ConnexionError
|
62
|
+
|
63
|
+
#
|
64
|
+
#Raised when an invalid Sql request is sent to the database.
|
65
|
+
#
|
66
|
+
#Development will aim at never raise such error (as the user doesn't have to
|
67
|
+
#deal with Sql).
|
68
|
+
#
|
69
|
+
class RequestError < DatabaseError
|
70
|
+
def initialize(request)
|
71
|
+
super "Received error : #{$!.to_s.chomp}\nfor DBI sql request : '#{request}'"
|
72
|
+
end
|
73
|
+
end #~ RequestError
|
74
|
+
|
75
|
+
end #~ Sqlyzer
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# SQLYZER Ruby Object serializer to SQL.
|
2
|
+
# For more information visit http://sqlyzer.rubyforge.org
|
3
|
+
#
|
4
|
+
# This program is free software; you can redistribute it and/or
|
5
|
+
# modify it under the terms of the GNU General Public License
|
6
|
+
# as published by the Free Software Foundation; either version 2
|
7
|
+
# of the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'singleton'
|
20
|
+
|
21
|
+
require 'sqlyzer/errors'
|
22
|
+
require 'sqlyzer/db'
|
23
|
+
require 'sqlyzer/request'
|
24
|
+
|
25
|
+
module Sqlyzer
|
26
|
+
|
27
|
+
#
|
28
|
+
#Singleton class handling generation and execution of all Sql commands.
|
29
|
+
#This is the only place where Sql requests are executed.
|
30
|
+
#
|
31
|
+
class Handler
|
32
|
+
include Singleton
|
33
|
+
|
34
|
+
public
|
35
|
+
|
36
|
+
#
|
37
|
+
#Register an instance of class extended with Sqlyzer::Serializer.
|
38
|
+
#This method will create the Sql table associated with _sender_ class if there
|
39
|
+
#is no table named like _sender_#sql_container_table().
|
40
|
+
#
|
41
|
+
def register_sender(sender)
|
42
|
+
Db::do sender.sql_serialize(:sql_table) unless
|
43
|
+
Db::tables.include?(sender.sql_container_table)
|
44
|
+
end
|
45
|
+
|
46
|
+
public
|
47
|
+
|
48
|
+
#
|
49
|
+
#Static method called by Sqlyzer::Serializer to request execution and generation of
|
50
|
+
#every Sql command.
|
51
|
+
#The command to generate and execute is determined by _action_ Symbol value :
|
52
|
+
#* :sql_select,
|
53
|
+
#* :sql_insert,
|
54
|
+
#* :sql_update,
|
55
|
+
#* :sql_delete.
|
56
|
+
#
|
57
|
+
#When _action_ value is :sql_select, this method restore all _sender_ attributes from data
|
58
|
+
#returned by generated Sql SELECT command execution.
|
59
|
+
#
|
60
|
+
#When _sender_ call this method for the first time, it is automatically registered
|
61
|
+
#through register_sender.
|
62
|
+
#
|
63
|
+
#TODO: This method is very trivial for now, but further optimizations of Sql
|
64
|
+
#commands execution timelime have to go there.
|
65
|
+
#
|
66
|
+
def Handler.request(sender, action)
|
67
|
+
Handler.instance.register_sender sender
|
68
|
+
case action
|
69
|
+
when :sql_select then
|
70
|
+
Db::query(sender.sql_serialize(:sql_select)) { |data|
|
71
|
+
data.each { |key, value|
|
72
|
+
attrib = sender.sql_container_values[key]
|
73
|
+
if attrib.nil?
|
74
|
+
sender.sql_container_keys[key].to_owner(sender, value)
|
75
|
+
else
|
76
|
+
attrib.to_owner(sender, value)
|
77
|
+
end
|
78
|
+
}
|
79
|
+
}
|
80
|
+
else
|
81
|
+
Db::do(sender.sql_serialize(action))
|
82
|
+
end
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
86
|
+
end #~ Handler
|
87
|
+
|
88
|
+
end #~ Sqlyzer
|
@@ -0,0 +1,448 @@
|
|
1
|
+
# SQLYZER Ruby Object serializer to SQL.
|
2
|
+
# For more information visit http://sqlyzer.rubyforge.org
|
3
|
+
#
|
4
|
+
# This program is free software; you can redistribute it and/or
|
5
|
+
# modify it under the terms of the GNU General Public License
|
6
|
+
# as published by the Free Software Foundation; either version 2
|
7
|
+
# of the License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'sqlyzer/errors'
|
20
|
+
|
21
|
+
module Sqlyzer
|
22
|
+
|
23
|
+
#
|
24
|
+
#Handling of class attributes to serialize
|
25
|
+
#
|
26
|
+
module Parameter
|
27
|
+
|
28
|
+
#
|
29
|
+
#Every Sql type Mixin with serialize/unserialize procedures
|
30
|
+
#
|
31
|
+
module Types
|
32
|
+
|
33
|
+
public
|
34
|
+
|
35
|
+
#Sql Integer type Mixin
|
36
|
+
module Int
|
37
|
+
def to_sql_type; 'INT'; end
|
38
|
+
end #~ Int
|
39
|
+
|
40
|
+
#Sql Integer2 type Mixin
|
41
|
+
module Int2
|
42
|
+
def to_sql_type; 'INT2'; end
|
43
|
+
end #~ Int2
|
44
|
+
|
45
|
+
#Sql Integer4 type Mixin
|
46
|
+
module Int4
|
47
|
+
def to_sql_type; 'INT4'; end
|
48
|
+
end #~ Int4
|
49
|
+
|
50
|
+
#Sql Integer8 type Mixin
|
51
|
+
module Int8
|
52
|
+
def to_sql_type; 'INT8'; end
|
53
|
+
end #~ Int8
|
54
|
+
|
55
|
+
#Sql Float type Mixin
|
56
|
+
module Float
|
57
|
+
def to_sql_type; 'FLOAT'; end
|
58
|
+
end #~ Float
|
59
|
+
|
60
|
+
#Sql Float4 type Mixin
|
61
|
+
module Float4
|
62
|
+
def to_sql_type; 'FLOAT4'; end
|
63
|
+
end #~ Float4
|
64
|
+
|
65
|
+
#Sql Float8 type Mixin
|
66
|
+
module Float8
|
67
|
+
def to_sql_type; 'FLOAT8'; end
|
68
|
+
end #~ Float8
|
69
|
+
|
70
|
+
#Sql Boolean type Mixin
|
71
|
+
module Bool
|
72
|
+
def to_sql_type; 'BOOL'; end
|
73
|
+
end #~ Bool
|
74
|
+
|
75
|
+
#Sql Text type Mixin
|
76
|
+
module Text
|
77
|
+
def to_sql_type; 'TEXT'; end
|
78
|
+
#Ruby String to Sql Text serialization with Sql escaping notation.
|
79
|
+
def to_sql(owner)
|
80
|
+
"E'#{super(owner).to_s.gsub "'", "\\'"}'"
|
81
|
+
end
|
82
|
+
end #~ Text
|
83
|
+
|
84
|
+
#Sql Varchar type Mixin
|
85
|
+
module VarChar
|
86
|
+
#Return _VARCHAR_ if no capacity was specified by the user.
|
87
|
+
def to_sql_type
|
88
|
+
return 'VARCHAR' if @capacity.nil?
|
89
|
+
"VARCHAR(#{@capacity})"
|
90
|
+
end #
|
91
|
+
#Overload default parameter assigment for setting VarChar capacity with a Ruby Range object.
|
92
|
+
def /(default)
|
93
|
+
@capacity = default.max
|
94
|
+
super ''
|
95
|
+
end
|
96
|
+
#Ruby String to Sql Varchar serialization like Text, but truncate the String if too long.
|
97
|
+
def to_sql(owner)
|
98
|
+
if @capacity.nil?
|
99
|
+
"E'#{super(owner).to_s.gsub "'", "\\'"}'"
|
100
|
+
else
|
101
|
+
"E'#{super(owner).to_s[0..@capacity - 1].gsub "'", "\\'"}'"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end #~ VarChar
|
105
|
+
|
106
|
+
#Sql Date type Mixin
|
107
|
+
module Date
|
108
|
+
def to_sql_type; 'DATE'; end
|
109
|
+
#Ruby Time object to Sql Date String representation
|
110
|
+
def to_sql(owner)
|
111
|
+
sql_parameter_eval(owner).strftime "'%Y-%m-%d'"
|
112
|
+
end
|
113
|
+
#DBI::Date object to Ruby Time
|
114
|
+
def to_owner(owner, data)
|
115
|
+
sql_parameter_set owner, data.to_time
|
116
|
+
end
|
117
|
+
end #~ Date
|
118
|
+
|
119
|
+
#Sql Time type Mixin
|
120
|
+
module Time
|
121
|
+
def to_sql_type; 'TIME'; end
|
122
|
+
#Ruby Time object to Sql Time String representation
|
123
|
+
def to_sql(owner)
|
124
|
+
sql_parameter_eval(owner).strftime "'%H:%M:%S'"
|
125
|
+
end
|
126
|
+
#Sql Time type to Ruby Time object
|
127
|
+
def to_owner(owner, data)
|
128
|
+
sql_parameter_set owner, ::Time.parse(data)
|
129
|
+
end
|
130
|
+
end #~ Time
|
131
|
+
|
132
|
+
#Sql DateTime type Mixin
|
133
|
+
module DateTime
|
134
|
+
def to_sql_type; 'DATETIME'; end
|
135
|
+
#Ruby Time object to Sql DateTime String representation
|
136
|
+
def to_sql(owner)
|
137
|
+
sql_parameter_eval(owner).strftime "'%Y-%m-%d %H:%M:%S'"
|
138
|
+
end
|
139
|
+
#DBI::DateTime object to Ruby Time object
|
140
|
+
def to_owner(owner, data)
|
141
|
+
sql_parameter_set owner, data.to_time
|
142
|
+
end
|
143
|
+
end #~ DateTime
|
144
|
+
|
145
|
+
public
|
146
|
+
|
147
|
+
module Alias
|
148
|
+
|
149
|
+
#Constant alias for Sqlyzer::Parameter::Types::Int
|
150
|
+
SQL_INT = Sqlyzer::Parameter::Types::Int
|
151
|
+
#Constant alias for Sqlyzer::Parameter::Types::Int2
|
152
|
+
SQL_INT2 = Sqlyzer::Parameter::Types::Int2
|
153
|
+
#Constant alias for Sqlyzer::Parameter::Types::Int4
|
154
|
+
SQL_INT4 = Sqlyzer::Parameter::Types::Int4
|
155
|
+
#Constant alias for Sqlyzer::Parameter::Types::Int8
|
156
|
+
SQL_INT8 = Sqlyzer::Parameter::Types::Int8
|
157
|
+
#Constant alias for Sqlyzer::Parameter::Types::Float
|
158
|
+
SQL_FLOAT = Sqlyzer::Parameter::Types::Float
|
159
|
+
#Constant alias for Sqlyzer::Parameter::Types::Float4
|
160
|
+
SQL_FLOAT4 = Sqlyzer::Parameter::Types::Float4
|
161
|
+
#Constant alias for Sqlyzer::Parameter::Types::Float8
|
162
|
+
SQL_FLOAT8 = Sqlyzer::Parameter::Types::Float8
|
163
|
+
#Constant alias for Sqlyzer::Parameter::Types::Bool
|
164
|
+
SQL_BOOL = Sqlyzer::Parameter::Types::Bool
|
165
|
+
#Constant alias for Sqlyzer::Parameter::Types::Text
|
166
|
+
SQL_TEXT = Sqlyzer::Parameter::Types::Text
|
167
|
+
#Constant alias for Sqlyzer::Parameter::Types::VarChar
|
168
|
+
SQL_VARCHAR = Sqlyzer::Parameter::Types::VarChar
|
169
|
+
#Constant alias for Sqlyzer::Parameter::Types::Date
|
170
|
+
SQL_DATE = Sqlyzer::Parameter::Types::Date
|
171
|
+
#Constant alias for Sqlyzer::Parameter::Types::Time
|
172
|
+
SQL_TIME = Sqlyzer::Parameter::Types::Time
|
173
|
+
#Constant alias for Sqlyzer::Parameter::Types::DateTime
|
174
|
+
SQL_DATETIME = Sqlyzer::Parameter::Types::DateTime
|
175
|
+
|
176
|
+
end #~ Alias
|
177
|
+
|
178
|
+
end #~ Types
|
179
|
+
|
180
|
+
#
|
181
|
+
#Proxy class for Symbol. Permit to extend a Symbol class with coresponding
|
182
|
+
#Sql type handling Mixin.
|
183
|
+
#
|
184
|
+
#This class mainly exists to enable extending a Symbol, which is not possible
|
185
|
+
#with Ruby regular Symbol class. This is nearly an abstract class (as Ruby doesn't
|
186
|
+
#really implement this concept) and must be extended with coresponding Sql type Mixin.
|
187
|
+
#If no type specification is given, the class will be considered as a
|
188
|
+
#Sqlyzer::Parameter::Types::Text attribute.
|
189
|
+
#
|
190
|
+
class Default
|
191
|
+
include Comparable
|
192
|
+
|
193
|
+
attr_reader :symbol
|
194
|
+
|
195
|
+
public
|
196
|
+
|
197
|
+
#
|
198
|
+
#Constructor method. The fresh Default object will possess _symbol_ as @symbol attribute.
|
199
|
+
#
|
200
|
+
def initialize(symbol)
|
201
|
+
@symbol = symbol
|
202
|
+
end
|
203
|
+
|
204
|
+
private
|
205
|
+
|
206
|
+
#
|
207
|
+
#Evaluate the Symbol value in the given _owner_ object.
|
208
|
+
#If Symbol does not exists in _owner_, try to reach default value else raise
|
209
|
+
#an error.
|
210
|
+
#
|
211
|
+
def sql_parameter_eval(owner)
|
212
|
+
begin
|
213
|
+
res = owner.send(@symbol)
|
214
|
+
return res unless res.nil?
|
215
|
+
@default
|
216
|
+
rescue => err
|
217
|
+
raise err unless @default
|
218
|
+
@default
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
#
|
223
|
+
#Assign the Symbol _value_ in to _owner_ object.
|
224
|
+
#
|
225
|
+
def sql_parameter_set(owner, value)
|
226
|
+
owner.method("#{@symbol}=").call value
|
227
|
+
end
|
228
|
+
|
229
|
+
#
|
230
|
+
#Set parameter default in case of non existent Symbol.
|
231
|
+
#
|
232
|
+
#See sql_parameter_eval.
|
233
|
+
#
|
234
|
+
def sql_parameter_default(val)
|
235
|
+
@default = val
|
236
|
+
end
|
237
|
+
|
238
|
+
public
|
239
|
+
|
240
|
+
#
|
241
|
+
#Implement the Ruby Comparable Mixin, enabling to compare Default
|
242
|
+
#with Default, Symbol or String (in this order).
|
243
|
+
#
|
244
|
+
def <=>(other)
|
245
|
+
if other.kind_of?(Default)
|
246
|
+
@symbol.to_i <=> other.symbol.to_i
|
247
|
+
elsif other.kind_of?(Symbol)
|
248
|
+
@symbol.to_i <=> other.to_i
|
249
|
+
else
|
250
|
+
@symbol.to_s <=> other.to_s
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
#
|
255
|
+
#Call sql_parameter_default and return _self_.
|
256
|
+
#
|
257
|
+
def /(default)
|
258
|
+
sql_parameter_default default
|
259
|
+
self
|
260
|
+
end
|
261
|
+
|
262
|
+
#
|
263
|
+
#Call contained Symbol to_s method.
|
264
|
+
#
|
265
|
+
def to_s
|
266
|
+
@symbol.to_s
|
267
|
+
end
|
268
|
+
|
269
|
+
#
|
270
|
+
#Return the Sql type name of the current instance.
|
271
|
+
#
|
272
|
+
#This method will raise an error unless current instance was extend with
|
273
|
+
#coresponding Sql type Mixin.
|
274
|
+
#
|
275
|
+
def to_sql_type
|
276
|
+
raise 'unreached'
|
277
|
+
end
|
278
|
+
|
279
|
+
#
|
280
|
+
#Serialize the Symbol value contained in _owner_ to Sql representation.
|
281
|
+
#
|
282
|
+
def to_sql(owner)
|
283
|
+
sql_parameter_eval(owner).to_s
|
284
|
+
end
|
285
|
+
|
286
|
+
#
|
287
|
+
#Unserialize Sql representation of _data_ to assign it to _owner_.
|
288
|
+
#
|
289
|
+
def to_owner(owner, data)
|
290
|
+
sql_parameter_set(owner, data)
|
291
|
+
end
|
292
|
+
|
293
|
+
public
|
294
|
+
|
295
|
+
#
|
296
|
+
#Create an instance of Default by giving a Symbol and a default value.
|
297
|
+
#Coresponding Sql type Mixin will be determined from default value type.
|
298
|
+
#
|
299
|
+
#Here is the list of coresponding Sql type for each Ruby class handled :
|
300
|
+
#* Integer, Fixnum <=> Sqlyzer::Parameter::Types::Int (SQL_INT),
|
301
|
+
#* Float <=> Sqlyzer::Parameter::Types::Float (SQL_FLOAT),
|
302
|
+
#* Time <=> Sqlyzer::Parameter::Types::Date (SQL_DATE),
|
303
|
+
#* TrueClass, FalseClass <=> Sqlyzer::Parameter::Types::Bool (SQL_BOOL),
|
304
|
+
#* Range <=> Sqlyzer::Parameter::Types::VarChar (SQL_VARCHAR).
|
305
|
+
#
|
306
|
+
#Any other Ruby class will be considered as a Sqlyzer::Parameter::Types::Text (SQL_TEXT).
|
307
|
+
#
|
308
|
+
def Default.get_from_default(symbol, val)
|
309
|
+
res = Default.new(symbol)
|
310
|
+
case val
|
311
|
+
when Object::Integer, Object::Fixnum then
|
312
|
+
res.extend Types::Alias::SQL_INT
|
313
|
+
when Object::Float then
|
314
|
+
res.extend Types::Alias::SQL_FLOAT
|
315
|
+
when Object::Time then
|
316
|
+
res.extend Types::Alias::SQL_DATE
|
317
|
+
when Object::TrueClass, Object::FalseClass then
|
318
|
+
res.extend Types::Alias::SQL_BOOL
|
319
|
+
when Object::Range then
|
320
|
+
res.extend Types::Alias::SQL_VARCHAR
|
321
|
+
else
|
322
|
+
res.extend Types::Alias::SQL_TEXT
|
323
|
+
end
|
324
|
+
res/val
|
325
|
+
end
|
326
|
+
|
327
|
+
#
|
328
|
+
#Create a new instance of Default by giving a Symbol and the coresponding
|
329
|
+
#Sql type Mixin.
|
330
|
+
#
|
331
|
+
def Default.get_from_type(symbol, type)
|
332
|
+
res = Default.new(symbol)
|
333
|
+
res.extend type
|
334
|
+
res
|
335
|
+
end
|
336
|
+
|
337
|
+
end #~ Default
|
338
|
+
|
339
|
+
#
|
340
|
+
#Overloaded Array class to store Default class list.
|
341
|
+
#
|
342
|
+
class List < Array
|
343
|
+
|
344
|
+
public
|
345
|
+
|
346
|
+
#
|
347
|
+
#Create a new instance of List with given _elements_ considered as an Array
|
348
|
+
#of Symbol or a List.
|
349
|
+
#If no parameter is given, create an empty List.
|
350
|
+
#
|
351
|
+
def initialize(elements = nil)
|
352
|
+
push_parameters elements if elements
|
353
|
+
end
|
354
|
+
|
355
|
+
public
|
356
|
+
|
357
|
+
#
|
358
|
+
#Return a new Array class containing each contained Default class Sql representation
|
359
|
+
#from values retreived in _owner_.
|
360
|
+
#
|
361
|
+
def to_sql(owner)
|
362
|
+
collect { |symbol|
|
363
|
+
symbol.to_sql owner
|
364
|
+
}
|
365
|
+
end
|
366
|
+
|
367
|
+
public
|
368
|
+
|
369
|
+
#
|
370
|
+
#Search trough contained Default classes for _key_.
|
371
|
+
#_key_ should be a Default class, a Symbol or a String.
|
372
|
+
#
|
373
|
+
#See Default#<=> for more informations.
|
374
|
+
#
|
375
|
+
def fetch_parameter(key)
|
376
|
+
each { |parameter|
|
377
|
+
if parameter == key
|
378
|
+
yield parameter if block_given?
|
379
|
+
return parameter
|
380
|
+
end
|
381
|
+
}
|
382
|
+
nil
|
383
|
+
end
|
384
|
+
alias [] fetch_parameter
|
385
|
+
|
386
|
+
public
|
387
|
+
|
388
|
+
#
|
389
|
+
#Push a _symbol_ on the top of the Array.
|
390
|
+
#_symbol_ should be Default class or a Symbol. If _symbol_ is a Symbol, it
|
391
|
+
#will be automatically converted to a Default class extended with Text Sql
|
392
|
+
#type handling.
|
393
|
+
#
|
394
|
+
def push(symbol)
|
395
|
+
return if include?(symbol)
|
396
|
+
if symbol.kind_of?(Default)
|
397
|
+
super symbol
|
398
|
+
else
|
399
|
+
super(symbol/Sqlyzer::Parameter::Types::Text)
|
400
|
+
end
|
401
|
+
end
|
402
|
+
alias push_parameter push
|
403
|
+
alias << push
|
404
|
+
|
405
|
+
#
|
406
|
+
#Push each item of _data_ Array by calling previous push_paramether method.
|
407
|
+
#
|
408
|
+
def push_parameters(data)
|
409
|
+
data.each { |symbol|
|
410
|
+
push symbol
|
411
|
+
}
|
412
|
+
self
|
413
|
+
end
|
414
|
+
alias + push_parameters
|
415
|
+
|
416
|
+
#
|
417
|
+
#Overloaded version on Array#join to handle suffix on each element.
|
418
|
+
#
|
419
|
+
def join(separator = ', ', suffix = '')
|
420
|
+
"#{super("#{suffix}#{separator}")}#{suffix}"
|
421
|
+
end
|
422
|
+
alias join_parameters join
|
423
|
+
|
424
|
+
end #~ List
|
425
|
+
|
426
|
+
end #~ Parameter
|
427
|
+
end #~ Sqlyzer
|
428
|
+
|
429
|
+
#
|
430
|
+
#Extend regular Symbol class of Ruby to enable sexy explicit Sql type cast
|
431
|
+
#through divide (/) operator.
|
432
|
+
#
|
433
|
+
class Symbol
|
434
|
+
#
|
435
|
+
#Create a new instance of Sqlyzer::Parameter::Default containing current Symbol
|
436
|
+
#instance.
|
437
|
+
#If _param_ is a Ruby Module, the new Sqlyzer::Parameter::Default class will be
|
438
|
+
#generated by calling Sqlyzer::Parameter::Default::get_from_type(), else from
|
439
|
+
#Sqlyzer::Parameter::Default::get_from_default().
|
440
|
+
#
|
441
|
+
def /(param)
|
442
|
+
if param.kind_of?(Module)
|
443
|
+
Sqlyzer::Parameter::Default.get_from_type self, param
|
444
|
+
else
|
445
|
+
Sqlyzer::Parameter::Default.get_from_default self, param
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end #~ Symbol
|