-- initial shell type so that it can be used as a TYPE in the 'bs_date_in' and 'bs_date_out' function staements CREATE TYPE bs_date; /* The reason we have to create these intermediary 'bs_date_in' and 'bs_date_out' functions here instead of directly making use of our C implementation is because: - For custom type definiti8ons, the INPUT and OUTPUT functions must reference SQL functions that are already registered in the database's system catalog (pg_proc). - These functions need to be defined first in the extension's SQL file before the 'CREATE TYPE' statement can reference them. - We can't specify 'MODULE_PATHNAME', 'bs_date_in' in the TYPE definition - The TYPE expects function names as strings, not direct module/symbol references. - PostgreSQL looks up these names in the database to get the function OIDs, and the functions must exist as SQL-callable entities. - The C functions in our shared libarary aren't directly callable from SQL without being wrapped in SQL function definition */ /* # Why set 'cstring' as the type - cstring is a null-terminated C string (basically a char* type) - when PostgreSQL parses a string literal (e.g. '2081/01/12'::bs_date, it directly passes the raw string to the type's INPUT function as a 'cstring'. raw string literal --> cstring --> bs_date_in All built-in PostgreSQL types (e.g., int4, text, date) follow this pattern. Their input functions take cstring and return the internal type representation. Examples: - int4in(cstring) for integers - textin(cstring) for text - date_in(cstring) for dates */ CREATE FUNCTION bs_date_in(cstring) RETURNS bs_date AS 'MODULE_PATHNAME', 'bs_date_in' LANGUAGE C IMMUTABLE STRICT; CREATE FUNCTION bs_date_out(bs_date) RETURNS cstring AS 'MODULE_PATHNAME', 'bs_date_out' LANGUAGE C IMMUTABLE STRICT; CREATE TYPE bs_date ( INPUT = bs_date_in, OUTPUT = bs_date_out, INTERNALLENGTH = 4, PASSEDBYVALUE );