You are not logged in.
I've modified the sample Project04Server (HTTP) to use external tables.
My goal is to setup a mini project with a client and a server to explore remote ORM.
But as soon as I call CreateMissingTables, tables are created in the internal SQlite database instead of the external FirebirdDB.
What is wrong with my picture?
The following code is excerpted from the server:
procedure TForm1.FormCreate(Sender: TObject);
var
FirebirdServerIP: RawUTF8;
FirebirdFDBFile: RawUTF8;
begin
FirebirdServerIP := '127.0.0.1';
FirebirdFDBFile := 'C:\Users\fabio.SFERACONSULTING\Desktop\Mormot Samples Fabio\04 - HTTP Client-Server\data\MORMOT_CLIENT_SERVER.FDB';
DeleteFile(UTF8ToString(FirebirdFDBFile));
// 0. Create an AnyDAC Physical DriverLink for Firebird (or drop a TADPhysIBDriverLink on the form)
TADPhysIBDriverLink.Create(Application).VendorLib := 'fbclient.dll';
// 1. Populate the AnyDAC/FireDAC Firebird ConnectionProperties
fConnectionProps := TSQLDBFireDACConnectionProperties.Create('IB?CreateDatabase=Yes',
FirebirdServerIP + ':' + FirebirdFDBFile,
'SYSDBA','masterkey'
);
// 2. Connecting has the side effect of creating the database file
fConnectionProps.ThreadSafeConnection.Connect;
// 3. Create the Model
Model := CreateSampleModel;
// 4. Register all external tables (*BEFORE* calling TSQLRestClientDB/TSQLRestServerDB.Create!)
VirtualTableExternalRegister(Model, TSQLSampleRecord, fConnectionProps, 'SampleRecord');
DB := TSQLRestServerDB.Create(Model, ChangeFileExt(paramstr(0), '.db3'), true);
DB.CreateMissingTables(0); <======= Tables are not created in external Firebird DB, but instead are created in to the SQlite database
Server := TSQLHttpServer.Create('8080',[DB],'+',useHttpApiRegisteringURI);
Server.AccessControlAllowOrigin := '*'; // allow cross-site AJAX queries
end;
Offline
Is not the main SQLite3 already existing?
You have to start from a void SQlite3 main DB - perhaps even use VirtualTableExternalRegisterAll() and SQLITE_MEMORY_DATABASE_NAME as main database name.
AFAIR initial fConnectionProps.ThreadSafeConnection.Connect is not needed: it will be made the first time the ORM would use the external DB.
Offline
I've modified my code as for your suggestion.
Now the problem is that I get the following exception:
exception class : ESQLite3Exception
exception message : TSQLSampleRecord: unable to create external missing field SampleRecord.Time - SQL="ALTER TABLE SampleRecord ADD Time BIGINT".
As far as I can see, the firebird database is created but it seems that there is an attempt to alter table SampleRecord *before* having first created it.
In fact the firebird database is empty after I run the program.
Any ideas?
procedure TForm1.FormCreate(Sender: TObject);
var
FirebirdServerIP: RawUTF8;
FirebirdFDBFile: RawUTF8;
begin
FirebirdServerIP := '127.0.0.1';
FirebirdFDBFile := 'C:\data\MORMOT_CLIENT_SERVER.FDB';
DeleteFile(UTF8ToString(FirebirdFDBFile));
// 0. Create an AnyDAC Physical DriverLink for Firebird (or drop a TADPhysIBDriverLink on the form)
TADPhysIBDriverLink.Create(Application).VendorLib := 'fbclient.dll';
// 1. Populate the AnyDAC/FireDAC Firebird ConnectionProperties
fConnectionProps := TSQLDBFireDACConnectionProperties.Create('IB?CreateDatabase=Yes',
FirebirdServerIP + ':' + FirebirdFDBFile,
'SYSDBA','masterkey'
);
// 2. Connecting has the side effect of creating the database file ( *if* 'IB?CreateDatabase=Yes')
//
// N.B. AFAIR initial fConnectionProps.ThreadSafeConnection.Connect is not needed:
// it will be made the first time the ORM would use the external DB.
// fConnectionProps.ThreadSafeConnection.Connect;
// 3. Create the Model
Model := CreateSampleModel;
// 4. Register all external tables (*BEFORE* calling TSQLRestClientDB/TSQLRestServerDB.Create!)
// VirtualTableExternalRegister(Model, TSQLSampleRecord, fConnectionProps, 'SampleRecord');
VirtualTableExternalRegisterAll(Model, fConnectionProps, false);
// 5. Create missing tables
DB := TSQLRestServerDB.Create(Model, SQLITE_MEMORY_DATABASE_NAME, true);
DB.CreateMissingTables();
Server := TSQLHttpServer.Create('8080',[DB],'+',useHttpApiRegisteringURI);
Server.AccessControlAllowOrigin := '*'; // allow cross-site AJAX queries
end;
Last edited by fabvit (2014-10-28 08:41:22)
Offline
Just ignore this exception, which is run only at startup (due to some missing metadata from FireDac), and is catched by the code.
AFAIR it doe not stop the process.
OR perhaps I did miss something, but I'm not able to reproduce the issue here.
Offline
>Just ignore this exception,
but... no tables are created in the external firebird database after calling CreateMissingTables
Do you think the external tables will be created when I will add some data to them from the client?
Offline
No, the tables are created at startup only.
But I'm not able to reproduce the issue here.
I just tried to use FireBird via FireDAC, and it worked as expected - see http://synopse.info/fossil/finfo?name=S … rebird.dpr
Perhaps try to create the DB first, then close the connection, and re create a new connection properties without the "CreateDatabase=Yes" parameter.
Offline
Ok thanks: I will try to follow your suggestion but I will first try to update from GitHub my local mormot repository to a more recent version than the one I've installed on my pc.
As a side note, I'm using the last stable release of AnyDAC not FireDAC and this may be something that I've to further investigate.
I'll surely let you know my findings.
thank you!
fabio
Offline
Hi Arnaud: finally I've founded the problem!!!!
In unit SampleData.pas is defined the TSQLSampleRecord class.
This class had a property defined as follow:
property Time: TModTime read fTime write fTime;
Guess what? "Time" is a reserved word in Firebird, hence when CreateMissingTables() is called there is an error creating a table with a column that has a reserved word name!
I changed the above line as follow and voila the problem disappeared.
property ModTime: TModTime read fModTime write fModTime;
May be it would be useful to change the SampleData.pas in the public mormot repository to avoid other user the same problem when they try to use external tables *AND* Firebird.
thank you!
fabio
Offline
I have created a feature request for this.
See http://synopse.info/fossil/tktview/7fbbd53966
IMHO such fields should be auto-mapped when used on an external DB.
For instance, "Time" property name may be mapped as "_Time" column name for FireBird.
Offline
Note:
Zeos provides a huge ',' delimited String for SQLKeyWords in any kind:
IZConnection.GetMetadata.GetDatabaseInfo.GetSQLKeywords: String;
So you could prevent such issues...
{**
Gets a comma-separated list of all a database's SQL keywords
that are NOT also SQL92 keywords.
@return the list
}
function TZInterbase6DatabaseInfo.GetSQLKeywords: string;
begin
Result := 'ACTIVE,AFTER,ASCENDING,BASE_NAME,BEFORE,BLOB,' +
'CACHE,CHECK_POINT_LENGTH,COMPUTED,CONDITIONAL,CONTAINING,' +
'CSTRING,DATABASE,RDB$DB_KEY,DEBUG,DESCENDING,DO,ENTRY_POINT,' +
'EXIT,FILE,FILTER,FUNCTION,GDSCODE,GENERATOR,GEN_ID,' +
'GROUP_COMMIT_WAIT_TIME,IF,INACTIVE,INPUT_TYPE,INDEX,' +
'LOGFILE,LOG_BUFFER_SIZE,MANUAL,MAXIMUM_SEGMENT,MERGE, MESSAGE,' +
'MODULE_NAME,NCHAR,NUM_LOG_BUFFERS,OUTPUT_TYPE,OVERFLOW,PAGE,' +
'PAGES,PAGE_SIZE,PARAMETER,PASSWORD,PLAN,POST_EVENT,PROTECTED,' +
'RAW_PARTITIONS,RESERV,RESERVING,RETAIN,RETURNING_VALUES,RETURNS,' +
'SEGMENT,SHADOW,SHARED,SINGULAR,SNAPSHOT,SORT,STABILITY,STARTS,' +
'STARTING,STATISTICS,SUB_TYPE,SUSPEND,TRIGGER,VARIABLE,RECORD_VERSION,' +
'WAIT,WHILE,WORK,VALUE,POSITION,USER,CURRENCY,OPTION,DATE,START,END,USER,' +
'READ,PARENT,TYPE'+
{Ticket #63: http://sourceforge.net/p/zeoslib/tickets/62/}
',DEC,TIME,MIN,MAX'+
{FireBird 3.0}
',DETERMINISTIC,OVER,RETURN,SCROLL,SQLSTATE';
end;
Last edited by EgonHugeist (2014-10-28 19:47:51)
Offline
Great!
Thank you!
fabio
Offline
I've added a new TSQLModelRecordPropertiesExternal.MapAutoKeywordFields method.
See http://synopse.info/fossil/info/c6453db6e2
The corresponding documentation is available at
http://synopse.info/files/html/Synopse% … #TITLE_187
Offline
@ab
After last changes:
12 - SynDB Explorer
Error: TSQLConnection.Database field name conflicts with a SQL keyword
on startup.
mORMotr 1.18.496 Delphi XE2-32
Michal
Offline
We have let SQL keywords check be a little less restrictive in TSQLRecord, so that SynDBExplorer runs without exception.
See http://synopse.info/fossil/info/f2c2e35a50
Thanks for the feedback!
Offline