Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Нужен совет по написанию функции на pl/perl / 25 сообщений из 29, страница 1 из 2
26.10.2006, 07:43
    #34082127
shrdlu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
Задался целью проверять данные, вводимые в базу через веб-форму на предмет отсутствия в полях данных недопустимых символов. Например, есть поля для хранения имени и фамилии, в них, соответственно, не должно быть ничего, кроме русских букв, пробелов и дефиса. Для этого написал такую вот монстроподобную функцию на pl/perl и триггер к ней:

create function check_users() returns trigger as $$
my $errstr = "";
if ( !($_TD->{new}{lastname} =~ /^[^A-Za-z0-9\!\@\#\$\%\^\&\*\(\)\_\+\=\\\/\?\,\.\<\>\~\`\"\'\;\:\{\}\[\]]+$/) ) {
$errstr.= "<br>\nCHECK_USERS: Недопустимый символ в поле ФАМИЛИЯ";
}
if ( !($_TD->{new}{firstname} =~ /^[^A-Za-z0-9\!\@\#\$\%\^\&\*\(\)\_\+\=\\\/\?\,\.\<\>\~\`\"\'\;\:\{\}\[\]]+$/) ) {
$errstr.= "<br>\nCHECK_USERS: Недопустимый символ в поле ИМЯ";
}
if ( $errstr ne '' ) {
elog(ERROR, $errstr);
return "SKIP";
}
else { return; }
$$ language 'plperl';

create trigger tg_check_users before insert or update on users
for each row execute procedure check_users();

Проблема в том, что используемые регэкспы не желают отлавливать одинарные кавычки, слеши и некоторые другие спецсимволы при выполнении этой функции - хотя будучи использованы в приложении на perl, эти регэкспы отрабатывают как надо и не пропускают ничего, кроме руских буковок.
Вот собственно и вопрос - что предпринять для того, чтобы данная функция заработала как надо, или каким еще способом можно осуществлять такого рода проверки?
...
Рейтинг: 0 / 0
26.10.2006, 10:50
    #34082561
ilejn
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
Ответа на поставленный вопрос я не знаю, но происходит изобретение велосипеда.

CHECK constraint http://www.postgresql.org/files/documentation/books/aw_pgsql/node132.html

в сочетании с SIMILAR TO легко решит поставленную задачу безо всяких перлов и триггеров.
...
Рейтинг: 0 / 0
26.10.2006, 11:13
    #34082676
shrdlu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
ilejnОтвета на поставленный вопрос я не знаю, но происходит изобретение велосипеда.
Мда, действительно. Спасибо за наводку.
...
Рейтинг: 0 / 0
26.10.2006, 12:09
    #34082979
shrdlu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
ilejnв сочетании с SIMILAR TO легко решит поставленную задачу безо всяких перлов и триггеров.
Оно конечно проще, но своей цели я не добился - спецсимволы по-прежнему просачиваются:

Создал тестовую табличку createtestbase.sql:

create table test (
uid serial8 primary key,
lastname varchar(64) not null,
firstname varchar(64) not null,
constraint empty_field
check ( lastname <> '' and firstname <> ''),
constraint valid_chars
check ( lastname not similar to '^[A-Za-z0-9\\\']+$')
);

insert into test (lastname, firstname) values ('Smith', 'Jonh');
insert into test (lastname, firstname) values ('Петров', 'Иван');
insert into test (lastname, firstname) values ('Пе\тров', 'Ив\'ан');

Проверяем:

# su -l pgsql -c "exec /usr/local/bin/psql testbase < createtestbase.sql"
CREATE DATABASE
NOTICE: CREATE TABLE will create implicit sequence "test_uid_seq" for serial column "test.uid"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"
CREATE TABLE
ERROR: new row for relation "test" violates check constraint "valid_chars"
INSERT 0 1
INSERT 0 1

Вставились две записи вместо одной :(

# su -l pgsql -c "exec /usr/local/bin/psql testbase"

Welcome to psql 8.1.4, the PostgreSQL interactive terminal.

Type: \copyright for distribution terms
\h for help with SQL commands
\? for help with psql commands
\g or terminate with semicolon to execute query
\q to quit

testbase=# select * from test;
uid | lastname | firstname
-----+----------+-----------
2 | Петров | Иван
3 | Петров | Ив'ан
(записей: 2)

testbase=# \q

Вопрос по-прежнему открыт - можно ли заблокировать ввод пользователем слешей, кавычек и прочих служебных символов и каким образом это делать, кроме как в самом приложении-клиенте?
...
Рейтинг: 0 / 0
26.10.2006, 13:00
    #34083244
ilejn
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
Такой вариант

create table const_check
(
f text
check (f similar to '[А-Яа-я -]+')
)

не рассматривался?

Если используется UNICODE, все будет работать.
...
Рейтинг: 0 / 0
26.10.2006, 13:13
    #34083325
shrdlu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
ilejnТакой вариант

create table const_check
(
f text
check (f similar to '[А-Яа-я -]+')
)

не рассматривался?

Если используется UNICODE, все будет работать.

Рассматривался, но используется KOI8-R, и в ближайшее воемя перейти на юникод не получится
...
Рейтинг: 0 / 0
26.10.2006, 15:17
    #34084031
Jelis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
shrdlu ilejnТакой вариант

create table const_check
(
f text
check (f similar to '[А-Яа-я -]+')
)

не рассматривался?

Если используется UNICODE, все будет работать.

Рассматривался, но используется KOI8-R, и в ближайшее воемя перейти на юникод не получится
А может тогда попробовать вначале приводить к UTF8, специально для проверки. Примерно так

create table const_check
(
f text
check (convert(f , 'koi8', 'utf8') similar to '[А-Яа-я -]+')
)
...
Рейтинг: 0 / 0
26.10.2006, 15:19
    #34084046
Jelis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
Да и почему на уникод не получиться перейти? Клиета то можно оставить как и было, в КОИ8, а базу переделать под уникод.
...
Рейтинг: 0 / 0
26.10.2006, 15:27
    #34084086
shrdlu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
JelisДа и почему на уникод не получиться перейти? Клиета то можно оставить как и было, в КОИ8, а базу переделать под уникод.
Конвертацию в проверке я обязательно попробую, а перейти не получится по причине моих ограниченных знаний и прав для работы с БД. Да и если бы были права, не хотелось бы невзначай убить неосторожным движением рабочие базы, я с Postgresql очень недавно дело имею.
...
Рейтинг: 0 / 0
26.10.2006, 15:43
    #34084182
shrdlu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
Jelis А может тогда попробовать вначале приводить к UTF8, специально для проверки. Примерно так

Сделал по твоему совету:

create table test (
uid serial8 primary key,
lastname varchar(64) not null,
firstname varchar(64) not null,
constraint empty_field
check ( lastname <> '' and firstname <> ''),
constraint valid_chars
check (convert(lastname , 'koi8', 'utf8') similar to '[А-Яа-я -]+')
);

insert into test (lastname, firstname) values ('Smith', 'Jonh');
insert into test (lastname, firstname) values ('Петров', 'Иван');
insert into test (lastname, firstname) values ('Пе\тров', 'Ив\'ан');

увы, не работает

CREATE DATABASE
NOTICE: CREATE TABLE will create implicit sequence "test_uid_seq" for serial column "test.uid"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"
CREATE TABLE
ERROR: new row for relation "test" violates check constraint "valid_chars"
ERROR: new row for relation "test" violates check constraint "valid_chars"
ERROR: new row for relation "test" violates check constraint "valid_chars"
...
Рейтинг: 0 / 0
26.10.2006, 20:28
    #34085200
ilejn
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
shrdlu

увы, не работает



Нет ничего удивительного: cтрока в UTF, а паттерн в KOI-8.
...
Рейтинг: 0 / 0
27.10.2006, 03:39
    #34085592
фффф
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
Что-то вас не в ту степь понесло. При чём тут юникод?
\w должен давать совпадение с буквами в любой однобайтной кодировке (а вот в юникоде - наоборот не работает).
Код: plaintext
1.
CHECK lastname ~ $re$^\w+$$re$
...
Рейтинг: 0 / 0
27.10.2006, 07:09
    #34085646
shrdlu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
ilejnНет ничего удивительного: cтрока в UTF, а паттерн в KOI-8.
Блин.
В общем, как я понял, пока база в кодировке KOI, решения не существует?
...
Рейтинг: 0 / 0
27.10.2006, 09:05
    #34085760
shrdlu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
ффффЧто-то вас не в ту степь понесло. При чём тут юникод?
\w должен давать совпадение с буквами в любой однобайтной кодировке (а вот в юникоде - наоборот не работает).
Код: plaintext
1.
CHECK lastname ~ $re$^\w+$$re$

в поле lastname по моему замыслу допустимы только РУССКИЕ буквы, пробел и дефис, так что \w никак не поможет
...
Рейтинг: 0 / 0
27.10.2006, 09:14
    #34085773
ilejn
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
shrdlu
В общем, как я понял, пока база в кодировке KOI, решения не существует?

Что мешает сконвертировать в UTF и pattern тоже?


Вообще-то, мне непонятно, почему это не работает в KOI-8 само по себе.

Казалось бы, кодировка официально поддерживается, сортировка по ней есть, а вот сделать regexp поленились, получается? Странно это.

Что возвращает show lc_collate на Вашей базе?
...
Рейтинг: 0 / 0
27.10.2006, 09:35
    #34085822
shrdlu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
ilejnЧто мешает сконвертировать в UTF и pattern тоже?
Либо мои кривые руки, либо BSD не дружит с юникодом. На FreeBSD 6.1 пробую так:
# iconv -f koi8-r -t utf8 1.txt
iconv: conversion to utf8 unsupported
ilejnВообще-то, мне непонятно, почему это не работает в KOI-8 само по себе. Казалось бы, кодировка официально поддерживается, сортировка по ней есть, а вот сделать regexp поленились, получается? Странно это.
Очень странно, действительно
ilejnЧто возвращает show lc_collate на Вашей базе?
testbase=# show lc_collate;
lc_collate
--------------
ru_RU.KOI8-R
(1 запись)

testbase=#
...
Рейтинг: 0 / 0
27.10.2006, 09:59
    #34085891
фффф
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
shrdlu фффф
в поле lastname по моему замыслу допустимы только РУССКИЕ буквы, пробел и дефис, так что \w никак не поможет
Условия на проверку одним регэкспом тоже нет
Код: plaintext
1.
lastname ~ '^([[:alnum:]]|-| )+$' AND lastname !~ '[a-zA-Z0-9]'
...
Рейтинг: 0 / 0
27.10.2006, 10:09
    #34085921
shrdlu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
ффффУсловия на проверку одним регэкспом тоже нет
Код: plaintext
1.
lastname ~ '^([[:alnum:]]|-| )+$' AND lastname !~ '[a-zA-Z0-9]'

Кавычки и слеши по-прежнему проскакивают сквозь этот регэксп.
Начинаю подозревать, что запретить их на уровне сервера БД вообще невозможно
...
Рейтинг: 0 / 0
27.10.2006, 11:01
    #34086146
ilejn
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
shrdlu
На FreeBSD 6.1 пробую так:
# iconv -f koi8-r -t utf8 1.txt
iconv: conversion to utf8 unsupported


Вы же используете PostgreSQL'ный convert для строки. Используйте его же для образца.
...
Рейтинг: 0 / 0
27.10.2006, 11:15
    #34086195
shrdlu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
ilejnВы же используете PostgreSQL'ный convert для строки. Используйте его же для образца.
Это я уже пробовал, резуультат тот же.
Пишу

check (convert(lastname , 'koi8', 'utf8') similar to convert('[А-Яа-я -]+', 'koi8', 'utf8'))

в ответ на

insert into test (lastname, firstname) values ('Smith', 'Jonh');
insert into test (lastname, firstname) values ('Петров', 'Иван');
insert into test (lastname, firstname) values ('Пе\тров', 'Ив\'ан');

получал

ERROR: new row for relation "test" violates check constraint "valid_chars"
ERROR: new row for relation "test" violates check constraint "valid_chars"
ERROR: new row for relation "test" violates check constraint "valid_chars"
...
Рейтинг: 0 / 0
27.10.2006, 12:47
    #34086636
glebofff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
Не нужно никуда ничего конвертировать. Всё в KOI8-R работает (FreeBSD 6.0, 6.1, Postgresql 8.1.4).

Могу предположить, что:
1. наверняка проблемы с кодировкой у клиента
2. несмотря на то, что кодировка БД koi8-r, сами данные там хранятся в другой кодировке (что возможно по причине п. 1, сам с таким сталкивался)
...
Рейтинг: 0 / 0
27.10.2006, 12:57
    #34086697
ilejn
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
Согласен с glebofff. С кодировками полная беда.

Кроме культурного решения - разобраться с кодировками, существует еще очевидное и некультурное - отказаться от диапазонов и перечислить все русские буковки one by one в квадратных скобках.
...
Рейтинг: 0 / 0
27.10.2006, 13:02
    #34086719
shrdlu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
glebofff1. наверняка проблемы с кодировкой у клиента
А если клиент - штатный psql?
С утра на виртуалке поднял PostgreSQL и в нем ковыряюсь. Сортировки/поиск/upper/lower работают. Работают, в общем-то и рэгэкспы, одно НО - они пропускают символы "\" и "'" (обратный слэш и одинарная кавычка)
Слушайте, может, я зря вообще парюсь? Может не так уж и опасно допускать ввод этих символов?
...
Рейтинг: 0 / 0
27.10.2006, 13:05
    #34086739
shrdlu
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
ilejnнекультурное - отказаться от диапазонов и перечислить все русские буковки one by one в квадратных скобках.
Есть и третье решение - делать эти проверки в клиенте, благо в перловой CGIшке все это работает на ура. Но вот в целях повышения самообразованности задался целью все проверки/правила организовать именно на сервере... хотя может и зря :-\
...
Рейтинг: 0 / 0
27.10.2006, 15:02
    #34087308
glebofff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужен совет по написанию функции на pl/perl
shrdlu glebofff1. наверняка проблемы с кодировкой у клиента
А если клиент - штатный psql?
С утра на виртуалке поднял PostgreSQL и в нем ковыряюсь. Сортировки/поиск/upper/lower работают. Работают, в общем-то и рэгэкспы, одно НО - они пропускают символы "\" и "'" (обратный слэш и одинарная кавычка)
Слушайте, может, я зря вообще парюсь? Может не так уж и опасно допускать ввод этих символов?

PostgreSQL: Documentation: Manuals: PostgreSQL 8.1: Pattern Matching

Читаем там: Note : Remember that the backslash (\) already has a special meaning in PostgreSQL string literals. To write a pattern constant that contains a backslash, you must write two backslashes in the statement.

Там же можно найти про \B - альяс для \.
Код: plaintext
select '\'\\' ~ '[\'\\B]' 
может выглядеть как
Код: plaintext
select '\'\\' ~ '[\'\\\\]'

(и пусть вся подсветка сойдёт с ума! )
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Нужен совет по написанию функции на pl/perl / 25 сообщений из 29, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]