active-orient 0.4 → 0.80
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.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.graphs.txt.swp +0 -0
- data/Gemfile +9 -5
- data/Guardfile +12 -4
- data/README.md +70 -281
- data/VERSION +1 -1
- data/active-orient.gemspec +9 -7
- data/bin/active-orient-0.6.gem +0 -0
- data/bin/active-orient-console +97 -0
- data/changelog.md +60 -0
- data/config/boot.rb +70 -17
- data/config/config.yml +10 -0
- data/config/connect.yml +11 -6
- data/examples/books.rb +154 -65
- data/examples/streets.rb +89 -85
- data/graphs.txt +70 -0
- data/lib/active-orient.rb +78 -6
- data/lib/base.rb +266 -168
- data/lib/base_properties.rb +76 -65
- data/lib/class_utils.rb +187 -0
- data/lib/database_utils.rb +99 -0
- data/lib/init.rb +80 -0
- data/lib/java-api.rb +442 -0
- data/lib/jdbc.rb +211 -0
- data/lib/model/custom.rb +29 -0
- data/lib/model/e.rb +6 -0
- data/lib/model/edge.rb +114 -0
- data/lib/model/model.rb +134 -0
- data/lib/model/the_class.rb +657 -0
- data/lib/model/the_record.rb +313 -0
- data/lib/model/vertex.rb +371 -0
- data/lib/orientdb_private.rb +48 -0
- data/lib/other.rb +423 -0
- data/lib/railtie.rb +68 -0
- data/lib/rest/change.rb +150 -0
- data/lib/rest/create.rb +287 -0
- data/lib/rest/delete.rb +150 -0
- data/lib/rest/operations.rb +222 -0
- data/lib/rest/read.rb +189 -0
- data/lib/rest/rest.rb +120 -0
- data/lib/rest_disabled.rb +24 -0
- data/lib/support/conversions.rb +42 -0
- data/lib/support/default_formatter.rb +7 -0
- data/lib/support/errors.rb +41 -0
- data/lib/support/logging.rb +38 -0
- data/lib/support/orient.rb +305 -0
- data/lib/support/orientquery.rb +647 -0
- data/lib/support/query.rb +92 -0
- data/rails.md +154 -0
- data/rails/activeorient.rb +32 -0
- data/rails/config.yml +10 -0
- data/rails/connect.yml +17 -0
- metadata +89 -30
- data/lib/model.rb +0 -461
- data/lib/orient.rb +0 -98
- data/lib/query.rb +0 -88
- data/lib/rest.rb +0 -1036
- data/lib/support.rb +0 -347
- data/test.rb +0 -4
- data/usecase.md +0 -91
data/lib/railtie.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
|
2
|
+
module ActiveOrient
|
3
|
+
class Railtie < Rails::Railtie
|
4
|
+
puts "Railtie included!!"
|
5
|
+
initializer 'active_orient.logger' do
|
6
|
+
ActiveSupport.on_load(:active_orient) do
|
7
|
+
ActiveOrient::Base.logger = Rails.logger
|
8
|
+
ActiveOrient::OrientDB.logger = Rails.logger
|
9
|
+
#self.logger ||= Rails.logger
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
initializer 'active_orient.initialize_database_access' do
|
15
|
+
# config.active_orient = ActiveSupport::OrderedOptions.new
|
16
|
+
begin
|
17
|
+
config_file = Rails.root.join('config', 'config.yml')
|
18
|
+
configyml = YAML.load_file( config_file )[:active_orient]
|
19
|
+
connect_file = Rails.root.join('config', 'connect.yml')
|
20
|
+
connectyml = YAML.load_file( connect_file )[:orientdb][:admin]
|
21
|
+
databaseyml = YAML.load_file( connect_file )[:orientdb][:database]
|
22
|
+
rescue Errno::ENOENT => e
|
23
|
+
Rails.logger.error{ "config/connect.yml/config.yml not present" }
|
24
|
+
puts "config/***yml not present"
|
25
|
+
Rails.logger.error{ "Using defaults to connect database-server" }
|
26
|
+
puts "Using defaults to connect database-server"
|
27
|
+
end
|
28
|
+
## Rails.root is a Pathname, as well as model_dir
|
29
|
+
ActiveOrient::Model.model_dir = Rails.root.join configyml.present? ? configyml[:model_dir] : "app/model"
|
30
|
+
|
31
|
+
# set the database
|
32
|
+
ActiveOrient.database = databaseyml[Rails.env.to_sym] || 'temp'
|
33
|
+
|
34
|
+
# don't allocate models if no file is provided
|
35
|
+
ActiveOrient::Model.keep_models_without_file = false
|
36
|
+
|
37
|
+
if connectyml.present? and connectyml[:user].present? and connectyml[:pass].present?
|
38
|
+
ActiveOrient.default_server= { user: connectyml[:user], password: connectyml[:pass] ,
|
39
|
+
server: 'localhost', port: 2480 }
|
40
|
+
end
|
41
|
+
ActiveOrient::Init.define_namespace namespace: :object
|
42
|
+
::DB = ::ORD = ActiveOrient::OrientDB.new preallocate: true
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
# We're not doing migrations (yet)
|
47
|
+
config.send(:app_generators).orm :active_orient, migration: false
|
48
|
+
console do
|
49
|
+
Rails.logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
|
50
|
+
puts '_'*45
|
51
|
+
puts "ORD points to the REST-Instance, Database: #{ActiveOrient.database}"
|
52
|
+
puts "DB is the API-Instance of the database, DB.db gets the DB-Api-base " if RUBY_PLATFORM == 'java'
|
53
|
+
|
54
|
+
puts '-'* 45
|
55
|
+
ns= case ActiveOrient::Model.namespace
|
56
|
+
when Object
|
57
|
+
"No Prefix, just ClassName#CamelCase"
|
58
|
+
else
|
59
|
+
ActiveOrient::Model.namespace.to_s + "{ClassName.camelcase}"
|
60
|
+
end
|
61
|
+
puts "Namespace for model-classes : #{ns}"
|
62
|
+
puts "Present Classes (Hierarchy) "
|
63
|
+
|
64
|
+
puts ::ORD.class_hierarchy.to_yaml
|
65
|
+
puts ActiveOrient::show_classes
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/rest/change.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
module RestChange
|
2
|
+
|
3
|
+
############### DATABASE ####################
|
4
|
+
|
5
|
+
# Changes the working-database to {name}
|
6
|
+
|
7
|
+
def change_database name
|
8
|
+
@classes = []
|
9
|
+
@database = name
|
10
|
+
ActiveOrient.database = name
|
11
|
+
end
|
12
|
+
|
13
|
+
############# OBJECTS #################
|
14
|
+
|
15
|
+
=begin
|
16
|
+
Convient update of the dataset by calling sql-patch
|
17
|
+
|
18
|
+
The argument record can be specified as ActiveOrient::Model-instance or as rid-string( #0:0 )
|
19
|
+
|
20
|
+
called from ModelRecord#update
|
21
|
+
|
22
|
+
if the update was successful, the updated data are returned as Hash.
|
23
|
+
|
24
|
+
First the cached object is retrieved
|
25
|
+
Its modified by the parameters provided
|
26
|
+
and then patched
|
27
|
+
|
28
|
+
better would be: update the cached object and patch that.
|
29
|
+
=end
|
30
|
+
|
31
|
+
def update record, attributes , version=0
|
32
|
+
r = ActiveOrient::Model.autoload_object record.rid
|
33
|
+
return(false) unless r.is_a?(ActiveOrient::Model)
|
34
|
+
raise "Cannot update the record, version-information missing. please reload ! " if version.nil?
|
35
|
+
version = r.version if version.zero?
|
36
|
+
result = patch_record(r.rid) do
|
37
|
+
attributes.merge({'@version' => version, '@class' => r.class.ref_name })
|
38
|
+
end
|
39
|
+
# returns a new instance of ActiveOrient::Model and updates any reference on rid
|
40
|
+
# It's assumed, that the version
|
41
|
+
# if the patch is not successfull no string is returned and thus no record is fetched
|
42
|
+
# JSON.parse(result) if result.is_a?(String)
|
43
|
+
if result.is_a?(String)
|
44
|
+
JSON.parse(result) # return value
|
45
|
+
else
|
46
|
+
logger.error{ "REST::Update was not successfull" }
|
47
|
+
nil # returnvalue
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
=begin
|
53
|
+
Example:
|
54
|
+
ORD.update_documents classname, set: {:symbol => 'TWR'}, where: {con_id: 340}
|
55
|
+
|
56
|
+
Replaces the symbol to TWR in each record where the con_id is 340
|
57
|
+
|
58
|
+
Both set and where take multiple attributes
|
59
|
+
|
60
|
+
Returns the JSON-Response.
|
61
|
+
|
62
|
+
# todo: clear the rid-cache
|
63
|
+
=end
|
64
|
+
|
65
|
+
def update_records o_class, set:{}, where: {}, remove: nil
|
66
|
+
logger.progname = 'RestChange#UpdateRecords'
|
67
|
+
count = execute do
|
68
|
+
if set.present?
|
69
|
+
"UPDATE #{classname(o_class)} SET #{generate_sql_list(set)} #{compose_where(where)}"
|
70
|
+
elsif remove.present?
|
71
|
+
"UPDATE #{classname(o_class)} remove #{remove} #{compose_where(where)}"
|
72
|
+
end
|
73
|
+
end &.first
|
74
|
+
rescue Exception => e
|
75
|
+
logger.error{e.message}
|
76
|
+
nil
|
77
|
+
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
# Lazy Updating of the given Record.
|
82
|
+
# internal using while updating records
|
83
|
+
def patch_record rid # :nodoc: (used by #update )
|
84
|
+
logger.progname = 'RestChange#PatchRecord'
|
85
|
+
content = yield
|
86
|
+
if content.is_a? Hash
|
87
|
+
begin
|
88
|
+
ActiveOrient.db_pool.checkout do | conn |
|
89
|
+
conn["/document/#{ActiveOrient.database}/#{rid}"].patch content.to_orient.to_json
|
90
|
+
end
|
91
|
+
rescue RestClient::Conflict => e # (409)
|
92
|
+
# most probably the server is busy. we wait for a second print an Error-Message and retry
|
93
|
+
sleep(1)
|
94
|
+
logger.error{ "RestClient::Error(409): Server is signaling a conflict ... retrying" }
|
95
|
+
retry
|
96
|
+
rescue RestClient::InternalServerError => e
|
97
|
+
sentence= JSON.parse( e.response)['errors'].last['content']
|
98
|
+
logger.error{sentence}
|
99
|
+
logger.error{ e.backtrace.map {|l| " #{l}\n"}.join }
|
100
|
+
logger.error{e.message.to_s}
|
101
|
+
end
|
102
|
+
else
|
103
|
+
logger.error{"PATCH FAILED: The Block must provide an Hash with properties to be updated"}
|
104
|
+
end
|
105
|
+
end
|
106
|
+
alias patch_document patch_record
|
107
|
+
|
108
|
+
|
109
|
+
#### EXPERIMENTAL ##########
|
110
|
+
|
111
|
+
=begin
|
112
|
+
Used to add restriction or other properties to the Property of a Class.
|
113
|
+
See http://orientdb.com/docs/2.1/SQL-Alter-Property.html
|
114
|
+
=end
|
115
|
+
|
116
|
+
def alter_property o_class, property:, attribute: "DEFAULT", alteration: # :nodoc: because untested
|
117
|
+
logger.progname = 'RestChange#AlterProperty'
|
118
|
+
begin
|
119
|
+
attribute.to_s! unless attribute.is_a? String
|
120
|
+
attribute.capitalize_first_letter
|
121
|
+
case attribute
|
122
|
+
when "LINKEDCLASS", "LINKEDTYPE", "NAME", "REGEX", "TYPE", "REGEX", "COLLATE", "CUSTOM"
|
123
|
+
unless alteration.is_a? String
|
124
|
+
logger.error{"#{alteration} should be a String."}
|
125
|
+
return 0
|
126
|
+
end
|
127
|
+
when "MIN", "MAX"
|
128
|
+
unless alteration.is_a? Integer
|
129
|
+
logger.error{"#{alteration} should be an Integer."}
|
130
|
+
return 0
|
131
|
+
end
|
132
|
+
when "MANDATORY", "NOTNULL", "READONLY"
|
133
|
+
unless alteration.is_a? TrueClass or alteration.is_a? FalseClass
|
134
|
+
logger.error{"#{alteration} should be an Integer."}
|
135
|
+
return 0
|
136
|
+
end
|
137
|
+
when "DEFAULT"
|
138
|
+
else
|
139
|
+
logger.error{"Wrong attribute."}
|
140
|
+
return 0
|
141
|
+
end
|
142
|
+
|
143
|
+
execute { "ALTER PROPERTY #{class_name(o_class)}.#{property} #{attribute} #{alteration}"}
|
144
|
+
rescue Exception => e
|
145
|
+
logger.error{e.message}
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
end
|
data/lib/rest/create.rb
ADDED
@@ -0,0 +1,287 @@
|
|
1
|
+
module RestCreate
|
2
|
+
|
3
|
+
######### DATABASE ##########
|
4
|
+
|
5
|
+
=begin
|
6
|
+
Creates a database with the given name and switches to this database as working-database. Types are either 'plocal' or 'memory'
|
7
|
+
|
8
|
+
Returns the name of the working-database
|
9
|
+
=end
|
10
|
+
|
11
|
+
def create_database type: 'plocal', database:
|
12
|
+
logger.progname = 'RestCreate#CreateDatabase'
|
13
|
+
old_d = ActiveOrient.database
|
14
|
+
ActiveOrient.database_classes = {}
|
15
|
+
ActiveOrient.database = database
|
16
|
+
begin
|
17
|
+
response = ActiveOrient.db_pool.checkout do | conn |
|
18
|
+
conn["database/#{ActiveOrient.database}/#{type}"].post ""
|
19
|
+
end
|
20
|
+
if response.code == 200
|
21
|
+
logger.info{"Database #{ActiveOrient.database} successfully created and stored as working database"}
|
22
|
+
else
|
23
|
+
logger.error{"Database #{ActiveOrient.database} was NOT created. Working Database is still #{ActiveOrient.database}"}
|
24
|
+
ActiveOrient.database = old_d
|
25
|
+
end
|
26
|
+
rescue RestClient::InternalServerError => e
|
27
|
+
logger.error{"Database #{ActiveOrient.database} was NOT created. Working Database is still #{ActiveOrient.database}"}
|
28
|
+
ActiveOrient.database = old_d
|
29
|
+
end
|
30
|
+
ActiveOrient.database # return_value
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
=begin
|
36
|
+
|
37
|
+
This is the historic method CreateClasses. It's just performing the database-stuff and now private
|
38
|
+
|
39
|
+
it takes superclass and abstract (a hash) as block
|
40
|
+
|
41
|
+
usually, only one classname is provided, however the method takes a row of classnames as argument
|
42
|
+
|
43
|
+
#todo reintegrate the ability to create abstract classes
|
44
|
+
=end
|
45
|
+
private
|
46
|
+
def create_this_class *db_classname #nodoc#
|
47
|
+
if block_given?
|
48
|
+
additional_args = yield
|
49
|
+
superclass = additional_args[ :superclass ]
|
50
|
+
abstract = additional_args[ :abstract ].presence || nil
|
51
|
+
else
|
52
|
+
superclass = nil
|
53
|
+
abstract = nil
|
54
|
+
end
|
55
|
+
#
|
56
|
+
db_classname.map do | database_class |
|
57
|
+
c = if superclass.present?
|
58
|
+
"CREATE CLASS #{database_class} EXTENDS #{superclass}"
|
59
|
+
else
|
60
|
+
"CREATE CLASS #{database_class} "
|
61
|
+
end
|
62
|
+
c << " ABSTRACT" if abstract.present?
|
63
|
+
execute( tolerated_error_code: /already exists/ ){ c }
|
64
|
+
end
|
65
|
+
# execute anything as batch, don't roll back in case of an error
|
66
|
+
|
67
|
+
# execute transaction: false, tolerated_error_code: /already exists/ do
|
68
|
+
# command
|
69
|
+
# end
|
70
|
+
|
71
|
+
rescue ArgumentError => e
|
72
|
+
logger.error{ e.backtrace.map {|l| " #{l}\n"}.join }
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
public
|
77
|
+
|
78
|
+
############## OBJECT #############
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
=begin
|
83
|
+
Creates a Record in the Database and returns this as ActiveOrient::Model-Instance
|
84
|
+
|
85
|
+
Creates a Record with the attributes provided in the attributes-hash e.g.
|
86
|
+
create_record @classname, attributes: {con_id: 343, symbol: 'EWTZ'}
|
87
|
+
|
88
|
+
Puts the database-response into the cache by default
|
89
|
+
|
90
|
+
Argument: silence
|
91
|
+
if silence is specified, no Error-Messages are raised. Instead
|
92
|
+
|
93
|
+
* if a record failes to be created, because an index-error occured, it is replaced by that specified in the database response
|
94
|
+
|
95
|
+
=end
|
96
|
+
|
97
|
+
def create_record o_class, attributes: {}, cache: true, silence: true # use Model#create instead
|
98
|
+
logger.progname = 'RestCreate#CreateRecord'
|
99
|
+
attributes = yield if attributes.empty? && block_given?
|
100
|
+
# @class must not quoted! Quote only attributes(strings)
|
101
|
+
post_argument = {'@class' => classname(o_class)}.merge(attributes.to_orient)
|
102
|
+
response = nil
|
103
|
+
begin
|
104
|
+
response = ActiveOrient.db_pool.checkout do | conn |
|
105
|
+
conn["/document/#{ActiveOrient.database}"].post post_argument.to_json
|
106
|
+
end
|
107
|
+
data = JSON.parse(response.body)
|
108
|
+
the_object = ActiveOrient::Model.orientdb_class(name: data['@class']).new data ## return_value
|
109
|
+
if cache
|
110
|
+
ActiveOrient::Base.store_rid( the_object )
|
111
|
+
else
|
112
|
+
the_object
|
113
|
+
end
|
114
|
+
rescue RestClient::InternalServerError => e
|
115
|
+
sentence= JSON.parse( e.response)['errors'].last['content']
|
116
|
+
if sentence =~ /found duplicated key/
|
117
|
+
raise "Duplicate Key" unless silence
|
118
|
+
rid = sentence.split("#").last
|
119
|
+
logger.info{ "found duplicated Key --> loaded #{rid} instead of creating "}
|
120
|
+
## reading database content -- maybe update attributes?
|
121
|
+
get_record rid
|
122
|
+
else
|
123
|
+
response = JSON.parse(e.response)['errors'].pop
|
124
|
+
logger.error{response['content'].split(':')[1..-1].join(':')}
|
125
|
+
logger.error{"No Object allocated"}
|
126
|
+
nil # return_value
|
127
|
+
end
|
128
|
+
rescue Errno::EADDRNOTAVAIL => e
|
129
|
+
sleep(2)
|
130
|
+
retry
|
131
|
+
end
|
132
|
+
end
|
133
|
+
alias create_document create_record
|
134
|
+
|
135
|
+
# UPDATE <class>|CLUSTER:<cluster>|<recordID>
|
136
|
+
# [SET|INCREMENT|ADD|REMOVE|PUT <field-name> = <field-value>[,]*]|[CONTENT|MERGE <JSON>]
|
137
|
+
# [UPSERT]
|
138
|
+
# [RETURN <returning> [<returning-expression>]]
|
139
|
+
# [WHERE <conditions>]
|
140
|
+
# [LOCK default|record]
|
141
|
+
# [LIMIT <max-records>] [TIMEOUT <timeout>]
|
142
|
+
|
143
|
+
=begin
|
144
|
+
update or insert one record is implemented as upsert.
|
145
|
+
The where-condition is merged into the set-attributes if its a hash.
|
146
|
+
Otherwise it's taken unmodified.
|
147
|
+
|
148
|
+
The method returns the included or the updated dataset
|
149
|
+
|
150
|
+
## to do
|
151
|
+
# yield works for updated and for inserted datasets
|
152
|
+
# upsert ( ) do | what, record |
|
153
|
+
# if what == :insert
|
154
|
+
# do stuff with insert
|
155
|
+
# if what == :update
|
156
|
+
# do stuff with update
|
157
|
+
# end
|
158
|
+
# returns nil if no insert and no update was made, ie. the dataset is identical to the given attributes
|
159
|
+
=end
|
160
|
+
def upsert o_class, set: , where: # use Model#Upsert instead
|
161
|
+
logger.progname = 'RestCreate#Upsert'
|
162
|
+
specify_return_value = "return after @rid"
|
163
|
+
# set.merge! where if where.is_a?( Hash ) # copy where attributes to set
|
164
|
+
command = "Update #{classname(o_class)} set #{generate_sql_list( set ){','}} upsert #{specify_return_value} #{compose_where where}"
|
165
|
+
result = execute( tolerated_error_code: /found duplicated key/){ command }
|
166
|
+
# puts "result #{result.inspect}"
|
167
|
+
result =result.pop if result.is_a? Array
|
168
|
+
end
|
169
|
+
############### PROPERTIES #############
|
170
|
+
|
171
|
+
=begin
|
172
|
+
Creates properties
|
173
|
+
|
174
|
+
and (if defined in the provided block) associates an index
|
175
|
+
create_properties(classname or class, properties as hash){index}
|
176
|
+
|
177
|
+
The default-case
|
178
|
+
create_properties(:my_high_sophisticated_database_class,
|
179
|
+
con_id: {type: :integer},
|
180
|
+
details: {type: :link, linked_class: 'Contracts'}) do
|
181
|
+
contract_idx: :notunique
|
182
|
+
end
|
183
|
+
|
184
|
+
A composite index
|
185
|
+
create_properties(:my_high_sophisticated_database_class,
|
186
|
+
con_id: {type: :integer},
|
187
|
+
symbol: {type: :string}) do
|
188
|
+
{name: 'indexname',
|
189
|
+
on: [:con_id, :details] # default: all specified properties
|
190
|
+
type: :notunique # default: :unique
|
191
|
+
}
|
192
|
+
end
|
193
|
+
=end
|
194
|
+
|
195
|
+
def create_properties o_class, all_properties, &b
|
196
|
+
logger.progname = 'RestCreate#CreateProperties'
|
197
|
+
all_properties_in_a_hash = Hash.new #WithIndifferentAccess.new
|
198
|
+
all_properties.each{|field, args| all_properties_in_a_hash.merge! translate_property_hash(field, args)}
|
199
|
+
count, response = 0, nil
|
200
|
+
# puts "all_properties_in_a_hash #{all_properties_in_a_hash.to_json}"
|
201
|
+
if all_properties_in_a_hash.is_a?(Hash)
|
202
|
+
begin
|
203
|
+
response = ActiveOrient.db_pool.checkout do | conn |
|
204
|
+
conn["/property/#{ActiveOrient.database}/#{classname(o_class)}"].post all_properties_in_a_hash.to_json
|
205
|
+
end
|
206
|
+
# puts response.inspect
|
207
|
+
# response.body.to_i returns response.code, only to_f.to_i returns the correct value
|
208
|
+
count= response.body.to_f.to_i if response.code == 201
|
209
|
+
rescue RestClient::InternalServerError => e
|
210
|
+
logger.progname = 'RestCreate#CreateProperties'
|
211
|
+
response = JSON.parse(e.response)['errors'].pop
|
212
|
+
error_message = response['content'].split(':').last
|
213
|
+
logger.error{"Properties in #{classname(o_class)} were NOT created"}
|
214
|
+
logger.error{"The Error was: #{response['content'].split(':').last}"}
|
215
|
+
nil
|
216
|
+
end
|
217
|
+
end
|
218
|
+
### index
|
219
|
+
if block_given?# && count == all_properties_in_a_hash.size
|
220
|
+
index = yield
|
221
|
+
if index.is_a?(Hash)
|
222
|
+
if index.size == 1
|
223
|
+
create_index o_class, name: index.keys.first, on: all_properties_in_a_hash.keys, type: index.values.first
|
224
|
+
else
|
225
|
+
index_hash = {type: :unique, on: all_properties_in_a_hash.keys}.merge index
|
226
|
+
create_index o_class, name: index_hash[:name], on: index_hash[:on], type: index_hash[:type]
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
count # return_value
|
231
|
+
end
|
232
|
+
|
233
|
+
=begin
|
234
|
+
Create a single property.
|
235
|
+
|
236
|
+
Supported types: https://orientdb.com/docs/last/SQL-Create-Property.html
|
237
|
+
|
238
|
+
If an index is to be specified, it's defined in the optional block
|
239
|
+
|
240
|
+
create_property(class, field){:unique | :notunique}
|
241
|
+
--> creates an automatic-Index on the given field
|
242
|
+
|
243
|
+
create_property(class, field){{»name« => :unique | :notunique | :full_text}}
|
244
|
+
--> creates a manual index
|
245
|
+
=end
|
246
|
+
|
247
|
+
def create_property o_class, field, index: nil, **args, &b
|
248
|
+
logger.progname = 'RestCreate#CreateProperty'
|
249
|
+
args= { type: :string} if args.blank? # the default case
|
250
|
+
c = create_properties o_class, {field => args}
|
251
|
+
if index.nil? && block_given?
|
252
|
+
index = yield
|
253
|
+
end
|
254
|
+
if index.present?
|
255
|
+
if index.is_a?(String) || index.is_a?(Symbol)
|
256
|
+
create_index o_class, name: field, type: index
|
257
|
+
elsif index.is_a? Hash
|
258
|
+
bez = index.keys.first
|
259
|
+
create_index o_class, name: bez, type: index[bez], on: [field]
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
################# INDEX ###################
|
265
|
+
|
266
|
+
# Used to create an index
|
267
|
+
|
268
|
+
def create_index o_class, name:, on: :automatic, type: :unique
|
269
|
+
logger.progname = 'RestCreate#CreateIndex'
|
270
|
+
c = classname o_class
|
271
|
+
if execute( transaction: false, tolerated_error_code: /found duplicated key/) do
|
272
|
+
if on == :automatic
|
273
|
+
"CREATE INDEX #{c}.#{name} #{type.to_s.upcase}"
|
274
|
+
elsif on.is_a? Array
|
275
|
+
"CREATE INDEX #{name} ON #{c}(#{on.join(', ')}) #{type.to_s.upcase}"
|
276
|
+
else
|
277
|
+
"CREATE INDEX #{name} ON #{c}(#{on.to_s}) #{type.to_s.upcase}"
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
logger.info{"Index on #{c} based on #{name} created."}
|
282
|
+
else
|
283
|
+
logger.error {"index #{name}.#{type} on #{c} NOT created"}
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|