Это похоже на то, что вы хотите (я нашел его на http://huddledmasses.org/powershell-find-path/ )
Function Find-Path($Path, [switch]$All=$false, [Microsoft.PowerShell.Commands.TestPathType]$type="Any")
## You could comment out the function stuff and use it as a script instead, with this line:
# param($Path, [switch]$All=$false, [Microsoft.PowerShell.Commands.TestPathType]$type="Any")
if($(Test-Path $Path -Type $type)) {
return $path
} else {
[string[]]$paths = @($pwd);
$paths += "$pwd;$env:path".split(";")
$paths = Join-Path $paths $(Split-Path $Path -leaf) | ? { Test-Path $_ -Type $type }
if($paths.Length -gt 0) {
if($All) {
return $paths;
} else {
return $paths[0]
}
}
}
throw "Couldn't find a matching path of type $type"
}
Set-Alias find Find-Path
Это должно сделать это:
CREATE OR REPLACE FUNCTION device_bid_modifiers_count_per()
RETURNS TRIGGER AS
$func$
DECLARE
devices_count int := device_types_count();
table_name regclass := TG_ARGV[0];
column_name text := TG_ARGV[1];
BEGIN
LOCK TABLE device_types IN EXCLUSIVE MODE;
EXECUTE format('LOCK TABLE %s IN EXCLUSIVE MODE', table_name);
IF TG_OP = 'DELETE' THEN
PERFORM validate_bid_modifiers_count(table_name
, column_name
, (row_to_json(OLD) ->> column_name)::bigint
, devices_count);
ELSE
PERFORM validate_bid_modifiers_count(table_name
, column_name
, (row_to_json(NEW) ->> column_name)::bigint
, devices_count);
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
Непосредственной причиной сообщения об ошибке была внешняя SELECT
. Без цели вам нужно заменить ее на PERFORM
в plpgsql. Но внутреннее PERFORM
в строке запроса, переданной EXECUTE
, тоже было неверным. PERFORM
- это команда plpgsql, недопустимая в строке SQL, переданной в EXECUTE
, которая ожидает код SQL. Вы должны использовать SELECT
там. Наконец, OLD
и NEW
не видны внутри EXECUTE
, и каждый из них вызовет свое собственное исключение, как у вас. Все проблемы устранены путем удаления EXECUTE
.
Простой и быстрый способ получить значение динамического имени столбца из типов строк OLD
и NEW
: приведение к json
, затем вы можете параметризовать имя ключа, как показано , Должно быть немного проще и быстрее, чем альтернатива с динамическим SQL - что также возможно, например:
...
EXECUTE format('SELECT validate_bid_modifiers_count(table_name
, column_name
, ($1.%I)::bigint
, devices_count)', column_name)
USING OLD;
...
Связанный:
В стороне: не уверен, зачем нужны тяжелые блокировки.
В сторону 2: рассмотрите возможность написания отдельной функции триггера для каждого триггера. Более шумный DDL, но проще и быстрее для выполнения.
Как я указывал в комментарии к ответу Эрвина Брандштеттера , изначально у меня было почти идентичное решение.
Но проблема была в том, что я получал ошибку
ERROR: record "new" has no field "column_name"
CONTEXT: SQL statement "SELECT validate_bid_modifiers_count(table_name, column_name, NEW.column_name, devices_count)"
PL/pgSQL function device_bid_modifiers_count_per() line 15 at PERFORM
Вот почему я подумал, что мне нужен способ динамической оценки вещей.
В настоящее время это работает со следующим, все еще уродливым, ищущим меня решением (уродливо, потому что мне не нравятся 2 IF
утверждения, я хотел бы, чтобы оно было супер динамичным, но, возможно, я прошу слишком много): 117]
CREATE OR REPLACE FUNCTION device_bid_modifiers_count_per()
RETURNS TRIGGER AS
$func$
DECLARE
row RECORD;
table_name regclass := TG_ARGV[0];
column_name text := TG_ARGV[1];
devices_count INTEGER;
BEGIN
LOCK TABLE device_types IN EXCLUSIVE MODE;
EXECUTE format('LOCK TABLE %s IN EXCLUSIVE MODE', table_name);
devices_count := device_types_count();
IF TG_OP = 'DELETE' THEN
row := OLD;
ELSE
row := NEW;
END IF;
IF column_name = 'campaign_id' THEN
PERFORM validate_bid_modifiers_count(table_name, column_name, row.campaign_id, devices_count);
ELSIF column_name = 'adgroup_id' THEN
PERFORM validate_bid_modifiers_count(table_name, column_name, row.adgroup_id, devices_count);
ELSE
RAISE EXCEPTION 'invalid_column_name %', column_name;
END IF;
RETURN NEW;
END;
$func$ LANGUAGE plpgsql;
Я открыт для более надежных решений.
По существу, второе условие kind'a почти не имеет цели иметь единственную функцию, и я мог бы разделить ее на две функции. Потому что цель состоит в том, чтобы определить несколько (2) триггеров, используя эту функцию (предоставив ей аргументы).