IBX query - best practise lazarus / 16-Databases ---------------------------------------------------------------------- Nicole · 2022-08-20 09:37 I am new to IBX and portate code from FireDAC. If I can use many snippets from there, it would be great. Since days I study the IBX manuals and there are many ways to do it. And many ways to have created MESS after having done or failed. Can anybody give me hints, how to perform a query best without leaving connections and transactions active behind? And what is more usedful: IBSQL or IBQuery? I do not fully understand the manual. So what do I want to do (syntax freestyle bebause this task is unimportant): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function tell_me_the_number (boat: string): integer; SQL.text:='select id, boat from tbboats ' + 'where boat = :myBoat';Param(:myBoat): =boat;  result:= id; What is needed are the elements around and I would prefer to use a minimum of code lines: - set the "code" active (probalby I will have to set a dataset to active) - have a transaction ready for this - clean up As such tasks are very common, it would be great, if anybody could donate me some code-snippets of how he does it. Thanks. ---------------------------------------------------------------------- rvk · 2022-08-20 11:52 You could do something like this: I also made it so it doesn't need to be a class-function. But in that case you'll need to pass the TIBDatabase to the function. It also creates it's own TIBTransaction when nil is passed. Sometimes this is not desired and you could create an optional parameter for the transaction. In that case you wouldn't want to rollback the transaction because it can be part of a larger transaction. But for simple queries you can just leave it out (you don't need to pass anything). Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i OneBoat := Tell_me_the_number('123', IBDatabase1);//..AnotherBoat := Tell_me_the_number('123', IBDatabase1, LargerTransaction); Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function Tell_me_the_number(Boat: string; Db: TIBDatabase; Trans: TIBTransaction = nil): integer;var  Query: TIBQuery;begin  Result := -1;  Query := tIBQuery.Create(nil);  try    Query.Database := Db;    if Trans = nil then    begin      Trans := TIBTransaction.Create(Query);      Trans.DefaultDatabase := Db;      Trans.DefaultAction := TARollback;    end;    Query.Transaction := Trans;    Query.Transaction.Active := True;    Query.SQL.Text := 'select id, boat from tbboats where boat = :myBoat';    Query.ParamByName('myBoat').AsString := Boat;    Query.Open;    if Query.RecordCount > 0 then      Result := Query.FieldByName('id').AsInteger;    Query.Close;  finally    Query.Free;  end;end; Of course you could even create am more generic function like GetQueryResult() where you pass the SQL and you get a TStringList back with all the fields of that record (without leaving a query open). ---------------------------------------------------------------------- Nicole · 2022-08-20 15:50 Thank you so much! I may have a hundred or more of such snippets alike "get this information about". Do you think it a good idea, if I make this a function for all tables in my DB_Modul where I just send SQL into it and get answers out? Like this: function Tell_me_the_number(myQuery: string; Db: TIBDatabase; Trans: TIBTransaction = nil): integer; begin (your work) end; and called by myInteger:=function Tell_me_the_number(SQL_Query); (The paramsByName-parameter would be the next topic, I will thing about them later) ---------------------------------------------------------------------- rvk · 2022-08-20 16:50 Yes, you can pass on a specific SQL to make this more generic. You could also pass a field-name you want returned. It would be a string because you might want a string or integer returned You could also return a variant (which could be a string, integer, double etc). For example this could return an id, boat-name or anything else you could think of. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function Tell_me_the_value(myField, myQuery: string; Db: TIBDatabase; Trans: TIBTransaction = nil): variant; ---------------------------------------------------------------------- Nicole · 2022-08-20 18:39 thank you! ---------------------------------------------------------------------- tonyw · 2022-08-21 14:07 Quote from: Nicole on August 20, 2022, 11:37:28 amI am new to IBX and portate code from FireDAC. If I can use many snippets from there, it would be great. Since days I study the IBX manuals and there are many ways to do it. And many ways to have created MESS after having done or failed. Can anybody give me hints, how to perform a query best without leaving connections and transactions active behind? And what is more usedful: IBSQL or IBQuery? I do not fully understand the manual. I believe that the point that you are missing is the difference between IBX's "Database Access Components" and the "DataSet Components". These are in separate major sections in the manual and for good reason. The former are low level components and intended to be little more than object oriented wrappers around the actual Firebird API. They allow a user to place database connections, transactions and statements as components on a form or a data module, at design time, and then execute them at run time. They work together and typically you need all three to execute a query. You use a TIBDatabase component to define, open and manage a connection to the database. You use a TIBTransaction component to create a transaction for the database and to later commit it (or rollback). You use a TIBSQL to define and execute a query under a given transaction. This can be a select, update, insert or delete query. Select queries can return multiple rows, one after the other, while the others, at most return a singleton row. On the other hand, the Dataset components are intended to map a Firebird dataset into a Delphi (or FPC) TDataset. The dataset can then be used by data aware controls to view and update the database. The TIBQuery is typically used to access a read only dataset. A TIBQuery internally uses a TIBSQL to run a select query which returns the dataset. However, a TIBSQL only returns the dataset one row at a time. TIBQuery reads all rows and buffers them locally, allowing you to scroll backwards and forwards through the dataset. TIBQuery is much more powerful than TIBSQL, but you only need to use it when you are also using data aware controls. If all you want to do is to just execute (e.g. an update query) then TIBSQL is much simpler and quicker. When you want to update a dataset, you add a TIBUpdateSQL component and link it to the TIBQuery. You provide it with SQL statements to Update, Insert and Delete rows - and to refresh a row after update. Fortunately, IBX helps you (at design time) to build these queries - so you don't have to do it all yourself. Given that TIBQuery is a buffered dataset, it allows you to edit rows one by one and then "post" the changes before moving on to the next row in the dataset. Also under the heading of Dataset Components, you have TIBTable: this is for use with a single Firebird table and automatically builds all SQL statements that you need to access the table. It is often the best choice for a beginner. TIBDataset: this combines a TIBQuery and TIBUpdateSQL into a single component. This tends to be the preferred choice of intermediate to advanced users I hope this helps and thank you using IBX. ---------------------------------------------------------------------- rvk · 2022-08-21 16:32 QuoteTIBQuery is much more powerful than TIBSQL, but you only need to use it when you are also using data aware controls. If all you want to do is to just execute (e.g. an update query) then TIBSQL is much simpler and quicker. Yes, I used TIBQuery in my example here. But in my own program in Delphi, with IBX for Delphi, I actually use TIBSQL for my own GetQueryResult() and GetQueryResultList() functions. So that might have been a better choice over TIBQuery (because you only query just one (or several) values from a read-only dataset and only the first record is needed). ---------------------------------------------------------------------- tonyw · 2022-08-21 22:04 Quote from: rvk on August 21, 2022, 06:32:04 pmQuoteTIBQuery is much more powerful than TIBSQL, but you only need to use it when you are also using data aware controls. If all you want to do is to just execute (e.g. an update query) then TIBSQL is much simpler and quicker. Yes, I used TIBQuery in my example here. But in my own program in Delphi, with IBX for Delphi, I actually use TIBSQL for my own GetQueryResult() and GetQueryResultList() functions. So that might have been a better choice over TIBQuery (because you only query just one (or several) values from a read-only dataset and only the first record is needed). It's not just fetching all records that gives rise to the inefficiency. Both IBX for Delphi and Lazarus, when a TIBQuery is opened, run an extra query to get the dataset metadata from the Firebird System Tables. From this, the fields array is created and the buffers set up. TIBSQL avoids all of this overhead and just returns the rows you want. ---------------------------------------------------------------------- Nicole · 2022-08-22 09:06 @Tonyw: Thank you for this explanation. This helps a lot! This is exactly what I tried to find in tutorials and manuals all the time, but was not secure of how to understand. The first part of your posting is saved to my notes. The line where I a was out starts with: "When you want to update a dataset, you add a TIBUpdateSQL component an...." What is "update SQL"?! What are selectSQL and insertSQL? I saw it in the properties already. And found there SQL generators, which are fine. For my old code this is all the same Query. One time there is myADquery.text.sql: "Insert Into...", "Update to...", the same Query is set from active false and gets a ...sql:="Delete from" and set to true again. In my understanding is SQL the language in which I talk to my Firebird. Firebird understands, if I want to select, update, insert, generate or delete. I rather would prefer to have only one SQL-property. And there is something, I miss: Can I EXECUTE my SQL anywhere at design-time? IBX just says "looks ok", but does not show me the result. So I have an IBDynamicGrid for this result-showing at the moment, which does not make me too happy. ---------------------------------------------------------------------- rvk · 2022-08-22 09:27 @tonyw: In IBX for Delphi there was a property TIBQuery.UpdateObject. In IBX for Lazarus it is still there but I can't find it in the Object Inspector. So I can't assign a TIBUpdateSQL to a TIBQuery at design-time? @Nicole: Concerning UpdateSQL.... Imagine you have a TDBGrid. To connect a query with dataset (so records are visible) you have a TDataSource attached to it. And the TDataSource in turn is connected to a dataset like TIBQuery. In that case the TIBQuery would have a SELECT statement in the TIBQuery.SQL. Now imagine you enter the edit-mode of the TDBGrid (you can change values right in the grid or use TDBEdit and such). With a SELECT statement, the program doesn't know how to update/insert/delete records. That's where TIBUpdateSQL comes in. It provides the correct INSERT, UPDATE and DELETE SQL statements for the TIBQuery object. Now when the TDBGrid goes into edit mode and you perform a Insert/Edit/Post on it, it can take the TIBUpdateSQL.Insert etc from that object to actually insert/edit the records in the database. You don't have to use a separate TIBSQL or TIBQuery for that. So, SELECT is in TIBQuery.SQL. and INSERT is in TUpdateSQL.InsertSQL and DELETE is in TUpdateSQL.DeleteSQL. No need to switch statements in the one TIBQuery.SQL in that case (which is especially useful with active TDBGrids). For the Execute popup menu in TIBQuery... Why would you want to execute the query? Setting it to active would automatically execute the query and for DELETE and INSERT you wouldn't want to do that in design-time. I think IBX does a prepare to see it the command is valid but doesn't actually execute it (but I'm not sure). Is there a special reason why are you using TIBDynamicGrid over the standard TDBGrid? And why doesn't that make happy. If you don't use any of the special features of it then you can also just use the TDBGrid. ---------------------------------------------------------------------- jujibo · 2022-08-22 09:48 Quote from: rvk on August 22, 2022, 11:27:18 am@tonyw: In IBX for Delphi there was a property TIBQuery.UpdateObject. In IBX for Lazarus it is still there but I can't find it in the Object Inspector. So I can't assign a TIBUpdateSQL to a TIBQuery at design-time? Look at the attached image ---------------------------------------------------------------------- tonyw · 2022-08-22 09:51 Quote from: jujibo on August 22, 2022, 11:48:51 amQuote from: rvk on August 22, 2022, 11:27:18 am@tonyw: In IBX for Delphi there was a property TIBQuery.UpdateObject. In IBX for Lazarus it is still there but I can't find it in the Object Inspector. So I can't assign a TIBUpdateSQL to a TIBQuery at design-time? Look at the attached image It may be that rvk was looking at the properties for a TIBDataset and not a TIBQuery. The former does not include an UpdateObject (doesn't need it) while the latter does (as does TIBTable). ---------------------------------------------------------------------- rvk · 2022-08-22 09:54 Quote from: tonyw on August 22, 2022, 11:51:50 amQuote from: jujibo on August 22, 2022, 11:48:51 amQuote from: rvk on August 22, 2022, 11:27:18 am@tonyw: In IBX for Delphi there was a property TIBQuery.UpdateObject. In IBX for Lazarus it is still there but I can't find it in the Object Inspector. So I can't assign a TIBUpdateSQL to a TIBQuery at design-time? Look at the attached image It may be that rvk was looking at the properties for a TIBDataset and not a TIBQuery. The former does not include an UpdateObject (doesn't need it) while the latter does (as does TIBTable). Mmmm, no, I'm really looking at TIBQuery. See attached. Waaaaaaaaaaaaaargh. Scratch that. It has a scroll bar ---------------------------------------------------------------------- jujibo · 2022-08-22 09:56 Quote from: tonyw on August 22, 2022, 11:51:50 amIt may be that rvk was looking at the properties for a TIBDataset and not a TIBQuery. The former does not include an UpdateObject (doesn't need it) while the latter does (as does TIBTable). May be, but he pointed out to TIBQuery. ---------------------------------------------------------------------- rvk · 2022-08-22 09:58 Argh....  I didn't see it had a scrollbar. I was fooled by the big empty space below the list (where normally the explanation goes). When nothing selected it is really not clear there are more properties. (I already found it strange I couldn't find it there because it was in the autocomplete in code.) ---------------------------------------------------------------------- tonyw · 2022-08-22 09:58 Quote from: rvk on August 22, 2022, 11:27:18 amFor the Execute popup menu in TIBQuery... Why would you want to execute the query? Setting it to active would automatically execute the query and for DELETE and INSERT you wouldn't want to do that in design-time. I think IBX does a prepare to see it the command is valid but doesn't actually execute it (but I'm not sure). When you click on the "Test" button in the IBX SQL Editor (at Design Time), it does indeed perform a "prepare" in order to validate the statement syntax. Quote from: rvk on August 22, 2022, 11:27:18 amIs there a special reason why are you using TIBDynamicGrid over the standard TDBGrid? And why doesn't that make happy. If you don't use any of the special features of it then you can also just use the TDBGrid. I always used TIBDynamicGrid because: (a) I wrote it. (b) It automatically sets column widths so that row data fits the grid - even when you change the form size. (c) Automatic column sort by clicking on a column header (d) Row expansion by replacing a the current row with a panel that can expand on the presentation of the row - including images. ---------------------------------------------------------------------- jujibo · 2022-08-22 10:14 Quote from: rvk on August 22, 2022, 11:58:14 amArgh....  I didn't see it had a scrollbar. Happens ---------------------------------------------------------------------- Nicole · 2022-08-22 10:36 @ tonyw You WROTE TIBDynamicGrid ?! Thank you so much for it. I never heard about before, but found it mentioned in a manual some days ago. It was love at first sight. Before, I had buttons activating SQL-statements with "... order by this"  and "...order by that". It was exciting to trash these buttons after code-migration. I sat there like a child and sorted the columns by click, which had NO sort-buttons before. ---------------------------------------------------------------------- zoltanleo · 2022-08-23 19:33 Hi Nicole There used to be very popular FIBPlus components. Unfortunately, the authors don't currently develop them (there are not very legal fan projects, for example this one https://github.com/madorin/fibplus#disclaimer). But what remains of these components are excellent user manuals and a developer's guide. Here is one of them: http://www.intitec.com/varios/Guia_desarrollo_FIBplus.pdf or https://github.com/madorin/fibplus/tree/master/Docs This guide explains not only examples of their use, but also the basic principles of using read and write transactions. Unfortunately, most of the manuals for fibplus I have exist in Russian. ---------------------------------------------------------------------- Nicole · 2022-08-24 14:54 Thank you for the link. How does FibPlus interact with IBX? Are they sisters, competes, ancestors or mates? ---------------------------------------------------------------------- rvk · 2022-08-24 15:52 Quote from: Nicole on August 24, 2022, 04:54:37 pmThank you for the link. How does FibPlus interact with IBX? Are they sisters, competes, ancestors or mates? They are similar (in the fact they are for interbase/firebird directly). But I would advise you to stay with IBX. (You shouldn't mix those) IBX has excellent support here (as you have seen). You can't beat that. There is also ZeosLib. ZeosLib has a little support here but not nearly as much as IBX. You can look at documents of other components to learn about transaction handling in Firebird etc. but as far as components concerned, either use IBX or sqldb (in standard). ZeosLib has the advantage that it can access other DB-servers like mysql, progres etc. But for just Firebird it has some disadvantages too (like poor transaction flexibility). In case you are looking for an alternative for IBX, because you want other DB-servers you could use standard sqldb. But if you plan to stay with Firebird, IBX is the way to go (in my opinion). ---------------------------------------------------------------------- zoltanleo · 2022-08-24 16:28 Quote from: Nicole on August 24, 2022, 04:54:37 pmThank you for the link. How does FibPlus interact with IBX? Are they sisters, competes, ancestors or mates? both of these components have a common ancestor (unfortunately, I forgot the exact name of this component and his author) ---------------------------------------------------------------------- Nicole · 2022-08-24 16:47 Thank you so much for the support!! I tried ZEOs already some time ago. I was not able to do first steps there. And I was told, that IBX allows the multiuse of transactions, while Zeos doesn't. This is the second reason, why I prefer IBX. My database will remain Firebird, so I can live with the fact, that other dbs are not supported. However: did I see right, when I read with one eye other db-names in the component-tab like oracle? ---------------------------------------------------------------------- rvk · 2022-08-24 17:03 Quote from: zoltanleo on August 24, 2022, 06:28:44 pmboth of these components have a common ancestor (unfortunately, I forgot the exact name of this component and his author)  If I remember correctly, FibPlus wasn't free. I looked into this a long time ago and looked into FIBPlus, IBX, IBObjects, UIB and Zeos. (Wasn't FibPlus from devrace for a few hundred $ upto $1200. But I guess that's only for a supported version) From FibPlus on github: QuoteFIBPlus is based in part on the product Free IB Components, written by Gregory H. Deatz for Hoagland, Longo, Moran, Dunst & Doukas Company. From IBX for Delphi: QuoteInterBase Express is based in part on the product Free IB Components, written by Gregory H. Deatz for Hoagland, Longo, Moran, Dunst & Doukas Company. Free IB Components is used under license. So they both have the same basis from where it is developed. Quote from: Nicole on August 24, 2022, 06:47:25 pmHowever: did I see right, when I read with one eye other db-names in the component-tab like oracle?Both the default sqldb in lazarus/FPC and ZeosLib have support for other databases, yes. Like microsoft sql server, oracle, mysql/mariadb, sqlite, etc. That's why, if you really need multiple DB support (different servers at you customer base) you can choose for sqldb and have the flexibility to switch servers. If you use IBX, that won't be that easy. But different SQL servers can also have different SQL dialects and not all SQL statements would be exactly the same. So it's not that easy as it looks on first glance ---------------------------------------------------------------------- zoltanleo · 2022-08-24 18:23 Quote from: rvk on August 24, 2022, 07:03:26 pm From FibPlus on github: QuoteFIBPlus is based in part on the product Free IB Components, written by Gregory H. Deatz for Hoagland, Longo, Moran, Dunst & Doukas Company. From IBX for Delphi: QuoteInterBase Express is based in part on the product Free IB Components, written by Gregory H. Deatz for Hoagland, Longo, Moran, Dunst & Doukas Company. Free IB Components is used under license. So they both have the same basis from where it is developed. You're absolutely right.  i found this http://ivarus.chat.ru/FIBComponents.html#SEC52 ---------------------------------------------------------------------- Nicole · 2022-08-24 19:58 This is what I found as well: Originally it was not free. If I would pay for anything, I would take FireDAC. I really was happy with it. And FireDAC should be free with the community edition. Unfortunately, the community edition is free for only one year and -  only if Embarcadero will exist one more year. The problem is not only, that every upgrade is many thougsands Euros for all component if it is not free any more. The problem is, that a quit of those component providers will cease in the long run my own work as well. ---------------------------------------------------------------------- rvk · 2022-08-24 20:10 Delphi Community Edition is not only free for one year but always free. But you can't earn money from a program you make in Community edition (CE) or you would need to upgrade to Pro. And you also need to apply for a new license each year stating you don't earn money (and that involves reinstalling Delphi CE each year). Also, CE doesn't do database access to servers (no client/server connections in FireDAC). But you can use IBX for Delphi for that in CE. Pro version also hasn't client/server DB access in FireDAC but I use IBX in Delphi. (Although IBX for Delphi is more Interbase oriented than Firebird, it still works for me.) I'm still on Delphi/IBX because I have a very large program and use some specific Delphi features but when (not if) I switch to Lazarus I will use IBX for Lazarus (which would be a pretty smooth conversion process I think). ---------------------------------------------------------------------- Nicole · 2022-08-25 07:19 Do not ask me how, but I managed FireDAC to run with Delphi Pro. As the Embarcadero support left me alone with my troubles that time, I tried all the hints of forums. One of it made FireDAC run in the pro version in a way said "only Enterprise" at their homepage. Probably a hint, Embarcadero hat not thought, that there may be an open door. The problem is, "you need to apply for a new licence". We saw Borland die, we found Imprise pass away, - how long will Embarcadero live? Nobody knows. For this reason, my Delphi will always be in a VM, because I do not want to HOPE they generate me a new password WHEN the day comes, my desktop computer passes away. I will copy the VM from my backup and no need to say, "please, please allow me to use on, what I have paid for". ---------------------------------------------------------------------- rvk · 2022-08-25 09:13 Yes, FireDAC works in Delphi Pro. But it can only access local databases. Not remote ones on other servers. It's the reason I stayed far away from FireDAC. I'm not planning on buying Enterprise. I remember a time where a Delphi upgrade cost $150. Those where the days. Now they did away with upgrades all together and went subscriptions based. I would only upgrade one every 3 years but now (with these prices) I would only upgrade if it's absolutely necessary. And the subscription price isn't cheaper if you only need to upgrade once every few years. If you program for Android then it is essential because you would actually need a new version every year. But the state of Android programming in Delphi is very poor too. So I was happy IBX was still on Pro and able to do remote connections. I would welcome a "IBX for Lazarus" for Delphi though (or a "FBX", Firebird Express for Lazarus and Delphi) And yes, I wonder too how long Embarcadero can keep up their ever growing restrictive and more expensive policies. ---------------------------------------------------------------------- tonyw · 2022-08-25 09:37 Quote from: rvk on August 25, 2022, 11:13:19 am. I would welcome a "IBX for Lazarus" for Delphi though (or a "FBX", Firebird Express for Lazarus and Delphi) Nice idea but I have the same problem with respect to the cost of Delphi and without paying up for access to the TDataset source code I could not maintain an IBX for Lazarus for Delphi. I gave up with Delphi 2010 and have never looked back. ---------------------------------------------------------------------- Nicole · 2022-08-25 15:57 There is another point you may not be aware of: Your strength as a group of Lazarus programmers. Embarcadero has to pay its programmers and "half of them" are busy - to program the license restrictions. How many programmers may it be? How many hours do they work a month as a group? Really many, but not endless. Nobody can afford to work full time for Lazarus. But here are MANY. Under the line, I ask myself if there is a quality shift from paid programs to open source. This Lazarus software IS good! When I work with my Delphi IDE again, it feels lame and buggy. Embarcadero does not look back. They left me alone with my version and really severe bugs within the IDE filling up the RAM and forcing me to restart the IDE every some hours again. Often enough I lost my work and saved every 2 minutes. So I lost my last working versions out of sight when I was stuck. To sum up: Lazarus is better than Delphi. ---------------------------------------------------------------------- Handoko · 2022-08-25 16:11 I was a fan of Delphi 5..7. But as a hobbyist, I don't earn much in programming, so I choose Lazarus. I thought I might purchase a Delphi license if I managed to earn enough from my programming jobs to pay for it. Quote from: Nicole on August 25, 2022, 05:57:44 pmTo sum up: Lazarus is better than Delphi. Thank you for sharing your experience with Delphi. Good to know about it. I can save the money for used in other things.