Пример:
Код: Выделить всё
function TDM_WORK_BASE.saveTable(orderId: Integer;
table: TVirtualTable): Boolean;
var
q:TUniQuery;
lastId:Integer;
I: Integer;
begin
try
DM_BASE.set_locale;
Result:=true;
q:=TUniQuery.Create(nil);
q.Connection:=DM_BASE.dbConnect;
table.First;
q.SQL.Clear;
for I := 1 to table.RecordCount do
begin
if table.FieldByName('old').AsInteger=1 then
begin
table.Next;
Continue;
end
else;
q.SQL.Add('INSERT INTO t_order (dt,orderid,itemid,note,printerid,complex,price,sum,quantity,servicesum,discountsum,printed,measure_id,salesum)VALUES');
if getBase='mysql' then
q.SQL.Add('(NOW()')
else
begin
q.SQL.Add('(&now');
q.MacroByName('now').AsString:=FormatDateTime('yyyy-mm-dd hh:mm:ss', now);
end;
q.SQL.Add(',&orderid,&itemid,¬e,&printerid,&complex,&price,&sum,&quantity,&servicesum,&discountsum,&printed,&measure_id,&salesum);');
q.MacroByName('orderid').AsInteger:=orderId;
q.MacroByName('itemid').AsString:=table.FieldByName('itemid').AsString;
q.MacroByName('note').AsString:=table.FieldByName('note').AsString;
q.MacroByName('printerid').AsString:=table.FieldByName('divid').AsString;
q.MacroByName('complex').AsString:=table.FieldByName('complex').AsString;
q.MacroByName('price').AsString:=table.FieldByName('price').AsString;
q.MacroByName('sum').AsString:=table.FieldByName('summa').AsString;
q.MacroByName('quantity').AsString:=table.FieldByName('quantity').AsString;
q.MacroByName('servicesum').AsString:=table.FieldByName('service_sum').AsString;
q.MacroByName('discountsum').AsString:=table.FieldByName('discount_sum').AsString;
q.MacroByName('printed').AsInteger:=0;
q.MacroByName('measure_id').AsInteger:=0;
q.MacroByName('salesum').AsString:=table.FieldByName('sale_sum').AsString;
table.Next;
end;
try
if q.SQL.Text.Length>0 then
q.ExecSQL
else;
Except on E:Exception do
begin
ShowMessage('INSIDE:Ошибка при сохранении таблицы чека. '+e.Message+' Строка '+i.ToString);
result:=false;
q.Free;
exit;
end;
end;
finally
q.Free;
end;
end;
function TDM_WORK_BASE.saveOrder(var header: THeader;
table: TVirtualTable): Boolean;
var
q:TUniQuery;
lastId:Integer;
begin
try
DM_BASE.set_locale;
Result:=false;
q:=TUniQuery.Create(nil);
q.Connection:=DM_BASE.dbConnect;
q.SQL.Clear;
q.SQL.Add('INSERT INTO d_order (idout,creationdt,t_certificate_id,parentid,changeid,employeeid,clientid,'+
'objectid,discountid,servicepercent,servicesum,discountpercent,discountsum,printed,closed,guestcount,totalsum,idautomated_point,wpid,note,idlink_online) VALUES ');
q.SQL.Add('(&idout,');
if getBase='mysql' then
q.SQL.Add('NOW()')
else
begin
q.SQL.Add('&now');
q.MacroByName('now').AsString:=FormatDateTime('yyyy-mm-dd hh:mm:ss', now);
end;
q.SQL.Add(',&t_certificate_id,&parentid,&changeid,&employeeid,&clientid,&objectid,&discountid,&servicepercent,&servicesum,');
q.SQL.Add('&discountpercent,&discountsum,&printed,&closed,&guestcount,&totalsum,&idautomated_point,&wpid,¬e,NULL)');
q.MacroByName('idout').AsString:=DM_BASE.getOrderIDOUT;
q.MacroByName('t_certificate_id').AsInteger:=0;
q.MacroByName('parentid').AsInteger:=header.parent_id;
q.MacroByName('changeid').AsInteger:=DM_BASE.get_change_id;
q.MacroByName('employeeid').AsInteger:=S_EMPOYEE_ID;
q.MacroByName('clientid').AsInteger:=header.client_id;
q.MacroByName('objectid').AsInteger:=header.object_id;
q.MacroByName('discountid').AsInteger:=header.discount_id;
q.MacroByName('servicepercent').AsInteger:=header.service_percent;
q.MacroByName('servicesum').AsFloat:=header.service_sum;
q.MacroByName('discountpercent').AsInteger:=header.discount_percent;
q.MacroByName('discountsum').AsFloat:=header.discount_sum;
q.MacroByName('printed').AsInteger:=header.printed;
q.MacroByName('closed').AsInteger:=header.closed;
q.MacroByName('guestcount').AsInteger:=header.guest;
q.MacroByName('totalsum').AsFloat:=header.total;
q.MacroByName('idautomated_point').AsInteger:=G_IDAP;
q.MacroByName('wpid').AsInteger:=G_WPID;
q.MacroByName('note').AsString:=header.note;
try
q.ExecSQL;
if getBase='mysql' then
q.SQL.Text:='SELECT LAST_INSERT_ID() as last_id'
else
q.SQL.Text:='SELECT last_insert_rowid() as last_id';
q.Open;
lastId:=q.FieldByName('last_id').AsInteger;
try
if saveTable(lastId,table) then
begin
header.order_id:=lastId;
result:=True;
end
else
begin
DM_BASE._ROLLBACK;
end;
except on E:Exception do
begin
DM_BASE._ROLLBACK;
ShowMessage('OUTSIDE:Ошибка при сохранении таблицы чека. '+e.Message);
end;
end;
except on E:Exception do
begin
DM_BASE._ROLLBACK;
ShowMessage('Ошибка при сохранении шапки чека. '+e.Message);
end;
end;
finally
q.Free;
end;
end;
function pay:Boolean;
begin
DM_BASE._START_TRANSACTION; // Старт транзакции от TuniConnection.startTran...
if DM_WORK_BASE.saveOrder(head,payVirtualTable) then //Сохранение данных в этой функции происходит только INSERT данных, тут все ок
begin
if not DM_WORK_BASE.payOrder(head) then // вся загвоздка в этой функции
begin
DM_BASE._ROLLBACK;
Layout1.Enabled:=true;
exit;
end;
DM_BASE._COMMIT;
self.Close;
FM_SALES.reInitSale;
FM_SALES.openSale(0);
Layout1.Enabled:=true;
end
else;
end;
function TDM_WORK_BASE.payOrder(Header: THeader): Boolean;
var
q:TUniQuery;
begin
try
Result:=False;
q:=TUniQuery.Create(nil);
q.Connection:=DM_BASE.dbConnect;
q.SQL.Clear;
q.SQL.Add('UPDATE d_order SET');
if getBase='mysql' then
q.SQL.Add('dtclose=NOW(),')
else
begin
q.SQL.Add('dtclose=&now,');
q.MacroByName('now').AsString:=FormatDateTime('yyyy-mm-dd hh:mm:ss', now);
end;
q.SQL.Add('paymentid=&paymentid,');
q.SQL.Add('sumfromclient=&sumfromclient,');
q.SQL.Add('emp_pay=&emp_pay,');
q.SQL.Add('closed=1');
q.SQL.Add('Where id=&id');
q.MacroByName('paymentid').AsInteger:=Header.payId;
q.MacroByName('sumfromclient').AsFloat:=Header.clientSum;
q.MacroByName('emp_pay').AsInteger:=S_EMPOYEE_ID;
q.MacroByName('id').AsInteger:=Header.order_id;
try
q.Execute;
Result:=true;
except on E:Exception do
begin
Result:=false;
q.Free;
ShowMessage(e.Message);
exit;
end;
end;
finally
q.Free;
end;
end;
Когда компилю под Win32 все хорошо работает и нет ошибок.
Но когда компилю под андоид он выдает сообщение мол база не доступна,
методом тыка догадался закоментить транзации, и прога заработала.
Причем заметил что ломается только когда в теле транзакции выполняются update запросы, на insert он такую ошибку не дает.
Может это из за того что ReadCommited стоит и он не может проапдейтить запись которая еще по факту не в базе?
P.S. Вспомнил, еще была проблема в функции SaveTable. Там в цикле проиходит insert записей, так вот, был изначально так что execSQL был в теле функции и происходила такая же ошибка Enable to open database file, после того как начинала сохранятся запись под номером 2, т.е. если одна запись и цикл выполняется один раз, то мир-жвачка, а если больше одного то ошибка.
Потом пока лазил тут по ветками форума (англ версия), наткнулся на пример, вначале сформируй sql запрос а потом выполняй. Ну и заработало в итоге.
Тестовую базу не могу выслать так как просто не скомпилите, проект, заморочек дольше будет, вы лучше пример может организуете какой, чтобы я у себя скомпилить мог и глянуть как правильно делать?