Ответ 1
На самом деле это не напрямую связано с перегрузкой функций (которую невозможно "отключить"). Это вопрос разрешения типа функции. (Конечно, этот алгоритм может быть более разрешающим без перегруженных функций.)
Все это будет работать:
SELECT * FROM myfunc(day_number := '1');
SELECT * FROM myfunc('1'); -- note the quotes
SELECT * FROM myfunc(1::smallint);
SELECT * FROM myfunc('1'::smallint);
Зачем?
Последние два довольно очевидны, вы уже упоминали об этом в своем вопросе.
Первые два более интересны, объяснение скрыто в Резолюции Типа Функции:
Предполагается, что неизвестные литералы могут быть преобразованы во что-либо для этой цели.
И это должно быть простым решением для вас: использовать строковые литералы.
Нетипизированный литерал '1'
(с кавычками) или "строковый литерал", как определено в стандарте SQL, по своей природе отличается от типизированного литерала (или константы).
Числовая константа 1
(без кавычек) сразу преобразуется в числовой тип. Руководство:
Числовая константа, которая не содержит ни десятичной точки, ни экспоненты, изначально считается типом integer, если ее значение соответствует типу
integer
(32 бита); в противном случае предполагается, что это типbigint
если его значение соответствует типуbigint
(64 бита); в противном случае он считается типомnumeric
. Константы, которые содержат десятичные точки и/или показатели, всегда изначально считаютсяnumeric
.Первоначально назначенный тип данных числовой константы является лишь отправной точкой для алгоритмов разрешения типов. В большинстве случаев константа будет автоматически приведена к наиболее подходящему типу в зависимости от контекста. При необходимости вы можете принудительно интерпретировать числовое значение как определенный тип данных путем его приведения.
Жирный акцент мой.
Назначение в вызове функции (day_number := 1
) является особым случаем, тип данных day_number
неизвестен на данный момент. Postgres не может получить тип данных из этого присваивания, и по умолчанию используется integer
.
Следовательно, Postgres ищет функцию, которая сначала принимает integer
. Тогда для функций, принимающих тип только неявное приведение от integer
, другими словами:
SELECT casttarget::regtype
FROM pg_cast
WHERE castsource = 'int'::regtype
AND castcontext = 'i';
Все они будут найдены - и конфликтуют, если существует более одной функции. Это будет перегрузкой функции, и вы получите другое сообщение об ошибке. С двумя функциями-кандидатами:
SELECT * FROM myfunc(1);
ERROR: function myfunc(integer) is not unique
Обратите внимание на "целое число" в сообщении: числовая константа была приведена к integer
.
Однако приведение от integer
к smallint
является "только" приведением присваивания. И это, где путешествие заканчивается:
No function matches the given name and argument types.
Более подробное объяснение в этих связанных ответах:
-
PostgreSQL ОШИБКА: функция to_tsvector (символ меняется, неизвестно) не существует
-
Создать серию дат - используя тип даты в качестве входных данных
Грязная починка
Вы можете исправить это, "обновив" приведение от integer
до smallint
к неявному приведению:
UPDATE pg_cast
SET castcontext = 'i'
WHERE castsource = 'int'::regtype
AND casttarget = 'int2'::regtype;
Но я бы настоятельно не рекомендовал вмешиваться в систему кастинга по умолчанию. Только подумайте, если вы точно знаете, что делаете. Вы найдете соответствующие обсуждения в списках Postgres. Он может иметь всевозможные побочные эффекты, начиная с разрешения типа функции, но не заканчивая там.
В сторону
Разрешение типа функции полностью не зависит от используемого языка. Функция SQL будет конкурировать с PL/perl или PL/pgSQL или "внутренними" функциями точно так же. Подпись функции имеет важное значение. Встроенные функции pg_catalog
первыми, потому что pg_catalog
стоит первым в стандартном search_path
.