Console

The DASQL console sample demonstrates using DA SQL to retrieve data from an instance of Relativity Server. DA SQL is a technology introduced to Data Abstract that gives clients the full flexibility of SQL queries to describe their data needs which will be run against the middle tier rather than against the back-end database(s), using the table and field names that are defined in the schema rather than those defined in the back-end database.

Getting Started

The Console sample is typically located in /Developer/RemObjects Software/Samples/Data Abstract/Console/DASQL, though you may have installed the Data Abstract for Cocoa and it's samples in another location.

To build it, you will of course need Xcode, and like all the samples provided with Data Abstract for Cocoa you will need to be running the Relativity Server with the DASamples Domain and the Simple Schema available.

Lastly this sample makes use of a convenience method (DALogTable) provided by a class extension to NSArray that we ship with Data Abstract for Cocoa. It is actually a #define method that uses one of three new log methods added to NSArray to print the contents of a DADataTable in a pretty fashion to the console using NSLog. To use this in your own code you must add the following to your import statements #import <DataAbstract/NSArray+DADataTableLog.h>. Please note that this class extension is intended for test purposes only.

Running the Sample

When run, the sample sets up the connection to the server (Step 1). It then generates a basic DA SQL statement to retrieve the clientid, clientname, clientphone and clientaddress fields from the clients table where the clientid is equal to 20 and passes it to the server using getDataTable:withSQL: and prints the results to the console (Step 2). A more complex SQL statement is then generated and executed using the variant getDataTableWithSQL: method (Step 3). Finally the previous complex DA SQL statement is reused but this time executed using the asynchronous method beginGetDataTable:withSQL:withBlock: (Step 4).

Examining the Code

The code for creating the connection to the server and handling logging in is covered by other samples. In this section we shall focus solely on Steps 2 through 4 which handle the creation of the DA SQL statement and retrieving the records using the getDataTable:withSQL:, getDataTableWithSQL: and beginGetDataTable:withSQL:withBlock: methods of DARemoteDataAdapter.

NOTE If the table name, or the field names do not exist or if there is a mistake in the SQL statement then an ROException will be raised and should be handled appropriately.

Using a simple DA SQL statement (Step 2)

A DA SQL statement is simply a normal SQL statement that uses the table & field names from the schema rather than the ones in the back-end Database. There is no special class required, simply put the DA SQL statement in an NSString and pass it as the second argument to the getDataTable:withSQL: method; the first argument is the name to be assigned to the returned table, while it can be whatever you wish it is recommended that you don't make it the same as other tables in the schema.

Here we create a DA SQL statement that retrieves the clientid, clientname, clientphone and clientaddress fields from the clients table where the clientid is 20. Its passed to getDataTable:withSQL:, along with the table name "MyData". The result of the call is then printed to the console. You can see in the output below that the table has been assigned the name "MyData".

NSLog(@"STEP 2. Simple DASQL ...");
NSString *template = @"SELECT clientid, clientname, clientphone, clientaddress FROM clients WHERE clientid = %@";
NSString *dasql = [NSString stringWithFormat:template, @20];
NSLog(@"DASQL: %@", dasql);
DADataTable *table = [dataAdapter getDataTable:@"MyData" withSQL:dasql];
DALogTable(table);

Using a complex DA SQL statement (Step 3)

DA SQL statements aren't limited to basic requests, you can compose as complex a request as you need by using a multi-line NSString. Here the statement retrieves a table where the rows are comprised of 3 fields which are assigned different names (Group, Product and Sold) from 3 different tables (OrderDetails, Products and ProductGroups) where the order Type was "2", and the order date was between "2013-01-01" and "2013-12-12" and the data is grouped together and ordered by two columns, first by column "3" (i.e. the amount sold) and then by the "Desc" column.

If you aren't interested in assigning your own table name to the retrieved table you can use the method getDataTableWithSQL: instead. This method simply takes the DA SQL statement to be executed and it will assign the table the name "@dasqldata".

NSLog(@"STEP 3. Complex DASQL ...");

NSString *fromDate = @"2013-01-01";
NSString *toDate = @"2013-12-12";

template =
@"\n"
@"SELECT     g.Name        AS [Group],   \n"
@"           p.Name        AS Product,   \n"
@"           sum(d.Amount) AS Sold       \n"
@"FROM                                   \n"
@"           OrderDetails d              \n"
@"INNER JOIN Orders o                    \n"
@"        ON o.Id = d.[Order]            \n"
@"INNER JOIN Products p                  \n"
@"        ON p.Id = d.Product            \n"
@"INNER JOIN ProductGroups g             \n"
@"        ON g.Id = p.[Group]            \n"
@"WHERE                                  \n"
@"           o.Type = %d                 \n"
@"AND        o.Date > '%@'               \n"
@"AND        o.Date <= '%@'              \n"
@"GROUP BY                               \n"
@"           g.Id,                       \n"
@"           g.Name,                     \n"
@"           p.Name                      \n"
@"ORDER BY                               \n"
@"           3 Desc                      \n";

dasql = [NSString stringWithFormat:template, 2, fromDate, toDate];

NSLog(@"DASQL: %@", dasql);

table = [dataAdapter getDataTableWithSQL:dasql];
DALogTable(table);

Using a complex DA SQL statement asynchronously (Step 4)

This step makes use of the complex DA SQL statement created for the previous step, and uses it as an argument to the asynchronous method beginGetDataTable:withSQL:withBlock:, which like the method in Step 2 has a first argument that is the name of the table to assign to the returned table. The last argument is a block to execute when the method call is finished.

Here we request a table that will have the name "MyData", whose content will be the records that match the dasql complex DA SQL statement. When the call is complete we execute the anonymous block that prints the table to the console and sets the done bool flag to YES; which will cause the sample to end.

NSLog(@"STEP 4. The same as previous STEP but Asynchronous ...");

static BOOL done = NO;

NSLog(@"Begin to select data ...");
[dataAdapter beginGetDataTable:@"MyData" withSQL:dasql withBlock:^(DADataTable * t) {
      NSLog(@"Data has been retrieved");
      DALogTable(t);
      done = YES;
}];

Example Output

This is an example of the output you will see when the sample is run.

DASQL sample has been started.
Target URL is http://localhost:7099/bin.
RO SDK layer is configured.
RO DataAbstract layer is configured.
Trying to login with login string User=simple;Password=simple;Domain=DASamples;Schema=Simple...
Login successful

STEP 2. Simple DASQL ...
DASQL: SELECT clientid, clientname, clientphone, clientaddress FROM clients WHERE clientid = 20
TABLE: MyData (1 rows from 1)
-----------------------------------------------------------------------------------
| ClientId| ClientName            | ClientPhone           | ClientAddress         |
-----------------------------------------------------------------------------------
| 20      | Anna H. Kugler        | (817) 249-9525        | 597 Loving Acres Road |
-----------------------------------------------------------------------------------

STEP 3. Complex DASQL ...
DASQL:
SELECT     g.Name        AS [Group],   
           p.Name        AS Product,   
           sum(d.Amount) AS Sold       
FROM                                   
           OrderDetails d              
INNER JOIN Orders o                    
        ON o.Id = d.[Order]            
INNER JOIN Products p                  
        ON p.Id = d.Product            
INNER JOIN ProductGroups g             
        ON g.Id = p.[Group]            
WHERE                                  
           o.Type = 2                 
AND        o.Date > '2013-01-01'               
AND        o.Date <= '2013-12-12'              
GROUP BY                               
           g.Id,                       
           g.Name,                     
           p.Name                      
ORDER BY                               
           3 Desc                      
TABLE: @dasqldata (17 rows from 17)
-----------------------------------------------------------
| Group                 | Product               | Sold    |
-----------------------------------------------------------
| RAM                   | RAM DDR3 4096Mb       | 4       |
| Monitors              | Monitor 22"; Dell     | 4       |
| Motherboards          | Motherboard INTEL BOXD| 2       |
| Hard-Disk Drives      | HDD Seagate Barracuda | 2       |
| CPU                   | CPU INTEL i5-4670     | 2       |
| Cases                 | Case CM HAF 912 - Mid | 2       |
| Tablets               | Apple A1474 iPad Air 1| 2       |
| Solid State Disks     | SSD Intel 240 Gb      | 1       |
| Video                 | Video Asus NVidia R928| 1       |
| Mouses                | Mouse Logitech Wireles| 1       |
| Monitors              | Monitor 22"; Asus     | 1       |
| Notebooks             | Apple MacBook Air 11" | 1       |
| Notebooks             | Notebook 15.6"; ASUS X| 1       |
| Netbooks              | Ultrabook 13.3"FHD Toc| 1       |
| Tablets               | Tablet 10,1"; ASUS Viv| 1       |
| Players               | TRANSCEND T.sonic 870;| 1       |
| Laser Printers        | Printer HP LaserJet P2| 1       |
-----------------------------------------------------------

STEP 4. The same as previous STEP but Asynchronous ...
Begin to select data ...
Waiting for completion asynchronous GetData call...
Data has been retrieved
TABLE: MyData (17 rows from 17)
-----------------------------------------------------------
| Group                 | Product               | Sold    |
-----------------------------------------------------------
| RAM                   | RAM DDR3 4096Mb       | 4       |
| Monitors              | Monitor 22"; Dell     | 4       |
| Motherboards          | Motherboard INTEL BOXD| 2       |
| Hard-Disk Drives      | HDD Seagate Barracuda | 2       |
| CPU                   | CPU INTEL i5-4670     | 2       |
| Cases                 | Case CM HAF 912 - Mid | 2       |
| Tablets               | Apple A1474 iPad Air 1| 2       |
| Solid State Disks     | SSD Intel 240 Gb      | 1       |
| Video                 | Video Asus NVidia R928| 1       |
| Mouses                | Mouse Logitech Wireles| 1       |
| Monitors              | Monitor 22"; Asus     | 1       |
| Notebooks             | Apple MacBook Air 11" | 1       |
| Notebooks             | Notebook 15.6"; ASUS X| 1       |
| Netbooks              | Ultrabook 13.3"FHD Toc| 1       |
| Tablets               | Tablet 10,1"; ASUS Viv| 1       |
| Players               | TRANSCEND T.sonic 870;| 1       |
| Laser Printers        | Printer HP LaserJet P2| 1       |
-----------------------------------------------------------
Done!
Program ended with exit code: 0

NOTE: For clarity the date and process name and ID have been removed from the sample text above