(Feat): Initial Commit
This commit is contained in:
89
scripts/sql/default_zero_values.sql
Normal file
89
scripts/sql/default_zero_values.sql
Normal file
@@ -0,0 +1,89 @@
|
||||
-- Errors if DEFAULT values for certain column data_types
|
||||
-- is NOT set to the golang zero value
|
||||
--
|
||||
-- https://github.com/volatiletech/sqlboiler/issues/409
|
||||
-- https://github.com/volatiletech/sqlboiler/issues/237
|
||||
-- https://golang.org/ref/spec#The_zero_value
|
||||
--
|
||||
-- https://github.com/volatiletech/sqlboiler#diagnosing-problems
|
||||
-- A field not being inserted (usually a default true boolean), boil.Infer
|
||||
-- looks at the zero value of your Go type (it doesn’t care what the default
|
||||
-- value in the database is) to determine if it should insert your field or
|
||||
-- not. In the case of a default true boolean value, when you want to set it to
|
||||
-- false; you set that in the struct but that’s the zero value for the bool
|
||||
-- field in Go so sqlboiler assumes you do not want to insert that field and
|
||||
-- you want the default value from the database. Use a whitelist/greylist to
|
||||
-- add that field to the list of fields to insert.
|
||||
--
|
||||
-- boil.Infer() assumes all SQL defaults are Go zero value
|
||||
--
|
||||
-- To mitigate the above situation we disallow setting DEFAULT to anything
|
||||
-- other than the default golang zero value of this type. Otherwise this issue
|
||||
-- is fairly hard to debug (boil.Infer() does not insert DEFAULT as expected).
|
||||
--
|
||||
-- If a default value is actually set, we only allow the respective mapped golang zero value:
|
||||
-- 0 for all integer types
|
||||
-- 0.0 for floating point numbers
|
||||
-- false for booleans
|
||||
-- "" for strings
|
||||
-- nil for pointers
|
||||
--
|
||||
-- https://stackoverflow.com/questions/8146448/get-the-default-values-of-table-columns-in-postgres
|
||||
-- https://dba.stackexchange.com/questions/205471/why-does-information-schema-have-yes-and-no-character-strings-rather-than-bo
|
||||
CREATE OR REPLACE FUNCTION check_default_go_sql_zero_values ()
|
||||
RETURNS SETOF information_schema.columns
|
||||
AS $BODY$
|
||||
BEGIN
|
||||
RETURN QUERY
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
information_schema.columns
|
||||
WHERE (table_schema = 'public'
|
||||
AND column_default IS NOT NULL)
|
||||
AND is_nullable = 'NO'
|
||||
AND ((data_type = 'boolean'
|
||||
AND column_default <> 'false')
|
||||
OR (data_type IN ('char', 'character', 'varchar', 'character varying', 'text')
|
||||
AND column_default NOT LIKE concat('''''', '::%'))
|
||||
OR (data_type IN ('smallint', 'integer', 'bigint', 'smallserial', 'serial', 'bigserial')
|
||||
AND (column_default <> '0'
|
||||
AND column_default NOT LIKE 'nextval(%'))
|
||||
OR (data_type IN ('decimal', 'numeric', 'real', 'double precision')
|
||||
AND column_default <> '0.0'));
|
||||
END
|
||||
$BODY$
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER;
|
||||
|
||||
CREATE OR REPLACE FUNCTION default_zero_values ()
|
||||
RETURNS void
|
||||
AS $$
|
||||
DECLARE
|
||||
item record;
|
||||
BEGIN
|
||||
FOR item IN
|
||||
SELECT
|
||||
table_name,
|
||||
column_name,
|
||||
data_type,
|
||||
column_default,
|
||||
is_nullable
|
||||
FROM
|
||||
check_default_go_sql_zero_values ()
|
||||
LOOP
|
||||
RAISE WARNING ' %.% % : INVALID DEFAULT ''%''', item.table_name, item.column_name, item.data_type, item.column_default USING HINT = to_json(item);
|
||||
END LOOP;
|
||||
IF FOUND THEN
|
||||
RAISE EXCEPTION 'NOT NULL columns require the respective go zero value () AS their DEFAULT value or no DEFAULT at all'
|
||||
USING HINT = '0 for integer types, 0.0 for floating point numbers, false for booleans, "" for strings';
|
||||
END IF;
|
||||
END;
|
||||
$$
|
||||
LANGUAGE plpgsql;
|
||||
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
default_zero_values ();
|
||||
|
||||
57
scripts/sql/fk_missing_index.sql
Normal file
57
scripts/sql/fk_missing_index.sql
Normal file
@@ -0,0 +1,57 @@
|
||||
-- Errors if FKs do not have an index
|
||||
CREATE OR REPLACE FUNCTION fk_missing_index ()
|
||||
RETURNS void
|
||||
AS $$
|
||||
DECLARE
|
||||
item record;
|
||||
BEGIN
|
||||
FOR item IN
|
||||
SELECT
|
||||
c.conrelid::regclass AS "table",
|
||||
/* list of key column names in order */
|
||||
string_agg(a.attname, ',' ORDER BY x.n) AS columns,
|
||||
pg_catalog.pg_size_pretty(pg_catalog.pg_relation_size(c.conrelid)) AS size,
|
||||
c.conname AS constraint,
|
||||
c.confrelid::regclass AS referenced_table
|
||||
FROM
|
||||
pg_catalog.pg_constraint c
|
||||
/* enumerated key column numbers per foreign key */
|
||||
CROSS JOIN LATERAL unnest(c.conkey)
|
||||
WITH ORDINALITY AS x (attnum, n)
|
||||
/* name for each key column */
|
||||
JOIN pg_catalog.pg_attribute a ON a.attnum = x.attnum
|
||||
AND a.attrelid = c.conrelid
|
||||
WHERE
|
||||
NOT EXISTS
|
||||
/* is there a matching index for the constraint? */
|
||||
(
|
||||
SELECT
|
||||
1
|
||||
FROM
|
||||
pg_catalog.pg_index i
|
||||
WHERE
|
||||
i.indrelid = c.conrelid
|
||||
/* the first index columns must be the same as the
|
||||
key columns, but order doesn't matter */
|
||||
AND (i.indkey::smallint[])[0:cardinality(c.conkey) - 1] @> c.conkey)
|
||||
AND c.contype = 'f'
|
||||
GROUP BY
|
||||
c.conrelid,
|
||||
c.conname,
|
||||
c.confrelid
|
||||
ORDER BY
|
||||
pg_catalog.pg_relation_size(c.conrelid) DESC LOOP
|
||||
RAISE WARNING 'CREATE INDEX "idx_%_fk_%" ON "%" ("%");', item.table, item.columns, item.table, item.columns USING HINT = to_json(item);
|
||||
END LOOP;
|
||||
IF FOUND THEN
|
||||
RAISE EXCEPTION ' We require ALL FOREIGN keys TO have an INDEX defined. ';
|
||||
END IF;
|
||||
END;
|
||||
$$
|
||||
LANGUAGE plpgsql;
|
||||
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
fk_missing_index ();
|
||||
|
||||
15
scripts/sql/info.sql
Normal file
15
scripts/sql/info.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
-- This file just queries for the currently applied tables/columns as an overview
|
||||
SELECT
|
||||
table_name,
|
||||
column_name,
|
||||
data_type,
|
||||
column_default,
|
||||
is_nullable
|
||||
FROM
|
||||
information_schema.columns
|
||||
WHERE (table_schema = 'public')
|
||||
ORDER BY
|
||||
table_name,
|
||||
is_nullable,
|
||||
column_name;
|
||||
|
||||
Reference in New Issue
Block a user