You are not logged in.
Another problem,
function TSQLTableToDataSet(aOwner: TComponent; aTable: TSQLTable; aClient: TSQLRest
{$ifndef UNICODE}; aForceWideString: boolean{$endif}): TDataSet;
...
{$ifdef UNICODE} // for Delphi 2009+ TWideStringField = UnicodeString!
Add(aFieldName,ftWideString,aTable.FieldLengthMax(F,true)); //here should deal with null string
{$else}should deal with null string, else the null string will convert to string 'null'.
Another problem regard to TSQLTableToDataSet, since the return JSON schema
{"fieldCount":4,"values":["ID","Time","Name","Question"],"rowCount":0} has no column length type and length info,
so when no record return, the create dataset's string field length is alway 1, this make edit dataset impossible, also there has a latency problem, even if there has record return, the fieldlength is get the max length of the return record add one, suppose we have a string field length is 50, but current return record's max length is 20, then we will not able to input length big than 20, If this is the reason forced me to leave mORMot, it will be very sad. ![]()
After test, there has some little problem, for SQlite db,
client after call SQLTable := Database.MultiFieldValues(TSQLSampleRecord, '', '1=2');
the SQLTable result is
((TSQLSampleRecord), 'SELECT ID,Time,Name,Question FROM SampleRecord WHERE 1=2;', (), 0, 0, 4, $FB32C8, (), (), (), (), [], 0, 4, (0, 0, sftUnknown, False), nil, False, 0, '{"fieldCount":4,"values":["ID'#0#0'"Time'#0#0'"Name'#0#0'"Question'#0#0',"rowCount":0}'#$A, ('ID', 'Time', 'Name', 'Question'), 0)client after call SQLTable := Database.MultiFieldValues(TSQLSampleRecord, '', 'ID=?', [0]);
the SQLTable result is
((TSQLSampleRecord), 'SELECT ID,Time,Name,Question FROM SampleRecord WHERE ID=:(0):;', (), 0, 0, 4, $FB33C8, (), (), (), (), [], 0, 4, (0, 0, sftUnknown, False), nil, False, 0, '{"fieldCount":4,"values":["ID'#0#0'"Time'#0#0'"Name'#0#0'"Question'#0#0',"rowCount":0}'#$A, ('ID', 'Time', 'Name', 'Question'), 0)but for External DB,
client after call SQLTable := Database.MultiFieldValues(TSQLSampleRecord, '', '1=2');
the SQLTable result is nil, because the server raised exception class ESQLite3Exception with message 'no such column: ID'.
client after call SQLTable := Database.MultiFieldValues(TSQLSampleRecord, '', 'ID=?', [0]);
the SQLTable result is
((TSQLSampleRecord), 'SELECT ID,Time,Name,Question FROM SampleRecord WHERE ID=:(0):;', (), 0, 0, 4, $FB3288, (), (), (), (), [], -1, 1, (0, 0, sftUnknown, False), nil, False, 0, '{"fieldCount":4,"values":["'#0'ID"'#0'",'#0'"Time"'#0'",'#0'"Name"'#0'",'#0'"Question"'#0'"],"rowCount":0}'#$A, ('', ',', ',', ','), 0)then client will raised exception class EDatabaseError with message 'DS2: Field name missing'.
you can see the below two part is different
["ID'#0#0'"Time'#0#0'"Name'#0#0'"Question'#0#0',"rowCount":0}'#$A // ******SQLite3
["'#0'ID"'#0'",'#0'"Time"'#0'",'#0'"Name"'#0'",'#0'"Question"'#0'"],"rowCount":0}'#$A //MS SQL
('ID', 'Time', 'Name', 'Question'), // ******SQLite3
('', ',', ',', ','), //MS SQL
So problem perhaps have two, for External DB, where call where '1=2', for system think it's a complex SQl, then routing the SQL to TSQLRestServerDB.EngineList,
function TSQLRestServer.InternalAdaptSQL(TableIndex: integer; var SQL: RawUTF8): TSQLRestServerStatic;
begin
result := nil;
if (self<>nil) and (TableIndex>=0) then begin // SQL refers to this unique table
if fStaticData<>nil then
// no SQLite3 module available for fStaticData[] -> we need to
// retrieve manualy any static table from the SQL SELECT statement
result := fStaticData[TableIndex];
if (result=nil) and fVirtualTableDirect and (fStaticVirtualTable<>nil) then begin
result := fStaticVirtualTable[TableIndex];
// virtual table may need adaptation (e.g. RowID -> ID)
if (result<>nil) and not result.AdaptSQLForEngineList(SQL) then
// complex request will use SQlite3 virtual engine module
result := nil; //******** this set
end;
end;
end;then GetAndPrepareStatement generate exception
function TSQLRestServerDB.EngineList(const SQL: RawUTF8; ForceAJAX: Boolean=false;
...
Req := GetAndPrepareStatement(SQL); //*******here generate exceptionfor External DB, where call ID=0, the return SQLTableJSON result is not same as call for the SQLite3.
thanks!
about External DB not return column info, after debug, when use sqlite, in TSQLRequest.Execute
after step, there has
function TSQLRequest.Execute(aDB: TSQLite3DB; const aSQL: RawUTF8; JSON: TStream;
Expand: boolean=false): PtrInt;
...
if (result=0) and W.Expand then begin // ****** deal with RowCount = 0
// we want the field names at least, even with no data: we allow RowCount=0
W.Expand := false; // {"FieldCount":2,"Values":["col1","col2"]}
W.CancelAll;
for i := 0 to FieldCount-1 do
W.ColNames[i] := sqlite3.column_name(Request,i);
W.AddColumns;
end;
W.EndJSONObject(0,result);when use External DB, in TSQLDBStatement.FetchAllToJSON
after step, there is no code deal with RowCount=0,
function TSQLDBStatement.FetchAllToJSON(JSON: TStream; Expanded: boolean;
DoNotFletchBlobs: Boolean=false): PtrInt;
...
// write rows data
while Step do begin
ColumnsToJSON(W,DoNotFletchBlobs);
W.Add(',');
inc(result);
end;
// ****** there is no code deal with RowCount = 0
W.EndJSONObject(0,result);so when rowcount=0, the column info is not write.
after some debug,
when client run:
SQLTable := Database.MultiFieldValues(TSQLSampleRecord, '', '1=2');
in TSQLRestServer.InternalAdaptSQL
if (result<>nil) and not result.AdaptSQLForEngineList(SQL) then
// complex request will use SQlite3 virtual engine module
result := nil;
here SQL is
'SELECT ID,Time,Name,Question FROM SampleRecord WHERE 1=2;'
when call result.AdaptSQLForEngineList(SQL), result is false,
so will pass the SQL to TSQLRestServer.EngineList to do this SQL,
then raised exception class ESQLite3Exception with message 'no such column: ID'.
so client will return a nil TSQLTableJSON,
but problem not only this, if comment the result := nil;
// complex request will use SQlite3 virtual engine module
// result := nil;
force SQL to deal with TSQLRestServerStaticExternal.EngineList
function TSQLRestServerStaticExternal.EngineList(const SQL: RawUTF8;
ForceAJAX: Boolean; ReturnedRowCount: PPtrInt): RawUTF8;
var Stmt: ISQLDBStatement;
begin
if ReturnedRowCount<>nil then
raise ESQLDBException.Create('TSQLRestServerStaticExternal.EngineList(ReturnedRowCount<>nil)');
Stmt := PrepareInlinedForRows(SQL);
if Stmt=nil then
result := '' else
Stmt.ExecutePreparedAndFetchAllAsJSON(ForceAJAX or (not NoAJAXJSON),result);
end;
here call result will be '[]'#$A, not the expect
'{"fieldCount":4,"values":["ID","Time","Name","Question"],"rowCount":0}'#$A
so client will return a TSQLTableJSON but with no column info
when client run:
SQLTable := Database.MultiFieldValues(TSQLSampleRecord, '', 'ID=?', [0]);
this will pass the SQL
'SELECT ID,Time,Name,Question FROM SampleRecord WHERE ID=:(0):;'
to TSQLRestServerStaticExternal.EngineList
function TSQLRestServerStaticExternal.EngineList(const SQL: RawUTF8;
ForceAJAX: Boolean; ReturnedRowCount: PPtrInt): RawUTF8;
but this return the same result '[]'#$A, so client will return a TSQLTableJSON but with no column info,
then when client create dataset will raise such 'No fields defined. Cannot create dataset' exception.
Ab, can you look at this, if need I send you testcase, please make a note.
thanks!
Your .db3 file sounds broken.
As I stated above, you can not change the DB layout from internal to external without dropping any previous internal table.You have to stick with external tables.
Then you can use an external SQLite3 table, and switch to other DB engine when needed.
After my post, I see your post, this is not important, only I learn found, but this two method,
SQLTable := Database.MultiFieldValues(TSQLSampleRecord, '', '1=2'); //or
SQLTable := Database.MultiFieldValues(TSQLSampleRecord, '', 'ID=?', [0]);
i want return a valid JSON result to create a valid dataset:
fDataSet := TSQLTableToDataSet(Self, SQLTable, Database);
for sqlite3 db, no problem, but for external DB, the two method all failed,
the first method return a nil SQLTable, the second return a SQLTable has no column info.
thanks!
Please ensure you got the LATEST 1.18 source code.
We fixed this issue some days ago, AFAIR.
Yes, since you update very quickly, I alway update before I ask question, use the 35cd8533cb38acd4 build,
download 11/7
thanks
Client If change :
SQLTable := Database.MultiFieldValues(TSQLSampleRecord, '', '1=2'); to
SQLTable := Database.MultiFieldValues(TSQLSampleRecord, '', 'ID=?', [0]);if Use TSQLRestServerDB then also ok, but after change server to External DB
VirtualTableExternalRegisterAll(Model, MSSQLConnectionProperties);then Client return SQLTable has no column info, then TSQLTableToDataSet will
generate such exception:
---------------------------
Debugger Exception Notification
---------------------------
Project Project04Client.exe raised exception class EDatabaseError with message 'No fields defined. Cannot create dataset'.
---------------------------
Break Continue Help
---------------------------Another problem, if first test use sqlite db, after some test, then change to External DB,
seems should manual delete the *.db3 file, from External DB to sqlite db, also need manual
delete the *.db3 file, else will generate such
---------------------------
Debugger Exception Notification
---------------------------
Project Project04Server.exe raised exception class ESQLite3Exception with message 'no such module: External'.
---------------------------
Break Continue Help
---------------------------I want add data in dbgrid, so I change Sample04 Client, such change is ok,
procedure TForm1.Button1Click(Sender: TObject);
var
SQLTable: TSQLTableJSON;
begin
SQLTable := Database.MultiFieldValues(TSQLSampleRecord, '', '1=2');
if Assigned(SQLTable) then
try
FreeAndNil(fDataSet);
fDataSet := TSQLTableToDataSet(Self, SQLTable, Database);
DataSource1.DataSet := fDataSet;
finally
SQLTable.Free;
end;
end;But When I Change Sample04 Server to use external MS SQLSerer, such change:
procedure TForm1.FormCreate(Sender: TObject);
begin
MSSQLConnectionProperties := TOleDBMSSQLConnectionProperties.Create('localhost', 'TestDB', '', '');
Model := CreateSampleModel;
VirtualTableExternalRegisterAll(Model, MSSQLConnectionProperties);
DB := TSQLRestServerDB.Create(Model,ChangeFileExt(paramstr(0),'.db3'));
DB.CreateMissingTables(0);
Server := TSQLHttpServer.Create('8080',[DB],'+',useHttpApiRegisteringURI);
Server.AccessControlAllowOrigin := '*'; // allow cross-site AJAX queries
end;When the server run, I can see SampleRecord table in the MSSQL DB,
but when run the change Client, the Client dataset can't create duty server generate such exeception:
---------------------------
Debugger Exception Notification
---------------------------
Project Project04Server.exe raised exception class ESQLite3Exception with message 'no such column: ID'.
---------------------------
Break Continue Help
---------------------------Thanks!
I has upload a picture at http://pan.baidu.com/s/1h6yly, you can see the picture.
Manual search in TestSQL3.map file, not found the address,
In IDE run, the Exception not generate, sorry, i don't know how to search the address in IDE.
TestSQL3.exe and TestSQL3.map is in the same folder.
Yes, the last version, just download from source control.
strange, TestSQL3.map has generate, but the log file still no line number, I have set link the Detailed Map file.
DelphiXE run TestSQL3 in ide, no exception, when run without debug, generate exception
! Exception EInterfaceFactoryException raised with message:
! Invalid fake ICalculator.ComplexCall interface call: : {
"ErrorCode":500,
"ErrorText":"Exception EAccessViolation: Access violation at address..."
}
here is log file content
20131029 17590243 fail TTestLowLevelCommon(010DA878) Low level common: Soundex "" stack trace API 0048C25A 004908CF 0047C5F7 005F5D52 0047D0FB 006338E7 00639319 7C82F23B
20131029 17592353 fail TTestSynopsePDF(010DACA0) Synopse PDF: TPdfDocument "" stack trace API 0048C25A 004908CF 0047C5F7 00611894 0047D0FB 006338E7 00639319 7C82F23B
20131029 17592359 fail TTestSynopsePDF(010DACA0) Synopse PDF: TPdfDocumentGDI "" stack trace API 0048C25A 004908CF 0047C5F7 00613B9C 0047D0FB 006338E7 00639319 7C82F23B
20131029 18001247 fail TTestBasicClasses(010DAD80) Basic classes: TSQLRecord "" stack trace API 0048C25A 004908CF 0047C5F7 0060D5BC 0047D0FB 006338E7 00639319 7C82F23B
20131029 18001247 fail TTestBasicClasses(010DAD80) Basic classes: TSQLRecord "" stack trace API 0048C25A 004908CF 0047C5F7 0060D666 0047D0FB 006338E7 00639319 7C82F23B
20131029 18001247 fail TTestBasicClasses(010DAD80) Basic classes: TSQLRecord "" stack trace API 0048C25A 004908CF 0047C5F7 0060D75B 0047D0FB 006338E7 00639319 7C82F23B
20131029 18001247 fail TTestBasicClasses(010DAD80) Basic classes: TSQLRecord "" stack trace API 0048C25A 004908CF 0047C5F7 0060D9EA 0047D0FB 006338E7 00639319 7C82F23B
20131029 18001247 fail TTestBasicClasses(010DAD80) Basic classes: TSQLRecord "" stack trace API 0048C25A 004908CF 0047C5F7 0060DB6B 0047D0FB 006338E7 00639319 7C82F23B
20131029 18001247 fail TTestBasicClasses(010DAD80) Basic classes: TSQLRecord "" stack trace API 0048C25A 004908CF 0047C5F7 0060DD39 0047D0FB 006338E7 00639319 7C82F23B
20131029 18001247 fail TTestBasicClasses(010DAD80) Basic classes: TSQLRecord "" stack trace API 0048C25A 004908CF 0047C5F7 0060DDC3 0047D0FB 006338E7 00639319 7C82F23B
20131029 18001639 EXCOS EAccessViolation (C0000005) at 004626B2 stack trace API 0048B110 00407190
20131029 18001639 EXC EInterfaceFactoryException ("Invalid fake ICalculator.ComplexCall interface call: : {\r\n\"ErrorCode\":500,\r\n\"ErrorText\":\"Exception EAccessViolation: Access violation at address 004626B2 in module 'TestSQL3.exe'. Read of address 001A1000\"\r\n}") at 0057DD36 stack trace API 0048B110 00407190
For I not only pure new project, these are projects to maintain and evolution,
for thin Client Program customer like DB binding cxGrid, its function is rich, so i can't
just throw it away, i person like coding, but for UI part, I like Rad Designer.
About MVC, I like the idea, but i don't know how design the UI part.
>>I believe there are more important tasks to be considered.
Yes, I also feeling this, these days I learn mORMot,
for I the lack a bridge between Old UI DB Bind Designer is a issue, and auto master-detail applyupdate,
I want the bidirectional edit of clientdataset, I think if this
feature implement, will able to attract a number of the original developers,
just my personal view, sorry for my poor english.
Thank you very much, download and confirm Mocks and stubs is passed. Very Excellent!
<<About ValVariant missing field, it is strange, since I'm not able to reproduce it.
Are you sure you retrieved the latest version from http://synopse.info/fossil - see http://synopse.info/fossil/wiki?name=Get+the+source ?>>
Yes, I get the latest version, from 2013-01-03 [2a15d8630c], Just download from 2013-01-04 [5dc09927e3], test result is same.
<<Are you sure you did not define the LVCL conditional?>>
Yes, Just download and Extract File, not change anything.
<<Other problems comes directly from the fact that the system is MBCS, so ANSI functions are not consistent, and regression tests fail.>>
So this will not affect the real application, we can ignore these?
! - Mocks and stubs: 1 / 30,031 FAILED 115.39ms
When run TestSQL3 from IDE, Mocks and stubs will all pass, but if run TestSQL3 not from IDE, then 1 FAILED, not know where it occur.
! - IdemPropName: 1 / 10 FAILED 2.28ms
Check(UpperCaseU(WinAnsiToUTF8('a殓D'))='AECD'); ==> Failed at 2121
! - Soundex: 1 / 35 FAILED 175us
Check(SoundExAnsi(' 123 bonjourtr'+chr(232)+'slongmotquid'+chr(233)+'passe m',@PC)<>0);
Check((PC<>nil) and (PC^=' ')); ==> Failed at 881, here PC^ is #168
! - TPdfDocument: 1 / 2 FAILED 50.62ms
Check(Hash32(MS.Memory,MS.Position)=Hash[embed]); ==> Failed at 3971, left Hash32 is 3879243249, right hash is 394327692
! - TPdfDocumentGDI: 1 / 3 FAILED 690.91ms
i := PosEx('/FontBBox [',s);
if CheckFailed(i=5650) then exit; ==> Failed at 4132, here i is 5654
! - TSQLRecord: 7 / 52 FAILED 1.22ms
s := T.GetSQLValues;
Check(s='Int,Test,Unicode,Ansi,ValFloat,ValWord,ValDate,Next,ValVariant '+
'VALUES (0,'''','''','''',0,0,'''',0,null)'); ==> Failed at: 3304, s is 'Int,Test,Unicode,Ansi,ValFloat,ValWord,ValDate,Next VALUES (0,'''','''','''',0,0,'''',0)'
s := ObjectToJSON(T);
Check(s='{"ID":0,"Int":0,"Test":"","Unicode":"","Ansi":"","ValFloat":0,'+
'"ValWord":0,"ValDate":"","Next":0,"Data":"","ValVariant":null}'); ==>Failed at: 3308, s is '{"ID":0,"Int":0,"Test":"","Unicode":"","Ansi":"","ValFloat":0,"ValWord":0,"ValDate":"","Next":0,"Data":""}'
T.ValDate := 39882.888612; // a fixed date and time
T.Ansi := 'abcde'+chr(233)+'ef'+chr(224)+chr(233);
T.Test := WinAnsiToUTF8('abcde'+chr(233)+'ef'+chr(224)+chr(233));
T.Unicode := Utf8DecodeToRawUnicode(T.fTest);
Check(RawUnicodeToWinAnsi(T.fUnicode)=T.fAnsi); ==> Failed at:3315, here T.fUnicode is 'a'#0'b'#0'c'#0'd'#0'e'#0#$E9#0'e'#0'f'#0#$E0#0#$E9#0#0#0#0#0#$A8#0#0, T.fAnsi is 'abcdeéefàé'
s := T.GetSQLSet;
Check(s='Int=0, Test='''+T.Test+''', Unicode='''+T.Test+
''', Ansi='''+T.Test+''', ValFloat=3.141592653, ValWord=1203, '+
'ValDate=''2009-03-10T21:19:36'', Next=0'{$ifdef USEVARIANTS}+
', ValVariant=''3.1416'''{$endif}); ==>Failed at:3324, s is 'Int=0, Test=''abcde茅ef脿茅'', Unicode=''abcde茅ef脿茅'', Ansi=''abcde茅ef脿茅'', ValFloat=3.141592653, ValWord=1203, ValDate=''2009-03-10T21:19:36'', Next=0'
s := T.GetSQLValues;
Check(Hash32(s)=$2D344A5E); ==>Failed at 3329: s is 'Int,Test,Unicode,Ansi,ValFloat,ValWord,ValDate,Next VALUES (0,''abcde茅ef脿茅'',''abcde茅ef脿茅'',''abcde茅ef脿茅'',3.141592653,1203,''2009-03-10T21:19:36'',0)'
s := T.GetJSONValues(false,true,soSelect);
Check(s='{"fieldCount":10,"values":["RowID","Int","Test","Unicode","Ansi",'+
'"ValFloat","ValWord","ValDate","Next"'{$ifdef USEVARIANTS}+
',"ValVariant"'{$endif}+',0,0,"'+T.Test+'","'+
T.Test+'","'+T.Test+'",3.141592653,1203,"2009-03-10T21:19:36",0,'
{$ifdef USEVARIANTS}+'3.1416'{$endif}+']}'); ==> Falied at 3331: s is '{"fieldCount":9,"values":["RowID","Int","Test","Unicode","Ansi","ValFloat","ValWord","ValDate","Next",0,0,"abcde茅ef脿茅","abcde茅ef脿茅","abcde茅ef脿茅",3.141592653,1203,"2009-03-10T21:19:36",0]}'
s := ObjectToJSON(T);
Check(s='{"ID":10,"Int":0,"Test":"'+T.Test+'","Unicode":"'+T.Test+
'","Ansi":"'+T.Test+'","ValFloat":3.141592653,"ValWord":1203,'+
'"ValDate":"2009-03-10T21:19:36","Next":0,"Data":""'{$ifdef USEVARIANTS}
+',"ValVariant":3.1416'{$endif}+'}'); ==Failed at 3351: s is '{"ID":10,"Int":0,"Test":"abcde茅ef脿茅","Unicode":"abcde茅ef脿茅","Ansi":"abcde茅ef脿茅","ValFloat":3.141592653,"ValWord":1203,"ValDate":"2009-03-10T21:19:36","Next":0,"Data":""}'
T.Int := 1234567890123456;
s := T.GetJSONValues(true,true,soSelect);
Check(s='{"RowID":10,"Int":1234567890123456,"Test":"'+T.Test+'","Unicode":"'+T.Test+
'","Ansi":"'+T.Test+'","ValFloat":3.141592653,"ValWord":1203,'+
'"ValDate":"2009-03-10T21:19:36","Next":0,"ValVariant":3.1416}'); ==> Failed at 3363: s is '{"RowID":10,"Int":1234567890123456,"Test":"abcde茅ef脿茅","Unicode":"abcde茅ef脿茅","Ansi":"abcde茅ef脿茅","ValFloat":3.141592653,"ValWord":1203,"ValDate":"2009-03-10T21:19:36","Next":0}'
s := T.GetJSONValues(true,true,soSelect);
Check(s='{"RowID":10,"Int":1234567890123456,"Test":"'+T.Test+'","Unicode":"'+T.Test+
'","Ansi":"'+T.Test+'","ValFloat":3.141592653,"ValWord":1203,'+
'"ValDate":"2009-03-10T21:19:36","Next":0'{$ifdef USEVARIANTS}
+',"ValVariant":"'+T.Test+'"'{$endif}+'}'); == Failed at: 3376, s is '{"RowID":10,"Int":1234567890123456,"Test":"abcde茅ef脿茅","Unicode":"abcde茅ef脿茅","Ansi":"abcde茅ef脿茅","ValFloat":3.141592653,"ValWord":1203,"ValDate":"2009-03-10T21:19:36","Next":0}'
s := T.GetSQLSet;
Check(s='Int=1234567890123456, Test='''+T.Test+''', Unicode='''+T.Test+
''', Ansi='''+T.Test+''', ValFloat=3.141592653, ValWord=1203, '+
'ValDate=''2009-03-10T21:19:36'', Next=0'{$ifdef USEVARIANTS}+
', ValVariant='''+T.Test+''''{$endif}); ==> Failed at 3381, s is 'Int=1234567890123456, Test=''abcde茅ef脿茅'', Unicode=''abcde茅ef脿茅'', Ansi=''abcde茅ef脿茅'', ValFloat=3.141592653, ValWord=1203, ValDate=''2009-03-10T21:19:36'', Next=0'
Just foud the great opensource framework, download the newest source, followed Readme.txt, run TestSQL3, found below not passed, under XE, Chinese windows 2003 server, search forum also find a topic, is this can just ignore or need correct?
1.1. Low level common:
! - IdemPropName: 1 / 10 FAILED 2.28ms
! - Soundex: 1 / 35 FAILED 175us
1.6. Synopse PDF:
! - TPdfDocument: 1 / 2 FAILED 50.62ms
! - TPdfDocumentGDI: 1 / 3 FAILED 690.91ms
2.1. Basic classes:
! - TSQLRecord: 7 / 52 FAILED 1.22ms
2.6. Service oriented architecture:
! - Mocks and stubs: 1 / 30,031 FAILED 115.39ms
thanks!