orientdb 1.2.0-java
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/.document +5 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +32 -0
- data/LICENSE +20 -0
- data/README.rdoc +88 -0
- data/Rakefile +58 -0
- data/bin/orientdb_console +23 -0
- data/lib/jars/blueprints-core-2.2.0-SNAPSHOT.jar +0 -0
- data/lib/jars/blueprints-orient-graph-2.2.0-SNAPSHOT.jar +0 -0
- data/lib/jars/orient-commons-1.2.0.jar +0 -0
- data/lib/jars/orientdb-client-1.2.0.jar +0 -0
- data/lib/jars/orientdb-core-1.2.0.jar +0 -0
- data/lib/jars/orientdb-distributed-1.2.0.jar +0 -0
- data/lib/jars/orientdb-enterprise-1.2.0.jar +0 -0
- data/lib/jars/orientdb-graphdb-1.2.0.jar +0 -0
- data/lib/jars/orientdb-server-1.2.0.jar +0 -0
- data/lib/jars/orientdb-tools-1.2.0.jar +0 -0
- data/lib/jars/pipes-2.0.0-SNAPSHOT.jar +0 -0
- data/lib/orientdb.rb +29 -0
- data/lib/orientdb/constants.rb +57 -0
- data/lib/orientdb/database.rb +167 -0
- data/lib/orientdb/document.rb +78 -0
- data/lib/orientdb/ext.rb +13 -0
- data/lib/orientdb/oclass.rb +141 -0
- data/lib/orientdb/property.rb +37 -0
- data/lib/orientdb/record.rb +18 -0
- data/lib/orientdb/rid.rb +46 -0
- data/lib/orientdb/schema.rb +33 -0
- data/lib/orientdb/sql.rb +18 -0
- data/lib/orientdb/sql/common.rb +247 -0
- data/lib/orientdb/sql/delete.rb +23 -0
- data/lib/orientdb/sql/ext.rb +249 -0
- data/lib/orientdb/sql/insert.rb +37 -0
- data/lib/orientdb/sql/query.rb +138 -0
- data/lib/orientdb/sql/update.rb +57 -0
- data/lib/orientdb/storage.rb +51 -0
- data/lib/orientdb/version.rb +3 -0
- data/orientdb.gemspec +96 -0
- data/spec/database_spec.rb +111 -0
- data/spec/document_spec.rb +99 -0
- data/spec/graph_spec.rb +39 -0
- data/spec/orientdb_spec.rb +10 -0
- data/spec/spec.opts +7 -0
- data/spec/spec_basic_helper.rb +25 -0
- data/spec/spec_helper.rb +68 -0
- data/spec/sql_spec.rb +839 -0
- data/spec/tinkerpop_graph_spec.rb +32 -0
- metadata +165 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
module OrientDB
|
2
|
+
|
3
|
+
class Document
|
4
|
+
|
5
|
+
def values
|
6
|
+
field_names.map { |field_name| [field_name, self[field_name]] }
|
7
|
+
end
|
8
|
+
|
9
|
+
alias :db :database
|
10
|
+
|
11
|
+
def [](field_name)
|
12
|
+
field field_name.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
def []=(field_name, value)
|
16
|
+
field field_name.to_s, value
|
17
|
+
end
|
18
|
+
|
19
|
+
def field?(name)
|
20
|
+
contains_field(name.to_s) || (schema_class && schema_class.exists_property?(name.to_s))
|
21
|
+
end
|
22
|
+
|
23
|
+
def respond_to?(method_name)
|
24
|
+
return true if field?(method_name.to_s)
|
25
|
+
match = method_name.to_s.match(/(.*?)([?=!]?)$/)
|
26
|
+
return true if match[2] == '='
|
27
|
+
return true if match[2] == '?' && field?(match[1])
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
def method_missing(method_name, *args, &blk)
|
32
|
+
return self[method_name] if field?(method_name)
|
33
|
+
|
34
|
+
match = method_name.to_s.match(/(.*?)([?=!]?)$/)
|
35
|
+
case match[2]
|
36
|
+
when "="
|
37
|
+
self[match[1]] = args.first
|
38
|
+
when "?"
|
39
|
+
field(match[1]) ? !!self[match[1]] : super
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def rid
|
46
|
+
identity.to_s
|
47
|
+
end
|
48
|
+
|
49
|
+
def inspect
|
50
|
+
props = values.map { |k, v| "#{k}:#{v.inspect}" }.join(' ')
|
51
|
+
%{#<OrientDB::Document:#{class_name}:#{rid}#{props.empty? ? '' : ' ' + props}>}
|
52
|
+
end
|
53
|
+
|
54
|
+
alias :to_s :inspect
|
55
|
+
|
56
|
+
class << self
|
57
|
+
|
58
|
+
alias_method :native_new, :new
|
59
|
+
|
60
|
+
def new(db, klass_name, fields = {})
|
61
|
+
obj = native_new db, klass_name.to_s
|
62
|
+
fields.each do |name, value|
|
63
|
+
obj.field name.to_s, value
|
64
|
+
end
|
65
|
+
obj
|
66
|
+
end
|
67
|
+
|
68
|
+
def create(db, klass_name, fields = {})
|
69
|
+
obj = new db, klass_name, fields
|
70
|
+
obj.save
|
71
|
+
obj
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
data/lib/orientdb/ext.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
module OrientDB
|
2
|
+
|
3
|
+
class OClassImpl
|
4
|
+
|
5
|
+
def type_for(value)
|
6
|
+
self.class.type_for value, schema
|
7
|
+
end
|
8
|
+
|
9
|
+
def add(property_name, type, options = { })
|
10
|
+
property_name = property_name.to_s
|
11
|
+
if exists_property(property_name)
|
12
|
+
puts "We already have that property name [#{property_name}]"
|
13
|
+
return false
|
14
|
+
end
|
15
|
+
|
16
|
+
type = type.oclass if type.respond_to?(:oclass)
|
17
|
+
case type
|
18
|
+
when SchemaType
|
19
|
+
prop = create_property property_name, type
|
20
|
+
when Symbol
|
21
|
+
prop = create_property property_name, type_for(type)
|
22
|
+
when OClassImpl
|
23
|
+
prop = create_property property_name, type_for(:link), type
|
24
|
+
when Array
|
25
|
+
type, sub_type = type_for(type.first), type_for(type.last)
|
26
|
+
prop = create_property property_name, type, sub_type
|
27
|
+
else
|
28
|
+
raise "ERROR! Unknown type [ #{property_name} | #{type} : #{type.class.name} ]"
|
29
|
+
end
|
30
|
+
|
31
|
+
prop.set_min options[:min].to_s unless options[:min].nil?
|
32
|
+
prop.set_max options[:max].to_s unless options[:max].nil?
|
33
|
+
prop.set_mandatory !!options[:mandatory] unless options[:mandatory].nil?
|
34
|
+
prop.set_not_null options[:not_null] unless options[:not_null].nil?
|
35
|
+
unless options[:index].nil?
|
36
|
+
index_type = options[:index] == true ? INDEX_TYPES[:notunique] : INDEX_TYPES[options[:index]]
|
37
|
+
prop.createIndex index_type
|
38
|
+
end
|
39
|
+
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_index
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
def [](property_name)
|
48
|
+
property_name = property_name.to_s
|
49
|
+
exists_property(property_name) ? get_property(property_name) : nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def db
|
53
|
+
document.database
|
54
|
+
end
|
55
|
+
|
56
|
+
def schema
|
57
|
+
db.metadata.schema
|
58
|
+
end
|
59
|
+
|
60
|
+
def inspect
|
61
|
+
props = properties.map { |x| "#{x.name}=#{x.type.name}#{x.is_indexed? ? '(idx)' : ''}" }.join(' ')
|
62
|
+
"#<OrientDB::OClassImpl:" + name +
|
63
|
+
(getSuperClass ? ' super=' + getSuperClass.name : '') +
|
64
|
+
(props.empty? ? '' : ' ' + props) +
|
65
|
+
">"
|
66
|
+
end
|
67
|
+
|
68
|
+
alias :to_s :inspect
|
69
|
+
|
70
|
+
class << self
|
71
|
+
|
72
|
+
def type_for(value, schema)
|
73
|
+
value = value.oclass if value.respond_to?(:oclass)
|
74
|
+
type = case value
|
75
|
+
when OrientDB::SchemaType, OrientDB::OClassImpl
|
76
|
+
value
|
77
|
+
when String
|
78
|
+
if schema.exists_class?(value)
|
79
|
+
schema.get_class(value)
|
80
|
+
else
|
81
|
+
FIELD_TYPES[value.to_sym]
|
82
|
+
end
|
83
|
+
when Symbol
|
84
|
+
FIELD_TYPES[value]
|
85
|
+
else
|
86
|
+
FIELD_TYPES[value.to_s.to_sym]
|
87
|
+
end
|
88
|
+
raise "Uknown schema type for [#{value}] (#{value.class.name})" unless type
|
89
|
+
type
|
90
|
+
end
|
91
|
+
|
92
|
+
def create(db, name, fields = { })
|
93
|
+
name = name.to_s
|
94
|
+
add_cluster = fields.delete :add_cluster
|
95
|
+
add_cluster = true if add_cluster.nil?
|
96
|
+
use_cluster = fields.delete :use_cluster
|
97
|
+
|
98
|
+
if db.schema.exists_class? name
|
99
|
+
klass = db.get_class name
|
100
|
+
else
|
101
|
+
if use_cluster
|
102
|
+
klass = db.schema.create_class name, use_cluster
|
103
|
+
elsif add_cluster && !db.storage.cluster_names.include?(name.downcase)
|
104
|
+
#debugger
|
105
|
+
cluster = db.storage.add_cluster STORAGE_TYPES[:physical], name.downcase, "/tmp/database", 'default', {}
|
106
|
+
klass = db.schema.create_class name, cluster
|
107
|
+
else
|
108
|
+
klass = db.schema.create_class name
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
super_klass = fields.delete :super
|
113
|
+
super_klass = db.get_class(super_klass.to_s) unless super_klass.is_a?(OrientDB::OClassImpl)
|
114
|
+
klass.set_super_class super_klass if super_klass
|
115
|
+
db.schema.save
|
116
|
+
|
117
|
+
unless fields.empty?
|
118
|
+
fields.each do |property_name, type|
|
119
|
+
case type
|
120
|
+
when Symbol, Array, OrientDB::OClassImpl
|
121
|
+
klass.add property_name, type
|
122
|
+
when Hash
|
123
|
+
options = type.dup
|
124
|
+
type = options.delete :type
|
125
|
+
klass.add property_name, type, options
|
126
|
+
else
|
127
|
+
raise "Unknown field options [#{type.inspect}]"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
db.schema.save
|
131
|
+
end
|
132
|
+
|
133
|
+
klass
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module OrientDB
|
2
|
+
class PropertyImpl
|
3
|
+
|
4
|
+
def type_short
|
5
|
+
@type_short ||= OrientDB::FIELD_TYPES.select { |k, v| v.name == getType.name }.first.first
|
6
|
+
end
|
7
|
+
|
8
|
+
def linked_type_short
|
9
|
+
@linked_type_short ||= getLinkedType && OrientDB::FIELD_TYPES.select { |k, v| v.name == getLinkedType.name }.first.first
|
10
|
+
end
|
11
|
+
|
12
|
+
def info
|
13
|
+
{
|
14
|
+
:name => name,
|
15
|
+
:type => type_short,
|
16
|
+
:index => indexed? ? getIndex.name : nil,
|
17
|
+
:min => min,
|
18
|
+
:max => max,
|
19
|
+
:mandatory => is_mandatory?,
|
20
|
+
:not_null => is_not_null?,
|
21
|
+
:linked_type => linked_type_short,
|
22
|
+
:linked_class => linked_type_short ? getLinkedClass.name : nil,
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def inspect
|
27
|
+
"#<OrientDB::Property:#{name} type=#{type_short} " +
|
28
|
+
"#{linked_type_short ? "linked_type=#{linked_type_short} linked_class=#{getLinkedClass.name}" : ''}" +
|
29
|
+
"indexed=#{is_indexed?} mandatory=#{is_mandatory?} not_null=#{is_not_null}" +
|
30
|
+
"#{min ? " min=#{min}" : ''}#{max ? " max=#{max}" : ''}" +
|
31
|
+
">"
|
32
|
+
end
|
33
|
+
|
34
|
+
alias :to_s :inspect
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module OrientDB
|
2
|
+
|
3
|
+
class RecordList
|
4
|
+
def inspect
|
5
|
+
"#<OrientDB::RecordList:#{toString}>"
|
6
|
+
end
|
7
|
+
|
8
|
+
alias :to_s :inspect
|
9
|
+
end
|
10
|
+
|
11
|
+
class RecordSet
|
12
|
+
def inspect
|
13
|
+
"#<OrientDB::RecordSet:#{toString}>"
|
14
|
+
end
|
15
|
+
|
16
|
+
alias :to_s :inspect
|
17
|
+
end
|
18
|
+
end
|
data/lib/orientdb/rid.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
class OrientDB::RID
|
2
|
+
|
3
|
+
attr_reader :cluster_id, :document_id
|
4
|
+
|
5
|
+
def initialize(rid = '#-1:-1')
|
6
|
+
parts = rid.to_s.gsub('#', '').split ":"
|
7
|
+
if parts.size == 2
|
8
|
+
self.cluster_id = parts.first.to_i
|
9
|
+
self.document_id = parts.last.to_i
|
10
|
+
else
|
11
|
+
raise "Unknown rid [#{rid}]"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def cluster_id=(value)
|
16
|
+
@cluster_id = value.to_s.strip.to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
def document_id=(value)
|
20
|
+
@document_id = value.to_s.strip.to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
def inspect
|
24
|
+
"##{cluster_id}:#{@document_id}"
|
25
|
+
end
|
26
|
+
|
27
|
+
alias :to_s :inspect
|
28
|
+
|
29
|
+
def unsaved?
|
30
|
+
to_s == '#-1:-1'
|
31
|
+
end
|
32
|
+
|
33
|
+
def saved?
|
34
|
+
cluster_id > 0 && document_id >= 0
|
35
|
+
end
|
36
|
+
|
37
|
+
def valid?
|
38
|
+
saved? || unsaved?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class String
|
43
|
+
def valid_orientdb_rid?
|
44
|
+
OrientDB::RID.new(self).valid?
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module OrientDB
|
2
|
+
|
3
|
+
#class Schema
|
4
|
+
#
|
5
|
+
# def inspect
|
6
|
+
# "#<OrientDB::Schema:#{toString}>"
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# alias :to_s :inspect
|
10
|
+
#
|
11
|
+
#end
|
12
|
+
#
|
13
|
+
#class SchemaProxy
|
14
|
+
#
|
15
|
+
# def inspect
|
16
|
+
# "#<OrientDB::SchemaProxy:#{toString}>"
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# alias :to_s :inspect
|
20
|
+
#
|
21
|
+
#end
|
22
|
+
#
|
23
|
+
#class SchemaType
|
24
|
+
#
|
25
|
+
# def inspect
|
26
|
+
# "#<OrientDB::SchemaType:#{name}>"
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# alias :to_s :inspect
|
30
|
+
#
|
31
|
+
#end
|
32
|
+
|
33
|
+
end
|
data/lib/orientdb/sql.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module OrientDB::SQL
|
2
|
+
class SQLSynchQuery
|
3
|
+
|
4
|
+
def inspect
|
5
|
+
%{#<OrientDB::SQLSynchQuery:#{name} text="#{text}">}
|
6
|
+
end
|
7
|
+
|
8
|
+
alias :to_s :inspect
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'orientdb/sql/common'
|
14
|
+
require 'orientdb/sql/ext'
|
15
|
+
require 'orientdb/sql/query'
|
16
|
+
require 'orientdb/sql/insert'
|
17
|
+
require 'orientdb/sql/update'
|
18
|
+
require 'orientdb/sql/delete'
|
@@ -0,0 +1,247 @@
|
|
1
|
+
module OrientDB::SQL
|
2
|
+
|
3
|
+
module UtilsMixin
|
4
|
+
|
5
|
+
def select_single_string(arg)
|
6
|
+
arg.to_s.split('___').join(' AS ').split('__').join('.')
|
7
|
+
end
|
8
|
+
|
9
|
+
def field_name(name)
|
10
|
+
name.to_s.split('__').join('.')
|
11
|
+
end
|
12
|
+
|
13
|
+
def quote(value)
|
14
|
+
case value
|
15
|
+
when Numeric, Symbol
|
16
|
+
value.to_s
|
17
|
+
when String
|
18
|
+
quote_string(value)
|
19
|
+
when Array
|
20
|
+
"[" + value.map { |x| quote(x) }.join(", ") + "]"
|
21
|
+
when Regexp
|
22
|
+
quote_regexp(value)
|
23
|
+
when OrientDB::SQL::LiteralExpression
|
24
|
+
value.to_s
|
25
|
+
else
|
26
|
+
quote value.to_s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def quote_string(str)
|
31
|
+
str = str.dup
|
32
|
+
return str if str[0, 1] == "'" && str[-1, 1] == "'"
|
33
|
+
last_pos = 0
|
34
|
+
while (pos = str.index("'", last_pos))
|
35
|
+
str.insert(pos, "\\") if pos > 0 && str[pos - 1, 1] != "\\"
|
36
|
+
last_pos = pos + 1
|
37
|
+
end
|
38
|
+
"'#{str}'"
|
39
|
+
end
|
40
|
+
|
41
|
+
def quote_regexp(regexp)
|
42
|
+
regexp = regexp.inspect
|
43
|
+
left_index = regexp.index('/') + 1
|
44
|
+
right_index = regexp.rindex('/') - 1
|
45
|
+
str = regexp[left_index..right_index]
|
46
|
+
"'#{str}'"
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
module ClassClusterParametersMixin
|
52
|
+
|
53
|
+
def oclass(new_oclass)
|
54
|
+
@oclass = new_oclass.to_s
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
alias :oclass! :oclass
|
59
|
+
|
60
|
+
def cluster(new_cluster)
|
61
|
+
@cluster = new_cluster.to_s
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
alias :cluster! :cluster
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def target_sql(command)
|
70
|
+
command = command.to_s.upcase.gsub('_', ' ')
|
71
|
+
if @oclass
|
72
|
+
"#{command} #{@oclass} "
|
73
|
+
elsif @cluster
|
74
|
+
"#{command} cluster:#{@cluster} "
|
75
|
+
else
|
76
|
+
raise "Missing oclass or cluster"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
module FieldsValuesParametersMixin
|
83
|
+
|
84
|
+
def fields(*args)
|
85
|
+
args.each do |arg|
|
86
|
+
case arg
|
87
|
+
when String, Symbol, Integer
|
88
|
+
@fields << field_name(arg)
|
89
|
+
when Hash
|
90
|
+
arg.each { |k, v| @fields << field_name(k); @values << quote(v) }
|
91
|
+
when Array
|
92
|
+
arg.each { |x| @fields << field_name(x) }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
self
|
96
|
+
end
|
97
|
+
|
98
|
+
def fields!(*args)
|
99
|
+
@fields = []
|
100
|
+
@values = []
|
101
|
+
fields *args
|
102
|
+
end
|
103
|
+
|
104
|
+
def values(*args)
|
105
|
+
args.each do |arg|
|
106
|
+
case arg
|
107
|
+
when String, Symbol, Integer
|
108
|
+
arg = quote(arg)
|
109
|
+
@values << arg
|
110
|
+
when Hash
|
111
|
+
arg.each { |k, v| @fields << field_name(k); @values << quote(v) }
|
112
|
+
when Array
|
113
|
+
arg.each { |x| @values << quote(x) }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
119
|
+
def values!(*args)
|
120
|
+
@fields = []
|
121
|
+
@values = []
|
122
|
+
values *args
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
module ConditionsParametersMixin
|
128
|
+
def where(*args)
|
129
|
+
@conditions << ConditionExpression.new(:and) if @conditions.empty?
|
130
|
+
@conditions.last.add *args
|
131
|
+
self
|
132
|
+
end
|
133
|
+
|
134
|
+
def where!(*args)
|
135
|
+
@conditions = []
|
136
|
+
where *args
|
137
|
+
end
|
138
|
+
|
139
|
+
def and(*args)
|
140
|
+
@conditions << ConditionExpression.new(:and)
|
141
|
+
@conditions.last.add *args
|
142
|
+
self
|
143
|
+
end
|
144
|
+
|
145
|
+
def or(*args)
|
146
|
+
@conditions << ConditionExpression.new(:or)
|
147
|
+
@conditions.last.add *args
|
148
|
+
self
|
149
|
+
end
|
150
|
+
|
151
|
+
def and_not(*args)
|
152
|
+
@conditions << ConditionExpression.new(:and_not)
|
153
|
+
@conditions.last.add *args
|
154
|
+
self
|
155
|
+
end
|
156
|
+
|
157
|
+
def or_not(*args)
|
158
|
+
@conditions << ConditionExpression.new(:or_not)
|
159
|
+
@conditions.last.add *args
|
160
|
+
self
|
161
|
+
end
|
162
|
+
|
163
|
+
private
|
164
|
+
|
165
|
+
def conditions_sql
|
166
|
+
case @conditions.size
|
167
|
+
when 0
|
168
|
+
''
|
169
|
+
when 1
|
170
|
+
"WHERE #{@conditions.first.conditions_str} "
|
171
|
+
else
|
172
|
+
"WHERE #{@conditions.first.parens_conditions_str} #{@conditions[1..-1].map { |x| x.to_s }.join('')}"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
class LiteralExpression
|
179
|
+
|
180
|
+
def initialize(value)
|
181
|
+
@value = value.to_s
|
182
|
+
end
|
183
|
+
|
184
|
+
def to_s
|
185
|
+
@value
|
186
|
+
end
|
187
|
+
|
188
|
+
include Comparable
|
189
|
+
|
190
|
+
def <=>(other)
|
191
|
+
to_s <=> other.to_s
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
class ConditionExpression
|
197
|
+
|
198
|
+
attr_reader :conditions
|
199
|
+
|
200
|
+
def initialize(type)
|
201
|
+
@type = type
|
202
|
+
@conditions = []
|
203
|
+
end
|
204
|
+
|
205
|
+
def type
|
206
|
+
@type.to_s.upcase.gsub('_', ' ')
|
207
|
+
end
|
208
|
+
|
209
|
+
def add(*conds)
|
210
|
+
conds.each do |cond|
|
211
|
+
case cond
|
212
|
+
when ConditionExpression
|
213
|
+
conditions << cond.to_s
|
214
|
+
when Hash
|
215
|
+
cond.each { |k, v| conditions << "#{k} = #{Query.quote(v)}" }
|
216
|
+
when Array
|
217
|
+
cond.each { |x| conditions << x.to_s }
|
218
|
+
else
|
219
|
+
conditions << cond.to_s
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def clear
|
225
|
+
@conditions = []
|
226
|
+
end
|
227
|
+
|
228
|
+
def conditions_str
|
229
|
+
conditions.join(' AND ')
|
230
|
+
end
|
231
|
+
|
232
|
+
def parens_conditions_str
|
233
|
+
conditions.size > 1 ? "(#{conditions_str})" : conditions_str
|
234
|
+
end
|
235
|
+
|
236
|
+
def to_s
|
237
|
+
"#{type} #{parens_conditions_str} "
|
238
|
+
end
|
239
|
+
|
240
|
+
include Comparable
|
241
|
+
|
242
|
+
def <=>(other)
|
243
|
+
to_s <=> other.to_s
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|