data_store 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.rvmrc +1 -0
- data/.travis.yml +27 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +30 -0
- data/Guardfile +10 -0
- data/LICENSE +1 -1
- data/README.md +91 -2
- data/REMINDERS +8 -0
- data/Rakefile +13 -1
- data/config/database.yml +16 -0
- data/data_store.gemspec +1 -4
- data/db/data_store.db +0 -0
- data/lib/data_store/average_calculator.rb +93 -0
- data/lib/data_store/base.rb +108 -0
- data/lib/data_store/configuration.rb +66 -0
- data/lib/data_store/connector.rb +85 -0
- data/lib/data_store/definitions.rb +42 -0
- data/lib/data_store/table.rb +119 -0
- data/lib/data_store/version.rb +1 -1
- data/lib/data_store.rb +75 -1
- data/test/average_calculator_test.rb +196 -0
- data/test/configuration_test.rb +48 -0
- data/test/connector_test.rb +32 -0
- data/test/data_store_test.rb +117 -0
- data/test/integration_test.rb +66 -0
- data/test/table_test.rb +181 -0
- data/test/test_helper.rb +32 -0
- metadata +56 -66
data/.gitignore
CHANGED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.3@data_store --create
|
data/.travis.yml
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 1.9.3
|
4
|
+
- rbx-19mode
|
5
|
+
- jruby-19mode
|
6
|
+
|
7
|
+
matrix:
|
8
|
+
exclude:
|
9
|
+
- rvm: jruby-19mode
|
10
|
+
env: DB=sqlite
|
11
|
+
- rvm: rbx-19mode
|
12
|
+
env: DB=sqlite
|
13
|
+
|
14
|
+
branches:
|
15
|
+
only:
|
16
|
+
- master
|
17
|
+
|
18
|
+
script: "bundle exec rake test"
|
19
|
+
|
20
|
+
env:
|
21
|
+
- DB=postgres
|
22
|
+
- DB=mysql
|
23
|
+
- DB=sqlite
|
24
|
+
|
25
|
+
before_script:
|
26
|
+
- psql -c 'create database data_store_test;' -U postgres
|
27
|
+
- mysql -e 'create database data_store_test'
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
##0.0.2
|
2
|
+
|
3
|
+
* Readme driven development
|
4
|
+
* Configuration of DataStore with Connector class for database connection and dataset definition
|
5
|
+
* Introduction of DataStore::Base enriched behaviour with the use of Sequel::Model
|
6
|
+
* introduction of the DataStore::Table to add datapoints
|
7
|
+
|
8
|
+
##0.0.1
|
9
|
+
|
10
|
+
* Initial commit and release of gem
|
data/Gemfile
CHANGED
@@ -2,3 +2,33 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in data_store.gemspec
|
4
4
|
gemspec
|
5
|
+
|
6
|
+
gem 'rake'
|
7
|
+
gem 'sequel'
|
8
|
+
|
9
|
+
platforms :jruby do
|
10
|
+
gem 'jdbc-mysql'
|
11
|
+
gem 'jdbc-sqlite3'
|
12
|
+
gem 'jdbc-postgres', '9.1.901' #9.2 throws an error NameError: missing class or uppercase package name (`org.postgresql.Driver')
|
13
|
+
end
|
14
|
+
|
15
|
+
platforms :ruby do
|
16
|
+
gem 'mysql2'
|
17
|
+
gem 'sqlite3'
|
18
|
+
gem 'pg'
|
19
|
+
end
|
20
|
+
|
21
|
+
gem 'celluloid'
|
22
|
+
|
23
|
+
group :test, :development do
|
24
|
+
gem 'shoulda'
|
25
|
+
gem 'mocha'
|
26
|
+
gem 'guard'
|
27
|
+
gem 'guard-test'
|
28
|
+
gem 'rb-fsevent'
|
29
|
+
gem 'pry'
|
30
|
+
platforms :ruby do
|
31
|
+
gem 'yard'
|
32
|
+
gem 'redcarpet'
|
33
|
+
end
|
34
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :test do
|
5
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
|
6
|
+
watch(%r{^lib/data_store/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
|
7
|
+
watch(%r{^test/.+_test\.rb$})
|
8
|
+
watch('test/test_helper.rb') { "test" }
|
9
|
+
watch(%r{^lib/data_store/base.rb$}) { "test" }
|
10
|
+
end
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# DataStore
|
2
2
|
|
3
|
-
|
3
|
+
<a href='http://travis-ci.org/dovadi/data_store'>
|
4
|
+
![http://travis-ci.org/dovadi/data_store](https://secure.travis-ci.org/dovadi/data_store.png)
|
5
|
+
</a>
|
6
|
+
|
7
|
+
DataStore is designed to store real time data and manage the growth of your dataset by deciding the time period of your historical data. DataStore is tested with Ruby 1.9.3, Rubinius and JRuby and works with three database adapters Sqlite, Mysql and Postgresql.
|
4
8
|
|
5
9
|
## Installation
|
6
10
|
|
@@ -18,7 +22,86 @@ Or install it yourself as:
|
|
18
22
|
|
19
23
|
## Usage
|
20
24
|
|
21
|
-
|
25
|
+
### Configuration
|
26
|
+
|
27
|
+
DataStore.configure do |config|
|
28
|
+
config.prefix = 'ds_'
|
29
|
+
config.database = :mysql
|
30
|
+
config.compression_schema = [6,5,3]
|
31
|
+
config.data_type = :double
|
32
|
+
config.frequency = 10
|
33
|
+
config.maximum_datapoints = 800
|
34
|
+
config.log_file = 'data_store.log'
|
35
|
+
config.log_level = Logger::INFO
|
36
|
+
end
|
37
|
+
|
38
|
+
### Creation of a DataStore
|
39
|
+
|
40
|
+
DataStore::Base.create(identifier: 1, type: 'gauge', name: 'Electra', description: 'Actual usage of electra in the home')
|
41
|
+
|
42
|
+
This will result in the creation of 4 tables,
|
43
|
+
|
44
|
+
'ds_1'
|
45
|
+
'ds_1_6'
|
46
|
+
'ds_1_30'
|
47
|
+
'ds_1_90'
|
48
|
+
|
49
|
+
with the following structure:
|
50
|
+
|
51
|
+
id: integer
|
52
|
+
value: double
|
53
|
+
created: double #for unix timestamp
|
54
|
+
|
55
|
+
and a record to the main data_stores table with the corresponding field names
|
56
|
+
|
57
|
+
id
|
58
|
+
name
|
59
|
+
description
|
60
|
+
compression_schema
|
61
|
+
frequency
|
62
|
+
maximum_datapoints
|
63
|
+
data_type
|
64
|
+
|
65
|
+
### Add a datapoint
|
66
|
+
|
67
|
+
table = DataStore::Table.new(1)
|
68
|
+
table.add(120.34)
|
69
|
+
table.add(123.09)
|
70
|
+
table.add(125.01)
|
71
|
+
|
72
|
+
### Fetching datapoints
|
73
|
+
|
74
|
+
DataStore::Table.new(1).fetch(:from => (Time.now.utc - 3600).to_f, :till => Time.now.utc.to_f)
|
75
|
+
|
76
|
+
will result in an array of the maximum data points. An data point consists of an unix timestamp (UTC) and a value
|
77
|
+
|
78
|
+
[[1352668356, 120], [1352678356, 123.09], [1352688356, 125.01]]
|
79
|
+
|
80
|
+
### Getting meta data of your data set
|
81
|
+
|
82
|
+
DataStore::Table.new(1).parent
|
83
|
+
|
84
|
+
will return the corresponding record from the general data_stores table
|
85
|
+
|
86
|
+
or more specific count of the number of records
|
87
|
+
|
88
|
+
DataStore::Table.new(1).count #=> 1249336
|
89
|
+
|
90
|
+
last record
|
91
|
+
|
92
|
+
DataStore::Table.new(1).last
|
93
|
+
|
94
|
+
results
|
95
|
+
|
96
|
+
#< @values={:id=>2, :value=>120.38, :created=>1356621436.67489}>
|
97
|
+
|
98
|
+
### Managing the size of your data set
|
99
|
+
|
100
|
+
### Export a data store (NOT implemented yet)
|
101
|
+
|
102
|
+
DDataStore::Table.new(1).export
|
103
|
+
|
104
|
+
will result in a csv file with the name data_store_1.csv
|
22
105
|
|
23
106
|
## Contributing
|
24
107
|
|
@@ -27,3 +110,9 @@ TODO: Write usage instructions here
|
|
27
110
|
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
111
|
4. Push to the branch (`git push origin my-new-feature`)
|
29
112
|
5. Create new Pull Request
|
113
|
+
|
114
|
+
## Copyright
|
115
|
+
|
116
|
+
Copyright (c) 2013 Agile Dovadi BV - Frank Oxener.
|
117
|
+
|
118
|
+
See LICENSE.txt for further details.
|
data/REMINDERS
ADDED
data/Rakefile
CHANGED
@@ -1,2 +1,14 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
-
|
2
|
+
# encoding: utf-8
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler/gem_helper'
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
require 'rake/testtask'
|
8
|
+
Rake::TestTask.new(:test) do |test|
|
9
|
+
test.libs << 'lib' << 'test'
|
10
|
+
test.pattern = 'test/**/*_test.rb'
|
11
|
+
test.verbose = true
|
12
|
+
end
|
13
|
+
|
14
|
+
task :default => :test
|
data/config/database.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
postgres:
|
2
|
+
adapter: postgres
|
3
|
+
username: postgres
|
4
|
+
password:
|
5
|
+
database: data_store_test
|
6
|
+
host: localhost
|
7
|
+
|
8
|
+
sqlite:
|
9
|
+
adapter: sqlite
|
10
|
+
database: db/data_store.db
|
11
|
+
|
12
|
+
mysql:
|
13
|
+
adapter: mysql2
|
14
|
+
username: root
|
15
|
+
database: data_store_test
|
16
|
+
host: localhost
|
data/data_store.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.email = ['frank.oxener@gmail.com']
|
7
7
|
gem.description = %q{DataStore is designed to store real time data but still manage the growth of your dataset and still keeping historical data}
|
8
8
|
gem.summary = %q{DataStore for storing real time data}
|
9
|
-
gem.homepage = ''
|
9
|
+
gem.homepage = 'https://github.com/dovadi/data_store'
|
10
10
|
|
11
11
|
gem.licenses = ['MIT']
|
12
12
|
gem.files = `git ls-files`.split($\)
|
@@ -15,7 +15,4 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.name = 'data_store'
|
16
16
|
gem.require_paths = ['lib']
|
17
17
|
gem.version = DataStore::VERSION
|
18
|
-
|
19
|
-
gem.add_development_dependency 'shoulda'
|
20
|
-
gem.add_development_dependency 'rspec'
|
21
18
|
end
|
data/db/data_store.db
ADDED
Binary file
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module DataStore
|
2
|
+
|
3
|
+
class AverageCalculator
|
4
|
+
|
5
|
+
TIMESTAMP_CORRECTION_FACTOR = 0.0001
|
6
|
+
|
7
|
+
attr_reader :identifier, :base, :table_index, :table
|
8
|
+
|
9
|
+
def initialize(table)
|
10
|
+
@table = table
|
11
|
+
@identifier = table.identifier
|
12
|
+
@table_index = table.table_index
|
13
|
+
@base = Base.find(identifier: identifier)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Calculate average value if needed
|
17
|
+
# Average value is store dthrough an add call by a Table object
|
18
|
+
# So the average calculator is called again recursively
|
19
|
+
def perform
|
20
|
+
if calculation_needed?
|
21
|
+
average = previous_average_record ? calculate! : dataset.avg(:value)
|
22
|
+
table.add(average, table_index: table_index + 1, created: last[:created], type: :gauge)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def calculate!
|
29
|
+
last_time = previous_average_record[:created] + TIMESTAMP_CORRECTION_FACTOR
|
30
|
+
dataset.where{created > last_time}.avg(:value)
|
31
|
+
end
|
32
|
+
|
33
|
+
def calculation_needed?
|
34
|
+
return false if compression_finished
|
35
|
+
if previous_average_record
|
36
|
+
tolerance = DataStore.configuration.frequency_tolerance
|
37
|
+
time_difference_since_last_calculation >= (time_resolution - (time_resolution * tolerance))
|
38
|
+
else
|
39
|
+
dataset.count == base.compression_schema[table_index]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def time_difference_since_last_calculation
|
44
|
+
last[:created].round - previous_average_record[:created].round
|
45
|
+
end
|
46
|
+
|
47
|
+
def time_resolution
|
48
|
+
table.parent.frequency * compression_factors[table_index]
|
49
|
+
end
|
50
|
+
|
51
|
+
def compression_factors
|
52
|
+
array, factor = [], 1
|
53
|
+
base.compression_schema.each do |compression|
|
54
|
+
factor = (factor * compression)
|
55
|
+
array << factor
|
56
|
+
end
|
57
|
+
array
|
58
|
+
end
|
59
|
+
|
60
|
+
def previous_average_record
|
61
|
+
base.db[next_table].order(:created).last
|
62
|
+
end
|
63
|
+
|
64
|
+
def compression_finished
|
65
|
+
table_index == base.compression_schema.size
|
66
|
+
end
|
67
|
+
|
68
|
+
def last
|
69
|
+
dataset.order(:created).last
|
70
|
+
end
|
71
|
+
|
72
|
+
def dataset
|
73
|
+
base.db[table_name]
|
74
|
+
end
|
75
|
+
|
76
|
+
def table_name
|
77
|
+
if table_index == 0
|
78
|
+
prefix.chop.to_sym
|
79
|
+
else
|
80
|
+
(prefix + compression_factors[table_index - 1].to_s).to_sym
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def next_table
|
85
|
+
(prefix + compression_factors[table_index].to_s).to_sym
|
86
|
+
end
|
87
|
+
|
88
|
+
def prefix
|
89
|
+
DataStore.configuration.prefix + identifier.to_s + '_'
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module DataStore
|
2
|
+
|
3
|
+
class Base
|
4
|
+
|
5
|
+
# Set the default values with the globally defined values
|
6
|
+
# * :compression_schema
|
7
|
+
# * :frequency
|
8
|
+
# * :maximum_datapoints
|
9
|
+
# * :data_type
|
10
|
+
# See {Configuration}
|
11
|
+
def before_save
|
12
|
+
set_default_values
|
13
|
+
end
|
14
|
+
|
15
|
+
def after_create
|
16
|
+
drop_tables!
|
17
|
+
create_tables!
|
18
|
+
end
|
19
|
+
|
20
|
+
def before_destroy
|
21
|
+
drop_tables!
|
22
|
+
end
|
23
|
+
|
24
|
+
# Convert serialized compression schema as a string back into the array object itself.
|
25
|
+
# For example: "[5,4,3]" => [5,4,3]
|
26
|
+
def compression_schema
|
27
|
+
value = self.values[:compression_schema]
|
28
|
+
value.gsub(/\[|\]/,'').split(',').map(&:to_i) unless value.nil?
|
29
|
+
end
|
30
|
+
|
31
|
+
def table_names
|
32
|
+
names = [table_name]
|
33
|
+
factor = 1
|
34
|
+
compression_schema.each do |compression|
|
35
|
+
factor = (factor * compression)
|
36
|
+
names << (table_name.to_s + '_' + factor.to_s).to_sym
|
37
|
+
end
|
38
|
+
names
|
39
|
+
end
|
40
|
+
|
41
|
+
def time_borders
|
42
|
+
width = time_width
|
43
|
+
borders = [width]
|
44
|
+
compression_schema.each do |compression|
|
45
|
+
width = width * compression
|
46
|
+
borders << width
|
47
|
+
end
|
48
|
+
borders
|
49
|
+
end
|
50
|
+
|
51
|
+
def time_width
|
52
|
+
DataStore.configuration.frequency * DataStore.configuration.maximum_datapoints
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def default_values
|
58
|
+
['compression_schema', 'frequency', 'maximum_datapoints', 'data_type']
|
59
|
+
end
|
60
|
+
|
61
|
+
def set_default_values
|
62
|
+
default_values.each do |variable|
|
63
|
+
value = DataStore.configuration.send(variable)
|
64
|
+
self.send(variable+ '=', value) if self.send(variable).nil?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Create the database tables which are used for storing the datapoints
|
69
|
+
def create_tables!
|
70
|
+
migrate(:up)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Drop the database tables which are used for storing the datapoints
|
74
|
+
def drop_tables!
|
75
|
+
migrate(:down)
|
76
|
+
end
|
77
|
+
|
78
|
+
def migrate(direction = :up)
|
79
|
+
# Establish new connection to prevent mix up with associated db connection of the Base object
|
80
|
+
# Unless connected to a sqlite db, otherwise it is too time consuming
|
81
|
+
database = sqlite_db? ? db : DataStore::Connector.new.database
|
82
|
+
table_names.each do |name|
|
83
|
+
begin
|
84
|
+
settings = {name: name, data_type: data_type}
|
85
|
+
settings[:original_value] = type == 'counter'
|
86
|
+
DataStore.create_table(settings).apply(database, direction)
|
87
|
+
rescue Sequel::DatabaseError => e
|
88
|
+
raise e if e.message.include?('FATAL')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
database.disconnect unless sqlite_db?
|
92
|
+
end
|
93
|
+
|
94
|
+
def table_name
|
95
|
+
(prefix + identifier.to_s).to_sym
|
96
|
+
end
|
97
|
+
|
98
|
+
def prefix
|
99
|
+
DataStore.configuration.prefix
|
100
|
+
end
|
101
|
+
|
102
|
+
def sqlite_db?
|
103
|
+
DataStore.configuration.database.to_s == 'sqlite'
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module DataStore
|
2
|
+
|
3
|
+
# Used to set up and modify settings for the data store.
|
4
|
+
class Configuration
|
5
|
+
|
6
|
+
# The prefix is used as a prefix for the database table name.
|
7
|
+
attr_accessor :prefix
|
8
|
+
|
9
|
+
# The database used for storing the data.
|
10
|
+
attr_accessor :database
|
11
|
+
|
12
|
+
# The schema is the way avarages of the datapoints is calculated/
|
13
|
+
# Default: [6,5,3,4,4,3]
|
14
|
+
attr_accessor :compression_schema
|
15
|
+
|
16
|
+
# The frequency tells how often data entry is done.
|
17
|
+
# A frequency of 10 means a data entry once every 10 seconds.
|
18
|
+
# Default: 10 sec
|
19
|
+
attr_accessor :frequency
|
20
|
+
|
21
|
+
# Tolerance of the frequency in which datapoints are added
|
22
|
+
# Default: 0.05
|
23
|
+
# This means a 5% margin. So with a frequency of 10s,
|
24
|
+
# the next datapoint within 9.95 - 10.5 is considered the next datapoint
|
25
|
+
attr_accessor :frequency_tolerance
|
26
|
+
|
27
|
+
# The maximum datapoints is the maximum number of datapoint within a given timeframe
|
28
|
+
# Default: 800
|
29
|
+
attr_accessor :maximum_datapoints
|
30
|
+
|
31
|
+
# The data type in which the value is stored
|
32
|
+
# Default: double
|
33
|
+
attr_accessor :data_type
|
34
|
+
|
35
|
+
#The location of the database.yml file
|
36
|
+
attr_accessor :database_config_file
|
37
|
+
|
38
|
+
#Enable logging.
|
39
|
+
# Default: true
|
40
|
+
attr_accessor :enable_logging
|
41
|
+
|
42
|
+
#The location of the log file
|
43
|
+
# Default $stdout
|
44
|
+
attr_accessor :log_file
|
45
|
+
|
46
|
+
#The level of logging
|
47
|
+
# Default: Logger::ERROR
|
48
|
+
attr_accessor :log_level
|
49
|
+
|
50
|
+
def initialize
|
51
|
+
@prefix = 'ds_'
|
52
|
+
@database = :postgres
|
53
|
+
@compression_schema = [6,5,3,4,4,3]
|
54
|
+
@frequency = 10
|
55
|
+
@maximum_datapoints = 800
|
56
|
+
@data_type = :double
|
57
|
+
@database_config_file = File.expand_path('../../../config/database.yml', __FILE__)
|
58
|
+
@log_file = $stdout
|
59
|
+
@log_level = Logger::ERROR
|
60
|
+
@enable_logging = true
|
61
|
+
@frequency_tolerance = 0.05
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module DataStore
|
2
|
+
|
3
|
+
class Connector
|
4
|
+
|
5
|
+
# Create the data_stores table with the following attributes
|
6
|
+
#
|
7
|
+
# * primary_key :id
|
8
|
+
# * Integer :identifier, unique: true, null: false
|
9
|
+
# * String :name, null: false
|
10
|
+
# * String :type, null: false
|
11
|
+
# * String :description
|
12
|
+
# * DateTime :created_at
|
13
|
+
# * DateTime :updated_at
|
14
|
+
#
|
15
|
+
def create_table!
|
16
|
+
DataStore.create_data_stores.apply(database, :up)
|
17
|
+
rescue Sequel::DatabaseError => e
|
18
|
+
raise e if e.message.include?('FATAL')
|
19
|
+
end
|
20
|
+
|
21
|
+
# Drop data_stores table and recreate it
|
22
|
+
def reset!
|
23
|
+
drop_table!
|
24
|
+
create_table!
|
25
|
+
disconnect
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return the dataset associated with data_stores
|
29
|
+
def dataset
|
30
|
+
@dataset ||= begin
|
31
|
+
create_table!
|
32
|
+
database[:data_stores]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Return the database object to which its connected.
|
37
|
+
def database
|
38
|
+
@database ||= begin
|
39
|
+
if RUBY_PLATFORM == 'java'
|
40
|
+
Sequel.connect(jdbc_settings)
|
41
|
+
else
|
42
|
+
Sequel.connect(database_settings)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def jdbc_settings
|
50
|
+
settings = database_settings
|
51
|
+
db = case settings['adapter']
|
52
|
+
when 'postgres'
|
53
|
+
'postgresql'
|
54
|
+
when 'mysql2'
|
55
|
+
'mysql'
|
56
|
+
else
|
57
|
+
settings['adapter']
|
58
|
+
end
|
59
|
+
if db == 'sqlite'
|
60
|
+
uri = "jdbc:#{db}:#{settings['database']}"
|
61
|
+
else
|
62
|
+
uri = "jdbc:#{db}://#{settings['host']}/#{settings['database']}?user=#{settings['username']}"
|
63
|
+
end
|
64
|
+
settings['password'] ? uri + "&password=#{settings['password']}" : uri
|
65
|
+
end
|
66
|
+
|
67
|
+
def disconnect
|
68
|
+
database.disconnect
|
69
|
+
@database = nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def drop_table!
|
73
|
+
DataStore.create_data_stores.apply(database, :down)
|
74
|
+
rescue Sequel::DatabaseError => e
|
75
|
+
raise e if e.message.include?('FATAL')
|
76
|
+
end
|
77
|
+
|
78
|
+
def database_settings
|
79
|
+
config_file = DataStore.configuration.database_config_file
|
80
|
+
YAML.load(File.open(config_file))[DataStore.configuration.database.to_s]
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module DataStore
|
2
|
+
|
3
|
+
# Definition of the data_stores table
|
4
|
+
def self.create_data_stores
|
5
|
+
Sequel.migration do
|
6
|
+
change do
|
7
|
+
create_table(:data_stores) do
|
8
|
+
primary_key :id
|
9
|
+
Integer :identifier, unique: true, null: false
|
10
|
+
String :name, null: false
|
11
|
+
String :type, null: false
|
12
|
+
String :description
|
13
|
+
String :data_type
|
14
|
+
String :compression_schema
|
15
|
+
Integer :frequency
|
16
|
+
Integer :maximum_datapoints
|
17
|
+
DateTime :created_at
|
18
|
+
DateTime :updated_at
|
19
|
+
index :identifier
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.create_table(settings)
|
26
|
+
name = settings[:name]
|
27
|
+
original_value = settings[:original_value] || false
|
28
|
+
data_type = settings[:data_type]
|
29
|
+
|
30
|
+
Sequel.migration do
|
31
|
+
change do
|
32
|
+
create_table(name) do
|
33
|
+
primary_key :id
|
34
|
+
column :value, data_type
|
35
|
+
column :original_value, data_type if original_value
|
36
|
+
column :created, :double
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|