СУБД MySQL


Данная реализация DBFSQL для MySQL тестировалась с версией 3.22.25.

Чтобы построить приложение с использованием DBFSQL для MySQL его нужно слинковать с библиотекой libclip-mysql.so

Для подключения к серверу используйте конструктор класса TConnect в следующем синтаксисе:

ConnectNew("MS",[<host>],[<port>],[<login>], [<pwd>],[<dbName>],[<socket>], [<flags>]), где

"MS" - строка, идентифицирующая СУБД MySQL;

<host> - имя хоста (DNS) сервера MySQL;

<port> - номер порта сервера MySQL;

<login> - логин пользователя;

<pwd> - пароль пользователя.

<dbName> - имя базы данных;

<socket> - socket или pipe для соединения;

<flags> - флаги соединения (обычно 0);

Подробнее о параметрах соединения смотрите документацию по 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

Реализованы следующие типы 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