lib/pg_objects/parser.rb in pg_objects-1.0.3 vs lib/pg_objects/parser.rb in pg_objects-1.2.0
- old
+ new
@@ -1,47 +1,96 @@
require 'pg_query'
-module PgObjects
- ##
- # Reads directives from SQL-comments
- #
- # --!depends_on [name_of_dependency]
- #
- # name_of_dependency: short or full name of object as well as object_name
- #
- class Parser
- # rubocop: disable Style/WordArray
- ROUTES = [
- ['DefineStmt', 'defnames', 0, 'String', 'str'],
- ['CreateFunctionStmt', 'funcname', 0, 'String', 'str'],
- ['CreateTrigStmt', 'trigname'],
- ['CreateEventTrigStmt', 'trigname'],
- ['CompositeTypeStmt', 'typevar', 'RangeVar', 'relname'],
- ['ViewStmt', 'view', 'RangeVar', 'relname'],
- ['CreateConversionStmt', 'conversion_name', 0, 'String', 'str'],
- ['CreateTableAsStmt', 'into', 'IntoClause', 'rel', 'RangeVar', 'relname'],
- ['CreateOpClassStmt', 'opclassname', 0, 'String', 'str']
- ].freeze
- # rubocop: enable Style/WordArray
+##
+# Reads directives from SQL-comments
+#
+# --!depends_on [name_of_dependency]
+#
+# name_of_dependency: short or full name of object as well as object_name
+#
+class PgObjects::Parser
+ PG_ENTITIES = %i[operator_class trigger define_statement conversion event_trigger type function table].freeze
- class << self
- def fetch_directives(text)
- {
- depends_on: fetch_dependencies(text)
- }
- end
+ def initialize(source)
+ @source = source
+ end
- def fetch_object_name(text)
- parsed = PgQuery.parse(text).tree.dig(0, 'RawStmt', 'stmt')
- ROUTES.map { |route| parsed.dig(*route) }.compact[0]
- rescue PgQuery::ParseError, NoMethodError
- nil
- end
+ def fetch_directives
+ {
+ depends_on: fetch_dependencies
+ }
+ end
- private
+ def fetch_object_name
+ parse_query
+ object_name
+ rescue PgQuery::ParseError, NoMethodError
+ nil
+ end
- def fetch_dependencies(text)
- text.split("\n").grep(/^(--|#)!/).map { |ln| ln.split[1] if ln =~ /!depends_on/ }.compact
- end
- end
+ private
+
+ attr_reader :stmt, :parsed
+
+ def parse_query
+ @parsed = PgQuery.parse(@source)
+
+ @stmt = parsed.tree.stmts[0].stmt
+ end
+
+ def object_name
+ PG_ENTITIES.filter_map { |entity| send(:"check_#{entity}") }.first
+ end
+
+ def fetch_dependencies
+ @source.split("\n").grep(/^(--|#)!/).map { |ln| ln.split[1] if ln =~ /!depends_on/ }.compact
+ end
+
+ # also views
+ def table? = parsed.tables.size.positive?
+
+ def check_table
+ parsed.tables[0] if table?
+ end
+
+ def function? = parsed.functions.size.positive?
+
+ def check_function
+ parsed.functions[0] if function?
+ end
+
+ def operator_class? = stmt.respond_to?(:create_op_class_stmt) && stmt.create_op_class_stmt.present?
+
+ def check_operator_class
+ stmt.create_op_class_stmt.opclassname[0].string.sval if operator_class?
+ end
+
+ def trigger? = stmt.respond_to?(:create_trig_stmt) && stmt.create_trig_stmt.present?
+
+ def check_trigger
+ stmt.create_trig_stmt.trigname if trigger?
+ end
+
+ def define_statement? = stmt.respond_to?(:define_stmt) && stmt.define_stmt.present?
+
+ def check_define_statement
+ stmt.define_stmt.defnames[0].string.sval if define_statement?
+ end
+
+ def conversion? = stmt.respond_to?(:create_conversion_stmt) && stmt.create_conversion_stmt.present?
+
+ def check_conversion
+ stmt.create_conversion_stmt.conversion_name[0].string.sval if conversion?
+ end
+
+ def event_trigger? = stmt.respond_to?(:create_event_trig_stmt) && stmt.create_event_trig_stmt.present?
+
+ def check_event_trigger
+ stmt.create_event_trig_stmt.trigname if event_trigger?
+ end
+
+ def type? = stmt.respond_to?(:composite_type_stmt) && stmt.composite_type_stmt.present?
+
+ def check_type
+ stmt.composite_type_stmt.typevar.relname if type?
end
end