Module: XMigra

Defined in:
lib/xmigra/view.rb,
lib/xmigra/index.rb,
lib/xmigra/utils.rb,
lib/xmigra/plugin.rb,
lib/xmigra/console.rb,
lib/xmigra/version.rb,
lib/xmigra/function.rb,
lib/xmigra/new_file.rb,
lib/xmigra/migration.rb,
lib/xmigra/revert_file.rb,
lib/xmigra/branch_upgrade.rb,
lib/xmigra/schema_updater.rb,
lib/xmigra/access_artifact.rb,
lib/xmigra/db_support/psql.rb,
lib/xmigra/migration_chain.rb,
lib/xmigra/new_index_adder.rb,
lib/xmigra/vcs_support/git.rb,
lib/xmigra/vcs_support/svn.rb,
lib/xmigra/db_support/mssql.rb,
lib/xmigra/index_collection.rb,
lib/xmigra/stored_procedure.rb,
lib/xmigra/migration_conflict.rb,
lib/xmigra/schema_manipulator.rb,
lib/xmigra/declarative_support.rb,
lib/xmigra/new_migration_adder.rb,
lib/xmigra/declarative_migration.rb,
lib/xmigra/impdecl_migration_adder.rb,
lib/xmigra/source_tree_initializer.rb,
lib/xmigra/permission_script_writer.rb,
lib/xmigra/declarative_support/table.rb,
lib/xmigra/new_access_artifact_adder.rb,
lib/xmigra/reversion_script_building.rb,
lib/xmigra/access_artifact_collection.rb,
lib/xmigra.rb

Defined Under Namespace

Modules: Console, DeclarativeMigration, DeclarativeSupport, FoldedYamlStyle, GitSpecifics, LiteralYamlStyle, MSSQLSpecifics, NoSpecifics, PgSQLSpecifics, ReversionScriptBuilding, SubversionSpecifics, WarnToStderr Classes: AccessArtifact, AccessArtifactCollection, BranchUpgrade, Error, Function, ImpdeclMigrationAdder, Index, IndexCollection, Migration, MigrationChain, MigrationConflict, NewAccessArtifactAdder, NewIndexAdder, NewMigrationAdder, PermissionScriptWriter, Plugin, RevertFile, SchemaError, SchemaManipulator, SchemaUpdater, SourceTreeInitializer, StoredProcedure, SvnHistoryTracer, VersionControlError, View

Constant Summary collapse

VERSION =
"1.7.4"
FORMALIZATIONS =
{
  /xmigra/i=>"XMigra",
}
DBOBJ_NAME_SPLITTER =
/^
  (?:(\[[^\[\]]+\]|[^.\[]+)\.)?     (?# Schema, match group 1)
  (\[[^\[\]]+\]|[^.\[]+)            (?# Object name, match group 2)
$/x
DBQUOTE_STRIPPER =
/^\[?([^\]]+)\]?$/
PLATFORM =
case
when (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/) then :mswin
else :unix
end
NULL_FILE =
case PLATFORM
when :mswin then 'NUL'
else '/dev/null'
end
BASE_32_ENCODING =
'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
DatabaseSupportModules =
[]
VersionControlSupportModules =
[]

Class Method Summary collapse

Class Method Details

.access_artifact(info) ⇒ Object



224
225
226
227
228
229
230
231
232
# File 'lib/xmigra.rb', line 224

def access_artifact(info)
  case info["define"]
  when "stored procedure" then StoredProcedure.new(info)
  when "view" then View.new(info)
  when "function" then Function.new(info)
  else
    raise SchemaError, "'define' not specified for access artifact '#{info['name']}'"
  end
end

.base32encoding(bytes) ⇒ Object



271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/xmigra.rb', line 271

def base32encoding(bytes)
  carry = 0
  carry_bits = 0
  ''.tap do |result|
    bytes.each_byte do |b|
      # From b we need the (5 - carry_bits) most significant bits
      needed_bits = 5 - carry_bits
      code_unit = (carry << needed_bits) | b >> (8 - needed_bits)
      result << BASE_32_ENCODING[code_unit]
      
      if needed_bits <= 3
        # Extra character out of this byte
        code_unit = (b >> (3 - needed_bits)) & 0x1F
        result << BASE_32_ENCODING[code_unit]
        carry_bits = (3 - needed_bits)
      else
        carry_bits = 8 - needed_bits
      end
      carry = b & ((1 << carry_bits) - 1)
    end
    
    if carry_bits > 0
      code_unit = carry << (5 - carry_bits)
      result << BASE_32_ENCODING[code_unit]
    end
    
    result << '=' * (7 - ((result.length + 7) % 8))
  end
end

.canonize_path_case(s) ⇒ Object



191
192
193
194
195
196
# File 'lib/xmigra.rb', line 191

def self.canonize_path_case(s)
  case PLATFORM
  when :mswin then s.downcase
  else s
  end
end

.command_line_programObject



341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/xmigra.rb', line 341

def self.command_line_program
  XMigra::Program.run(
    ARGV,
    :error=>proc do |e|
      STDERR.puts("#{e} (#{e.class})") unless e.is_a?(XMigra::Program::QuietError)
      if e.class.const_defined? :COMMAND_LINE_HELP
        STDERR.puts(XMigra.program_message(e.class::COMMAND_LINE_HELP))
      end
      log_error(e)
      exit(2) if e.is_a?(OptionParser::ParseError)
      exit(2) if e.is_a?(XMigra::Program::ArgumentError)
      exit(1)
    end
  )
end

.dedent(s, prefix = '') ⇒ Object



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/xmigra/utils.rb', line 2

def self.dedent(s, prefix='')
  margin = nil
  s.lines.map do |l|
    case 
    when margin.nil? && l =~ /^ *$/
      l
    when margin.nil?
      margin = /^ */.match(l)[0].length
      l[margin..-1]
    else
      /^(?: {0,#{margin}})(.*)/m.match(l)[1]
    end
  end.tap do |lines|
    lines.shift if lines.first == "\n"
  end.map do |l|
    prefix + l
  end.join('')
end

.each_access_artifact(path) ⇒ Object



242
243
244
245
246
247
# File 'lib/xmigra.rb', line 242

def each_access_artifact(path)
  Dir.glob(File.join(path, '*.yaml')).each do |fpath|
    artifact = load_access_artifact(fpath)
    (yield artifact) if artifact
  end
end

.formalize(s) ⇒ Object



198
199
200
201
202
203
# File 'lib/xmigra.rb', line 198

def self.formalize(s)
  FORMALIZATIONS.each_pair do |pattern, result|
    return result if pattern === s
  end
  return s
end

.load_access_artifact(path) ⇒ Object



234
235
236
237
238
239
240
# File 'lib/xmigra.rb', line 234

def load_access_artifact(path)
  info = YAML.load_file(path)
  info['name'] = File.basename(path, '.yaml')
  artifact = access_artifact(info)
  artifact.file_path = File.expand_path(path)
  return artifact
end

.log_error(e) ⇒ Object



357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
# File 'lib/xmigra.rb', line 357

def self.log_error(e)
  if log_file = ENV['XMIGRA_LOG_FILE']
    Pathname(log_file).open('a') do |log|
      log.puts "#{Time.now}: #{e} (#{e.class})"
      e.backtrace.each do |frame|
        log.puts "    " + frame
      end
      
      while e.respond_to?(:cause) && e = e.cause
        log.puts "  Caused by: #{e} (#{e.class})"
        e.backtrace.each do |frame|
          log.puts "    " + frame
        end
      end
    end
  end
end

.program_message(message, options = {}) ⇒ Object



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/xmigra.rb', line 205

def self.program_message(message, options={})
  prog_pattern = options[:prog] || /%prog\b/
  
  steps = [$0]
  steps << (program = self.canonize_path_case(File.basename(steps[-1])))
  steps << (prog_name = self.formalize(File.basename(steps[-2], '.rb')))
  steps << message.to_s
  steps << steps[-1].gsub(prog_pattern, program)
  steps << steps[-1].gsub(/%program_name\b/, prog_name)
  steps << steps[-1].gsub(/%cmd\b/, options[:cmd] || '<cmd>')
  return steps[-1]
rescue
  STDERR.puts "steps: " + steps.inspect
  raise
end

.secure_digest(s, options = {:encoding=>:base64}) ⇒ Object



258
259
260
261
262
263
264
265
266
267
268
# File 'lib/xmigra.rb', line 258

def secure_digest(s, options={:encoding=>:base64})
  digest_value = Digest::MD5.digest(s)
  case options[:encoding]
  when nil
    digest_value
  when :base64
    [digest_value].pack('m0').chomp
  when :base32
    base32encoding(digest_value)
  end
end

.yaml_path(path) ⇒ Object



249
250
251
252
253
254
255
256
# File 'lib/xmigra.rb', line 249

def yaml_path(path)
  path_s = path.to_s
  if path_s.end_with?('.yaml')
    return path
  else
    return path.class.new(path_s + '.yaml')
  end
end