Recent

Author Topic: [SOLVED] Two DBGrids showing the same content  (Read 11565 times)

Gizmo

  • Hero Member
  • *****
  • Posts: 831
[SOLVED] Two DBGrids showing the same content
« on: September 26, 2017, 06:17:04 pm »
I don't know if this is an obvious question or not. I'm hoping someone can set me straight.

I'm making great progress converting my program from StringGrids to SQLIte and DBGrids. However, as some of you know, I've hit a few hurdles on the way that you have helped me with. My latest one is this :

My program has two forms. I have a DBGrid instance in each form. When the user presses a button in one form, one table of the SQLite DB is populated with data and then displayed in DBGrid1 in Form1.

When the user presses another button in another form, another different table of the same SQLite DB is populated with data as well (different data) and then displayed in DBGrid2 in Form2.

However, if the user then goes from Form2 back to Form1, the data that was shown in DBGrid2 is ALSO shown in DBGrid1. In other words, the initial display of data from button press one has been replaced with the display of data from button 2.

I'm guessing this is something to do with the whole initial setup of the initial database components (SQLQuery1, SQLTransaction1, DataSource1 and SQLIte3Connection1) which I have copied fairly blindly I admit without fully understanding how they all interlink.

Could one of you tell me where I am going wrong? Two example routines are below which give you the gist I hope. The problem is then replicated throughout most of my other routines.

Code: Pascal  [Select][+][-]
  1. // MainForm has one DBGrid in it
  2. procedure TfrmSQLiteDBases.UpdateGridFILES(Sender: TObject);
  3.   begin
  4.     try
  5.     SQLQuery1.Close;
  6.     SQLQuery1.SQL.Text := 'SELECT * FROM TBL_FILES';
  7.     SQLite3Connection1.Connected := True;
  8.     SQLTransaction1.Active := True;
  9.     SQLQuery1.Open;
  10.  
  11.     // Allow the DBGrid to view the results of our query
  12.     DataSource1.DataSet := SQLQuery1;
  13.     MainForm.RecursiveDisplayGrid1.DataSource := DataSource1;
  14.     MainForm.RecursiveDisplayGrid1.AutoFillColumns := true;
  15.     except
  16.     on E: EDatabaseError do
  17.     begin
  18.       MessageDlg('Error','A database error has occurred. Technical error message: ' + E.Message,mtError,[mbOK],0);
  19.     end;
  20.   end;
  21. end;
  22.  
  23. // frmDisplayGrid1 is the second form that shows different data.
  24. // After execution of this, the results also appear in MainForm.RecursiveDisplayGrid1
  25. procedure TfrmSQLiteDBases.UpdateGridCOPYTAB(Sender: TObject);
  26.   begin
  27.     try
  28.     SQLQuery1.Close;
  29.     SQLQuery1.SQL.Text := 'SELECT * FROM TBL_COPY';
  30.     SQLite3Connection1.Connected := True;
  31.     SQLTransaction1.Active := True;
  32.     SQLQuery1.Open;
  33.  
  34.     // Allow the DBGrid to view the results of our query
  35.     DataSource1.DataSet := SQLQuery1;
  36.     frmDisplayGrid1.RecursiveDisplayGrid_COPY.DataSource := DataSource1;
  37.     frmDisplayGrid1.RecursiveDisplayGrid_COPY.AutoFillColumns := true;
  38.     except
  39.     on E: EDatabaseError do
  40.     begin
  41.       MessageDlg('Error','A database error has occurred. Technical error message: ' + E.Message,mtError,[mbOK],0);
  42.     end;
  43.   end;
  44. end;    
  45.  
 
« Last Edit: October 03, 2017, 02:15:44 pm by Gizmo »

GAN

  • Sr. Member
  • ****
  • Posts: 370
Re: Two DBGrids showing the same content
« Reply #1 on: September 26, 2017, 09:24:33 pm »
Hi, the problem may be that you are using the same DataSource1in both grids and querys.
Lazarus 2.0.8 FPC 3.0.4 Linux Mint Mate 19.3
Zeos 7̶.̶2̶.̶6̶ 7.1.3a-stable - Sqlite 3.32.3 - LazReport

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Two DBGrids showing the same content
« Reply #2 on: September 26, 2017, 10:19:58 pm »
a bit of background info on the controls.
sqlquery: it communicates with the data server executes commands and retrieves responses that then keeps in the client's memory. when you  deactivate the control (sqlquery1.Active := false or sqlquery1.close, same thing) the control frees the data retrieved from the server and returns the memory to the application for farther use.

TField : holds the definition of a field, its size, type etc, this information is used by the TQuery control to decode the data send from the server and find and manage the value of a field.

TDatasource: sits between the dataset (tSQLquery, tzquery, some other dataset/framework) this enables you to change the underline database completely including the framework from SQLDB to zeos data objects to IBX or anything you like with out touching the GUI part of your application it usually reside on the same form/frame as the GUI it serves.

TConnection : The communication layer between dataset and data server, tcp/ip, disk, mail shots, compression, json, IPC etc, everything is usually encoded/decoded here and then given to the dataset as complete records ready to be processed.

Data aware controls dbgrid, dbedits etc. Those use a simple interface to communicate with the dataset (through the tdatasource), get the values, get informed when the data have changed for any reason, set values etc.

Keep in mind that dataset allows only a single record to be active at any given time it can buffer multiple records internally but it only allows access to a single record.

That should clear any misunderstandings you might have if not then ask more questions if yes then answer me this. Is the observed behaviour expected or not and why?
« Last Edit: September 26, 2017, 10:23:12 pm by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Gizmo

  • Hero Member
  • *****
  • Posts: 831
Re: Two DBGrids showing the same content
« Reply #3 on: September 27, 2017, 11:30:30 am »
Thanks Taaz for the insight, which is perhaps the most detailed I've read so far. But, alas, I am still confused. 

Quote
That should clear any misunderstandings you might have if not then ask more questions
Sorry!

I'm guessing then the two key elements here are the DataSource, which you say should be one per form, and I guess the SQLQuery?

So I tried creating a secondary Datasource that I linked to the same SQLite3Connection and a secondary SQLQuery instance that I linked to the Datasource. I then I adjusted my code for all the routines that involved my second database table (TBL_COPY) to use the second SQLQuery and Datasource. The result then was an empty grid in the second form :-(

So I guess I'm still not grasping how this all interlinks. Sorry.

In my head, theres a database over there with data in it - several tables full of rows of data. To get that data, you use SELECT statements and to put data in it, you use INSERT statements, which are forumlated by SQLQuery

So then there is the SQQuery which directs what values are retrieved from what parts of the database and what values are put in it, and where.

Then there is an SQLite3Connection, which is a mechanical system for joining the database line to the program - the means in which data is sent to and retrieved from the database.

Then there is the SQLTransaction, which I still don't get.

Then there is the DBGrid which is used to render the result from SQLQuery.Open. So whatever it gets back from the database, it displays in the appropriate grid. So if you have two separate queries and two separate grids, data from the same database can be directed to each I thought (following the replies from you two). But in my test, that has not happened. So either I'm on the right lines and just missed a final step somewhere or I am on the wrong lines! :-(

So then I tried creating a second SQLTransaction. Set the SQLIte3Connection as database. But it generated an error : "cannot start a transaction within a transaction" at one of my other routines (an INSERT procedure, with an SQLQuery.ExecSQL line generates it). So I tried setting the SQLTransaction1.Active to false, and SQLTransaction2.Active := True; but same error :-(

I'm getting very disheartened. I thought implementing SQLIte was supposed to be quite straight forward.

The full code, if it helps people see the wider context of what I am doing, is here : https://github.com/tedsmith/quickhash/blob/v3Branch/dbases_sqlite.pas 

The two procedures below show what I have just tried (which is not committed to GIT).
 
Code: Pascal  [Select][+][-]
  1. // MainForm has one DBGrid in it
  2. procedure TfrmSQLiteDBases.UpdateGridFILES(Sender: TObject);
  3.   begin
  4.     try
  5.     SQLQuery1.Close;
  6.     SQLQuery1.SQL.Text := 'SELECT * FROM TBL_FILES';
  7.     SQLite3Connection1.Connected := True;
  8.     SQLTransaction1.Active := True;
  9.     SQLQuery1.Open;
  10.  
  11.     // Allow the DBGrid to view the results of our query
  12.     DataSource1.DataSet := SQLQuery1;
  13.     MainForm.RecursiveDisplayGrid1.DataSource := DataSource1;
  14.     MainForm.RecursiveDisplayGrid1.AutoFillColumns := true;
  15.     except
  16.     on E: EDatabaseError do
  17.     begin
  18.       MessageDlg('Error','A database error has occurred. Technical error message: ' + E.Message,mtError,[mbOK],0);
  19.     end;
  20.   end;
  21. end;
  22.  
  23. // frmDisplayGrid1 is the second form that shows different data.
  24. // After execution of this, the results also appear in MainForm.RecursiveDisplayGrid1
  25. procedure TfrmSQLiteDBases.UpdateGridCOPYTAB(Sender: TObject);
  26.   begin
  27.     try
  28.     SQLQuery2.Close;
  29.     SQLQuery2.SQL.Text := 'SELECT * FROM TBL_COPY';
  30.     SQLite3Connection1.Connected := True;
  31.     SQLTransaction1.Active := True;  / And tried with a second transaction object, called SQLTransaction2, same problem
  32.     SQLQuery2.Open;
  33.  
  34.     // Allow the DBGrid to view the results of our query
  35.     DataSource2.DataSet := SQLQuery2;
  36.     frmDisplayGrid1.RecursiveDisplayGrid_COPY.DataSource := DataSource2;
  37.     frmDisplayGrid1.RecursiveDisplayGrid_COPY.AutoFillColumns := true;
  38.     except
  39.     on E: EDatabaseError do
  40.     begin
  41.       MessageDlg('Error','A database error has occurred. Technical error message: ' + E.Message,mtError,[mbOK],0);
  42.     end;
  43.   end;
  44. end;    
  45.  
« Last Edit: September 27, 2017, 04:45:43 pm by Gizmo »

Gizmo

  • Hero Member
  • *****
  • Posts: 831
Re: Two DBGrids showing the same content
« Reply #4 on: September 27, 2017, 11:48:31 am »
Taaz...I wish you'd managed to get this diagram in the FPC\Lazarus wiki! It helps a lot. (http://forum.lazarus.freepascal.org/index.php?topic=19431.0) . EXCEPT....SQL3LiteConnection has the property 'Transaction', which you can (and must?) specify to an SQLTransaction object. BUT, you can only choose one SQLTransaction per connection. But your diagram shows two SQLTransactions for one connection?

SQLTransaction1 and SQLTransaction2 can both be set to SQLite3Connection, but SQL3LiteConnection can only have one SQLTransaction. So I am still confused.

(NOTE: Others users struggling...be advised there is a good (but still quite confusing) explanation here http://wiki.freepascal.org/SQLdb_Programming_Reference )

Basically, I have one database with 5 tables in it. My program has 5 tabs in it. Each tab is responsible for putting data in and reading from the corresponding table of the database. So Tab2 = Table2. All I want to achieve is for the data in Tab2 or Tab3 to show the data from the table of Table2 or Table3. As you can see in the screenshot of my database form, I now have two SQLQueries, 2 Transactions, and two datasources with one SQLite3Connection. I'd like all the Components1 for one tab form of my program to deal with TableX, and all the Components2 for the second tab form of my program to deal with TableXX and so on.

And what I really need to find is a really simple (like an explanation for a child) explanation of how these 4 elements all bind together. And how you can use them to query ONE database with SEVERAL tables and have the results of those table queries output to different forms.  This must be what most people do with them, surely?
« Last Edit: September 27, 2017, 04:34:57 pm by Gizmo »

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Two DBGrids showing the same content
« Reply #5 on: September 27, 2017, 05:50:06 pm »
Taaz...I wish you'd managed to get this diagram in the FPC\Lazarus wiki! It helps a lot. (http://forum.lazarus.freepascal.org/index.php?topic=19431.0) . EXCEPT....SQL3LiteConnection has the property 'Transaction', which you can (and must?) specify to an SQLTransaction object. BUT, you can only choose one SQLTransaction per connection. But your diagram shows two SQLTransactions for one connection?

SQLTransaction1 and SQLTransaction2 can both be set to SQLite3Connection, but SQL3LiteConnection can only have one SQLTransaction. So I am still confused.


This is the default transactions it is used when the SQLQuery is not assigned its own transaction only.


(NOTE: Others users struggling...be advised there is a good (but still quite confusing) explanation here http://wiki.freepascal.org/SQLdb_Programming_Reference )

Basically, I have one database with 5 tables in it. My program has 5 tabs in it. Each tab is responsible for putting data in and reading from the corresponding table of the database. So Tab2 = Table2. All I want to achieve is for the data in Tab2 or Tab3 to show the data from the table of Table2 or Table3. As you can see in the screenshot of my database form, I now have two SQLQueries, 2 Transactions, and two datasources with one SQLite3Connection. I'd like all the Components1 for one tab form of my program to deal with TableX, and all the Components2 for the second tab form of my program to deal with TableXX and so on.

And what I really need to find is a really simple (like an explanation for a child) explanation of how these 4 elements all bind together. And how you can use them to query ONE database with SEVERAL tables and have the results of those table queries output to different forms.  This must be what most people do with them, surely?
I think I simplified as much as possible but here goes again.
1) connection talks to the database and pushes packets back and forth as needed.
2) query decodes the packets to records and field values manages the data in memory and raises events that allow data controls to refresh their view when things change
3) transaction used by a query to control when the data changes are pushed to the server and persisted on disk and how (commit, rollaback commitretaining etc)
4)datasource is the bridge between your datacontrol and your query. So instead of hunting down every single data control and change its dataset property to the new dataset you only change the datasource.dataset property and all controls see the new data at once. Maybe a proxy is a better analogy.

Now I have no idea what you do wrong and since I do not have access to a sample to take a part find attached a small sample that can show multiple grids on a form it is not, by any means, a complete demonstration it has its problems and I tried to comment on them in the code but it is a working sample that gives us a base line to expand.

I can't add more details because they are server based for example some servers do not support multiple active transactions on a single connection some do not support nested transactions add isolation levels and what is considered an active transaction might change from server to server and you have a very fluid environment that can't be generalized easily. I have small experience with sqlite my self so there is a moderate time investment in testing each reply before posting.
« Last Edit: September 27, 2017, 05:57:24 pm by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Two DBGrids showing the same content
« Reply #6 on: September 27, 2017, 07:41:08 pm »
The full code, if it helps people see the wider context of what I am doing, is here : https://github.com/tedsmith/quickhash/blob/v3Branch/dbases_sqlite.pas 
erm sorry missed this one I'll download the project and try it, probably tomorrow.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Gizmo

  • Hero Member
  • *****
  • Posts: 831
Re: Two DBGrids showing the same content
« Reply #7 on: September 28, 2017, 12:12:40 am »
Taaz...many many thanks for the demo! I've had a quick look before bed (which was fatal!) but I'll look closer when I have more time. It certainly helps! I need to take some time to see how you have linked those components together. It's certainly more concise than my system.

If you do get time to check out what I've done, I'd very much welcome your guidance. You'll no doubt spot lots of areas to not only fix my issue but probably offer advice on best practice. As I say, I am new to the whole DB interaction so following online guidance fairly blindly.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Two DBGrids showing the same content
« Reply #8 on: September 28, 2017, 04:07:21 am »
Taaz...many many thanks for the demo! I've had a quick look before bed (which was fatal!) but I'll look closer when I have more time. It certainly helps! I need to take some time to see how you have linked those components together. It's certainly more concise than my system.

If you do get time to check out what I've done, I'd very much welcome your guidance. You'll no doubt spot lots of areas to not only fix my issue but probably offer advice on best practice. As I say, I am new to the whole DB interaction so following online guidance fairly blindly.
fatal? you killed a squirel with your screams or something :P
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Gizmo

  • Hero Member
  • *****
  • Posts: 831
Re: Two DBGrids showing the same content
« Reply #9 on: October 02, 2017, 09:03:06 pm »
Ha...I meant because once you start looking at something, before you know it, and hour has passed!

So I've spent some time looking at your example, and excellent as it is, I am still unclear how the same dataconnection is enabling two different grid displays to be active at the same time.

In my project, there are (now) two seemingly independent grids. Grid1 and Grid2.

Grid1 is populated by the result of SQLQuery1.
Grid2 is populated by the result of SQLQuery2.
Both SQLQuerys use SQLTransaction1.
Both SQLQuerys use SQLiteDatabase1.
Both work fine in that they both display their respective content from each query, which is pulling data from two different tables of the same database.

Therefore, why, when I return to DBGrid1 after executing the SQLQuery2 and seeing the result of SQLQuery2 in DBGrid2, do I find the content of DBGrid2 in DBGrid1!? I must be missing something hugely obvious but not obvious to me - you have clearly made it work very well, but I don't see where. It is making no sense to my somewhat limited logic.

In my head, the result of SQLQurey1 that is shown in DBGrid1 should stay there and not change again until SQLQuery1 is executed again. I can't see why or how the execution of SQLQuery2 in DBGrid2 is making DBGrid1 change
« Last Edit: October 02, 2017, 09:06:05 pm by Gizmo »

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Two DBGrids showing the same content
« Reply #10 on: October 02, 2017, 10:08:15 pm »
Ha...I meant because once you start looking at something, before you know it, and hour has passed!

So I've spent some time looking at your example, and excellent as it is, I am still unclear how the same dataconnection is enabling two different grid displays to be active at the same time.
I just downloaded everything from your repository (https://github.com/tedsmith/quickhash/tree/v3Branch). I can see the one dbgrid in the main form only one sqlquery in the frmsqlitebases form. assuming that everything compiles correctly what I have to do to see the problem? Keep in mind I'm on windows if that plays any role.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Gizmo

  • Hero Member
  • *****
  • Posts: 831
Re: Two DBGrids showing the same content
« Reply #11 on: October 02, 2017, 11:25:13 pm »
Thanks taaz...you'll need to add\install the HashLib4Pascal package, the TZTimeControl package (both in the git repo), and the lazdbexport package via the Lazarus package IDE to compile it. You'll also need the SQLite3.dll for windows, from http://sqlite.org/2017/sqlite-dll-win32-x86-3200100.zip and copy the dll to the project folder.

Then go to files tab. Choose a folder with 5 or 6 small files in. The grid will populate with data about those files.

Then go to the Copy tab. Choose a folder with a few files in let hand tree view then choose a destination folder from the tree view on the right and hit go. You'll be shown a new grid with data about those files.

Now go back to the files tab and the same data will be in that grid which formerly held data about the files you looked initially.

Bear in mind that when I said above "I have two data sources and two sql queries " etc, the additions are not in that git repository. That said, even with the additions on my local working folder the behaviour is the same. I mention it just so you don't go looking for two instances and thinking "he said he has two but he only has one". The point is that the version in git behaves the same way as my local non git committed version. I was just trying something out after studying your example and decided to just try and separate it but the problem persist

Appreciate you helping me with this.
« Last Edit: October 03, 2017, 12:08:56 am by Gizmo »

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: Two DBGrids showing the same content
« Reply #12 on: October 03, 2017, 10:43:00 am »
I can't compile it. (tried it last week but it didn't work then either)

First... I only have a project1_linux.lpi to open in Lazarus (no project1.lpi). Ok, I'm on Windows but will try that one.

Then I get:
Quote
project1.lpr(10,10) Fatal: Cannot find lazdbexport used by project1. Check if package lazdbexport is in the dependencies of the Project Inspector.
Yes, I did install lazdbexport. But you might want to add lazdbexport as dependency in your project manager so it's mandatory to install it and the path will be included automatically.

Then I got
Quote
dbases_sqlite.pas(718,2) Fatal: Cannot open include file "dbases_sqlite.lrs"
on the line
Code: Pascal  [Select][+][-]
  1. {$I dbases_sqlite.lrs}
I can't get past that because I don't have that file.

If I comment out that line the compile works but running the program gives this immediately in a black screen. But that was to be expected if I comment random things out :)
Quote
[FORMS.PP] ExceptionOccurred
  Sender=EClassNotFound
  Exception=Class "TStringGrid" not found
  Stack trace:
  $0045AE77
  $00459017
  $004595B2
  $004541CB
  $0045A8EA
  $004DAF96
  $004DADC9
  $004DA118
  $0041D8E3
  $0041D7CC
  $0041FC78
  $004268F6
TApplication.HandleException Class "TStringGrid" not found
  Stack trace:
  $0045AE77
  $00459017
  $004595B2
  $004541CB
  $0045A8EA
  $004DAF96
  $004DADC9
  $004DA118
  $0041D8E3
  $0041D7CC
  $0041FC78
  $004268F6

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Two DBGrids showing the same content
« Reply #13 on: October 03, 2017, 10:50:04 am »
I have also added in the required packages the lclbase package and when ever I comment out the {$I xxxxx.lrs} I also add the {$R *.lfm} right below the implementation delcaraion, after any uses clause it might have. In some cases I had to remove the lrs to overcome the error tstringgrid class not found.
« Last Edit: October 03, 2017, 10:52:01 am by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: Two DBGrids showing the same content
« Reply #14 on: October 03, 2017, 11:11:36 am »
Yes, that worked. I removed ALL the .lrs includes and replaced them with the {$R under implementation.

Why are there {$I xxxxx.lrs} lines?
Did a very old version of Lazarus once work that way?

I also noticed all the forms are not included in the Project Manager. So I can't switch to them easily with Ctrl+F12.

 

TinyPortal © 2005-2018