Change a FireDAC query SQL string from DataSnap client - delphi

I have set up a client connecting to a DataSnap Server in Delphi XE7. I need to send a SQL string created on the client to the server to be executed against a Firebird DB. I am using FireDAC, but I get similar results if I use DB Express.
I have TFDPhysFBDriverLink -> TFDConnection -> TFDQuery -> TDataSetProvider on the server.
I have TSQLConnection -> TDSProviderConnection -> TClientDataSet -> TDataSource -> DBGrid on the client
The TFDQuery seems to require a SQL.Text value at design time. (e.g. select * from Cust_Master) I can send the SQL string (e.g. select * from Proj_Master) back to the server fine and load it into the TFDQuery, and if I check the rows affected before and after I change the SQL.Text, I get the right number of rows returned for the customers and the projects queries. The problem is that on the client side, I only get the results of the design time SQL i.e. customers, not the SQL I sent to the server i.e. projects being displayed in the grid. I do call ClientDataSet.Refresh after sending the SQL to the server.
I need to be able to send various SQL queries back to the server, I can't have them all defined at design time. Am I using the right components to achieve this?

You have to close and reopen the ClientDataSet. A simple Refresh won't do.

You need to set DSServer's lifecycle to Invocation or create the FBQuery directly in the ServerMethods' class function. I recommend the second one though.

Check TDataSetProvider->Options->poAllowCommandText is checked

Related

How to fix the DevExpress TcxGrid GridMode using a TSQLDataSet linked to a TSQLQuery?

I'm trying to load about 500k+ data linked to an Oracle DB on my TcxGrid, I want to make the process faster using the GridView "GridMode" property, but I need to do that using a TSQLQuery (DBExpress Component) and it just doesn't work, Gridmode seems inoperable (doesn't load data faster on the Grid, doesn't load custom quantity of records using the "BufferCount" property, etc.)
Here I created a TSQLQuery component and used a query script for my 500k table (for performance purposes I just got 500 values but I need to load 500k+):
TSQLQuery
When I link the TSQLDataSet to the Grid and activate the TSQLQuery it shows all the records from the query, even if the GridMode is TRUE and the GridModeBufferCount is 5
GridWithTSQLQuery
On the other hand, when I use a TQuery, the GridMode just works properly, in this case I had to open SQL Explorer, make the connection and assign that connection to the TQuery DataBase property:
SQLExplorer
Here I show my TQuery with the values mentioned before:
TQuery
And when I activate my TQuery.. voilá:
GridWithTQuery
What I'm doing wrong? or do I need to do more things on my TSQLQuery besides linking it to my dataset and then linking the dataset to the grid?
It's impossible that a very old Tquery can do this and not a newer dbExpress component
Thank you so much guys

Delphi Datasnap: How to manually build dataset when using a TDatasetProvider

I would like to manually build the dataset used by a TDatasetProvider to return the data to the client.
The SQL request is taking a long time to run as a query and I am trying to speed up things by splitting the logic in code and using a kbmMemtable to hold my data before returning it to the client.
Can I do this:
kbmMemtable -> TDatasetProvider -> TClientDataset
If this can be done, in what event of my TDatasetProvider should I set the data in the memtable ?
Using Delphi XE
you could do it in BeforeGetRecords/OnGetData event handler or even elsewhere

Set up SQL Database table in Delphi with TDBGrid (Unidirectional error)

How can i set the whole table of a database to show in my delphi form? Using TDBGrid i presume; but when I configure the data source (connected to a query) I receive an error message about it being Unidirectional. I've heard about a Clientdataset but that didnt seem to work. Could i have some clear instructions on how to do this please? Thank you in advance, Toby.
You say you are using TSQLQuery. This is one of the dbExpress components which are designed to be Unidirectional only (except the TSimpleDataSet). You either have to connect the TSQLQuery to a TDataSetProvider and TClientDataSet or change your query component to one that will buffer the data locally.
To use TDataSetProvider and TClientDataSet:
Set the DataSet property of TDataSetProvider to the SQLQuery.
Set the ProviderName property of the TClientDataSet to the DataSetProvider.
When the ClientDataset is opened, it will contain the data from your SQLQuery.
Set the DataSet Property of your TDataSource to the ClientDataset so the data can be displayed in your DBGrid.
Since you appear to be new to using databases with Delphi, I would recommend you use a different query component, because using the TDataSetProvider and TClientDataSet can be complicated. I suggest
TSimpleDatSet in dbExpress,
TADOQUery or TADODataset in dbGo,
TQuery in BDE (not recommended),
TFDQuery in FireDAC, or
other third party query components.

TADODataSet.MasterFields - Performance

I have a Delphi application which has 2 TADODataSet objects that reference CLIENT (Master) and ORDER (detail) data. I have the 2 components linked via the DataSource and Masterfields (using ClientCode) properties and everything functions as expected. However, I've noticed a performance issue recently and have discovered that even if only just one client record is returned for for the master record set, the entire orders table is returned and then filtered for the specific client. Is this how it should function? From tracing the database activity I can see that the following SQL is being executed:
-- the one client that I wanted to view
SELECT fields FROM Client WHERE ClientCode = 1;
SELECT fields from Order; -- entire orders table
I am using Delphi 2006 BDS
You just have to watch that Masterfield is named correctly with the fieldname of your masterdataset.
Make sure the parameter types are the same in both cases, i.e. master and child.

Extract query definition from JET database via ADO

I have a program in Delphi 2010 that uses a JET (mdb) database via ADO. I would like to be able to extract the definitions of some of the queries in the database and display them to the user. Is this possible either via SQL, some ADO interface, or by interrogating the database itself (I don't seem to have rights to MSysObjects).
Some of that information is available via ADOX calls. There is an overview of the api with some examples (unfortunately not in Delphi) on the MSDN website.
Basically what you will want to do is to is to import the ADOX type library, and then use the wrapper that is generated for you to access the underlying API. From there its as simple as navigating the hierarchy to get at the data you need.
You will need to access the specific View object, and from there get the command property.
Via DAO, it's pretty easy. You just extract the SQL property of each QueryDef. In DAO from within Access, that would be:
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = DBEngine.OpenDatabase("[path/name of database]")
For Each qdf In db
Debug.Print qdf.SQL
Next qdf
Set qdf = Nothing
db.Close
Set db = Nothing
I don't know how to translate that, but I think it's the simplest method once you're comfortable with using DAO instead of ADOX.
I don't use ADO at all, but I'm guessing that it has a collection of views and the SQL property would work for SELECT queries. However, if you're interested in getting the SQL for all saved QueryDefs, you'd also need to look at the DML queries, so you'd have to look at the stored procedures. I would have to look up the syntax for that, but I'm pretty certain that's how you'd get to the information via ADO.

Resources