Module: Arfi::Commands::FunctionsCreation

Included in:
Functions
Defined in:
lib/arfi/commands/functions_creation.rb,
sig/lib/arfi/commands/functions_creation.rbs

Overview

Function file creation helpers for Functions.

Constant Summary collapse

DEFAULT_SCHEMA =

Returns:

  • ("public")
ROOT_DIR =

Returns:

  • ("db/functions")
ADAPTERS =

Returns:

  • (::Array[:postgresql | :mysql | :trilogy])

Instance Method Summary collapse

Instance Method Details

#build_from_file(schema, function_name, original_ref:) ⇒ String

Build SQL content by evaluating a user-supplied template file.

Parameters:

  • schema (String?)

    PostgreSQL schema name (optional)

  • function_name (String)

    Function name

  • original_ref (String)

    Original function reference as passed by the user

  • original_ref: (String)

Returns:

  • (String)

    Evaluated SQL content



60
61
62
63
64
# File 'lib/arfi/commands/functions_creation.rb', line 60

def build_from_file(schema, function_name, original_ref:)
  schema_name = resolve_schema_name(schema)
  qualified_name = schema_name ? "#{schema_name}.#{function_name}" : function_name
  evaluate_template(function_name, schema_name, qualified_name, original_ref)
end

#build_mysql_skeleton(function_name) ⇒ String

Build a default MySQL function skeleton.

Parameters:

  • function_name (String)

    Function name

Returns:

  • (String)

    SQL skeleton



144
145
146
147
148
149
150
151
152
153
154
# File 'lib/arfi/commands/functions_creation.rb', line 144

def build_mysql_skeleton(function_name)
  <<~SQL
    -- MySQL note: you may need to DROP FUNCTION IF EXISTS #{function_name};
    -- and ensure your connection allows multi-statements if you include both.
    CREATE FUNCTION #{function_name} ()
    RETURNS return_type
    BEGIN
      -- Function body here
    END;
  SQL
end

#build_postgresql_skeleton(schema, function_name) ⇒ String

Build a default PostgreSQL function skeleton.

Parameters:

  • schema (String?)

    PostgreSQL schema name (defaults to 'public')

  • function_name (String)

    Function name

Returns:

  • (String)

    SQL skeleton



126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/arfi/commands/functions_creation.rb', line 126

def build_postgresql_skeleton(schema, function_name)
  sch = schema || DEFAULT_SCHEMA
  qualified = "#{sch}.#{function_name}"
  <<~SQL
    CREATE OR REPLACE FUNCTION #{qualified}() RETURNS TEXT[]
        LANGUAGE SQL
        IMMUTABLE AS
    $$
        -- Function body here
    $$
  SQL
end

#build_sql_function(schema, function_name, original_ref:) ⇒ String

Build the SQL function content, either from a custom template or from a skeleton.

Parameters:

  • schema (String?)

    PostgreSQL schema name (optional)

  • function_name (String)

    Function name

  • original_ref (String)

    Original function reference as passed by the user

  • original_ref: (String)

Returns:

  • (String)

    SQL function body

Raises:

  • (StandardError)

    If adapter is unknown



40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/arfi/commands/functions_creation.rb', line 40

def build_sql_function(schema, function_name, original_ref:)
  return build_from_file(schema, function_name, original_ref: original_ref) if options[:template]

  opt = adapter_opt
  if opt.nil? || opt == 'postgresql'
    build_postgresql_skeleton(schema, function_name)
  elsif %w[mysql trilogy].include?(opt)
    build_mysql_skeleton(function_name)
  else
    raise "Unknown adapter: #{opt}. Supported adapters: #{ADAPTERS.join(', ')}"
  end
end

#ensure_dirs!(adapter:, schema:) ⇒ void

This method returns an undefined value.

Ensure required function directories exist, creating them if necessary.

Parameters:

  • adapter (String?)

    Database adapter name (nil for generic)

  • schema (String?)

    PostgreSQL schema name (optional)

  • adapter: (String, nil)
  • schema: (String, nil)

Raises:



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/arfi/commands/functions_creation.rb', line 16

def ensure_dirs!(adapter:, schema:)
  root = Rails.root.join(ROOT_DIR)
  raise Arfi::Errors::NoFunctionsDir unless root.directory?

  FileUtils.mkdir_p(root.join(DEFAULT_SCHEMA))
  return if adapter.nil?

  adapter_root = root.join(adapter)
  FileUtils.mkdir_p(adapter_root)
  FileUtils.mkdir_p(adapter_root.join(DEFAULT_SCHEMA))
  return unless adapter == 'postgresql'

  sch = schema || DEFAULT_SCHEMA
  FileUtils.mkdir_p(adapter_root.join(sch))
end

#evaluate_template(function_name, schema_name, qualified_name, original_ref) ⇒ Object

Evaluate a user-supplied Ruby template file to produce SQL content.

Parameters:

  • function_name (String)

    Function name variable available in the template

  • schema_name (String?)

    Schema name variable available in the template

  • qualified_name (String)

    Qualified function name variable available in the template

  • original_ref (String)

    Original function reference variable available in the template

Returns:

  • (Object)

    Evaluated template result (expected to be a String)



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/arfi/commands/functions_creation.rb', line 108

def evaluate_template(function_name, schema_name, qualified_name, original_ref)
  tpl = File.read(options[:template])
  RubyVM::InstructionSequence.compile(<<~RUBY).eval # steep:ignore
    index_name     = #{function_name.inspect}
    function_name  = #{function_name.inspect}
    schema_name    = #{schema_name.inspect}
    qualified_name = #{qualified_name.inspect}
    original_ref   = #{original_ref.inspect}
    #{tpl}
  RUBY
end

#remove_function_file(schema, function_name) ⇒ void

This method returns an undefined value.

Delete a function file from disk, searching known locations.

Parameters:

  • schema (String?)

    PostgreSQL schema name (optional)

  • function_name (String)

    Function name



89
90
91
92
93
94
95
96
97
98
# File 'lib/arfi/commands/functions_creation.rb', line 89

def remove_function_file(schema, function_name)
  candidates = function_paths(schema, function_name)
  path = candidates.find { |p| File.exist?(p) }
  unless path
    puts "Not found. Looked in:\n  - #{candidates.map { rel(_1) }.join("\n  - ")}"
    return
  end
  FileUtils.rm(path)
  puts "Deleted: #{rel(path)}"
end

#write_file(schema, function_name, content) ⇒ void

This method returns an undefined value.

Write the SQL function content to disk, respecting --force option.

Parameters:

  • schema (String?)

    PostgreSQL schema name (optional)

  • function_name (String)

    Function name

  • content (String)

    SQL function body to write



73
74
75
76
77
78
79
80
81
# File 'lib/arfi/commands/functions_creation.rb', line 73

def write_file(schema, function_name, content)
  path = canonical_path(schema, function_name)
  if File.exist?(path) && !options[:force]
    puts "Already exists: #{rel(path)} (use --force to overwrite)"
    return
  end
  File.write(path, content.to_s)
  puts "Created: #{rel(path)}"
end