jungle_path 0.0.0
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 +7 -0
- data/.gitignore +21 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +22 -0
- data/README.md +5 -0
- data/jungle_path.gemspec +43 -0
- data/lib/jungle_path/api/helpers/auth.rb +45 -0
- data/lib/jungle_path/api/helpers/auth_local_user.rb +284 -0
- data/lib/jungle_path/api/helpers/auth_old.rb +232 -0
- data/lib/jungle_path/api/helpers/data_cache.rb +20 -0
- data/lib/jungle_path/api/helpers/defaults.rb +83 -0
- data/lib/jungle_path/api/helpers/logging.rb +36 -0
- data/lib/jungle_path/api/helpers/query_filters.rb +15 -0
- data/lib/jungle_path/api/helpers/rescues.rb +15 -0
- data/lib/jungle_path/api/helpers/result.rb +16 -0
- data/lib/jungle_path/api/helpers/standard_apis.rb +280 -0
- data/lib/jungle_path/api/helpers.rb +16 -0
- data/lib/jungle_path/api/template.erb +35 -0
- data/lib/jungle_path/api.rb +5 -0
- data/lib/jungle_path/app/a.gitignore +1 -0
- data/lib/jungle_path/app/api/server_base.rb +95 -0
- data/lib/jungle_path/app/api/server_custom.rb +121 -0
- data/lib/jungle_path/app/api/server_gen.rb +11 -0
- data/lib/jungle_path/app/auth/authorization.rb +96 -0
- data/lib/jungle_path/app/config/a.gitignore +1 -0
- data/lib/jungle_path/app/config/config.rb +240 -0
- data/lib/jungle_path/app/config/override.rb +3 -0
- data/lib/jungle_path/app/config.ru +28 -0
- data/lib/jungle_path/app/logs/log_files_go_here +0 -0
- data/lib/jungle_path/app/run.sh +4 -0
- data/lib/jungle_path/app/schemas/schema.rb +21 -0
- data/lib/jungle_path/app/schemas/schema_all_in_one.rb +181 -0
- data/lib/jungle_path/app.rb +8 -0
- data/lib/jungle_path/authentication/auth_provider/default.rb +83 -0
- data/lib/jungle_path/authentication/auth_provider.rb +7 -0
- data/lib/jungle_path/authentication/data_provider/default.rb +144 -0
- data/lib/jungle_path/authentication/data_provider.rb +7 -0
- data/lib/jungle_path/authentication/helpers.rb +19 -0
- data/lib/jungle_path/authentication/identity.rb +30 -0
- data/lib/jungle_path/authentication/password_hash.rb +124 -0
- data/lib/jungle_path/authentication.rb +9 -0
- data/lib/jungle_path/authorization/filter.rb +106 -0
- data/lib/jungle_path/authorization/paths.rb +71 -0
- data/lib/jungle_path/authorization.rb +5 -0
- data/lib/jungle_path/cache.rb +36 -0
- data/lib/jungle_path/config.rb +65 -0
- data/lib/jungle_path/controller/authentication.rb +129 -0
- data/lib/jungle_path/controller/base.rb +193 -0
- data/lib/jungle_path/controller/helpers.rb +47 -0
- data/lib/jungle_path/controller/template.erb +14 -0
- data/lib/jungle_path/controller.rb +7 -0
- data/lib/jungle_path/db_access/import/db_dir.rb +74 -0
- data/lib/jungle_path/db_access/import/delete.rb +30 -0
- data/lib/jungle_path/db_access/import/insert.rb +168 -0
- data/lib/jungle_path/db_access/import/schema.rb +34 -0
- data/lib/jungle_path/db_access/import/select.rb +68 -0
- data/lib/jungle_path/db_access/import.rb +15 -0
- data/lib/jungle_path/db_access/io/chunked_file_reader.rb +62 -0
- data/lib/jungle_path/db_access/io/config.rb +19 -0
- data/lib/jungle_path/db_access/io/copy.rb +73 -0
- data/lib/jungle_path/db_access/io/db.rb +82 -0
- data/lib/jungle_path/db_access/io/delete.rb +23 -0
- data/lib/jungle_path/db_access/io/init_db.rb +39 -0
- data/lib/jungle_path/db_access/io/insert.rb +24 -0
- data/lib/jungle_path/db_access/io/schema.rb +21 -0
- data/lib/jungle_path/db_access/io/select.rb +44 -0
- data/lib/jungle_path/db_access/io/update.rb +36 -0
- data/lib/jungle_path/db_access/io.rb +104 -0
- data/lib/jungle_path/db_model/column.rb +186 -0
- data/lib/jungle_path/db_model/params.rb +60 -0
- data/lib/jungle_path/db_model/schema.rb +100 -0
- data/lib/jungle_path/db_model/string.rb +9 -0
- data/lib/jungle_path/db_model/table.rb +307 -0
- data/lib/jungle_path/db_model.rb +34 -0
- data/lib/jungle_path/exceptions.rb +10 -0
- data/lib/jungle_path/gen/api.rb +52 -0
- data/lib/jungle_path/gen/controller.rb +0 -0
- data/lib/jungle_path/gen/db.rb +0 -0
- data/lib/jungle_path/gen/schema.rb +47 -0
- data/lib/jungle_path/gen/schema_tree/filter.rb +33 -0
- data/lib/jungle_path/gen/schema_tree/match_columns.rb +54 -0
- data/lib/jungle_path/gen/schema_tree/match_table_data.rb +22 -0
- data/lib/jungle_path/gen/schema_tree/match_tables.rb +70 -0
- data/lib/jungle_path/gen/schema_tree/node.rb +39 -0
- data/lib/jungle_path/gen/schema_tree.rb +105 -0
- data/lib/jungle_path/gen.rb +9 -0
- data/lib/jungle_path/json/base.rb +29 -0
- data/lib/jungle_path/json/time.rb +8 -0
- data/lib/jungle_path/json.rb +6 -0
- data/lib/jungle_path/logging.rb +23 -0
- data/lib/jungle_path/query/alias_info.rb +16 -0
- data/lib/jungle_path/query/engine.rb +878 -0
- data/lib/jungle_path/query/entity.rb +141 -0
- data/lib/jungle_path/query/field.rb +28 -0
- data/lib/jungle_path/query/field_primary_key.rb +27 -0
- data/lib/jungle_path/query/filter.rb +34 -0
- data/lib/jungle_path/query/float_value.rb +16 -0
- data/lib/jungle_path/query/from.rb +33 -0
- data/lib/jungle_path/query/int_value.rb +16 -0
- data/lib/jungle_path/query/limit.rb +19 -0
- data/lib/jungle_path/query/nested_hash_sorter.rb +94 -0
- data/lib/jungle_path/query/operator.rb +17 -0
- data/lib/jungle_path/query/query.rb +23 -0
- data/lib/jungle_path/query/sort_field.rb +34 -0
- data/lib/jungle_path/query/sql_string.rb +145 -0
- data/lib/jungle_path/query/string_value.rb +16 -0
- data/lib/jungle_path/query.rb +19 -0
- data/lib/jungle_path/rack/basic_credentials.rb +70 -0
- data/lib/jungle_path/rack/json_body_parser.rb +41 -0
- data/lib/jungle_path/rack.rb +6 -0
- data/lib/jungle_path/schema/auth.rb +83 -0
- data/lib/jungle_path/schema/base.rb +6 -0
- data/lib/jungle_path/schema/db.rb +10 -0
- data/lib/jungle_path/schema/version.rb +19 -0
- data/lib/jungle_path/schema.rb +8 -0
- data/lib/jungle_path/sql/auth_local_user.rb +5 -0
- data/lib/jungle_path/sql/general.rb +10 -0
- data/lib/jungle_path/sql/helpers.rb +11 -0
- data/lib/jungle_path/sql/key.rb +107 -0
- data/lib/jungle_path/sql/query_filter.rb +5 -0
- data/lib/jungle_path/sql/role.rb +5 -0
- data/lib/jungle_path/sql/user.rb +35 -0
- data/lib/jungle_path/sql/user_role.rb +5 -0
- data/lib/jungle_path/sql.rb +12 -0
- data/lib/jungle_path.rb +13 -0
- data/test.rb +33 -0
- data/test2.rb +15 -0
- metadata +200 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
module JunglePath
|
2
|
+
module DBAccess
|
3
|
+
module Import
|
4
|
+
require 'jungle_path/db_access/import/delete'
|
5
|
+
require 'jungle_path/db_access/import/insert'
|
6
|
+
require 'jungle_path/db_access/import/schema'
|
7
|
+
require 'jungle_path/db_access/import/select'
|
8
|
+
|
9
|
+
class DBDir
|
10
|
+
attr_reader :config
|
11
|
+
attr_reader :path
|
12
|
+
attr_reader :log_path
|
13
|
+
attr_reader :postgresql
|
14
|
+
attr_reader :select
|
15
|
+
attr_reader :insert
|
16
|
+
attr_reader :delete
|
17
|
+
attr_reader :schema
|
18
|
+
|
19
|
+
def initialize(config, logger=nil)
|
20
|
+
@logger = logger
|
21
|
+
@config = config
|
22
|
+
@path = config.path
|
23
|
+
@log_path = config.log_path
|
24
|
+
@postgresql = config.postgresql
|
25
|
+
Dir.mkdir(path) unless Dir.exist?(path)
|
26
|
+
clear_import_files
|
27
|
+
@select = JunglePath::DBAccess::Import::Select.new @config, @logger
|
28
|
+
@insert = JunglePath::DBAccess::Import::Insert.new @config, @logger
|
29
|
+
@delete = JunglePath::DBAccess::Import::Delete.new @config, @logger
|
30
|
+
@schema = JunglePath::DBAccess::Import::Schema.new @config, @logger
|
31
|
+
end
|
32
|
+
|
33
|
+
def reset_sequence_for_table(table_name)
|
34
|
+
@insert.db.reset_sequence_for_table(table_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def transaction
|
38
|
+
begin_transaction
|
39
|
+
yield
|
40
|
+
commit_transaction
|
41
|
+
rescue
|
42
|
+
rollback_transaction
|
43
|
+
raise
|
44
|
+
end
|
45
|
+
|
46
|
+
def clear_import_files
|
47
|
+
if Dir.exist?(path)
|
48
|
+
data_files = Dir.glob(File.join(path, "*.dat"))
|
49
|
+
data_files.each do |file_name|
|
50
|
+
File.delete file_name
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def begin_transaction
|
58
|
+
# not implemented :)
|
59
|
+
end
|
60
|
+
|
61
|
+
def commit_transaction
|
62
|
+
@insert.close_files
|
63
|
+
@insert.write_to_db
|
64
|
+
@insert.reset
|
65
|
+
end
|
66
|
+
|
67
|
+
def rollback_transaction
|
68
|
+
@insert.close_files
|
69
|
+
@insert.reset
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module JunglePath
|
2
|
+
module DBAccess
|
3
|
+
require 'jungle_path/db_access/io/db'
|
4
|
+
|
5
|
+
module Import
|
6
|
+
require 'jungle_path/db_access/import'
|
7
|
+
|
8
|
+
class Delete
|
9
|
+
def initialize(config, logger=nil)
|
10
|
+
@logger = logger
|
11
|
+
@path = config.path
|
12
|
+
@db = nil
|
13
|
+
if config.postgresql
|
14
|
+
@db = JunglePath::DBAccess::IO::DB.new(config.postgresql, @logger)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def _models(model, force=false)
|
19
|
+
if force
|
20
|
+
file_name = JunglePath::DBAccess::Import.data_file_name(@path, model.class.table_name)
|
21
|
+
File.delete file_name if File.exist?(file_name)
|
22
|
+
if @db
|
23
|
+
@db.delete._models(model, force)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
module JunglePath
|
2
|
+
module DBAccess
|
3
|
+
require 'jungle_path/db_access/io/db'
|
4
|
+
|
5
|
+
module Import
|
6
|
+
require 'jungle_path/db_access/import'
|
7
|
+
|
8
|
+
class Insert
|
9
|
+
attr_reader :db
|
10
|
+
def initialize(config, logger=nil)
|
11
|
+
@logger = logger
|
12
|
+
@path = config.path
|
13
|
+
@db = nil
|
14
|
+
if config.postgresql
|
15
|
+
@db = JunglePath::DBAccess::IO::DB.new(config.postgresql, logger)
|
16
|
+
end
|
17
|
+
reset
|
18
|
+
end
|
19
|
+
|
20
|
+
def _model(model)
|
21
|
+
table_name = model.class.table_name
|
22
|
+
file = open_file(model)
|
23
|
+
@counters[table_name] += 1
|
24
|
+
if model.respond_to?(:id) and model.id == nil
|
25
|
+
model.id = @counters[table_name]
|
26
|
+
end
|
27
|
+
file.puts model_values_to_string(model)
|
28
|
+
puts " #{table_name} rows processed count: #{@counters[table_name]}." if @counters[table_name] % 1000 == 0
|
29
|
+
model
|
30
|
+
end
|
31
|
+
|
32
|
+
def open_file(model)
|
33
|
+
table_name = model.class.table_name
|
34
|
+
file = @files[table_name]
|
35
|
+
unless file
|
36
|
+
file = File.open(JunglePath::DBAccess::Import.data_file_name(@path, table_name), 'a')
|
37
|
+
@models[table_name] = model
|
38
|
+
@files[table_name] = file
|
39
|
+
@counters[table_name] = 0
|
40
|
+
puts "writing file: #{table_name}."
|
41
|
+
end
|
42
|
+
file
|
43
|
+
end
|
44
|
+
|
45
|
+
def close_files
|
46
|
+
@files.each do |key, file|
|
47
|
+
unless file.closed?
|
48
|
+
file.fsync
|
49
|
+
file.close
|
50
|
+
puts " #{key} rows processed count: #{@counters[key]}."
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def reset
|
56
|
+
@models = {}
|
57
|
+
@files = {}
|
58
|
+
@counters = {}
|
59
|
+
end
|
60
|
+
|
61
|
+
def write_to_db
|
62
|
+
if @db
|
63
|
+
@models.each do |key, model|
|
64
|
+
file_name = JunglePath::DBAccess::Import.data_file_name(@path, model.class.table_name)
|
65
|
+
@db.copy.into_table model.class, file_name
|
66
|
+
File.delete file_name
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def model_values_to_string(model)
|
72
|
+
values = []
|
73
|
+
model._columns.each do |key, column|
|
74
|
+
value = model._values[key]
|
75
|
+
if column.base_type == :json or column.base_type == :jsonb
|
76
|
+
values << json_dump(value)
|
77
|
+
else
|
78
|
+
values << value_to_string(value)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
values.join("\t")
|
82
|
+
end
|
83
|
+
|
84
|
+
def string_fix(value)
|
85
|
+
v = value.gsub('\\', '\\\\\\\\')
|
86
|
+
v = v.gsub('"', '\\\\\"')
|
87
|
+
v = v.gsub("\n", '\n')
|
88
|
+
v = v.gsub("\r", '\r')
|
89
|
+
v = v.gsub("\t", '\t')
|
90
|
+
end
|
91
|
+
|
92
|
+
def json_dump(value)
|
93
|
+
if value.class == Hash
|
94
|
+
json_dump_hash(value)
|
95
|
+
elsif value.class == Array
|
96
|
+
json_dump_array(value)
|
97
|
+
else
|
98
|
+
value_to_string(value, true)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def json_dump_hash(hash)
|
103
|
+
a = []
|
104
|
+
hash.each do |key, value|
|
105
|
+
if value.class == Hash
|
106
|
+
#a << json_dump_hash(value)
|
107
|
+
a << "\"#{key}\":#{json_dump_hash(value)}"
|
108
|
+
elsif value.class == Array
|
109
|
+
#a << json_dump_array(value)
|
110
|
+
a << "\"#{key}\":#{json_dump_array(value)}"
|
111
|
+
else
|
112
|
+
a << "\"#{key}\":#{value_to_string(value, true)}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
"{#{a.join(',')}}"
|
116
|
+
end
|
117
|
+
|
118
|
+
def json_dump_array(array)
|
119
|
+
values = []
|
120
|
+
array.each do |value|
|
121
|
+
if value.class == Hash
|
122
|
+
#a << json_dump_hash(value)
|
123
|
+
a << "\"#{key}\":#{json_dump_hash(value)}"
|
124
|
+
elsif value.class == Array
|
125
|
+
#a << json_dump_array(value)
|
126
|
+
a << "\"#{key}\":#{json_dump_array(value)}"
|
127
|
+
else
|
128
|
+
values << "#{value_to_string(value, true)}"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
"[#{values.join(',')}]"
|
132
|
+
end
|
133
|
+
|
134
|
+
def value_to_string value, json=false
|
135
|
+
v = nil
|
136
|
+
if value == nil
|
137
|
+
v = '\N'
|
138
|
+
elsif value.class == String
|
139
|
+
v = string_fix(value)
|
140
|
+
v = "\"#{v}\"" if json
|
141
|
+
elsif value.class == DateTime
|
142
|
+
v = value.strftime("%Y-%m-%d %H:%M:%S.%6N")
|
143
|
+
v = "\"#{v}\"" if json
|
144
|
+
elsif value.class == Date
|
145
|
+
v = value.strftime("%Y-%m-%d")
|
146
|
+
v = "\"#{v}\"" if json
|
147
|
+
elsif value.class == Fixnum
|
148
|
+
v = "#{value}"
|
149
|
+
elsif value.class == Float
|
150
|
+
v = "#{value}"
|
151
|
+
elsif value.class == Integer
|
152
|
+
v = "#{value}"
|
153
|
+
elsif value.class == TrueClass
|
154
|
+
v = "t"
|
155
|
+
v = "\"#{v}\"" if json
|
156
|
+
elsif value.class == FalseClass
|
157
|
+
v = "f"
|
158
|
+
v = "\"#{v}\"" if json
|
159
|
+
else
|
160
|
+
v = "#{value}"
|
161
|
+
v = "\"#{v}\"" if json
|
162
|
+
end
|
163
|
+
v
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module JunglePath
|
2
|
+
module DBAccess
|
3
|
+
require 'jungle_path/db_access/io/db'
|
4
|
+
|
5
|
+
module Import
|
6
|
+
require 'jungle_path/db_access/import'
|
7
|
+
|
8
|
+
class Schema
|
9
|
+
def initialize(config, logger=nil)
|
10
|
+
@logger = logger
|
11
|
+
@path = config.path
|
12
|
+
@db = nil
|
13
|
+
if config.postgresql
|
14
|
+
@db = JunglePath::DBAccess::IO::DB.new(config.postgresql, @logger)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def drop_table(table_class)
|
19
|
+
file_name = JunglePath::DBAccess::Import.data_file_name(@path, table_class.table_name)
|
20
|
+
File.delete file_name if File.exist?(file_name)
|
21
|
+
if @db
|
22
|
+
@db.schema.drop_table(table_class)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_table(table_class)
|
27
|
+
if @db
|
28
|
+
@db.schema.create_table(table_class)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module JunglePath
|
2
|
+
require 'jungle_path/controller/base'
|
3
|
+
|
4
|
+
module DBAccess
|
5
|
+
require 'jungle_path/db_access/io/db'
|
6
|
+
|
7
|
+
module Import
|
8
|
+
require 'jungle_path/db_access/import'
|
9
|
+
|
10
|
+
class Select
|
11
|
+
def initialize(config, logger=nil)
|
12
|
+
@logger = logger
|
13
|
+
@path = config.path
|
14
|
+
@db = nil
|
15
|
+
if config.postgresql
|
16
|
+
@db = JunglePath::DBAccess::IO::DB.new(config.postgresql, logger)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def _model(model)
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def _model_by_any(model)
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def _models(model)
|
29
|
+
if @db
|
30
|
+
@db.select._models(model)
|
31
|
+
else
|
32
|
+
from_file(model)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def from_file(model)
|
37
|
+
# select all of a given model.
|
38
|
+
file_name = JunglePath::DBAccess::Import.data_file_name(@path, model.class.table_name)
|
39
|
+
puts "file_name: #{file_name}."
|
40
|
+
models = []
|
41
|
+
lines = File.readlines(file_name)
|
42
|
+
puts "lines.count: #{lines.count}."
|
43
|
+
lines.each do |line|
|
44
|
+
values = line.split("\t")
|
45
|
+
hash = to_hash(model, values)
|
46
|
+
params = JunglePath::Controller::Base.transform(hash, model.class.columns)
|
47
|
+
models << model.class.new(params, false)
|
48
|
+
end
|
49
|
+
models
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_hash(model, values)
|
53
|
+
hash = {}
|
54
|
+
i = 0
|
55
|
+
model._columns.keys.each do |key|
|
56
|
+
value = values[i]
|
57
|
+
if value == '\N'
|
58
|
+
value = nil
|
59
|
+
end
|
60
|
+
hash[key] = value
|
61
|
+
i += 1
|
62
|
+
end
|
63
|
+
hash
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#require 'pry-byebug'
|
2
|
+
module JunglePath
|
3
|
+
module DBAccess
|
4
|
+
module Import
|
5
|
+
require 'jungle_path/db_access/import/db_dir'
|
6
|
+
require 'jungle_path/db_access/import/delete'
|
7
|
+
require 'jungle_path/db_access/import/insert'
|
8
|
+
require 'jungle_path/db_access/import/schema'
|
9
|
+
require 'jungle_path/db_access/import/select'
|
10
|
+
def self.data_file_name(path, table_name)
|
11
|
+
File.join(path, "#{table_name}.dat")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module JunglePath
|
2
|
+
module DBAccess
|
3
|
+
module IO
|
4
|
+
class ChunkedFileReader
|
5
|
+
# yield up chunks of lines. treat entire chunk as good or bad.
|
6
|
+
# if chunk size is 1 line and it is bad move start_at forward by 1 (chunk size).
|
7
|
+
# if chunk was good move start_at forward by chunk size.
|
8
|
+
attr_reader :start_at, :chunk_size, :data_file, :done, :line
|
9
|
+
def initialize data_file
|
10
|
+
@data_file = data_file
|
11
|
+
@start_at = 1
|
12
|
+
@chunk_size = 1000
|
13
|
+
@done = false
|
14
|
+
@line = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def was_bad_chunk
|
18
|
+
if @chunk_size == 1
|
19
|
+
@start_at = @start_at + 1
|
20
|
+
else
|
21
|
+
@chunk_size = @chunk_size / 2
|
22
|
+
if @chunk_size < 1
|
23
|
+
@chunk_size = 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def was_good_chunk
|
29
|
+
@start_at = @start_at + @chunk_size
|
30
|
+
@chunk_size = @chunk_size * 2
|
31
|
+
if @chunk_size > 1000000
|
32
|
+
@chunk_size = 1000000
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def each
|
37
|
+
@line = nil
|
38
|
+
pointer = 0
|
39
|
+
yield_size = 0
|
40
|
+
File.open(@data_file, 'r') do |file|
|
41
|
+
puts "reading: #{data_file}."
|
42
|
+
while line = file.gets
|
43
|
+
pointer += 1
|
44
|
+
if pointer == @start_at
|
45
|
+
puts "starting chunk at #{pointer}."
|
46
|
+
end
|
47
|
+
puts " at line number #{pointer}." if pointer % 10000 == 0
|
48
|
+
if pointer >= @start_at and yield_size < @chunk_size
|
49
|
+
@line = line
|
50
|
+
yield_size += 1
|
51
|
+
yield line
|
52
|
+
end
|
53
|
+
end
|
54
|
+
if yield_size == 0
|
55
|
+
@done = true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module JunglePath
|
2
|
+
module DBAccess
|
3
|
+
module IO
|
4
|
+
class Config
|
5
|
+
attr_accessor :name, :type, :user_name, :password, :host, :extensions, :port, :options
|
6
|
+
def initialize name: nil, type: nil, user_name: nil, password: nil, host: nil, extensions: [], port: nil, options: nil
|
7
|
+
@name = name
|
8
|
+
@type = type
|
9
|
+
@user_name = user_name
|
10
|
+
@password = password
|
11
|
+
@host = host
|
12
|
+
@extensions = extensions
|
13
|
+
@port = port
|
14
|
+
@options = options
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
|
3
|
+
module JunglePath
|
4
|
+
module DBAccess
|
5
|
+
module IO
|
6
|
+
require 'jungle_path/db_access/io/chunked_file_reader'
|
7
|
+
require 'jungle_path/db_access/io/init_db'
|
8
|
+
|
9
|
+
class Copy
|
10
|
+
include JunglePath::DBAccess::IO::InitDB
|
11
|
+
|
12
|
+
def from_table model_class
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def into_table model_class, data_file
|
17
|
+
done = false
|
18
|
+
loops = 0
|
19
|
+
until done
|
20
|
+
loops +=1
|
21
|
+
puts "loops: #{loops}."
|
22
|
+
error = nil
|
23
|
+
file_reader = JunglePath::DBAccess::IO::ChunkedFileReader.new data_file unless file_reader # must work with chunks of lines since we won't know which exact line was bad if there is a postgresql error.
|
24
|
+
begin
|
25
|
+
@db.copy_into(model_class.table_name, :data => file_reader)
|
26
|
+
rescue Sequel::ForeignKeyConstraintViolation => e
|
27
|
+
error = e
|
28
|
+
rescue Sequel::UniqueConstraintViolation => e
|
29
|
+
error = e
|
30
|
+
rescue Sequel::DatabaseError => e
|
31
|
+
error = e
|
32
|
+
rescue Exception => e
|
33
|
+
error = e
|
34
|
+
end
|
35
|
+
if error
|
36
|
+
if file_reader.chunk_size == 1
|
37
|
+
log_error "bad data: exception: #{error.class}."
|
38
|
+
log_error " message: #{error.message.gsub("\n", '\n').gsub("\r", '\r')}."
|
39
|
+
log_error " was_bad_chunk: start_at: #{file_reader.start_at}, chunk_size: #{file_reader.chunk_size}."
|
40
|
+
line = file_reader.line
|
41
|
+
log_error " line: #{line.gsub("\n", '\n').gsub("\r", '\r')}."
|
42
|
+
parts = line.split("\t")
|
43
|
+
parts.each_with_index do |part, index|
|
44
|
+
log_error " #{index}: part: #{part}."
|
45
|
+
end
|
46
|
+
end
|
47
|
+
file_reader.was_bad_chunk
|
48
|
+
else
|
49
|
+
puts "was_good_chunk: start_at: #{file_reader.start_at}, chunk_size: #{file_reader.chunk_size}."
|
50
|
+
file_reader.was_good_chunk
|
51
|
+
end
|
52
|
+
done = file_reader.done
|
53
|
+
if done
|
54
|
+
log "done with #{model_class.table_name}."
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def log_error(msg)
|
60
|
+
#binding.pry
|
61
|
+
puts "log error: #{msg}"
|
62
|
+
@logger.error(msg)
|
63
|
+
end
|
64
|
+
|
65
|
+
def log(msg)
|
66
|
+
#binding.pry
|
67
|
+
puts "log info: #{msg}"
|
68
|
+
@logger.info(msg) if @logger
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module JunglePath
|
2
|
+
module DBAccess
|
3
|
+
module IO
|
4
|
+
require 'jungle_path/db_access/io'
|
5
|
+
require 'jungle_path/db_access/io/select'
|
6
|
+
require 'jungle_path/db_access/io/insert'
|
7
|
+
require 'jungle_path/db_access/io/update'
|
8
|
+
require 'jungle_path/db_access/io/delete'
|
9
|
+
require 'jungle_path/db_access/io/schema'
|
10
|
+
require 'jungle_path/db_access/io/copy'
|
11
|
+
|
12
|
+
class DB
|
13
|
+
attr_reader :select
|
14
|
+
attr_reader :insert
|
15
|
+
attr_reader :update
|
16
|
+
attr_reader :delete
|
17
|
+
attr_reader :schema
|
18
|
+
attr_reader :copy
|
19
|
+
attr_reader :base
|
20
|
+
attr_reader :database_name
|
21
|
+
attr_reader :config
|
22
|
+
attr_reader :postgresql
|
23
|
+
|
24
|
+
def initialize(config, logger=nil)
|
25
|
+
@logger = logger
|
26
|
+
@config = config
|
27
|
+
@postgresql = config
|
28
|
+
@db = JunglePath::DBAccess::IO.connection(
|
29
|
+
database_type: config.type,
|
30
|
+
user_name: config.user_name,
|
31
|
+
database_name: config.name,
|
32
|
+
host: config.host,
|
33
|
+
extensions: config.extensions,
|
34
|
+
password: config.password,
|
35
|
+
port: config.port,
|
36
|
+
options: config.options
|
37
|
+
)
|
38
|
+
@select = JunglePath::DBAccess::IO::Select.new @db, @logger
|
39
|
+
@insert = JunglePath::DBAccess::IO::Insert.new @db, @logger
|
40
|
+
@update = JunglePath::DBAccess::IO::Update.new @db, @logger
|
41
|
+
@delete = JunglePath::DBAccess::IO::Delete.new @db, @logger
|
42
|
+
@schema = JunglePath::DBAccess::IO::Schema.new @db, @logger
|
43
|
+
@copy = JunglePath::DBAccess::IO::Copy.new @db, @logger
|
44
|
+
@base = @db
|
45
|
+
@database_name = config.name
|
46
|
+
end
|
47
|
+
|
48
|
+
def reset_sequence_for_table(table_name)
|
49
|
+
#max = @db[table_name.to_sym].max(:id) + 1
|
50
|
+
#@db.run "alter sequence #{table_name}_id_seq restart with #{max}"
|
51
|
+
@db.run "select setval('#{table_name}_id_seq', (select max(id)+1 from \"#{table_name}\"), false)"
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_max_id_for_table(table_name, id_column_name=:id)
|
55
|
+
ds = @db["select max(#{id_column_name}) as max_id from \"#{table_name}\""]
|
56
|
+
result = ds.first
|
57
|
+
max_id = result[:max_id]
|
58
|
+
end
|
59
|
+
|
60
|
+
def transaction
|
61
|
+
@db.transaction do
|
62
|
+
yield
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def begin_transaction
|
69
|
+
# not implemented :)
|
70
|
+
end
|
71
|
+
|
72
|
+
def commit_transaction
|
73
|
+
# not implemented :)
|
74
|
+
end
|
75
|
+
|
76
|
+
def rollback_transaction
|
77
|
+
# not implemented :)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module JunglePath
|
2
|
+
module DBAccess
|
3
|
+
module IO
|
4
|
+
require 'jungle_path/db_access/io/init_db'
|
5
|
+
|
6
|
+
class Delete
|
7
|
+
include JunglePath::DBAccess::IO::InitDB
|
8
|
+
|
9
|
+
def _model(model)
|
10
|
+
ds = @db[model._table_name].where(model._primary_key)
|
11
|
+
#puts ds.sql
|
12
|
+
ds.delete
|
13
|
+
end
|
14
|
+
|
15
|
+
def _models(model, confirm=false)
|
16
|
+
ds = @db[model._table_name].where(handle_json_columns(model, model._has_value_hash))
|
17
|
+
return ds.delete if confirm
|
18
|
+
return ds.sql
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
|
3
|
+
module JunglePath
|
4
|
+
module DBAccess
|
5
|
+
module IO
|
6
|
+
module InitDB
|
7
|
+
def initialize(db, logger=nil)
|
8
|
+
@db = db
|
9
|
+
@logger = logger
|
10
|
+
end
|
11
|
+
|
12
|
+
def handle_json_columns(model, hash)
|
13
|
+
new_hash = {}
|
14
|
+
columns = model.class.columns
|
15
|
+
hash.each do |key, value|
|
16
|
+
if columns[key].type == :json
|
17
|
+
unless value == nil
|
18
|
+
#if value.class == String # must convert to hash... (assuming this is a string of json...)
|
19
|
+
# value = JsonWrap.load value, {:mode => :compat, :symbol_keys => true, :indent=>0 }
|
20
|
+
#end
|
21
|
+
new_hash[key] = Sequel.pg_json(value)
|
22
|
+
end
|
23
|
+
elsif columns[key].type == :jsonb
|
24
|
+
unless value == nil
|
25
|
+
#if value.class == String # must convert to hash... (assuming this is a string of json...)
|
26
|
+
# value = JsonWrap.load value, {:mode => :compat, :symbol_keys => true, :indent=>0 }
|
27
|
+
#end
|
28
|
+
new_hash[key] = Sequel.pg_jsonb(value)
|
29
|
+
end
|
30
|
+
else
|
31
|
+
new_hash[key] = value unless value == nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
new_hash
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|