Class: Piggly::Installer

Inherits:
Object show all
Defined in:
lib/piggly/installer.rb

Instance Method Summary collapse

Constructor Details

#initialize(config, connection) ⇒ Installer

Returns a new instance of Installer.



4
5
6
# File 'lib/piggly/installer.rb', line 4

def initialize(config, connection)
  @config, @connection = config, connection
end

Instance Method Details

#install(procedures, profile) ⇒ void

This method returns an undefined value.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/piggly/installer.rb', line 9

def install(procedures, profile)
  @connection.exec("begin")

  install_support(profile)

  procedures.each do |p|
    begin
      trace(p, profile)
    rescue Parser::Failure
      $stdout.puts $!
    end
  end

  @connection.exec("commit")
rescue
  @connection.exec("rollback")
  raise
end

#install_support(profile) ⇒ Object

Installs necessary instrumentation support



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/piggly/installer.rb', line 65

def install_support(profile)
  @connection.set_notice_processor(&profile.notice_processor(@config))

# def connection.set_notice_processor
#   # do nothing: prevent the notice processor from being subverted
# end

  # install tracing functions
  @connection.exec <<-SQL
    -- Signals that a conditional expression was executed
    CREATE OR REPLACE FUNCTION piggly_cond(message varchar, value boolean)
      RETURNS boolean AS $$
    BEGIN
      IF value THEN
        RAISE WARNING '#{@config.trace_prefix} % t', message;
      ELSE
        RAISE WARNING '#{@config.trace_prefix} % f', message;
      END IF;
      RETURN value;
    END $$ LANGUAGE 'plpgsql' VOLATILE;
  SQL

  @connection.exec <<-SQL
    -- Generic signal
    CREATE OR REPLACE FUNCTION piggly_signal(message varchar, signal varchar)
      RETURNS void AS $$
    BEGIN
      RAISE WARNING '#{@config.trace_prefix} % %', message, signal;
    END $$ LANGUAGE 'plpgsql' VOLATILE;
  SQL

  @connection.exec <<-SQL
    -- Signals that a (sub)expression was executed. handles '' and NULL value
    CREATE OR REPLACE FUNCTION piggly_expr(message varchar, value varchar)
      RETURNS varchar AS $$
    BEGIN
      RAISE WARNING '#{@config.trace_prefix} %', message;
      RETURN value;
    END $$ LANGUAGE 'plpgsql' VOLATILE;
  SQL

  @connection.exec <<-SQL
    -- Signals that a (sub)expression was executed. handles all other types
    CREATE OR REPLACE FUNCTION piggly_expr(message varchar, value anyelement)
      RETURNS anyelement AS $$
    BEGIN
      RAISE WARNING '#{@config.trace_prefix} %', message;
      RETURN value;
    END $$ LANGUAGE 'plpgsql' VOLATILE;
  SQL

  @connection.exec <<-SQL
    -- Signals that a branch was taken
    CREATE OR REPLACE FUNCTION piggly_branch(message varchar)
      RETURNS void AS $$
    BEGIN
      RAISE WARNING '#{@config.trace_prefix} %', message;
    END $$ LANGUAGE 'plpgsql' VOLATILE;
  SQL
end

#trace(procedure, profile) ⇒ void

This method returns an undefined value.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/piggly/installer.rb', line 42

def trace(procedure, profile)
  # recompile with instrumentation
  compiler = Compiler::TraceCompiler.new(@config)
  result   = compiler.compile(procedure)
    # result[:tree] - tagged and rewritten parse tree
    # result[:tags] - collection of Tag values in the tree
    # result[:code] - instrumented

  @connection.exec(procedure.definition(result[:code]))
  
  profile.add(procedure, result[:tags], result)
rescue
  $!.message << "\nError installing traced procedure #{procedure.name} "
  $!.message << "from #{procedure.source_path(@config)}"
  raise
end

#uninstall(procedures) ⇒ void

This method returns an undefined value.



29
30
31
32
33
34
35
36
37
38
39
# File 'lib/piggly/installer.rb', line 29

def uninstall(procedures)
  @connection.exec("begin")

  procedures.each{|p| untrace(p) }
  uninstall_support

  @connection.exec("commit")
rescue
  @connection.exec("rollback")
  raise
end

#uninstall_supportObject

Uninstalls instrumentation support



127
128
129
130
131
132
133
134
# File 'lib/piggly/installer.rb', line 127

def uninstall_support
  @connection.set_notice_processor{|x| $stderr.puts x }
  @connection.exec "DROP FUNCTION IF EXISTS piggly_cond(varchar, boolean)"
  @connection.exec "DROP FUNCTION IF EXISTS piggly_expr(varchar, varchar)"
  @connection.exec "DROP FUNCTION IF EXISTS piggly_expr(varchar, anyelement)"
  @connection.exec "DROP FUNCTION IF EXISTS piggly_branch(varchar)"
  @connection.exec "DROP FUNCTION IF EXISTS piggly_signal(varchar, varchar)"
end

#untrace(procedure) ⇒ void

This method returns an undefined value.



60
61
62
# File 'lib/piggly/installer.rb', line 60

def untrace(procedure)
  @connection.exec(procedure.definition(procedure.source(@config)))
end