Клиент хочет хранить что-либо в отдельных таблицах. (Длинная история, это необходимо).
Для этого я построил функцию Postgres для создания новых таблиц на лету в своем собственном пространстве имен.
Эти таблицы могут иметь 2, 4 или 100 столбцов, как раз то, что хочет пользователь.
Нет проблем, это работает. Используемые типы данных в этих динамических таблицах являются нативными, например, текст, логические значения, целые числа и так далее.
Теперь возникает проблема, я должен вставить данные в эти таблицы. Дело в том, что пользователи не могут получить доступ к таблицам напрямую, они будут делать это через функцию.
Для пары типов данных это не проблема, но для текстовых типов данных это проблематично.
Вот функция до сих пор:
-- Function: add(integer, text[])
-- DROP FUNCTION add(integer, text[]);
CREATE OR REPLACE FUNCTION add(id integer, fields text[])
RETURNS integer AS
$BODY$
DECLARE
l_line_ending text := ')';
l_fieldtype integer;
l_ito_table_name text;
l_ito_fieldnames text;
l_field ito_fields%rowtype;
l_first_loop boolean := true;
l_values_to_insert text := 'VALUES (';
l_loop_counter integer := 0;
l_query text;
BEGIN
select into l_ito_table_name ito_table_name from ito where id = target_ito_id;
l_ito_fieldnames := 'insert into ' || l_ito_table_name || '(';
FOR l_field IN SELECT * FROM ito_fields
WHERE ito_fields.ito_id = target_ito_id
order by ito_fields.id asc
LOOP
l_loop_counter := l_loop_counter +1;
l_fieldtype := l_field.fieldtype;
if not l_first_loop THEN
l_values_to_insert := (l_values_to_insert || ', ');
end if;
if l_field.fieldtype = 1 THEN
l_values_to_insert := (l_values_to_insert || '''' || (fields[l_loop_counter]) || '''' );
elsif l_field.fieldtype = 2 THEN
l_values_to_insert := quote_literal(l_values_to_insert || private.cast_to_integer(fields[l_loop_counter]));
elsif l_field.fieldtype = 3 THEN
l_values_to_insert := quote_literal(l_values_to_insert || private.cast_to_boolean(fields[l_loop_counter]));
elsif l_field.fieldtype = 4 THEN
l_values_to_insert := quote_literal(l_values_to_insert || private.cast_to_float(fields[l_loop_counter]));
else
return 103;
end if;
if l_first_loop then
l_ito_fieldnames := l_ito_fieldnames || l_field.column_name;
l_first_loop := false;
else
l_ito_fieldnames := l_ito_fieldnames || ', ' || l_field.column_name;
end if;
END LOOP;
l_ito_fieldnames := l_ito_fieldnames || l_line_ending;
l_values_to_insert := ((l_values_to_insert) || (l_line_ending));
l_query := (l_ito_fieldnames || l_values_to_insert);
EXECUTE l_query;
return 0;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION add(integer, text[])
OWNER TO postgres;
В таблице ito_fields хранятся все метаданные поля, поэтому здесь хранятся тип данных, версии, описания.
в таблице ito хранятся все данные динамической таблицы.
Точка в этой функции - кавычки. Функция вставки создается динамически, поэтому мне нужно добавить несколько кавычек вокруг текстовых полей в функции вставки.
Postgres дает ошибки, как только я это делаю. Даже с функциями quote_literal это все еще проблема из-за конкатенации строк (я знаю, риски безопасности, но пока это не проблема).
Я пытался использовать quote_literal, quote_ident, даже заменяя кавычки (') заменой, пока не выполнится функция execute (replace (query, l_quote_rep,' '' ')). У меня действительно нет подсказки теперь как это исправить ...
Заранее спасибо.