Class: Sqlsnip::Source

Inherits:
Object
  • Object
show all
Defined in:
lib/sqlsnip.rb

Constant Summary collapse

UID_RE =
/(?:[.\w]+)/
TABLE_MODIFIERS_RE =
/(?:global|local|temporary|temp|unlogged)/
VIEW_MODIFIERS_RE =
/(?:temp|temporary|recursive)/
IF_NOT_EXISTS_RE =
/(?:if\s+not\s+exists)/
TRIGGER_MODIFIERS_RE =
/(?:constraint)/
FUNCTION_ARGMODE_RE =
/(?:in|out|inout|variadic)/
FUNCTION_ARGS_RE =
/(?:#{FUNCTION_ARGMODE_RE}\s*,\s*)/
FUNCTION_DEFAULT_RE =
/(?:default\s+.*)/
TABLE_RE =
/(?:#{TABLE_MODIFIERS_RE}\s+)*table\s+(?:#{IF_NOT_EXISTS_RE}?\s+)?(#{UID_RE})/i
VIEW_RE =
/(?:#{VIEW_MODIFIERS_RE}\s+)*view\s+(#{UID_RE})/i
MATERIALIZED_VIEW_RE =
/materialized\s+view\s*(#{UID_RE})/i
FUNCTION_RE =
/function\s+(#{UID_RE})\s*\((.*?)\)\s+(?:returns|$)/i
PROCEDURE_RE =
/function\s+(#{UID_RE})\s*\((.*?)\)\s+(?:as|$)/i
TRIGGER_RE =
/trigger\s+(#{UID_RE})\s+.*\s+on\s+(#{UID_RE})/i
DEFAULT_VALUE_RE =
/(?:[^,\(]+(?:\([^\)]*\))?)/
DEFAULT_RE =
/default\s+#{DEFAULT_VALUE_RE}/i
SEARCH_PATH_RE =
/^\s*set\s+search_path/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file, start_line = nil, stop_line = nil, search_path: nil) ⇒ Source

Returns a new instance of Source.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/sqlsnip.rb', line 51

def initialize(file, start_line = nil, stop_line = nil, search_path: nil)
  constrain file, String
  constrain start_line, Integer, nil
  constrain stop_line, Integer, nil
  constrain search_path, String, nil
  @file, @start_line, @stop_line = file, start_line, stop_line
  File.exist?(@file) or raise Error, "Can't find #{file}"
  @lines = []
  @stmts = nil
  @search_path = search_path
  if @search_path && !@search_path.empty?
    @search_path_stmt = "set search_path to #{@search_path};"
  end
  @project_dir = nil
end

Instance Attribute Details

#fileObject (readonly)

Source file



37
38
39
# File 'lib/sqlsnip.rb', line 37

def file
  @file
end

#linesObject (readonly)

The selected range of lines as read from the file



43
44
45
# File 'lib/sqlsnip.rb', line 43

def lines
  @lines
end

#search_pathObject (readonly)

Initial search path



49
50
51
# File 'lib/sqlsnip.rb', line 49

def search_path
  @search_path
end

#start_lineObject (readonly)

Starting and ending line (inclusive). May be nil



40
41
42
# File 'lib/sqlsnip.rb', line 40

def start_line
  @start_line
end

#stmtsObject (readonly)

Array of generated statements



46
47
48
# File 'lib/sqlsnip.rb', line 46

def stmts
  @stmts
end

#stop_lineObject (readonly)

Starting and ending line (inclusive). May be nil



40
41
42
# File 'lib/sqlsnip.rb', line 40

def stop_line
  @stop_line
end

Class Method Details

.parse(*args, **opts) ⇒ Object



73
# File 'lib/sqlsnip.rb', line 73

def self.parse(*args, **opts) self.new(*args, **opts).parse end

Instance Method Details

#generate(interactive: false) ⇒ Object



75
76
77
78
79
# File 'lib/sqlsnip.rb', line 75

def generate(interactive: false)
  generate_search_path_stmt if @search_path != ""
  generate_interactive_stmts if interactive
  @stmts
end

#generate_drop_stmtsObject



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
125
# File 'lib/sqlsnip.rb', line 81

def generate_drop_stmts
  @stmts = []
  for line in lines
    case line
      when /^\s*set\s+search_path/
        sql = line
      when /^\s*create\s+(.*)/
        object = $1
        case object 
          when TABLE_RE
            table = $1
            sql = "drop table if exists #{table} cascade;"
          when MATERIALIZED_VIEW_RE
            view = $1
            sql = "drop materialized view if exists #{view} cascade;"
          when VIEW_RE
            view = $1
            sql = "drop view if exists #{view} cascade;"
          when FUNCTION_RE
            function = $1
            args_str = $2
            # We assume that default values contain no commas
            args = args_str.split(/\s*,\s*/).map { |arg|
              arg.sub(/^#{UID_RE}\s+/, "").sub(/\s+#{FUNCTION_DEFAULT_RE}/, "") 
            }
            sql = "drop function if exists #{function}(#{args.join(', ')}) cascade;"
          when PROCEDURE_RE
            procedure, args_str = $1, $2
            # We assume that default values contain no commas
            args = args_str.split(/\s*,\s*/).map { |arg|
              arg.sub(/^#{UID_RE}\s+/, "").sub(/\s+#{FUNCTION_DEFAULT_RE}/, "") 
            }
            sql = "drop procedure if exists #{procedure}(#{args.join(', ')}) cascade;"
          when TRIGGER_RE
            trigger, table = $1, $2
            sql = "drop trigger if exists #{trigger} on #{table} cascade;"
        else
          next
        end
    else
      next
    end
    @stmts << sql
  end
end

#generate_interactive_stmtsObject



140
141
142
# File 'lib/sqlsnip.rb', line 140

def generate_interactive_stmts
  @stmts.unshift '\set ON_ERROR_STOP on'
end

#generate_search_path_stmtObject

Generate a ‘set search_path’ statement



128
129
130
131
132
133
134
135
136
137
138
# File 'lib/sqlsnip.rb', line 128

def generate_search_path_stmt
  if @search_path == ""
    return @stmts
  elsif @search_path_stmt
    @stmts.unshift @search_path_stmt
  else
    schema = find_schema_from_file(file)
    search_path = "set search_path to #{schema};"
    @stmts.unshift search_path
  end
end

#parseObject



67
68
69
70
71
# File 'lib/sqlsnip.rb', line 67

def parse
  read_lines
  generate_drop_stmts
  self
end