You are not logged in.
Pages: 1
Having read the SAD manual and several posts about the mormot framework I cannot understand if I can use legacy tables with mormot.
For example if I have a firebird table where its primary key is composed by several fields instead of the surrogate ID key field, how do I tell mormot to cope with this multi-field primary key? May be there is a way, in mormot, to configure a multi-field primary.
I've tried using firebird external tables in mormot. As far as I've investigated I've seen that every class property declared as string, will be translated in to a BLOB field in the corresponding Firebird extenal table: this surprises me a lot (I'm not a big fan of BLOB fields). Is there in mormot something to configure a string property of a class to be represented as VARCHAR or as CHAR in Firebird?
thank you so much
fabio vitale
Offline
No, there is no way to define such a multi-field primary key.
Primary keys are expected to be an integer.
This is due to several restrictions outside of mORMot, the main one being that SQLite3 virtual tables (the mechanism which is at the kernel of our ORM for external tables), expects primary keys to be defined as integer.
So you cannot use directly such legacy tables.
For them, you should better re-use your existing SQL statement, if possible using the SynDB classes instead of your former library.
In fact, in SynDB you would be able to return directly some JSON from the DB, and have a statement cache.
Then wrap your SQL queries into a persistent service, if possible using interfaces.
Please take care of the documentation: you have to specify a field width if you use an external table, by adding "index .." to the published field.
For instance:
property FirstName: RawUTF8 index 40 read fFirstName write fFirstName;
property LastName: RawUTF8 index 40 read fLastName write fLastName;
property Data: TSQLRawBlob read fData write fData;
This will create VARCHAR(40) columns, as you expect.
Without this 'index ...', the ORM will estimate that the field is a CLOB, without any maximum size.
Offline
For me "30 - MVC Server" and ZEOS 7.2 such database in Firebird 2.53 has created:
SET SQL DIALECT 3;
SET NAMES UTF8;
CREATE DATABASE 'MVCSERVERFIREBIRD.FDB'
USER 'SYSDBA' PASSWORD 'masterkey'
PAGE_SIZE 4096
DEFAULT CHARACTER SET UTF8 COLLATION UTF8;
/******************************************************************************/
/**** Tables ****/
/******************************************************************************/
CREATE TABLE ARTICLE (
ID INTEGER NOT NULL,
CREATEDAT BIGINT,
MODIFIEDAT BIGINT,
TITLE VARCHAR(80),
CONTENT BLOB SUB_TYPE 1 SEGMENT SIZE 2000,
AUTHOR BIGINT,
AUTHORNAME VARCHAR(50),
PUBLISHEDMONTH BIGINT,
ABSTRACT VARCHAR(1024),
TAGS BLOB SUB_TYPE 0 SEGMENT SIZE 2000
);
CREATE TABLE ARTICLESEARCH (
ID INTEGER NOT NULL,
TEXT BLOB SUB_TYPE 1 SEGMENT SIZE 2000
);
CREATE TABLE AUTHOR (
ID INTEGER NOT NULL,
CREATEDAT BIGINT,
MODIFIEDAT BIGINT,
LOGONNAME VARCHAR(30) NOT NULL,
FIRSTNAME VARCHAR(50),
FAMILYNAME VARCHAR(50),
BIRTHDATE TIMESTAMP,
EMAIL VARCHAR(40),
HASHEDPASSWORD VARCHAR(64),
VERIFIED BIGINT,
RIGHTS BIGINT
);
CREATE TABLE BLOGINFO (
ID INTEGER NOT NULL,
TITLE VARCHAR(80),
LANGUAGE VARCHAR(3),
DESCRIPTION VARCHAR(120),
COPYRIGHT VARCHAR(80),
ABOUT BLOB SUB_TYPE 1 SEGMENT SIZE 2000
);
CREATE TABLE COMMENT (
ID INTEGER NOT NULL,
CREATEDAT BIGINT,
MODIFIEDAT BIGINT,
TITLE VARCHAR(80),
CONTENT BLOB SUB_TYPE 1 SEGMENT SIZE 2000,
AUTHOR BIGINT,
AUTHORNAME VARCHAR(50),
ARTICLE BIGINT
);
CREATE TABLE TAG (
ID INTEGER NOT NULL,
IDENT BLOB SUB_TYPE 1 SEGMENT SIZE 2000,
OCCURENCE BIGINT,
CREATEDAT BIGINT
);
/******************************************************************************/
/**** Unique Constraints ****/
/******************************************************************************/
ALTER TABLE AUTHOR ADD UNIQUE (LOGONNAME);
/******************************************************************************/
/**** Primary Keys ****/
/******************************************************************************/
ALTER TABLE ARTICLE ADD PRIMARY KEY (ID);
ALTER TABLE ARTICLESEARCH ADD PRIMARY KEY (ID);
ALTER TABLE AUTHOR ADD PRIMARY KEY (ID);
ALTER TABLE BLOGINFO ADD PRIMARY KEY (ID);
ALTER TABLE COMMENT ADD PRIMARY KEY (ID);
ALTER TABLE TAG ADD PRIMARY KEY (ID);
/******************************************************************************/
/**** Indices ****/
/******************************************************************************/
CREATE INDEX NDXARTICLEAUTHOR ON ARTICLE (AUTHOR);
CREATE UNIQUE DESCENDING INDEX NDXARTICLEID ON ARTICLE (ID);
CREATE INDEX NDXARTICLEPUBLISHEDMONTH ON ARTICLE (PUBLISHEDMONTH);
CREATE UNIQUE DESCENDING INDEX NDXARTICLESEARCHID ON ARTICLESEARCH (ID);
CREATE UNIQUE DESCENDING INDEX NDXAUTHORID ON AUTHOR (ID);
CREATE UNIQUE DESCENDING INDEX NDXBLOGINFOID ON BLOGINFO (ID);
CREATE INDEX NDXCOMMENTARTICLE ON COMMENT (ARTICLE);
CREATE INDEX NDXCOMMENTAUTHOR ON COMMENT (AUTHOR);
CREATE UNIQUE DESCENDING INDEX NDXCOMMENTID ON COMMENT (ID);
CREATE UNIQUE DESCENDING INDEX NDXTAGID ON TAG (ID);
Michal
Offline
Yes, this is as expected by how the TSQL* classes have been defined.
The Content field is defined as RawUTF8 without "index", so is defined as a TEXT BLOB, as expected.
If you want, you just can define:
TSQLContent = class(TSQLRecordTimeStamped)
...
property Content: RawUTF8 index 32768 read fContent write fContent;
and you will have a VARCHAR(32768) column definition.
But the user won't be able to post more than 32768 UTF-8 characters... which may be less than expected for a blog post, sadly.
Offline
@fabvit
Yes, I can and you can. But I have to confess my tables don't have multi field-primary indexes.
If you have a special database, you have to know, you don't need the ORM of mORMot. You can use only interface based services.
E.g.
procedure TKontenService.GetKontostand(const datum: RAWUTF8; out res: RawUTF8);
var
tKonten: ISQLDBRows;
y, m, d: Integer;
a: TStringDynArray;
begin
a:= TStringDynArray(SplitString(datum, '-'));
if (Length(a) < 3) then exit;
y:= StrToInt(a[0]);
m:= StrToInt(a[1]);
d:= StrToInt(a[2]);
res:= '';
tKonten:= Props.Execute('select * from p_kontostand(?, ?)', [DateToSQL(EncodeDate(y,m,d)), 'EUR']);
res:= tKonten.FetchAllAsJSON(true);
end;
This service calls a stored procedure. You can't call a procedure with mORMot by default. But in your own service you can do all what you want to do with sql.
Offline
@ab
Thanks, I will try it.
Offline
@miab3
For your interest, I've just changed how foreign keys columns are defined: they will now be defined as 32 bit integer instead of 64 bit integer.
The same for enumerate/boolean or RecordRef fields.
It won't make a huge performance nor storage size difference, but sounded somewhat cleaner.
See http://synopse.info/fossil/info/dcbca02962e11
Offline
@ab
r 1.18.447, Zeos 7.2-beta r3438, Firebird 2.53
Indeed, there has been a change in the Firebird database:
SET SQL DIALECT 3;
SET NAMES UTF8;
CREATE DATABASE 'MVCSERVERFIREBIRD.FDB'
USER 'SYSDBA' PASSWORD 'masterkey'
PAGE_SIZE 4096
DEFAULT CHARACTER SET UTF8 COLLATION UTF8;
/******************************************************************************/
/**** Tables ****/
/******************************************************************************/
CREATE TABLE ARTICLE (
ID INTEGER NOT NULL,
CREATEDAT BIGINT,
MODIFIEDAT BIGINT,
TITLE VARCHAR(80),
CONTENT BLOB SUB_TYPE 1 SEGMENT SIZE 2000,
AUTHOR INTEGER,
AUTHORNAME VARCHAR(50),
PUBLISHEDMONTH BIGINT,
ABSTRACT VARCHAR(1024),
TAGS BLOB SUB_TYPE 0 SEGMENT SIZE 2000
);
CREATE TABLE ARTICLESEARCH (
ID INTEGER NOT NULL,
TEXT BLOB SUB_TYPE 1 SEGMENT SIZE 2000
);
CREATE TABLE AUTHOR (
ID INTEGER NOT NULL,
CREATEDAT BIGINT,
MODIFIEDAT BIGINT,
LOGONNAME VARCHAR(30) NOT NULL,
FIRSTNAME VARCHAR(50),
FAMILYNAME VARCHAR(50),
BIRTHDATE TIMESTAMP,
EMAIL VARCHAR(40),
HASHEDPASSWORD VARCHAR(64),
VERIFIED INTEGER,
RIGHTS BIGINT
);
CREATE TABLE BLOGINFO (
ID INTEGER NOT NULL,
TITLE VARCHAR(80),
LANGUAGE VARCHAR(3),
DESCRIPTION VARCHAR(120),
COPYRIGHT VARCHAR(80),
ABOUT BLOB SUB_TYPE 1 SEGMENT SIZE 2000
);
CREATE TABLE COMMENT (
ID INTEGER NOT NULL,
CREATEDAT BIGINT,
MODIFIEDAT BIGINT,
TITLE VARCHAR(80),
CONTENT BLOB SUB_TYPE 1 SEGMENT SIZE 2000,
AUTHOR INTEGER,
AUTHORNAME VARCHAR(50),
ARTICLE INTEGER
);
CREATE TABLE TAG (
ID INTEGER NOT NULL,
IDENT VARCHAR(80),
OCCURENCE BIGINT,
CREATEDAT BIGINT
);
/******************************************************************************/
/**** Unique Constraints ****/
/******************************************************************************/
ALTER TABLE AUTHOR ADD UNIQUE (LOGONNAME);
/******************************************************************************/
/**** Primary Keys ****/
/******************************************************************************/
ALTER TABLE ARTICLE ADD PRIMARY KEY (ID);
ALTER TABLE ARTICLESEARCH ADD PRIMARY KEY (ID);
ALTER TABLE AUTHOR ADD PRIMARY KEY (ID);
ALTER TABLE BLOGINFO ADD PRIMARY KEY (ID);
ALTER TABLE COMMENT ADD PRIMARY KEY (ID);
ALTER TABLE TAG ADD PRIMARY KEY (ID);
/******************************************************************************/
/**** Indices ****/
/******************************************************************************/
CREATE INDEX NDXARTICLEAUTHOR ON ARTICLE (AUTHOR);
CREATE UNIQUE DESCENDING INDEX NDXARTICLEID ON ARTICLE (ID);
CREATE INDEX NDXARTICLEPUBLISHEDMONTH ON ARTICLE (PUBLISHEDMONTH);
CREATE UNIQUE DESCENDING INDEX NDXARTICLESEARCHID ON ARTICLESEARCH (ID);
CREATE UNIQUE DESCENDING INDEX NDXAUTHORID ON AUTHOR (ID);
CREATE UNIQUE DESCENDING INDEX NDXBLOGINFOID ON BLOGINFO (ID);
CREATE INDEX NDXCOMMENTARTICLE ON COMMENT (ARTICLE);
CREATE INDEX NDXCOMMENTAUTHOR ON COMMENT (AUTHOR);
CREATE UNIQUE DESCENDING INDEX NDXCOMMENTID ON COMMENT (ID);
CREATE UNIQUE DESCENDING INDEX NDXTAGID ON TAG (ID);
I noticed that TITLE and CONTENT in COMMENT can not be a number, because throwing an error.
Michal
Last edited by miab3 (2014-10-31 11:01:58)
Offline
@ab
Yes, but it would be safer if they did not cause an error.
Why it happens?
Michal
Offline
@ab
If you type the text look much like a number, eg. 123 in TITLE or CONTENT field,
after Add Comment error is generated.
(It's about 30 - MVC Server)
Error Page
Low-level #500 Error occurred with the following message:
HTTP Error 500 - Internal Server Error
The following Exception did occur:
EMVCException raised in TMVCRendererFromViews.ExecuteCommand: TMVCRendererFromViews.CommandRunMethod: IBlogApplication.ArticleComment() execution error
Error context:
{
"main": {
"pageName": "ArticleComment",
"blog": {
"Title": "mORMot BLOG",
"Language": "en",
"Description": "Sample Blog Web Application using Synopse mORMot MVC",
"Copyright": "©2014 <a href=http://synopse.info>Synopse Informatique</a>",
"About": "Bla? Ble, bla ble, bli bla ble blu ble. Blo blu. Bla ble, blu bla blu blu bli blu blu bla, bli blo blo blo bli bli blu blo.\r\nBlo bla!"
},
"session": {
"AuthorName": "synopse",
"AuthorID": 1,
"AuthorRights": {
"canComment": true,
"canPost": true,
"canDelete": true,
"canAdministrate": true
},
"id": 1
},
...
Michal
Last edited by miab3 (2014-10-31 12:12:02)
Offline
Yes, the interface execution routine was very strict about incoming values.
I've allowed this case.
See http://synopse.info/fossil/info/4cf6a8959e
Thanks for the feedback - I never observed that!
Offline
@ab
Thanks.
Well, now it works.
Now you can type numerical poppycock.
Michal
Last edited by miab3 (2014-10-31 13:11:10)
Offline
Pages: 1