neo4j-core 5.0.10 → 5.1.0.rc.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.
- checksums.yaml +4 -4
- data/Gemfile +0 -4
- data/README.md +32 -6
- data/lib/neo4j-core.rb +0 -1
- data/lib/neo4j-core/helpers.rb +2 -7
- data/lib/neo4j-core/query.rb +19 -5
- data/lib/neo4j-core/query_clauses.rb +123 -35
- data/lib/neo4j-core/version.rb +1 -1
- data/lib/neo4j-embedded.rb +1 -1
- data/lib/neo4j-embedded/embedded_session.rb +15 -9
- data/lib/neo4j-server.rb +0 -1
- data/lib/neo4j-server/cypher_node.rb +8 -6
- data/lib/neo4j-server/cypher_relationship.rb +11 -5
- data/lib/neo4j-server/cypher_response.rb +9 -6
- data/lib/neo4j-server/cypher_session.rb +20 -14
- data/lib/neo4j-server/cypher_transaction.rb +0 -1
- data/lib/neo4j/label.rb +0 -1
- data/lib/neo4j/node.rb +6 -1
- data/neo4j-core.gemspec +1 -2
- metadata +8 -27
- data/lib/neo4j-core/cypher_translator.rb +0 -76
- data/lib/neo4j-core/hash_with_indifferent_access.rb +0 -174
- data/lib/neo4j-server/cypher_node_uncommited.rb +0 -14
- data/lib/neo4j/tasks/config_server.rb +0 -36
- data/lib/neo4j/tasks/neo4j_server.rake +0 -258
@@ -1,174 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
module Core
|
3
|
-
# Stolen from http://as.rubyonrails.org/classes/HashWithIndifferentAccess.html
|
4
|
-
# We don't want to depend on active support
|
5
|
-
class HashWithIndifferentAccess < Hash
|
6
|
-
# Always returns true, so that <tt>Array#extract_options!</tt> finds members of this class.
|
7
|
-
def extractable_options?
|
8
|
-
true
|
9
|
-
end
|
10
|
-
|
11
|
-
def with_indifferent_access
|
12
|
-
dup
|
13
|
-
end
|
14
|
-
|
15
|
-
def nested_under_indifferent_access
|
16
|
-
self
|
17
|
-
end
|
18
|
-
|
19
|
-
def initialize(constructor = {})
|
20
|
-
if constructor.is_a?(Hash)
|
21
|
-
super()
|
22
|
-
update(constructor)
|
23
|
-
else
|
24
|
-
super(constructor)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def default(key = nil)
|
29
|
-
if key.is_a?(Symbol) && include?(key = key.to_s)
|
30
|
-
self[key]
|
31
|
-
else
|
32
|
-
super
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.new_from_hash_copying_default(hash)
|
37
|
-
new(hash).tap do |new_hash|
|
38
|
-
new_hash.default = hash.default
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
|
43
|
-
alias_method :regular_update, :update unless method_defined?(:regular_update)
|
44
|
-
|
45
|
-
# Assigns a new value to the hash:
|
46
|
-
#
|
47
|
-
# hash = HashWithIndifferentAccess.new
|
48
|
-
# hash[:key] = "value"
|
49
|
-
#
|
50
|
-
def []=(key, value)
|
51
|
-
regular_writer(convert_key(key), convert_value(value))
|
52
|
-
end
|
53
|
-
|
54
|
-
alias_method :store, :[]=
|
55
|
-
|
56
|
-
# Updates the instantized hash with values from the second:
|
57
|
-
#
|
58
|
-
# hash_1 = HashWithIndifferentAccess.new
|
59
|
-
# hash_1[:key] = "value"
|
60
|
-
#
|
61
|
-
# hash_2 = HashWithIndifferentAccess.new
|
62
|
-
# hash_2[:key] = "New Value!"
|
63
|
-
#
|
64
|
-
# hash_1.update(hash_2) # => {"key"=>"New Value!"}
|
65
|
-
#
|
66
|
-
def update(other_hash)
|
67
|
-
if other_hash.is_a? HashWithIndifferentAccess
|
68
|
-
super(other_hash)
|
69
|
-
else
|
70
|
-
other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
|
71
|
-
self
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
alias_method :merge!, :update
|
76
|
-
|
77
|
-
# Checks the hash for a key matching the argument passed in:
|
78
|
-
#
|
79
|
-
# hash = HashWithIndifferentAccess.new
|
80
|
-
# hash["key"] = "value"
|
81
|
-
# hash.key? :key # => true
|
82
|
-
# hash.key? "key" # => true
|
83
|
-
#
|
84
|
-
def key?(key)
|
85
|
-
super(convert_key(key))
|
86
|
-
end
|
87
|
-
|
88
|
-
alias_method :include?, :key?
|
89
|
-
alias_method :has_key?, :key?
|
90
|
-
alias_method :member?, :key?
|
91
|
-
|
92
|
-
# Fetches the value for the specified key, same as doing hash[key]
|
93
|
-
def fetch(key, *extras)
|
94
|
-
super(convert_key(key), *extras)
|
95
|
-
end
|
96
|
-
|
97
|
-
# Returns an array of the values at the specified indices:
|
98
|
-
#
|
99
|
-
# hash = HashWithIndifferentAccess.new
|
100
|
-
# hash[:a] = "x"
|
101
|
-
# hash[:b] = "y"
|
102
|
-
# hash.values_at("a", "b") # => ["x", "y"]
|
103
|
-
#
|
104
|
-
def values_at(*indices)
|
105
|
-
indices.collect { |key| self[convert_key(key)] }
|
106
|
-
end
|
107
|
-
|
108
|
-
# Returns an exact copy of the hash.
|
109
|
-
def dup
|
110
|
-
self.class.new(self).tap do |new_hash|
|
111
|
-
new_hash.default = default
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
# Merges the instantized and the specified hashes together, giving precedence to the values from the second hash.
|
116
|
-
# Does not overwrite the existing hash.
|
117
|
-
def merge(hash)
|
118
|
-
dup.update(hash)
|
119
|
-
end
|
120
|
-
|
121
|
-
# Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second.
|
122
|
-
# This overloaded definition prevents returning a regular hash, if reverse_merge is called on a <tt>HashWithDifferentAccess</tt>.
|
123
|
-
def reverse_merge(other_hash)
|
124
|
-
super self.class.new_from_hash_copying_default(other_hash)
|
125
|
-
end
|
126
|
-
|
127
|
-
def reverse_merge!(other_hash)
|
128
|
-
replace(reverse_merge(other_hash))
|
129
|
-
end
|
130
|
-
|
131
|
-
# Removes a specified key from the hash.
|
132
|
-
def delete(key)
|
133
|
-
super(convert_key(key))
|
134
|
-
end
|
135
|
-
|
136
|
-
def stringify_keys!
|
137
|
-
self
|
138
|
-
end
|
139
|
-
|
140
|
-
def stringify_keys
|
141
|
-
dup
|
142
|
-
end
|
143
|
-
# undef :symbolize_keys!
|
144
|
-
def symbolize_keys
|
145
|
-
to_hash.symbolize_keys
|
146
|
-
end
|
147
|
-
|
148
|
-
def to_options!
|
149
|
-
self
|
150
|
-
end
|
151
|
-
|
152
|
-
# Convert to a Hash with String keys.
|
153
|
-
def to_hash
|
154
|
-
Hash.new(default).merge!(self)
|
155
|
-
end
|
156
|
-
|
157
|
-
protected
|
158
|
-
|
159
|
-
def convert_key(key)
|
160
|
-
key.is_a?(Symbol) ? key.to_s : key
|
161
|
-
end
|
162
|
-
|
163
|
-
def convert_value(value)
|
164
|
-
if value.is_a? Hash
|
165
|
-
value # .nested_under_indifferent_access
|
166
|
-
elsif value.is_a?(Array)
|
167
|
-
value.dup.replace(value.map { |e| convert_value(e) })
|
168
|
-
else
|
169
|
-
value
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
module Tasks
|
3
|
-
module ConfigServer
|
4
|
-
def config(source_text, port)
|
5
|
-
s = set_property(source_text, 'org.neo4j.server.webserver.https.enabled', 'false')
|
6
|
-
set_property(s, 'org.neo4j.server.webserver.port', port)
|
7
|
-
end
|
8
|
-
|
9
|
-
def set_property(source_text, property, value)
|
10
|
-
source_text.gsub(/#{property}\s*=\s*(\w+)/, "#{property}=#{value}")
|
11
|
-
end
|
12
|
-
|
13
|
-
# Toggles the status of Neo4j 2.2's basic auth
|
14
|
-
def toggle_auth(status, source_text)
|
15
|
-
status_string = status == :enable ? 'true' : 'false'
|
16
|
-
%w(dbms.security.authorization_enabled dbms.security.auth_enabled).each do |key|
|
17
|
-
source_text = set_property(source_text, key, status_string)
|
18
|
-
end
|
19
|
-
source_text
|
20
|
-
end
|
21
|
-
|
22
|
-
# POSTs to an endpoint with the form required to change a Neo4j password
|
23
|
-
# @param [String] target_address The server address, with protocol and port, against which the form should be POSTed
|
24
|
-
# @param [String] old_password The existing password for the "neo4j" user account
|
25
|
-
# @param [String] new_password The new password you want to use. Shocking, isn't it?
|
26
|
-
# @return [Hash] The response from the server indicating success/failure.
|
27
|
-
def change_password(target_address, old_password, new_password)
|
28
|
-
uri = URI.parse("#{target_address}/user/neo4j/password")
|
29
|
-
response = Net::HTTP.post_form(uri, 'password' => old_password, 'new_password' => new_password)
|
30
|
-
JSON.parse(response.body)
|
31
|
-
end
|
32
|
-
|
33
|
-
extend self
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,258 +0,0 @@
|
|
1
|
-
# :nocov:
|
2
|
-
# borrowed from architect4r
|
3
|
-
require 'os'
|
4
|
-
require 'httparty'
|
5
|
-
require 'zip'
|
6
|
-
require 'httparty'
|
7
|
-
require File.expand_path('../config_server', __FILE__)
|
8
|
-
|
9
|
-
namespace :neo4j do
|
10
|
-
def file_name
|
11
|
-
OS::Underlying.windows? ? 'neo4j.zip' : 'neo4j-unix.tar.gz'
|
12
|
-
end
|
13
|
-
|
14
|
-
def download_url(edition)
|
15
|
-
"http://dist.neo4j.org/neo4j-#{edition}-#{OS::Underlying.windows? ? 'windows.zip' : 'unix.tar.gz'}"
|
16
|
-
end
|
17
|
-
|
18
|
-
def download_neo4j_unless_exists(edition)
|
19
|
-
download_neo4j(edition) unless File.exist?(file_name)
|
20
|
-
end
|
21
|
-
|
22
|
-
def download_neo4j(edition)
|
23
|
-
success = false
|
24
|
-
|
25
|
-
File.open(file_name, 'wb') do |file|
|
26
|
-
file << request_url(download_url(edition))
|
27
|
-
success = true
|
28
|
-
end
|
29
|
-
|
30
|
-
file_name
|
31
|
-
ensure
|
32
|
-
File.delete(file_name) unless success
|
33
|
-
end
|
34
|
-
|
35
|
-
def request_url(url)
|
36
|
-
status = HTTParty.head(url).code
|
37
|
-
fail "#{edition} is not available to download, try a different version" if status < 200 || status >= 300
|
38
|
-
|
39
|
-
HTTParty.get(url)
|
40
|
-
end
|
41
|
-
|
42
|
-
def get_environment(args)
|
43
|
-
args[:environment] || 'development'
|
44
|
-
end
|
45
|
-
|
46
|
-
def install_location(args)
|
47
|
-
FileUtils.mkdir_p('db/neo4j')
|
48
|
-
"db/neo4j/#{get_environment(args)}"
|
49
|
-
end
|
50
|
-
|
51
|
-
def config_location(args)
|
52
|
-
"#{install_location(args)}/conf/neo4j-server.properties"
|
53
|
-
end
|
54
|
-
|
55
|
-
def start_server(command, args)
|
56
|
-
puts "Starting Neo4j #{get_environment(args)}..."
|
57
|
-
if OS::Underlying.windows?
|
58
|
-
start_windows_server(command, args)
|
59
|
-
else
|
60
|
-
start_starnix_server(command, args)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def system_or_fail(command)
|
65
|
-
system(command) or fail "Unable to run: #{command}" # rubocop:disable Style/AndOr
|
66
|
-
end
|
67
|
-
|
68
|
-
def start_windows_server(command, args)
|
69
|
-
if system_or_fail!('reg query "HKU\\S-1-5-19"').size > 0
|
70
|
-
system_or_fail("#{install_location(args)}/bin/Neo4j.bat #{command}") # start service
|
71
|
-
else
|
72
|
-
puts 'Starting Neo4j directly, not as a service.'
|
73
|
-
system_or_fail("#{install_location(args)}/bin/Neo4j.bat")
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def start_starnix_server(command, args)
|
78
|
-
system_or_fail("#{install_location(args)}/bin/neo4j #{command}")
|
79
|
-
end
|
80
|
-
|
81
|
-
def get_edition(args)
|
82
|
-
edition_string = args[:edition]
|
83
|
-
|
84
|
-
edition_string.gsub(/-latest$/) do
|
85
|
-
require 'open-uri'
|
86
|
-
puts 'Retrieving latest version...'
|
87
|
-
latest_version = JSON.parse(open('https://api.github.com/repos/neo4j/neo4j/releases/latest').read)['tag_name']
|
88
|
-
puts "Latest version is: #{latest_version}"
|
89
|
-
"-#{latest_version}"
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
desc 'Install Neo4j with auth disabled in v2.2+, example neo4j:install[community-latest,development]'
|
94
|
-
task :install, :edition, :environment do |_, args|
|
95
|
-
args.with_default_arguments(edition: 'community-latest', environment: 'development')
|
96
|
-
edition = get_edition(args)
|
97
|
-
environment = get_environment(args)
|
98
|
-
puts "Installing Neo4j-#{edition} environment: #{environment}"
|
99
|
-
|
100
|
-
downloaded_file = download_neo4j_unless_exists edition
|
101
|
-
|
102
|
-
if OS::Underlying.windows?
|
103
|
-
# Extract and move to neo4j directory
|
104
|
-
unless File.exist?(install_location(args))
|
105
|
-
Zip::ZipFile.open(downloaded_file) do |zip_file|
|
106
|
-
zip_file.each do |f|
|
107
|
-
f_path = File.join('.', f.name)
|
108
|
-
FileUtils.mkdir_p(File.dirname(f_path))
|
109
|
-
begin
|
110
|
-
zip_file.extract(f, f_path) unless File.exist?(f_path)
|
111
|
-
rescue
|
112
|
-
puts "#{f.name} failed to extract."
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
FileUtils.mv "neo4j-#{edition}", install_location(args)
|
117
|
-
FileUtils.rm downloaded_file
|
118
|
-
end
|
119
|
-
|
120
|
-
# Install if running with Admin Privileges
|
121
|
-
if system_or_fail('reg query "HKU\\S-1-5-19"').size > 0
|
122
|
-
system_or_fail("\"#{install_location(args)}/bin/neo4j install\"")
|
123
|
-
puts 'Neo4j Installed as a service.'
|
124
|
-
end
|
125
|
-
|
126
|
-
else
|
127
|
-
system_or_fail("tar -xvf #{downloaded_file}")
|
128
|
-
system_or_fail("mv neo4j-#{edition} #{install_location(args)}")
|
129
|
-
system_or_fail("rm #{downloaded_file}")
|
130
|
-
puts 'Neo4j Installed in to neo4j directory.'
|
131
|
-
end
|
132
|
-
rake_auth_toggle(args, :disable) unless /-2\.0|1\.[0-9]/.match(args[:edition])
|
133
|
-
puts "Type 'rake neo4j:start' or 'rake neo4j:start[ENVIRONMENT]' to start it\nType 'neo4j:config[ENVIRONMENT,PORT]' for changing server port, (default 7474)"
|
134
|
-
end
|
135
|
-
|
136
|
-
desc 'Start the Neo4j Server'
|
137
|
-
task :start, :environment do |_, args|
|
138
|
-
start_server('start', args)
|
139
|
-
end
|
140
|
-
|
141
|
-
desc 'Start the Neo4j Server asynchronously'
|
142
|
-
task :start_no_wait, :environment do |_, args|
|
143
|
-
start_server('start-no-wait', args)
|
144
|
-
end
|
145
|
-
|
146
|
-
desc 'Configure Server, e.g. rake neo4j:config[development,8888]'
|
147
|
-
task :config, :environment, :port do |_, args|
|
148
|
-
port = args[:port]
|
149
|
-
fail 'no port given' unless port
|
150
|
-
puts "Config Neo4j #{get_environment(args)} for port #{port}"
|
151
|
-
location = config_location(args)
|
152
|
-
text = File.read(location)
|
153
|
-
replace = Neo4j::Tasks::ConfigServer.config(text, port)
|
154
|
-
File.open(location, 'w') { |file| file.puts replace }
|
155
|
-
end
|
156
|
-
|
157
|
-
def validate_is_system_admin!
|
158
|
-
return unless OS::Underlying.windows?
|
159
|
-
return if system_or_fail("reg query \"HKU\\S-1-5-19\"").size > 0
|
160
|
-
|
161
|
-
fail 'You do not have administrative rights to stop the Neo4j Service'
|
162
|
-
end
|
163
|
-
|
164
|
-
def run_neo4j_command_or_fail!(args, command)
|
165
|
-
binary = OS::Underlying.windows? ? 'Neo4j.bat' : 'neo4j'
|
166
|
-
|
167
|
-
system_or_fail("#{install_location(args)}/bin/#{binary} #{command}")
|
168
|
-
end
|
169
|
-
|
170
|
-
desc 'Stop the Neo4j Server'
|
171
|
-
task :stop, :environment do |_, args|
|
172
|
-
puts "Stopping Neo4j #{get_environment(args)}..."
|
173
|
-
validate_is_system_admin!
|
174
|
-
|
175
|
-
run_neo4j_command_or_fail!(args, :stop)
|
176
|
-
end
|
177
|
-
|
178
|
-
desc 'Get info the Neo4j Server'
|
179
|
-
task :info, :environment do |_, args|
|
180
|
-
puts "Info from Neo4j #{get_environment(args)}..."
|
181
|
-
validate_is_system_admin!
|
182
|
-
|
183
|
-
run_neo4j_command_or_fail!(args, :info)
|
184
|
-
end
|
185
|
-
|
186
|
-
desc 'Restart the Neo4j Server'
|
187
|
-
task :restart, :environment do |_, args|
|
188
|
-
puts "Restarting Neo4j #{get_environment(args)}..."
|
189
|
-
validate_is_system_admin!
|
190
|
-
|
191
|
-
run_neo4j_command_or_fail!(args, :restart)
|
192
|
-
end
|
193
|
-
|
194
|
-
desc 'Reset the Neo4j Server'
|
195
|
-
task :reset_yes_i_am_sure, :environment do |_, args|
|
196
|
-
validate_is_system_admin!
|
197
|
-
|
198
|
-
run_neo4j_command_or_fail!(args, :stop)
|
199
|
-
|
200
|
-
# Reset the database
|
201
|
-
FileUtils.rm_rf("#{install_location(args)}/data/graph.db")
|
202
|
-
FileUtils.mkdir("#{install_location(args)}/data/graph.db")
|
203
|
-
|
204
|
-
# Remove log files
|
205
|
-
FileUtils.rm_rf("#{install_location(args)}/data/log")
|
206
|
-
FileUtils.mkdir("#{install_location(args)}/data/log")
|
207
|
-
|
208
|
-
run_neo4j_command_or_fail!(args, :start)
|
209
|
-
end
|
210
|
-
|
211
|
-
desc 'Neo4j 2.2: Change connection password'
|
212
|
-
task :change_password do
|
213
|
-
puts 'This will change the password for a Neo4j server'
|
214
|
-
puts 'Enter target IP address or host name without protocal and port, press enter for http://localhost:7474'
|
215
|
-
address = STDIN.gets.chomp
|
216
|
-
target_address = address.empty? ? 'http://localhost:7474' : address
|
217
|
-
|
218
|
-
puts 'Input current password. Leave blank if this is a fresh installation of Neo4j.'
|
219
|
-
password = STDIN.gets.chomp
|
220
|
-
old_password = password.empty? ? 'neo4j' : password
|
221
|
-
|
222
|
-
puts 'Input new password.'
|
223
|
-
new_password = STDIN.gets.chomp
|
224
|
-
fail 'A new password is required' if new_password.empty?
|
225
|
-
|
226
|
-
body = Neo4j::Tasks::ConfigServer.change_password(target_address, old_password, new_password)
|
227
|
-
if body['errors']
|
228
|
-
puts "An error was returned: #{body['errors'][0]['message']}"
|
229
|
-
else
|
230
|
-
puts 'Password changed successfully! Please update your app to use:'
|
231
|
-
puts 'username: neo4j'
|
232
|
-
puts "password: #{new_password}"
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
def rake_auth_toggle(args, status)
|
237
|
-
location = config_location(args)
|
238
|
-
text = File.read(location)
|
239
|
-
replace = Neo4j::Tasks::ConfigServer.toggle_auth(status, text)
|
240
|
-
File.open(location, 'w') { |file| file.puts replace }
|
241
|
-
end
|
242
|
-
|
243
|
-
def auth_toggle_complete(status)
|
244
|
-
puts "Neo4j basic authentication #{status}. Restart server to apply."
|
245
|
-
end
|
246
|
-
|
247
|
-
desc 'Neo4j 2.2: Enable Auth'
|
248
|
-
task :enable_auth, :environment do |_, args|
|
249
|
-
rake_auth_toggle(args, :enable)
|
250
|
-
auth_toggle_complete('enabled')
|
251
|
-
end
|
252
|
-
|
253
|
-
desc 'Neo4j 2.2: Disable Auth'
|
254
|
-
task :disable_auth, :environment do |_, args|
|
255
|
-
rake_auth_toggle(args, :disable)
|
256
|
-
auth_toggle_complete('disabled')
|
257
|
-
end
|
258
|
-
end
|