Class: Rails::Schema::Extractor::StructureSqlParser

Inherits:
Object
  • Object
show all
Defined in:
lib/rails/schema/extractor/structure_sql_parser.rb

Constant Summary collapse

SQL_TYPE_MAP =
{
  "character varying" => "string", "varchar" => "string",
  "integer" => "integer", "smallint" => "integer", "serial" => "integer",
  "bigint" => "bigint", "bigserial" => "bigint",
  "boolean" => "boolean", "text" => "text",
  "timestamp without time zone" => "datetime", "timestamp with time zone" => "datetime",
  "timestamp" => "datetime",
  "json" => "json", "jsonb" => "jsonb", "uuid" => "uuid",
  "numeric" => "decimal", "decimal" => "decimal", "money" => "decimal",
  "date" => "date",
  "float" => "float", "double precision" => "float", "real" => "float",
  "bytea" => "binary"
}.freeze
COMPOUND_TYPE_RE =
/\A(character\s+varying|bit\s+varying|double\s+precision|
timestamp(?:\(\d+\))?\s+with(?:out)?\s+time\s+zone)/ix.freeze
CONSTRAINT_RE =
/\A(CONSTRAINT|UNIQUE|CHECK|EXCLUDE|FOREIGN\s+KEY)\b/i.freeze
PK_CONSTRAINT_RE =
/PRIMARY\s+KEY\s*\(([^)]+)\)/i.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(structure_path = nil) ⇒ StructureSqlParser

Returns a new instance of StructureSqlParser.



33
34
35
36
# File 'lib/rails/schema/extractor/structure_sql_parser.rb', line 33

def initialize(structure_path = nil)
  @structure_path = structure_path
  @views = Set.new
end

Instance Attribute Details

#viewsObject (readonly)

Set of table names that are backed by SQL views (CREATE VIEW), not real tables. Populated by #parse / #parse_content. Lets downstream code badge view-backed models on the diagram.



31
32
33
# File 'lib/rails/schema/extractor/structure_sql_parser.rb', line 31

def views
  @views
end

Instance Method Details

#parseObject



38
39
40
41
42
43
# File 'lib/rails/schema/extractor/structure_sql_parser.rb', line 38

def parse
  path = resolve_path
  return {} unless path && File.exist?(path)

  parse_content(File.read(path))
end

#parse_content(content) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/rails/schema/extractor/structure_sql_parser.rb', line 45

def parse_content(content)
  tables = {}
  @views = Set.new

  content.scan(/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?([\w."]+)\s*\((.*?)\)\s*;/mi) do |table_name, body|
    name = extract_table_name(table_name)
    columns, pk_columns = parse_table_body(body)
    pk_columns.each { |pk| columns.find { |c| c[:name] == pk }&.[]= :primary, true }
    tables[name] = columns
  end

  parse_views(content, tables)
  tables
end