|
СУБД 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
|