infobright-loader 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +19 -0
  3. data/LICENSE-2.0.txt +202 -0
  4. data/README.md +232 -0
  5. data/Rakefile +2 -0
  6. data/bin/infobright-loader +45 -0
  7. data/control-file/template.yml +23 -0
  8. data/infobright-loader.gemspec +35 -0
  9. data/lib/infobright-loader.rb +5 -0
  10. data/lib/infobright-loader/cli/config.rb +204 -0
  11. data/lib/infobright-loader/cli/loader.rb +66 -0
  12. data/lib/infobright-loader/db.rb +90 -0
  13. data/lib/infobright-loader/loader.rb +175 -0
  14. data/lib/infobright-loader/version.rb +4 -0
  15. data/tests/manual/bad-files/.gitignore +1 -0
  16. data/tests/manual/bad-files/control-file-raw.yml +50 -0
  17. data/tests/manual/bad-files/data/b/b_1.txt +6 -0
  18. data/tests/manual/bad-files/data/b/b_2.txt +6 -0
  19. data/tests/manual/bad-files/data/b/b_3.txt +6 -0
  20. data/tests/manual/bad-files/data/b/b_4.txt +6 -0
  21. data/tests/manual/bad-files/data/b/b_5.txt +6 -0
  22. data/tests/manual/bad-files/data/b/b_6.txt +6 -0
  23. data/tests/manual/bad-files/data/c/c_1.txt +6 -0
  24. data/tests/manual/bad-files/data/c/c_2.txt +6 -0
  25. data/tests/manual/bad-files/data/c/c_3.txt +6 -0
  26. data/tests/manual/bad-files/data/c/c_4.txt +6 -0
  27. data/tests/manual/bad-files/data/c/c_5.txt +6 -0
  28. data/tests/manual/bad-files/data/c/c_6.txt +6 -0
  29. data/tests/manual/bad-files/data/d/d_1.txt +6 -0
  30. data/tests/manual/bad-files/data/d/d_2.txt +6 -0
  31. data/tests/manual/bad-files/data/d/d_3.txt +6 -0
  32. data/tests/manual/bad-files/data/d/d_4.txt +6 -0
  33. data/tests/manual/bad-files/data/d/d_5.txt +6 -0
  34. data/tests/manual/bad-files/data/d/d_6.txt +6 -0
  35. data/tests/manual/bad-files/data/e/e_1.txt +6 -0
  36. data/tests/manual/bad-files/data/e/e_2.txt +6 -0
  37. data/tests/manual/bad-files/data/e/e_3.txt +6 -0
  38. data/tests/manual/bad-files/data/e/e_4.txt +6 -0
  39. data/tests/manual/bad-files/data/e/e_5.txt +6 -0
  40. data/tests/manual/bad-files/data/e/e_6.txt +6 -0
  41. data/tests/manual/bad-files/data/f/f_1.txt +6 -0
  42. data/tests/manual/bad-files/data/f/f_2.txt +6 -0
  43. data/tests/manual/bad-files/data/f/f_3.txt +6 -0
  44. data/tests/manual/bad-files/data/f/f_4.txt +6 -0
  45. data/tests/manual/bad-files/data/f/f_5.txt +6 -0
  46. data/tests/manual/bad-files/data/f/f_6.txt +6 -0
  47. data/tests/manual/bad-files/run_test.sh +40 -0
  48. data/tests/manual/bad-files/setup.sql +8 -0
  49. data/tests/manual/bad-files/verify.sql +10 -0
  50. data/tests/manual/control-file/.gitignore +1 -0
  51. data/tests/manual/control-file/control-file-raw.yml +50 -0
  52. data/tests/manual/control-file/data/b/b_1.txt +6 -0
  53. data/tests/manual/control-file/data/b/b_2.txt +6 -0
  54. data/tests/manual/control-file/data/b/b_3.txt +6 -0
  55. data/tests/manual/control-file/data/b/b_4.txt +6 -0
  56. data/tests/manual/control-file/data/b/b_5.txt +6 -0
  57. data/tests/manual/control-file/data/b/b_6.txt +6 -0
  58. data/tests/manual/control-file/data/c/c_1.txt +6 -0
  59. data/tests/manual/control-file/data/c/c_2.txt +6 -0
  60. data/tests/manual/control-file/data/c/c_3.txt +6 -0
  61. data/tests/manual/control-file/data/c/c_4.txt +6 -0
  62. data/tests/manual/control-file/data/c/c_5.txt +6 -0
  63. data/tests/manual/control-file/data/c/c_6.txt +6 -0
  64. data/tests/manual/control-file/data/d/d_1.txt +6 -0
  65. data/tests/manual/control-file/data/d/d_2.txt +6 -0
  66. data/tests/manual/control-file/data/d/d_3.txt +6 -0
  67. data/tests/manual/control-file/data/d/d_4.txt +6 -0
  68. data/tests/manual/control-file/data/d/d_5.txt +6 -0
  69. data/tests/manual/control-file/data/d/d_6.txt +6 -0
  70. data/tests/manual/control-file/data/e/e_1.txt +6 -0
  71. data/tests/manual/control-file/data/e/e_2.txt +6 -0
  72. data/tests/manual/control-file/data/e/e_3.txt +6 -0
  73. data/tests/manual/control-file/data/e/e_4.txt +6 -0
  74. data/tests/manual/control-file/data/e/e_5.txt +6 -0
  75. data/tests/manual/control-file/data/e/e_6.txt +6 -0
  76. data/tests/manual/control-file/data/f/f_1.txt +6 -0
  77. data/tests/manual/control-file/data/f/f_2.txt +6 -0
  78. data/tests/manual/control-file/data/f/f_3.txt +6 -0
  79. data/tests/manual/control-file/data/f/f_4.txt +6 -0
  80. data/tests/manual/control-file/data/f/f_5.txt +6 -0
  81. data/tests/manual/control-file/data/f/f_6.txt +6 -0
  82. data/tests/manual/control-file/run_test.sh +40 -0
  83. data/tests/manual/control-file/setup.sql +8 -0
  84. data/tests/manual/control-file/verify.sql +10 -0
  85. data/tests/manual/folder/data/a/a_1.txt +6 -0
  86. data/tests/manual/folder/data/a/a_2.txt +6 -0
  87. data/tests/manual/folder/data/a/a_3.txt +6 -0
  88. data/tests/manual/folder/data/a/a_4.txt +6 -0
  89. data/tests/manual/folder/data/a/a_5.txt +6 -0
  90. data/tests/manual/folder/data/a/a_6.txt +6 -0
  91. data/tests/manual/folder/run_test.sh +37 -0
  92. data/tests/manual/folder/setup.sql +4 -0
  93. data/tests/manual/folder/verify.sql +2 -0
  94. metadata +158 -0
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2012 SnowPlow Analytics Ltd. All rights reserved.
4
+ #
5
+ # This program is licensed to you under the Apache License Version 2.0,
6
+ # and you may not use this file except in compliance with the Apache License Version 2.0.
7
+ # You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the Apache License Version 2.0 is distributed on an
11
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
13
+
14
+ # Author:: Alex Dean (mailto:support@snowplowanalytics.com)
15
+ # Copyright:: Copyright (c) 2012 SnowPlow Analytics Ltd
16
+ # License:: Apache License Version 2.0
17
+
18
+ $LOAD_PATH.unshift File.dirname(__FILE__)
19
+
20
+ require 'infobright-loader/cli/config'
21
+ require 'infobright-loader/cli/loader'
22
+ require 'infobright-loader/loader'
23
+
24
+ # This Ruby script is the command-line interface to the
25
+ # Infobright Ruby Loader.
26
+ #
27
+ begin
28
+ config = InfobrightLoader::Cli::Config.get_config()
29
+ InfobrightLoader::Cli::Loader.load(config)
30
+
31
+ rescue InfobrightLoader::Loader::LoadError => le
32
+ $stderr.puts(le.message)
33
+ exit 1
34
+ rescue InfobrightLoader::Cli::Config::ConfigError => e
35
+ $stderr.puts(e.message)
36
+ exit 1
37
+ rescue SystemExit => e
38
+ exit 1
39
+ rescue Exception => e
40
+ $stderr.puts("Unexpected error: " + e.message)
41
+ $stderr.puts(e.backtrace.join("\n"))
42
+ exit 1
43
+ end
44
+
45
+ exit 0
@@ -0,0 +1,23 @@
1
+ # Example control file for Infobright Ruby Loader
2
+
3
+ # Can be overridden at the command line...
4
+ :load:
5
+ :processes: ADD HERE
6
+ :database:
7
+ :name: ADD HERE
8
+ :username: ADD HERE # Or leave blank to default to the user running the script
9
+ :password: ADD HERE # Or leave blank if no password
10
+ :data_format:
11
+ :separator: ADD HERE
12
+ :encloser: ADD HERE # Or leave blank if no encloser
13
+ # ... end of variables overridable at command line.
14
+
15
+ # Map of tables to populate, along with files to load for each table
16
+ :data_loads:
17
+ # For each table, list the data files to load
18
+ TABLE_NAME_1:
19
+ - PATH/TO/FILE-1
20
+ - PATH/TO/FILE-2
21
+ TABLE_NAME_2:
22
+ - PATH/TO/FILE-3
23
+ - PATH/TO/FILE-4
@@ -0,0 +1,35 @@
1
+ # Copyright (c) 2012 SnowPlow Analytics Ltd. All rights reserved.
2
+ #
3
+ # This program is licensed to you under the Apache License Version 2.0,
4
+ # and you may not use this file except in compliance with the Apache License Version 2.0.
5
+ # You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
6
+ #
7
+ # Unless required by applicable law or agreed to in writing,
8
+ # software distributed under the Apache License Version 2.0 is distributed on an
9
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
11
+
12
+ # Author:: Alex Dean (mailto:support@snowplowanalytics.com)
13
+ # Copyright:: Copyright (c) 2012 SnowPlow Analytics Ltd
14
+ # License:: Apache License Version 2.0
15
+
16
+ # -*- encoding: utf-8 -*-
17
+ lib = File.expand_path('../lib', __FILE__)
18
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
19
+ require 'infobright-loader/version'
20
+
21
+ Gem::Specification.new do |gem|
22
+ gem.authors = ["Alex Dean <support@snowplowanalytics.com>"]
23
+ gem.email = ["support@snowplowanalytics.com"]
24
+ gem.description = %q{Loads data files into Infobright}
25
+ gem.summary = %{Infobright Ruby Loader (IRL) is a data loader for Infobright Community Edition (ICE) and Enterprise Edition (IEE), built as a Ruby gem. Inspired by ParaFlex (the bash equivalent)}
26
+ gem.homepage = "http://snowplowanalytics.com"
27
+
28
+ gem.files = `git ls-files`.split($\)
29
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
30
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
31
+ gem.name = InfobrightLoader::NAME
32
+ gem.version = InfobrightLoader::VERSION
33
+ gem.platform = Gem::Platform::RUBY
34
+ gem.require_paths = ["lib"]
35
+ end
@@ -0,0 +1,5 @@
1
+ require "infobright-loader/loader"
2
+
3
+ module InfobrightLoader
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,204 @@
1
+ # Copyright (c) 2012 SnowPlow Analytics Ltd. All rights reserved.
2
+ #
3
+ # This program is licensed to you under the Apache License Version 2.0,
4
+ # and you may not use this file except in compliance with the Apache License Version 2.0.
5
+ # You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
6
+ #
7
+ # Unless required by applicable law or agreed to in writing,
8
+ # software distributed under the Apache License Version 2.0 is distributed on an
9
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
11
+
12
+ # Author:: Alex Dean (mailto:support@snowplowanalytics.com)
13
+ # Copyright:: Copyright (c) 2012 SnowPlow Analytics Ltd
14
+ # License:: Apache License Version 2.0
15
+
16
+ require 'optparse'
17
+ require 'date'
18
+ require 'yaml'
19
+
20
+ require 'infobright-loader/db'
21
+
22
+ # Config module to hold functions related to CLI argument parsing
23
+ # and config file reading to support the daily ETL job.
24
+ module InfobrightLoader
25
+ module Cli
26
+ module Config
27
+
28
+ # What are we called?
29
+ SCRIPT_NAME = InfobrightLoader::NAME
30
+
31
+ # For errors
32
+ class ConfigError < ArgumentError; end
33
+
34
+ # Configuration for loading all the files from a specific directory into
35
+ # a specific table
36
+ LoadHashConfig = Struct.new(:load_hash, :db, :processes, :separator, :encloser)
37
+
38
+ # Configuration for loading a set of tables from a set of files (where
39
+ # each table can have multiple files loaded into it)
40
+ LoadFolderConfig = Struct.new(:folder, :table, :db, :separator, :encloser)
41
+
42
+ # Validates and returns the configuration.
43
+ #
44
+ # The configuration returned will either be
45
+ # a LoadMapConfig or a LoadFolderConfig.
46
+ def get_config()
47
+
48
+ options = Config.parse_args()
49
+
50
+ if options[:control].nil?
51
+
52
+ config = LoadFolderConfig.new
53
+ config.db = InfobrightLoader::Db::DbConfig.new(options[:db], options[:username], options[:password])
54
+ config.separator = options[:separator]
55
+ config.encloser = options[:encloser]
56
+ config.folder = options[:folder]
57
+ config.table = options[:table]
58
+
59
+ else
60
+
61
+ yaml = YAML.load_file(options[:control])
62
+
63
+ # Set the overridable fields if they haven't been overridden at the command-line
64
+ config = LoadHashConfig.new
65
+ get_or_else = lambda {|x, y| x.nil? ? y : x }
66
+ config.processes = get_or_else.call(options[:processes], yaml[:load][:processes])
67
+ config.separator = get_or_else.call(options[:separator], yaml[:data_format][:separator])
68
+ config.encloser = get_or_else.call(options[:encloser], yaml[:data_format][:encloser])
69
+
70
+ db_name = get_or_else.call(options[:db], yaml[:database][:name])
71
+ db_username = get_or_else.call(options[:username], yaml[:database][:username])
72
+ db_password = get_or_else.call(options[:password], yaml[:database][:password])
73
+ config.db = InfobrightLoader::Db::DbConfig.new(db_name, db_username, db_password)
74
+
75
+ # Finally grab the load map
76
+ config.load_hash = yaml[:data_loads]
77
+
78
+ # Check we have everything now
79
+ if db_name.nil?
80
+ raise ConfigError, "Database name not specified"
81
+ end
82
+ if config.processes.nil?
83
+ raise ConfigError, "Number of processes not specified"
84
+ end
85
+ if config.separator.nil? or config.separator.empty?
86
+ raise ConfigError, "Separator not specified - have you escaped ('\\') it in your control file?"
87
+ end
88
+
89
+ # Check that number of processes is a positive integer
90
+ unless config.processes.to_i > 0
91
+ raise ConfigError, "Parallel load processes '#{config.processes}' is not a positive integer"
92
+ end
93
+ config.processes = config.processes.to_i # A kitten dies, mutably.
94
+
95
+ # Check that we have some tables to load
96
+ if config.load_hash.nil? or config.load_hash.empty?
97
+ raise ConfigError, "Must specify at least one table to load"
98
+ end
99
+
100
+ end
101
+
102
+ config # Return either our LoadFolderConfig or our LoadHashConfig
103
+ end
104
+ module_function :get_config
105
+
106
+ # Parse the command-line arguments
107
+ # Returns: the hash of parsed options
108
+ def parse_args()
109
+
110
+ # Handle command-line arguments
111
+ options = {}
112
+ optparse = OptionParser.new do |opts|
113
+
114
+ opts.banner = "Usage: %s [options]" % SCRIPT_NAME
115
+ opts.separator ""
116
+ opts.separator "Specify a control file:"
117
+
118
+ opts.on('-c', '--control FILE', 'control file') { |config| options[:control] = config }
119
+ opts.on('-x', '--processes INT', 'optional number of parallel processes to run *') { |config| options[:processes] = config }
120
+
121
+ opts.separator ""
122
+ opts.separator "Or load a table from a folder of data files:"
123
+
124
+ opts.on('-d', '--db NAME', 'database name *') { |config| options[:db] = config }
125
+ opts.on('-u', '--username NAME', 'database username *') { |config| options[:username] = config }
126
+ opts.on('-p', '--password NAME', 'database password *') { |config| options[:password] = config }
127
+
128
+ opts.on('-t', '--table NAME', 'table to load data files into') { |config| options[:table] = config }
129
+ opts.on('-f', '--folder DIR', 'directory containing data files to load') { |config| options[:folder] = config }
130
+ opts.on('-s', '--separator CHAR', 'optional field separator, defaults to pipe bar (|) *') { |config| options[:separator] = config }
131
+ opts.on('-e', '--encloser CHAR', 'optional field encloser, defaults to none *') { |config| options[:encloser] = config }
132
+
133
+ opts.separator ""
134
+ opts.separator "* overrides the same setting in the control file if control file also specified"
135
+
136
+ opts.separator ""
137
+ opts.separator "Common options:"
138
+
139
+ opts.on_tail('-h', '--help', 'Show this message') { puts opts; exit }
140
+ opts.on_tail('-v', "--version", "Show version") do
141
+ puts "%s %s" % [SCRIPT_NAME, InfobrightLoader::VERSION]
142
+ exit
143
+ end
144
+ end
145
+
146
+ # Run OptionParser's structural validation
147
+ begin
148
+ optparse.parse!
149
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument
150
+ raise ConfigError, "#{$!.to_s}\n#{optparse}"
151
+ end
152
+
153
+ # If no control file given, most of the options are required
154
+ if options[:control].nil?
155
+
156
+ # Set defaults if necessary
157
+ options[:separator] ||= '|'
158
+ options[:encloser] ||= ''
159
+
160
+ # First check we have all the options we need
161
+ mandatory = [:db, :table, :folder]
162
+ missing = mandatory.select{ |param| options[param].nil? }
163
+ if not missing.empty?
164
+ raise ConfigError, "No control file specified, so missing options: #{missing.join(', ')}\n#{optparse}"
165
+ end
166
+
167
+ # Check our folder exists and is not empty
168
+ unless File.directory?(options[:folder])
169
+ raise ConfigError, "Specified folder '#{options[:folder]}' not found"
170
+ end
171
+ if (Dir.entries(options[:folder]) - %w{ . .. }).empty?
172
+ raise ConfigError, "Specified folder '#{options[:folder]}' is empty"
173
+ end
174
+
175
+ # Check user didn't try to override processes
176
+ unless options[:processes].nil?
177
+ raise ConfigError, "Limited to one process when loading only one table"
178
+ end
179
+
180
+ # Add trailing slash if needed to the folder
181
+ trail = lambda {|str| return str[-1].chr != '/' ? str << '/' : str}
182
+ options[:folder] = trail.call(options[:folder])
183
+
184
+ # We are working with the control file
185
+ else
186
+
187
+ # Check we don't have a conflict of purpose
188
+ unless options[:folder].nil? and options[:table].nil?
189
+ raise ConfigError, "Specifying a control file as well as a folder and table does not make sense"
190
+ end
191
+
192
+ # Check the control file exists
193
+ unless File.file?(options[:control])
194
+ raise ConfigError, "Control file '#{options[:control]}' does not exist, or is not a file."
195
+ end
196
+ end
197
+
198
+ options
199
+ end
200
+ module_function :parse_args
201
+
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,66 @@
1
+ # Copyright (c) 2012 SnowPlow Analytics Ltd. All rights reserved.
2
+ #
3
+ # This program is licensed to you under the Apache License Version 2.0,
4
+ # and you may not use this file except in compliance with the Apache License Version 2.0.
5
+ # You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
6
+ #
7
+ # Unless required by applicable law or agreed to in writing,
8
+ # software distributed under the Apache License Version 2.0 is distributed on an
9
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
11
+
12
+ # Author:: Alex Dean (mailto:support@snowplowanalytics.com)
13
+ # Copyright:: Copyright (c) 2012 SnowPlow Analytics Ltd
14
+ # License:: Apache License Version 2.0
15
+
16
+ require 'infobright-loader/cli/config'
17
+ require 'infobright-loader/loader'
18
+
19
+ # Loader determines which load action to run.
20
+ #
21
+ # It's a selective wrapper around
22
+ # load_from_folder() and load_from_map()
23
+ module InfobrightLoader
24
+ module Cli
25
+ module Loader
26
+
27
+ # Determine what type of config we have,
28
+ # and then call the appropriate load
29
+ def load(config)
30
+
31
+ failures = []
32
+
33
+ case config
34
+ when InfobrightLoader::Cli::Config::LoadFolderConfig
35
+ failures = InfobrightLoader::Loader::load_from_folder(
36
+ config.folder,
37
+ config.table,
38
+ config.db,
39
+ config.separator,
40
+ config.encloser
41
+ )
42
+
43
+ when InfobrightLoader::Cli::Config::LoadHashConfig
44
+ failures = InfobrightLoader::Loader::load_from_hash(
45
+ config.load_hash,
46
+ config.db,
47
+ config.processes,
48
+ config.separator,
49
+ config.encloser
50
+ )
51
+
52
+ else
53
+ raise ConfigError, "config argument passed to Cli::Loader::load() must be a LoadFolderConfig or a LoadHashConfig"
54
+ end
55
+
56
+ unless failures.empty?
57
+ error = "Load of following files failed (reason in brackets):\n" + \
58
+ failures.map{|f| " - " + f}.join("\n")
59
+ raise InfobrightLoader::Loader::LoadError, error
60
+ end
61
+ end
62
+ module_function :load
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,90 @@
1
+ # Copyright (c) 2012 SnowPlow Analytics Ltd. All rights reserved.
2
+ #
3
+ # This program is licensed to you under the Apache License Version 2.0,
4
+ # and you may not use this file except in compliance with the Apache License Version 2.0.
5
+ # You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
6
+ #
7
+ # Unless required by applicable law or agreed to in writing,
8
+ # software distributed under the Apache License Version 2.0 is distributed on an
9
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
11
+
12
+ # Author:: Alex Dean (mailto:support@snowplowanalytics.com)
13
+ # Copyright:: Copyright (c) 2012 SnowPlow Analytics Ltd
14
+ # License:: Apache License Version 2.0
15
+
16
+ require 'infobright-loader/loader'
17
+
18
+ module InfobrightLoader
19
+ module Db
20
+
21
+ # Configuration for accessing an Infobright database.
22
+ # :username and :password can be nil
23
+ DbConfig = Struct.new(:name, :username, :password)
24
+
25
+ # Is mysql-ib running and the
26
+ # Infobright server accessible?
27
+ def running?(db)
28
+ ib = ib_command_from(db)
29
+ `#{ib} -e \\\\q > /dev/null 2>&1`
30
+ ($?.to_i == 0)
31
+ end
32
+ module_function :running?
33
+
34
+ # Does the database exist and can
35
+ # we access it?
36
+ def db_exists?(db)
37
+ ib = ib_command_from(db)
38
+ `#{ib} -D #{db.name} -e \\\\q > /dev/null 2>&1`
39
+ ($?.to_i == 0)
40
+ end
41
+ module_function :db_exists?
42
+
43
+ # Does the table exist?
44
+ def table_exists?(table, db)
45
+ ib = ib_command_from(db)
46
+ `echo "desc "#{table}";" | #{ib} -D #{db.name} > /dev/null 2>&1`
47
+ ($?.to_i == 0)
48
+ end
49
+ module_function :table_exists?
50
+
51
+ # Load data
52
+ def load_file(file, table, db, separator='|', encloser='')
53
+
54
+ # Make sure seperator and encloser are escaped if either is " or '
55
+ escaper = lambda { |c| (c == '"' || c == "'") ? "\\" + c : c }
56
+ separator = escaper.call(separator)
57
+ encloser = escaper.call(encloser)
58
+
59
+ # Check the file exists
60
+ unless File.file?(file)
61
+ raise InfobrightLoader::Loader::LoadError, "file does not exist, or is not a file"
62
+ end
63
+
64
+ ib = ib_command_from(db)
65
+ load = "LOAD DATA INFILE '#{file}' " + \
66
+ "INTO TABLE #{table} " + \
67
+ "FIELDS TERMINATED BY '#{separator}' ENCLOSED BY '#{encloser}'; "
68
+
69
+ stdout_err = `echo "#{load}" | #{ib} -D #{db.name} 2>&1`
70
+ ret_val = $?.to_i
71
+ unless ret_val == 0
72
+ raise InfobrightLoader::Loader::LoadError, "mysql-ib error code #{ret_val}: #{stdout_err}"
73
+ end
74
+ end
75
+ module_function :load_file
76
+
77
+ private
78
+
79
+ # Get path to Infobright's mysql-ib client,
80
+ # then add in username and password as
81
+ # necessary
82
+ def ib_command_from(db)
83
+ `locate mysql-ib`[0...-1] + \
84
+ (db.username.nil? ? '' : " -u #{db.username}") + \
85
+ (db.password.nil? ? '' : " --password=#{db.password}")
86
+ end
87
+ module_function :ib_command_from
88
+
89
+ end
90
+ end