#51 Re: mORMot 1 » Demo application + some question / remarks. » 2011-02-16 10:49:19

if you have google account I'll let you commit the code ... just give me your uname wink

#52 Re: mORMot 1 » Demo application + some question / remarks. » 2011-02-16 07:35:43

Yup, still on google code, I don't plan to switch the hosting, I find google code perfect for such small code pieces. Btw if you don't cleanup .svn subdirectory, everyone will be able to update the code wink

but please, have a look at the code before including it, last thing I'd like to do is to provide people with example showing incorrect approach!

#53 Re: mORMot 1 » Demo application + some question / remarks. » 2011-02-15 18:23:48

Hi,
I've been very busy for quite a long time but now I'm back.
I believe the demo app is complete enough to give an overall view on how to start with SQLite Framework.
Would you like to review the current code and possibly include it to the Synopse SQLite FW demos?

#54 mORMot 1 » TSQLCache missing » 2011-02-02 11:28:19

migajek
Replies: 1

Hi,
today I've downloaded most current leaf (0088bc5396) and it seems to be missing TSQLCache class ...
Searching through the files points only two of them, SQLite3 and SQLite3Commons.

The SQLite3.pas tries to make use of that class, but in SQLite3Commons it is not declared, just mentioned in documentations comment.

#55 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-05 17:02:46

ab wrote:

TSQLRecord.ID reader has now a GetID() getter which can handle the fact that a published property declared as TSQLRecord (sftID type) contains not a true TSQLRecord instance, but the ID of this record: you can use aProperty.ID method in order to get the idea - but prefered method is to typecast it via PtrInt(aProperty), because GetID() relies on some low-level windows memory mapping trick.

So you can use aDest.ID to retrieve the ID - even if PtrInt(aDest) will be a bit faster, and will always work.

ok, now I'm confused sad I have no idea how is that supposed to work, except that in my case (HasRole) Dest is always integer ID of Dest record ... could you give some code examples?

Thanks for your feedback. I think it really helps the ORM to be easier to use. smile

I'm glad you like it, and thanks for introducing them smile

#56 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-04 23:36:20

ab wrote:
migajek wrote:

to be honest, RealDest came to my mind as opposite to Dest which (for me) was not Dest at all (just it's id) ]:->

What about "DestTempInstance" or "DestLocalInstance", since "Real" is some kind of floating-point type in Delphi?
Another direction could be "OwnedDest", since the TSQLRecordMany would be the owner of this intance.

It's completely up to you smile None of them is perfect, none of them is most intuitive, but we don't have better option, since "Dest" is taken already ... or maybe rename Dest to DestID, and call the new one just Dest? smile

#57 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-04 11:52:56

ab wrote:

Now I understand your proposal.

But in all cases, you'll need to have a type explicit conversion like TSQLADest(RealDest) before using it.

Typecasting is not a problem, since you define Dest type anyway, you're also certain about RealDest type.

Or I could use the same method as in TSQLRecordMany.Create... that is, if a "RealDest" property exists, it will instantiate an instance of it.
In this case, the fRealDest will have to be defined during the class definition, not at the TSQLRecord level, to avoid writing such cryptic TSQLADest(RealDest)...

it is up to you, whether you want us to define more fields in TSQLRecordMany, thus avoiding typecasts when using, or to use typecast each time smile

Perhaps it could make sense to name it "TempDest" or "FillManyDest" or "LocalDest". I don't know...

perhaps ... to be honest, RealDest came to my mind as opposite to Dest which (for me) was not Dest at all (just it's id) ]:->

#58 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-04 10:25:08

ab wrote:

Can you post some use code?

I don't get the exact idea here.
Is it just to avoid a aDest.Free call, and a try..finally block?

in case of FillMany - it doesn't make much sense, indeed. But would it be possible to fill both TSQLRecordMany and it's fRealDest (proposed above) with the result of DestGetJoinedTable? It'd allow using both data sources (pivot & dest table) in pure ORM way, with just one query only ...

#59 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-03 23:07:03

I think loading per-request could be a good idea to avoid recursion and other problems.
How about implementing a method "GetDest" or something similar:

pseudocode:

function TSQLRecordMany.GetDest: TSQLRecord;
if fRealDest = nil then
 begin
  fRealDest:= TDestClassType.NewInstance();
  fRealDest.Create(fDestId);
 end;
result:= fRealDest;
end;

of course, TSQLRecordMany will have to take care of freeing the "fRealDest" object on each FillOne and on destroy ...

#60 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-03 14:52:41

ab wrote:

All internal parameters will be taken from the Source and Dest properties of the TSQLRecordMany instance.

Indeed.
Unfortunately I must admit current way of accessing Dest / Source records is very misleading. I know it's necessary to tell the TSQLRecordMany Dest/Source ClassType, but it's confusing that the published field of type TSQLDest is in fact it's id, and - prior to accessing - needs to be casted as integer for actual TSQLDest creation...
see http://code.google.com/p/synopse-sqlite … n8&r=8#204

#61 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-03 14:26:52

How about some method executing

SELECT r.*,  p.* FROM UserRoles p JOIN UserRole r ON p.Dest = r.ID WHERE p.Source = %

on UserRoles (TSQLRecordMany)?

That way it'd be possible to fill both the TSQLRecordMany and it's Dest with proper data, using one query only.

Oh, btw - what has happened to
"constructor TSQLRecordMany.Create(aSourceClass: TSQLRecordClass; aSourceID: integer);" ?

#62 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-03 11:21:48

ab wrote:
     ! TSQLDestPivot = class(TSQLRecordMany)
     ! published
     !   property Source: TSQLSource read fSource; // map Source column
     !   property Dest: TSQLDest read fDest; // map Dest column

I'm sorry but I don't really get it ... the code you shown won't work, since there's no "fSource" field.
Declaring own fSource: TSQLSource (and fDest: TSQLDest, respectively) will compile, but I don't know how to retrieve the actual Dest / Source records ... The fSourceID / fDestID are nil after each FillOne ... ?

#63 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-03 10:48:17

ab wrote:

No, wrong guess: you can make an additional condition to the Pivot Table, since both the Pivot and the Dest tables are available. Just use 'PivotTableName.Field=value' syntax.

I know all the fields are available inside of query condition, but the only selected data is ID of Dest [which is obvious]. I don't however know the ID of pivot record, thus making it impossible to access ValidUntil field (in my example). Compare the code you have posted in post #11 ( http://synopse.info/forum/viewtopic.php?id=164#p866) and the current (r7) HasRole implementation.
http://code.google.com/p/synopse-sqlite … n7&r=7#189
I know it could be achieved by adding "UserRoles.ValidUntil >= date('now')" to select valid roles, but ... I want the ID of UserRoles record anyway, even when it has expired.

I don't get exactly your point here.

I was referring to the method described above.
So far I could either iterate pivot table one-by-one (User.Roles.FillMany, User.Roles.FillOne], thus having access both to the pivot's additional data stored [directly, via User.Roles.ValidUntil] and the actual record [Database.Retrieve(User.Roles.Dest)] - which is a bit inconvenient because I need to store & free later retrieved Dest record.
The second method was to call DestGet / DestGetJoined, but I had no access to the pivot data (ValidUntil).

Thus, if I need to DISPLAY [access via Delphi code] both UserRole.name AND UserRoles.ValidUntil, I had to use first method ... wink

#64 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-02 22:55:51

ab wrote:

About MOD() and performance, it won't be an issue.

The SQL request will get first, using the Index, getting all matches for the source ID. Very fast.
There will be as many response as there was a ManyAdd() call for this source ID. A very small list.
In this small list, the MOD() will be performed quite instantaneously (with SQLite3, it's a very fast integer operation).

good point smile Indeed, I was just looking at the second condition and all I heard about query optimization & functions in conditions came to my mind wink

The TRecordReference sounded to me like a powerful solution. But TSQLRecord could be clearer... worth looking at it tonight!

pointing the record directly would be much more consistent as for me wink
Currently, if I need to access additional data stored in pivot table, it's a bit tricky ...
see TForm1.lbUsersClick from my demo (fresh r7 available at svn wink )


Using DestGetJoined is very convenient but doesn't allow access to Pivot Table data (am I correct here?).

I could have used FillMany & iterate each Pivot Record, retrieve the data I needed there, than call db.Retrieve to access the actual Dest / Source record, free the accessed dest / source record, free Pivot Record after iteration finished.
That would be so much more convenient to call pivotRecord.Dest.Something ... directly smile

Also, that way we'll avoid mess in database. Referencing by record ID is most clear, allows to share the database to other systems, simplifies writing sql queries (especially JOINs on pivot table wink ) etc

#65 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-02 16:41:47

What is the purpose of DestGetJoined if that methods selects IDs only anyway?

So, in case of FillMany we do the following ->
SELECT FROM PivotTable WHERE source = .. AND MOD(dest, 64) = ...

than, once we have both RecordReferences we do SELECTs to find more data ...

While DestGetJoined selects list of ID's and then does id-based SELECTing, am I right?

if that eliminates usage of MOD(dest, 64) in WHERE clause than I like it smile I guess that might be a little bottleneck since I don't think indexes will be used when WHERE contains a function call?

By the way, there should be overloaded DestGetJoined wink

similar to that:

function TSQLRecordMany.DestGetJoined(aClient: TSQLRestClient;
  out DestIDs: TIntegerDynArray): boolean; 
begin
result:= DestGetJoined(aClient, '', fSourceID, DestIDs);
end;

wink

// -- edit
Oh, as I can see, DestGetJoined doesn't accept empty WHERE clause... but WHY? Do I have to add ' 1 = 1 ' if I want to list each associated record? Wouldn't it be smarter to do:

if aSQL <> '' then
 aSQL := ' AND ' + aSQL;

and later insert it as the last statement of the query? smile

also, it's a bit strange but ...

that works fine:

ACustomer.Tasks.DestGetJoined(Database, '1 = 1', ACustomer.ID, fIds); //debugger says: ACustomer.ID = 3

but if I pass 0 as sourceID, the auto retrieving fails. debugger says that fSourceID = 0, so it fails on the second "if aSourceID = 0" check in DestGetJoined ...

#66 Re: mORMot 1 » Latest source doesn't compile under D7 [2010-12-01 13:35:59] » 2010-12-02 12:15:28

Indeed, downloading lates commit & dropping unit cache solved that smile

#67 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-02 12:03:55

Thank you smile

I'll take a look at your sample application source.

I can't wait to know what I'm doing wrong smile

What bothers me now ... why doesn't TSQLRecord keep it's TSQLRest object once passed in constructor? Have a look at TUser.HasRole implementation ... I need to pass the connection reference all the time. I know I could use global variable, but ... why? wink

#68 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-01 21:46:44

Hi,
while working on the user access control functionality for the demo app (see latest commit on google code) I have one more idea.
to iterate record list, I need to do following
* obtain & store result of MultiFieldValues
* call FillPrepare
* while FillOne do ...
* free result of MultiFieldValues

now, how about one or two more overloaded constructors, first would take only one argument, TSQLRest. It would do all the above "preparing" operations, but take care of freeing result as well. That way user will end up with the code:

var 
 rec: TRecord;
begin
 rec:= TRecord.Create(Database);
 while rec.FillOne do
 /.. /
 rec.free;
end;

I find it much more convenient, since it is quite commonly used feature (actually the idea is copied from Yii [PHP framework] ORM)

The second idea (of second constructor) would be similar, except that instead of selecting all the records, one would specify the "WHERE" clause (which records to select).



And, one more question ... could you be please so kind to do quick review of the demo, mostly uCustomer, to see what design mistakes I did? So far I have had no experience with serious "native" application databasing (in contrary to PHP based development). The approach of Synopse SQLite FW is significantly different in some parts comparing to those PHP-based ORMs I know, thus I'd like to follow your design the very best way.

#69 mORMot 1 » Latest source doesn't compile under D7 [2010-12-01 13:35:59] » 2010-12-01 18:57:23

migajek
Replies: 2

I've downloaded latest source ( http://synopse.info/fossil/info/7ed35b947a ) and it doesn't compile under D7.

Build
  [Error] SQLite3Commons.pas(5165): Undeclared identifier: 'Iso8601ToDateTimePUTF8Char'
  [Error] SQLite3Commons.pas(6782): Undeclared identifier: 'DateToIso8601PChar'
  [Error] SQLite3Commons.pas(6792): Undeclared identifier: 'TimeToIso8601PChar'
  [Error] SQLite3Commons.pas(7020): Undeclared identifier: 'Iso8601ToDateTime'
  [Error] SQLite3Commons.pas(7024): Undeclared identifier: 'DateToIso8601'
  [Error] SQLite3Commons.pas(7026): Undeclared identifier: 'TimeToIso8601'
  [Error] SQLite3Commons.pas(7027): Undeclared identifier: 'DateTimeToIso8601'
  [Error] SQLite3Commons.pas(7193): Undeclared identifier: 'DateToIso8601'
  [Error] SQLite3Commons.pas(7195): Undeclared identifier: 'TimeToIso8601'
  [Error] SQLite3Commons.pas(7196): Undeclared identifier: 'DateTimeToIso8601'
  [Error] SQLite3Commons.pas(7331): Undeclared identifier: 'Iso8601ToDateTimePUTF8Char'
  [Error] SQLite3Commons.pas(12470): Undeclared identifier: 'DateToIso8601PChar'
  [Error] SQLite3Commons.pas(12471): Undeclared identifier: 'TimeToIso8601PChar'
  [Error] SQLite3Commons.pas(12876): Undeclared identifier: 'DateTimeToIso8601'
  [Error] SQLite3Commons.pas(12877): Undeclared identifier: 'Iso8601ToDateTime'
  [Error] SQLite3Commons.pas(12887): Undeclared identifier: 'TimeToIso8601'
  [Error] SQLite3Commons.pas(12889): Undeclared identifier: 'DateToIso8601'
  [Error] SQLite3Commons.pas(12961): Undeclared identifier: 'DateTimeToIso8601'
  [Fatal Error] Unit1.pas(20): Could not compile used unit 'SQLite3Commons.pas'

#70 Re: mORMot 1 » RecordRef purpose, instead of ID in pivot table » 2010-12-01 16:47:53

Did I understood correctly, that in the case of RecordRef I can actually have one single table for all the possible combination of "connections" between records?
Is RecordRef kind of hash of record ID and record table (class type)?

Thanks,
m.

#71 Re: mORMot 1 » Will the SQLite3UI units set become TMS-independent? » 2010-12-01 16:32:32

Currently it is available in SVN only, at the

http://code.google.com/p/synopse-sqlite-demo/

but I'll upload the zip archive in 15 minutes wink

#72 mORMot 1 » RecordRef purpose, instead of ID in pivot table » 2010-12-01 15:00:11

migajek
Replies: 3

Hi,
I don't really get the idea of keeping RecordReference which is a strange computed number, instead of simply record's ID in the pivot table?
What are advantages for internal design?
Cause for me it's only trouble, when I want to do some JOIN's in pure SQL I simply can't sad Should I keep record's ids on my own for that case?

#73 Re: mORMot 1 » Close future of the framework: database agnosticism » 2010-12-01 14:43:09

Hi,
may I ask you what is the progress of integrating ZDBC to the Framework? smile

#74 Re: mORMot 1 » Will the SQLite3UI units set become TMS-independent? » 2010-12-01 14:25:48

ab wrote:

The framework uses Iso8601 instead of TDateTime because it's much faster, and SQLite3 likes better Int64 values than double values.

thanks, my bad wink

#75 Re: mORMot 1 » Will the SQLite3UI units set become TMS-independent? » 2010-12-01 14:11:50

Hi,
indeed that was a bit unclear - since the demo 02 used the server directly. Unfortunately I'm the kind of guy who looks at the examples first, than refers to the documentations when needs to clarify something wink

I've changed the code to follow the correct pattern.

Also, the demo shows TSQLTableToGrid as well now smile

BTW please have a look at line 402 of current revision (r4). In my case, using the Iso8601Now instead of Now, causes "Invalid floating point operation", pointing the method

procedure DateToIso8601PChar(Date: TDateTime; P: PUTF8Char; Expanded: boolean); overload;
// we use YYYYMMDD date format
var Y,M,D: word;
begin
  DecodeDate(Date,Y,M,D);
  DateToIso8601PChar(P,Expanded,Y,M,D); // <-- debugger points that line.
end;

#76 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-01 13:37:40

ab wrote:

IMHO MayAdd will fail to work, because both n.ID=0 and n.fSourceID=0.

that's what I meant wink

In such case, you'll have to use the overloaded methods with a Source ID parameter.

What I thought of was a list of "not-yet-saved" related DestID's -> filled with data in case ManyAdd is called when fSourceID = 0.

"if user adds some elements to related list, but I'm not saved (so I dont have ID), keep the list of related IDs and add them to pivot table as soon as I'm assigned with ID (I'm saved for the first time)"

I've added some comments to warn about such problems.

that is definitely very important in current situation, since there's no need to pass SourceID, one may not be aware that he shouldn't add related until the source object is saved.

#77 Re: mORMot 1 » Will the SQLite3UI units set become TMS-independent? » 2010-12-01 10:41:57

ab wrote:

The Demo application idea is great!

What about using our Grid component?
It's not bundled to the TMS software, and it's definitively powerful.

See http://synopse.info/forum/viewtopic.php?pid=644#p644

Worth showing it in the demo, IMHO.

Hi,
indeed, so far I haven't played with UI classes at all, I just thought all of them depend on TMS.
As I can see, the TSQLTableToGrid can't use TSQLRestServerDB directly, I had to export it via named pipe and than create a client - just for TSQLTableGrid to access it. Is that really necessary?
Anyway, it's definitely worth showing but I won't commit it unless you tell me why does it require the URIClient to be created & used wink smile

#78 Re: mORMot 1 » Demo application + some question / remarks. » 2010-12-01 10:13:16

Hi,
I'm glad you like the demo and the ideas I had smile Thank you for implementing them! smile

one more remark / question / warning for ManyAdd.

Let's say I want to add some related to the newly created record, and I do so before I save the source record.
Pseudo coude:
n = NewRecord;
n.ManyAdd(task1);
n.ManyAdd(task2);
Database.Add(n);

I'm pretty sure this will cause "pivot" records to contain invalid source IDs, since they were assigned before the NewRecord had an ID assigned?

If so, how about solving it by keeping list of "dest" ids to be added when saved? Like that:
pseudocode:

ManyAdd();
begin

if fSourceId <= 0 then
fDestIDs.Add(fDestID);
else
// ... do the standard operations
end;

now when TSQLRecordMany is notified that the "owner" record has been just saved, assign the fSourceID and iterate fDestsIDs list adding each ID by standard ManyAdd?

#79 Re: mORMot 1 » Will the SQLite3UI units set become TMS-independent? » 2010-11-30 16:58:43

Hi,
I thought you're main point against native TToolBar & TTabSet is a poor look of those old components. SpTBXLib provides skinning support for TB2K (but not only, of course).
Anyway, I'd love to see the code which compiles under old Delphi with no dependencies on commercial component sets smile

#80 mORMot 1 » Demo application + some question / remarks. » 2010-11-30 16:56:55

migajek
Replies: 59

Hi,
I decided to build a very trivial yet closer to real life demo of SQLite3 Framework. The main reason behind this decision was to learn the Framework a bit smile
Currently the application is just a list of Customers with Tasks assigned to them (the relation type is "HAS MANY AND BELONGS TO MANY"). In my case, TCustomer publishes TTasks list.

I've also decided to share the code in hope that if anybody knows the better way for solving any of the "tasks", he might edit & share.
The code is available at http://code.google.com/p/synopse-sqlite-demo/


Now, during the development I had first contact with relations implementation. Probably some of the remarks are caused by mine poor knowledge of framework, in that case I hope you'll correct me and point the proper way smile

1. is that really necessary to specify SourceID each time I access "Dests" list?

 cust.Tasks.ManyAdd(Database, cust.ID, task.ID, true)

if Tasks (the TSQLRecordMany) is created & owned by TCustomer (TSQLRecord), why can't it access the owner's ID by itself? It would be more consistent, since the manner is following: SomeObject->ListOfItsRelatives->AddRelative
The same applies to others Many* methods.
Of course, keeping the overloaded versions which takes SourceID argument is a very good idea.

2. Let's say I have a Task and want to retrieve all it's clients. Currently I'm doing it by:
  * creating TCustomer instance
  * loading list of "Source" id's by specifying task.id as DestID.
  * iterating the id's one-by-one in "for" loop

First of all, why can't I create TTasks directly? Actually, I can -> but since it doesn't have an owner, calling SourceGet fails (IDWhereSQL returns empty string). That way it doesn't seem consistent at first look...
Moreover, I'd love to see FillSource method - equivalent of FillMany smile

3. why doesn't TSQLRecordMany publish "Source" and "Dest" fields? If they are declared in TSQLRecordMany, creating own "pivot" record becomes as simple as

type TTasks = class(TSQLRecordMany; 
published
property Dest;
property Source;

I believe in 99% of cases, user-declared code will call fDest and fSource respectively anyway.

#81 Re: mORMot 1 » Will the SQLite3UI units set become TMS-independent? » 2010-11-30 11:30:57

My main development environment for all the "private" (hobby) projects is Delphi 7 (Personal edition!) ..
That makes Synopse SQLite3 most complete and powerful DB framework available smile Of course I'm fully aware that I'm in minority, and I'll have to switch to more recent Delphi version one day.

Besides that, personally I don't like ribbon idea at all. I hate using Office 2007 just because it has ribbon instead of menus & toolbars. I don't get the idea of Ribbon, and don't know any advantages over menus & toolbars, except for bigger icons in Ribbon wink

Have you considered optional dependency on SpTBXLib which is a mature, customizable, attractive-looking MPL-licensed set of menu & toolbars components (based on Toolbar2000)?

#82 mORMot 1 » Will the SQLite3UI units set become TMS-independent? » 2010-11-29 21:27:23

migajek
Replies: 13

Hi,
I like the idea of SQLite3UI units, but what I dislike about them is their dependency on TMS components. It's a pity that there's no possibility to use them without those commercial externals...
Is there any plan for some alternatives?

Thanks,
m.

#83 Re: mORMot 1 » SQLite and multi-threading » 2010-10-05 22:56:47

ab wrote:

The Synchronize is not necessary at all.
All high-level methods of the framework are thread-safe.

Thank you.

Would you be so kind to explain me how is it done? wink So far I thought that any operation done on "shared" object (common for multiple threads) must be protected with "synchronize", no matter what. Apparently, I was wrong - in your code I found CriticalSection to be used in SQLite wrapper, but not SQLite3Commons at all. What is the difference, why isn't for example TSQLRestServerDB "protected" (locked) with CriticalSection?

How do I find what parts / methods of my code needs to be protected with CriticalSection and which not?

So far I haven't stumbled upon any interesting explanation / article / blog note, all google results are:

a) examples of synchronization between thread and the GUI. From simple progressbar to most complex, but still the topic is quite simple and obvious: each time you access / modify the property of GUI component, do that in "Synchronize"
b) articles explaining Critical Sections, Mutexes etc.
c) Examples of very very simple thread-safe classes (thread safe stack or list) - they all do the same - implement lock / unlock methods which do enter/leave critical section and return the actual stack/list pointer on locking.

Could you please provide me with a good reference to read which parts of code should be protected? smile

thank you!

#84 Re: mORMot 1 » SQLite and multi-threading » 2010-10-04 12:58:22

Does it mean I can do the following:

// Database is a global object
procedure TMyThread.Execute; 
begin
Database.Add(TSQLSampleRecord.Create(), true);
end;

or should I still have it synchronized:

// Database is a global object
procedure TMyThread.AddEmpty;
begin
Database.Add(TSQLSampleRecord.Create(), true);
end;

procedure TMyThread.Execute; 
begin
Synchronize(AddEmpty);
end;

#85 Re: mORMot 1 » Selecting multiple records? » 2010-10-04 12:51:40

Actually, I was looking for a way to get an array / list of TSQLRecord descendent ...
The MultiFieldValues returns a TSQLTableJSON which has all the data, but does it "wrap" the data in TSQLRecord descendents?

#86 mORMot 1 » Selecting multiple records? » 2010-10-03 09:38:23

migajek
Replies: 3

Hi,
once again very lame question but couldn't find it, it seems no sample apps shows this, and MainDemo doesn't compile for me since I don't have TMS controls pack.

How do I select multiple records? Let's say I want to list all the records in table using WHERE,
do I have to use Database.OneFieldValues, than use the array of ID's to create model with given ID? In that case, how do I find column name of unique ID field generated for my model (/record)? I've seen you were using 'ID' as a column name somewhere in this forums, but in sample DB it seems to be 'RowID' (unfortunately, Database.OneFieldValues(TSQLSampleRecord, 'RowID', '', arr) gives an empty array, yet there are some records in that DB).

If that is the only way, isn't it killing the performance? Don't know how about SQLite, but from my experience with MySQL + PHP, it's much much faster to select a thousand records using " SELECT * ... LIMIT 1000" than to do a loop and select one by one.

#87 Re: mORMot 1 » SQLite and multi-threading » 2010-10-03 09:28:58

Hi,
what I understood is that there are following methods of accessing DB:

  • HTTP

  • FastCGI

  • NamedPipes

  • Direct access

Are all of them thread-safe?

Which of these methods consumes less memory / CPU? My application is not a typical DB app, it's rather very uncommon to use ORM / SQL in such an application, but since it has rich GUI, it already uses quite a lot of memory ... and I'd like to avoid much more consumption.

I have two threads in my app:
main thread (obvious)
background worker thread

while the background worker thread keeps updating DB when necessary (it might be quite intense sometimes) with DELETE / UPDATE / INSERT queries, the main thread might want to do SELECT from time to time. The most crucial is SELECT time (it has to have highest priority) because I want to avoid UI from freezing (actually the SELECT itself is not a big deal, currently it is very poorly written, instead of SQLite it does three nested iterations and lots of slow string comparisons for building data list, so the only possible scenario for UI freeze would be waiting for Critical Section unlock).

Now, should I rely on client-server architecture (correct me if I'm wrong, but this would require me to use HTTP, FastCGI or Named Pipes?) to create a server in main thread, than use two clients -> one for main thread, and the second created in background worker? Under this scenario I don't have to care about synchronization, do I?

The second option would be using Direct access (create TSQLRestServerDB, than access it from both threads), but in that case I'd need to handle synchronization on my own, right?

#88 mORMot 1 » Many to many / one to many relations handling? » 2010-10-02 13:21:56

migajek
Replies: 2

Hi,
is there any example of handling one to many (has/belongs) and many to many relations?

thanks,
migajek

#89 mORMot 1 » SQLite and multi-threading » 2010-10-01 10:21:56

migajek
Replies: 8

Hi,
I'm using SQLite3 (although not your 'version' yet, just some old dll bindings for pascal). Since I'm about to start rebuilding the part of application which uses SQLite, I'd like to incorporate your 'version' of SQLite for Delphi, mostly because it doesn't require external DLL and it should be faster (using FastMM memory manager).
I ended up with messy code which uses your low-level headers (functions & types declaration) and a simple wrapper for SQLite which I used previously.

Now, my question is - does your implementation support multithreading? Please excuse me that question but the amount of code released as Synopse SQLite Framework is astonishing, but - unfortunately - making it very hard to find the answer wink

I'd also like to ask you for advice for my case - I'm building an application which parses lots of data and needs to keep them in SQLite database, than sometimes do SELECT on them or UPDATE, but from different threads. Thats why I'm asking for multithreading wink Is there any other interface to communicate with your framework than JSON format and plain SQL queries? Like, some wrappers for executing queries? Or some ORM-like native delphi objects?

I'd love to use the framework, yet avoiding time needed for generating and parsing JSON data on both "sides" since it is completely unnecessary in that case (as I don't need to send it over the network, nor between applications...)

Thanks in advance!

Board footer

Powered by FluxBB