СУБД MySQL

Данная реализация DBFSQL для MySQL тестировалась с версией 3.22.25.
Чтобы построить приложение с использованием DBFSQL для MySQL его нужно слинковать с библиотекой libclip-mysql.so
Для подключения к серверу используйте конструктор класса TConnect в следующем синтаксисе:
ConnectNew("MS",[<host>],[<port>],[<login>], [<pwd>],[<dbName>],[<socket>], [<flags>],,[<cIsolation>]), где
"MS" - строка, идентифицирующая СУБД MySQL;
<host> - имя хоста (DNS) сервера MySQL;
<port> - номер порта сервера MySQL;
<login> - логин пользователя;
<pwd> - пароль пользователя.
<dbName> - имя базы данных;
<socket> - socket или pipe для соединения;
<flags> - флаги соединения (обычно 0);
<cIsolation> - уровень изоляции по умолчанию.
Подробнее о параметрах соединения смотрите документацию по MySQL.
Если любой из аргументов опущен, используется соответствующая переменная окружения (см. документацию по MySQL). Если переменная окружения также не установлена, используется значение по умолчанию.
Все аргументы должны представлять собой текстовые значения, например port должно иметь значение "3306".
MySQL не предоставляет обычного для многих других СУБД механизма передачи параметров операторам SQL. Этот механизм лишь сзмулирован в данной реализации. Позтому повышения производительности при многократном выполнении одного и того же оператора SQL с разными параметрами не ждите. Сервер все равно будет обрабатывать каждый оператор в стандартном режиме (parser, planner, optimizer и т.д.).
Для связи записей набора (TRowset) и физической таблицы базы данных MySQL испольуется поле с модификатором AUTO_INCREMENT. Для полноценной работы с набором (с возможностью отражения производимых изменений набора записей в базе данных) в список запрашиваемых полей запроса SELECT следует явно включать зто поле.
В операторах автоматического отражения (deleteSQL и updateSQL, передаваемых конструктору TRowset) следует использовать предложение типа WHERE id=:id, где id - имя автоинкрементного поля. Например:
DELETE FROM mytable WHERE id=:id
UPDATE mytable SET fname=:fname,lname=:lname WHERE id=:id
Возможные значения параметра <cIsolation> для ConnectNew() и TConnect:Start():
"READ UNCOMMITTED"
"READ COMMITTED"
"REPEATABLE READ"
"SERIALIZABLE"
Реализованы следующие типы MySQL:

    Тип MySQL             Тип Clipper
    DECIMAL                  NUMERIC
    TINY                     NUMERIC
    SHORT                    NUMERIC
    LONG                     NUMERIC
    FLOAT                    NUMERIC
    DOUBLE                   NUMERIC
    LONGLONG                 NUMERIC
    INT24                    NUMERIC
    TIMESTAMP                DATE
    DATE                     DATE
    TIME                     Array {h,m,s},
    						 h,m,s - NUMERIC
    DATETIME                 DATE
    YEAR                     NUMERIC
    ENUM                     CHARACTER
    SET                      CHARACTER
    TINY_BLOB                CHARACTER
    MEDIUM_BLOB              CHARACTER
    LONG_BLOB                CHARACTER
    BLOB                     CHARACTER
    VAR_STRING               CHARACTER
    STRING                   CHARACTER

В качестве простейшего примера использования SQL с СУБД Postgres в комплект поставки включен файл mymysql.prg, функционально дублирующий утилиту mysql из комплекта поставки MySQL. Вот ее текст:

    PROCEDURE Main()

    LOCAL conn,rs,data
    LOCAL sql := ""
    LOCAL I := 1
    LOCAL host		// -h
    LOCAL user		// -u
    LOCAL passwd	// -p
    LOCAL db		// -d
    LOCAL port		// -P
    LOCAL socket	// -s
    LOCAL flag		// -f

    ErrorBlock({|e| SQLError(e)})
    DO WHILE param(I) != NIL
    	IF param(I) == "--help" .OR. param(I) == "-?"
    		? "mymysql  Ver 0.01 for MySQL Distrib 3.22.25, 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"
    		? "  -h             Connect to host"
    		? "  -u             User for login if not current user"
    		? "  -p             Password to use when connecting to server"
    		? "  -d             Database to work with"
    		? "  -P             Port number to use for connection"
    		? "  -s             Socket file to use for connection"
    		? "  -f             Extra flags to use for connection"
    		?
    		QUIT
    	ELSEIF param(I) == "-h"
    		host := param(++I)
    	ELSEIF param(I) == "-u"
    		user := param(++I)
    	ELSEIF param(I) == "-p"
    		passwd := param(++I)
    	ELSEIF param(I) == "-d"
    		db := param(++I)
    	ELSEIF param(I) == "-P"
    		port := param(++I)
    	ELSEIF param(I) == "-s"
    		socket := param(++I)
    	ELSEIF param(I) == "-f"
    		flag := param(++I)
    	ENDIF
    	I++
    ENDDO

    CLS

    BEGIN SEQUENCE
    	conn := ConnectNew("MS",host,port,user,passwd,db,socket,flag)
    RECOVER USING e
    	QUIT
    END SEQUENCE

    DO WHILE UPPER(sql := GetCommand()) != "Q"
    	IF UPPER(LEFT(sql,6))=="SELECT" .OR. UPPER(LEFT(sql,4))=="SHOW";
    		.OR. UPPER(LEFT(sql,8))=="DESCRIBE" .OR. UPPER(LEFT(sql,7))=="EXPLAIN"
    		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