
|
СУБД Postgres
Данная реализация DBFSQL для Postgres тестировалась с версией
PostgreSQL 6.5.3.
Чтобы построить приложение с использованием DBFSQL для Postgres
его нужно слинковать с библиотекой libclip-postgres.so
Для подключения к серверу используйте конструктор класса TConnect
в следующем синтаксисе:
ConnectNew("PG",[<host>],[<port>],[<login>],
[<pwd>],[<dbName>],[<pgtty>],
[<pgopt>]), где
"PG" - строка, идентифицирующая СУБД Postgres;
<host> - имя хоста (DNS) сервера Postgres;
<port> - номер порта сервера Postgres;
<login> - логин пользователя;
<pwd> - пароль пользователя.
<dbName> - имя базы данных;
<pgtty> - терминал для вывода сообщений от клиента;
<pgopt> - дополнительные опции соединения;
Если любой из аргументов опущен, используется соответствующая переменная
окружения (см. документацию по Postgres). Если переменная окружения также
не установлена, используется значение по умолчанию.
Все аргументы должны представлять собой текстовые значения, например
pgport должно иметь значение "5234".
Postgres не предоставляет обычного для многих других СУБД механизма
передачи параметров операторам SQL. Этот механизм лишь сзмулирован в
данной реализации. Позтому повышения производительности при многократном
выполнении одного и того же оператора SQL с разными параметрами не ждите.
Сервер все равно будет обрабатывать каждый оператор в стандартном режиме
(parser, planner, optimizer и т.д.).
Для связи записей набора (TRowset) и физической таблицы базы данных
Postgres испольуется поле OID, которое
присутствует во всех таблицах Postgres. Для полноценной работы
с набором (с возможностью отражения производимых изменений набора
записей в базе данных) в список запрашиваемых полей запроса SELECT
следует явно включать поле OID. Например:
SELECT oid,* FROM mytable
В операторах автоматического отражения (deleteSQL и updateSQL, передаваемых
конструктору TRowset) следует использовать предложение WHERE oid=:oid.
Например:
DELETE FROM mytable WHERE oid=:oid
UPDATE mytable SET fname=:fname,lname=:lname WHERE oid=:oid
Postgres может возвращать запрашиваемые записи (в терминологии Postgres -
tuples) в двух видах - текстовом и бинарном. Обычный SELECT
возвращает записи в текстовом виде. Для того чтобы получить бинарные записи,
следует сначала создать бинарный курсор, а затем для него выполнить команду
FETCH. Например:
conn:Command("BEGIN")
conn:Command("DECLARE mycur BINARY CURSOR FOR SELECT oid,* FROM mytable")
rs := conn:CreateRowset("FETCH ALL FROM mycur")
conn:Command("END")
Для правильной работы с датами следует правильно установить переменную
окружения PGDATESTYLE (в соответствии со значением PGDATESTYLE, используемым
сервером Postgres). Например:
export PGDATESTYLE=EURO
Возможные значения PGDATESTYLE:
Style Date Datetime
--------------------------------------------------------
ISO 1999-07-17 1999-07-17 07:09:18+01
SQL 17/07/1999 17/07/1999 07:09:19.00 BST
POSTGRES 17-07-1999 Sat 17 Jul 07:09:19 1999 BST
GERMAN 17.07.1999 17.07.1999 07:09:19.00 BST
NONEURO 07-17-1999 Sat Jul 17 07:09:19 1999 BST
US 07-17-1999 Sat Jul 17 07:09:19 1999 BST
EURO 17-07-1999 Sat 17 Jul 07:09:19 1999 BST
Реализованы следующие типы Postgres:
Тип Postgres Тип Clipper
ABSTIME DATE
BOOL LOGICAL
BOX Array {{x1,y1},{x2,y2}},
x1,y1,x2,y2 - NUMERIC
BPCHAR CHARACTER
BYTEA CHARACTER
CHAR CHARACTER
CID NUMERIC
CIDR Array {x1,...},
x1,... - NUMERIC
CIRCLE Array {x1,x2,x3},
x1,x2,x3 - NUMERIC
DATE DATE
FILENAME CHARACTER
FLOAT4 NUMERIC
FLOAT8 NUMERIC
INET Array {x1,x2,x3,x4,x5},
x1,x2,x3,x4,x5 - NUMERIC
INT2 NUMERIC
INT28 Array {x1,x2,...,x8},
x1,x2,...,x8 - NUMERIC
INT4 NUMERIC
LSEG Array {{x1,y1},{x2,y2}},
x1,y1,x2,y2 - NUMERIC
MONEY NUMERIC
NAME CHARACTER
NUMERIC NUMERIC
OID NUMERIC
OID8 Array {x1,x2,...,x8},
x1,x2,...,x8 - NUMERIC
PATH CHARACTER
POINT Array {x,y},
x,y - NUMERIC
POLYGON Array {{x1,y1},...{xn,yn}},
x1..xn, y1...yn - NUMERIC
RELTIME NUMERIC
TEXT CHARACTER
TIMESTAMP DATE
VARCHAR CHARACTER
XID NUMERIC
В качестве простейшего примера использования SQL с СУБД Postgres в комплект
поставки включен файл mypsql.prg, функционально дублирующий утилиту psql
из комплекта поставки Postgres. Вот ее текст:
PROCEDURE Main
LOCAL conn,rs,data
LOCAL sql := ""
LOCAL I
CLS
ErrorBlock({|e| SQLError(e)})
conn := ConnectNew("PG",,,,,"test")
DO WHILE UPPER(sql := GetCommand()) != "Q"
IF UPPER(LEFT(sql,6))=="SELECT" .OR. UPPER(LEFT(sql,5))=="FETCH"
BEGIN SEQUENCE
rs := conn:CreateRowset(sql)
RECOVER USING e
LOOP
END SEQUENCE
FOR I:=1 TO rs:NFields()
?? PADR(rs:FieldName(I),10),"|"
NEXT
?
FOR I:=1 TO rs:NFields()
?? "----------","|"
NEXT
DO WHILE !rs:Eof()
?
data := rs:Read()
FOR I:=1 TO rs:NFields()
tmp := data[HASHSTR(UPPER(rs:FieldName(I)))]
IF VALTYPE(tmp)=="A"
?? "{...} ","|"
ELSEIF tmp==NIL
?? "NIL ","|"
ELSE
?? PADR(data[HASHSTR(UPPER(rs:FieldName(I)))],10),"|"
ENDIF
NEXT
rs:Skip()
ENDDO
rs:Destroy()
ELSE
BEGIN SEQUENCE
?? LEFT(sql,LEN(sql)-1)+": "
conn:Command(sql)
?? "OK"
RECOVER USING e
LOOP
END SEQUENCE
ENDIF
?
ENDDO
conn:Destroy()
RETURN
FUNCTION GetCommand()
LOCAL ret := ""
LOCAL tmp := ""
LOCAL first := .T.
@ MAXROW(),0 SAY ""
DO WHILE !(";" $ tmp) .AND. ALLTRIM(UPPER(ret)) != "Q"
IF first
ACCEPT "SQL> " TO tmp
first := .F.
ELSE
ACCEPT "SQL---> " TO tmp
ENDIF
ret += tmp + " "
ENDDO
RETURN ALLTRIM(ret)
FUNCTION SQLError(e)
?? e:operation
BREAK(e)
RETURN NIL
|