defmodule Cldr.Unit.DDL do
@moduledoc """
Functions to return SQL DDL commands that support the
creation and deletion of the `cldr_unit` database
type and associated aggregate functions.
"""
# @doc since: "2.7.0"
@default_db :postgres
@supported_db_types :code.priv_dir(:ex_cldr_units_sql)
|> Path.join("SQL")
|> File.ls!()
|> Enum.map(&String.to_atom/1)
@doc """
Returns the SQL string which when executed will
define the `money_with_currency` data type.
## Arguments
* `db_type`: the type of the database for which the SQL
string should be returned. Defaults to `:postgres` which
is currently the only supported database type.
"""
def create_cldr_unit(db_type \\ @default_db) do
read_sql_file(db_type, "create_cldr_unit.sql")
end
@doc """
Returns the SQL string which when executed will
drop the `money_with_currency` data type.
## Arguments
* `db_type`: the type of the database for which the SQL
string should be returned. Defaults to `:postgres` which
is currently the only supported database type.
"""
def drop_cldr_unit(db_type \\ @default_db) do
read_sql_file(db_type, "drop_cldr_unit.sql")
end
@doc """
Returns the SQL string which when executed will
define aggregate functions for the `money_with_currency`
data type.
## Arguments
* `db_type`: the type of the database for which the SQL
string should be returned. Defaults to `:postgres` which
is currently the only supported database type.
"""
def define_aggregate_functions(db_type \\ @default_db) do
read_sql_file(db_type, "define_aggregate_functions.sql")
end
@doc """
Returns the SQL string which when executed will
drop the aggregate functions for the `money_with_currency`
data type.
## Arguments
* `db_type`: the type of the database for which the SQL
string should be returned. Defaults to `:postgres` which
is currently the only supported database type.
"""
def drop_aggregate_functions(db_type \\ @default_db) do
read_sql_file(db_type, "drop_aggregate_functions.sql")
end
@doc """
Returns a string that will Ecto `execute` each SQL
command.
## Arguments
* `sql` is a string of SQL commands that are
separated by three newlines ("\\n"),
that is to say two blank lines between commands
in the file.
## Example
iex> Money.DDL.execute "SELECT name FROM customers;\n\n\nSELECT id FROM orders;"
"execute \"\"\"\nSELECT name FROM customers;\n\n\nSELECT id FROM orders;\n\"\"\""
"""
def execute_each(sql) do
sql
|> String.split("\n\n\n")
|> Enum.map(&execute/1)
|> Enum.join("\n")
end
@doc """
Returns a string that will Ecto `execute` a single SQL
command.
## Arguments
* `sql` is a single SQL command
## Example
iex> Money.DDL.execute "SELECT name FROM customers;"
"execute \"SELECT name FROM customers;\""
"""
def execute(sql) do
sql = String.trim_trailing(sql, "\n")
if String.contains?(sql, "\n") do
"execute \"\"\"\n" <> sql <> "\n\"\"\""
else
"execute " <> inspect(sql)
end
end
defp read_sql_file(db_type, file_name) when db_type in @supported_db_types do
base_dir(db_type)
|> Path.join(file_name)
|> File.read!()
end
defp read_sql_file(db_type, file_name) do
raise ArgumentError,
"Database type #{db_type} does not have a SQL definition " <> "file #{inspect(file_name)}"
end
@app Mix.Project.config[:app]
defp base_dir(db_type) do
:code.priv_dir(@app)
|> Path.join(["SQL", "/#{db_type}"])
end
end