SELTA/Problems
|
Историческая страница: рабочие заметки начала разработки (2007 год). Описанные здесь проблемы решены: служебные запросы 1С ( |
Текущие проблемы
ODBC драйвер
Здесь отмечены изменения и недоработки ODBC драйвера PostgreSQL
1) Была изменена выводимая версия драйвера, чтобы 1С считала ее "родной"
2) Есть проблема с функцией SQLSetConnectionAttr (как, впрочем, и с SQLGetConnectionAttr)
1С пытается установить неизвестные параметры с кодами
1204
1219
-28236
Мне не удалось найти, что они означают, таких определений нет в заголовочных файлах VS 6.0
Сейчас сделано так, что ODBC драйвер их игнорирует, но возвращает, что операция прошла успешно. Для 1С этого пока что хватает.
3) Принципиальная проблема с курсорами: PostgreSQL и MS SQL Server в паре со своими ODBC драйверами совершенно по-разному работают с курсорами, если быть точнее - по разному возвращают данные, получаемые от SELECT:
MS SQL Server - после запроса SELECT на каждый дальнейший SQLFetch сервер пересылает клиенту одну запись, курсор хранится в самом сервере
PostgreSQL - после Select все данные передаются клиенту сразу, курсор хранится в ODBC у клиента.
Учитывая работу 1С - работа даже ускорится, т.к. она все-равно все данные втягивает в себя до последнего, производительность вырастет за счет уменьшения числа коннектов. Но это может создать ряд проблем, поскольку из-за этой особенности у ODBC-pg очень плохо реализована работа с динамическими курсорами.
Есть возможность довести эти функции до ума, но потребуется много времени.
Манипуляции в PostgreSQL
1) 1С при коннекте к базе ищет (системную) базу данных master. Чтобы она не ругалась - была создана пустая база master, к которой 1С по сути никога не обращается (при работе через наш ODBC драйвер + транслятор). Возможно тут что-то нужно сделать.
2) В PostgreSQL по умолчанию для баз не включена поддержка языка PL/pgSQL, при установке и настройке это нужно делать.
3) В файле postgresql.conf заменено client_min_messages с notice на error, чтобы подавить вывод ненужных сообщений.
4) Необходимо в базе template1 создавать ряд функций, таблиц и типов данных, хранятся в файле selta_install.sql и mchar.sql
SQL запросы
Здесь будут перечислены проблемные запросы 1С к базе, которые пока не удалось реализовать, или которые реализованы не полностью.
'test_sql' - имя базы данных.
Все запросы приведены так, как они передаются в ODBC драйвер.
1) Select * from master..sysdatabases where name='test_sql'
Этим запросом 1С проверяет, существует ли вообще такая база данных. В данный момент он заменен на
SELECT * FROM pg_database WHERE datname='test_sql'
Вывод запросов отличается, но для 1С важен сам факт, что ответ не пустой и это считается допустимым.
2) {call sp_helpdb('test_sql')}
Данный запрос выдает некоторую информацию о базе данных, для 1С интересны только 2 столбца: имя базы и ее владелец (1 и 3 столбец ответа), второй столбец - это текущий размер базы, не используется при обработке ответа. Запрос был заменен на следующее:
SELECT datname,dattablespace,rolname FROM pg_database,pg_authid WHERE datname='test_sql' AND pg_authid.oid=pg_database.datdba
В ответе - второй столбец - это просто мусор.
3) Use test_sql
Переключение на другую базу данных. Этот запрос пока не удалось заменить на что либо. Сейчас он заменяется на пустой запрос (пробел), и это не вызыает ошибки. Однако в дальнейшем это может стать критично. Следует найти что-то подобное в PostgreSQL. В клиенте psql переключение на другую базу производится командой "\c имя_базы", но мне пока не удалось отловить, что именно он при этом делает.
Рекомендуется выполнить reconnect, если это возможно.
4) {call sp_dboption('test_sql','single user','false')}
Устанавливает системные переменные, в данном случае 'single user' в 'false'. Пока не удалось найти в PostgreSQL аналогичной переменной, а в целом переменные можно устанавливать через "SET". Сейчас этот запрос заменяется на пробел.
5) Select COUNT(*) from master..sysprocesses where dbid=DB_ID('test_sql') and program_name='1CV7'
Подсчитывает количество подключенных процессов '1CV7' к базе. Сейчас это никак не реализовано для PostgreSQL, отложено до лучших времен, и в данный момент эта конструкция заменяется
на
SELECT COUNT(*) FROM pg_database WHERE encoding=0
чтобы было возвращено значение 0
6) If exists (select * from sysobjects where id = object_id('_1SCONNECT') and sysstat & 0xf = 3) Drop table _1SCONNECT
Удаляет таблицу _1SCONNECT если она есть.
Тут появилась большая проблема - не могу понять, как сделать IF в данном случае, и как реализовать его вообще. PostgreSQL на него выдает ошибку.
Совет: можно, наверное, просто удалять, и если вернули код ошибки "not exists" подменять его на ok
Язык PL/pgSQL к базе я подключил, вот вывод команды:
test_sql=# select * from pg_language;
lanname | lanispl | lanpltrusted | lanplcallfoid | lanvalidator | lanacl
internal | f | f | 0 | 2246 |
c | f | f | 0 | 2247 |
sql | f | t | 0 | 2248 |
plpgsql | t | t | 30412 | 30413 |
В документации я нашел, как использовать pgSQL в функциях (CREATE FUNCTION и далее...) с указанием языка. Но в данном случае нужно вставить элементы языка в обычный SQL запрос без использования хранимых процедур. Хотелось бы на будущее знать, реально ли вообще такое.
Сейчас мне заранее известно, что таблица _1SCONNECT существует, и этот запрос заменяется на
Drop table _1SCONNECT
Проблема с IF решена, будет написана специальная хранимая процедура вида IF_EXIST("условие", "действие")
Огромное спасибо за это форуму сайта sql.ru
7) Блокировки: требуется проверить, нужны ли принудительные блокировки таблиц, или обойтись автоматическими блокировками PostgreSQL. Версионная модель работы этому очень способствует.
8) SET DATEFIRST 1
Устанавливает формат вывода даты. Пока что отложено, заменяется на простой пробел.
9) Select 1 where 'A'='a'
Этим запросом 1С проверяет, как в базе установлена сортировка строк.
PostgreSQL этот запрос съедает, но в отличие от MS SQL Server для него 'A' и 'a' - это не одно и то же, запрос возвращает 0 записей, 1С ругается, что установлен неправильный, зависимый от регистра букв, порядок сортировки строк.
Для поведения MS SQL нужно пользоваться типами MCHAR и MVARCHAR, для них специальная патченная 1С PostgreSQL умеет регистровонезависимое сравнение.
А так надо select 1 where lower('a') = lower('A')