СУБД Oracle
Данная реализация DBFSQL для Oracle тестировалась с версией 8.1.6.
Чтобы построить приложение с использованием DBFSQL для Oracle
его нужно слинковать с библиотекой libclip-oracle.so
Для подключения к серверу используйте конструктор класса TConnect
в следующем синтаксисе:
ConnectNew("OR",NIL,NIL,<login>,<pwd>,[<dbname>]), где
"OR" - строка, идентифицирующая СУБД Oracle;
<login> - логин пользователя;
<pwd> - пароль пользователя.
<dbname> - имя базы данных (connect string);
Для связи записей набора (TRowset) и физической таблицы базы данных
Oracle испольуется поле с с именем ROWID. Для полноценной работы
с набором (с возможностью отражения производимых изменений набора
записей в базе данных) в список запрашиваемых полей запроса SELECT
следует явно включать зто поле.
В отличие от реализаций клиентов для других RDBMS (Postgres,MySQL),
массив параметров оператора SQL должен иметь вид:
{ { <parname>, <parvalue>, <partype> } }
где <partype> тип данных Oracle. Символические имена типов определены в файле
oracle.ch. Например:
rs := conn:CreateRowset("SELECT * FROM test WHERE name=:name",{{"name","Вова",ORT_VARCHAR2}})
В операторах автоматического отражения (deleteSQL и updateSQL, передаваемых
конструктору TRowset) следует использовать предложение типа
WHERE rowid=:rowid.
Например:
DELETE FROM mytable WHERE rowid=:rowid
UPDATE mytable SET fname=:fname,lname=:lname WHERE rowid=:rowid
В операторе автоматического отражения insertSQL следует использовать
предложение RETURNING rowid INTO :rowid. Это необходимо для дальнейшего
изменения вновь добавленной записи в зтом же наборе данных. Например:
INSERT INTO mytable (fname,lname) VALUES (:fname,:lname)
RETURNING rowid INTO :rowid
Библиотекой накладываются следующие ограничения:
1. Предложение RETURNING ... INTO ... понимается только для поля ROWID,
и лишь в операторе insertSQL.
2. Не поддерживаются типы данных NAMED DATA TYPE (Object) и REF.
Возможно в следующих версиях библиотеки зти фичи будут реализованы.
Не рекомендуется использование типов CLOB и BLOB в связи с их гемморойностью.
Вместо зтого следует использовать LONG VARCHAR и LONG RAW.
О сложностях работы с полями LOB читайте руководство Oracle. Эти типы, включая
и тип FILE, тем не менее реализованы и вы можете их использовать,
руководствуясь правилами, описанными Oracle.
Реализованы следующие типы Oracle:
Тип Oracle Тип Clipper
VARCHAR2 CHARACTER
CHAR CHARACTER
RAW CHARACTER
NUMBER NUMERIC
INTEGER NUMERIC
FLOAT NUMERIC
LONG CHARACTER
LONG VARCHAR CHARACTER
LONG RAW CHARACTER
DATE DATE
CLOB CHARACTER
BLOB CHARACTER
FILE CHARACTER
В качестве простейшего примера использования SQL с СУБД Oracle в комплект
поставки включен файл mysqlplus.prg, функционально дублирующий утилиту sqlplus
из комплекта поставки Oracle. Вот ее текст:
PROCEDURE Main()
LOCAL conn,rs,data
LOCAL sql := ""
LOCAL I := 1
LOCAL user := "scott" // -u
LOCAL passwd := "tiger" // -p
LOCAL db := "" // -d
ErrorBlock({|e| SQLError(e)})
DO WHILE param(I) != NIL
IF param(I) == "--help" .OR. param(I) == "-?"
? "mysqlplus Ver 0.01 for Oracle Distrib 8.1.6, for pc-linux-gnu (i686)"
? "By ITK Ltd., by Rusty"
? "This software comes with ABSOLUTELY NO WARRANTY."
?
? "Usage: mymysql [OPTIONS]"
?
? " -?, --help Display this help and exit"
? " -u User for login if not current user"
? " -p Password to use when connecting to server"
? " -d Database to work with"
?
QUIT
ELSEIF param(I) == "-u"
user := param(++I)
ELSEIF param(I) == "-p"
passwd := param(++I)
ELSEIF param(I) == "-d"
db := param(++I)
ENDIF
I++
ENDDO
CLS
BEGIN SEQUENCE
conn := ConnectNew("OR",NIL,NIL,user,passwd,db)
RECOVER USING e
QUIT
END SEQUENCE
DO WHILE UPPER(sql := GetCommand()) != "Q"
IF UPPER(LEFT(sql,6))=="SELECT"
sql := LEFT(sql,LEN(sql)-1)
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 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,NIL)
?? "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