СУБД Oracle

Данная реализация DBFSQL для Oracle тестировалась с версией 8.1.6.
Чтобы построить приложение с использованием DBFSQL для Oracle его нужно слинковать с библиотекой libclip-oracle.so
Для подключения к серверу используйте конструктор класса TConnect в следующем синтаксисе:
ConnectNew("OR",NIL,NIL,<login>,<pwd>,[<dbname>], NIL,NIL,NIL,[<cIsolation>]), где
"OR" - строка, идентифицирующая СУБД Oracle;
<login> - логин пользователя;
<pwd> - пароль пользователя;
<dbname> - имя базы данных (connect string);
<cIsolation> - уровень изоляции по умолчанию.
Для связи записей набора (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.
Значения параметра <cIsolation> для ConnectNew() и TConnect:Start() могут состоять из одной или нескольких из нижеследующих строк, разделенных символом ';':
"READ COMMITTED"
"SERIALIZABLE"
"READ ONLY"
"READ WRITE".
Например:
// начать транзакцию только для чтения с высоким уровнем изоляции
conn:Start("SERIALIZABLE;READ ONLY")
Реализованы следующие типы 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