Важной возможностью является исполнение нескольких запросов через ;, т.к. любая операция запрос-ответ является дорогой и просто не может быть выполнена быстрее нескольких сотен (максимум тысяча-две) в секунду.
А сохранение в базе какого-нибудь сложного объекта с подобъектами может требовать большой серии INSERT-ов, а если ещё сохраняется сотня-другая объектов...
В настоящий момент MysqlDriver не поддерживает возможности выполнить statement, содержащий через ; несколько запросов SQL.
Разрешить выполнять много SELECT-ов невозможно в рамках логики посистемы Sql, но с SELECT-ами не так критично - в конце концов, там есть JOIN (использование которого и предполагается в классической реляционной парадигме для выборки нужных данных одним запросом).
Короче, для возможности выполнения INSERT-ов или UPDATE-ов за один db.Exec я поправил немного MysqlDriver - прилагаю файл.
Мои изменения там выделены красным.
Код:
Driver = POINTER TO RECORD (SqlDrivers.Driver)
....
multiple: BOOLEAN
END;
(* новая процедура *)
PROCEDURE GetStatementType (IN statement: ARRAY OF CHAR; OUT op: ARRAY OF CHAR);
CONST tab = 09X; CR = 0DX; LF = 0AX;
VAR beg, end: INTEGER;
BEGIN
beg := 0;
WHILE (statement[beg] = ' ') OR (statement[beg] = tab) OR (statement [beg] = CR)
OR (statement[beg] = LF) DO
INC(beg)
END;
end := beg;
WHILE (statement[end] # 0X) & ~( (statement[end] = ' ') OR (statement[end] = tab) OR (statement [end] = CR) OR (statement[end] = LF) ) DO
INC(end)
END;
Strings.Extract(statement, beg, end-beg, op)
END GetStatementType;
PROCEDURE (d: Driver) BeginExec (IN statement: ARRAY OF CHAR; data: SqlDrivers.Blob;
async, showErr: BOOLEAN; OUT res: INTEGER);
VAR ......
stype: ARRAY 32 OF CHAR;
BEGIN
....
GetStatementType(statement, stype);
d.multiple := (stype = "INSERT") OR (stype = "UPDATE");
IF d.multiple THEN
res := Mysql.mysql_set_server_option(d.mysql, Mysql.MYSQL_OPTION_MULTI_STATEMENTS_ON)
END;
......
END BeginExec;
PROCEDURE (d: Driver) EndExec (VAR t: SqlDrivers.Table; OUT rows, columns, res: INTEGER);
BEGIN
......
IF ~d.multiple THEN
resultSet := Mysql.mysql_store_result(d.mysql); (* read the entire result of a query to the client *)
ELSE
REPEAT
resultSet := Mysql.mysql_store_result(d.mysql);
IF resultSet # NIL THEN
Mysql.mysql_free_result(resultSet)
END
UNTIL Mysql.mysql_next_result(d.mysql) # 0;
res := Mysql.mysql_set_server_option(d.mysql, Mysql.MYSQL_OPTION_MULTI_STATEMENTS_OFF)
END;
......