Adding & Reading from a Union Table

The first part of this article is written in a generic fashion to show creating a Union Table using either the Schema Modeler tool on Windows or the Server Explorer tool on Mac OS X. The second part provides a platform specific example of retrieving the data from the source tables.

We are going to create a Union Table called "PhoneBook" which will have three fields (ID, Name and Phone) and two source tables (Deps and Users).

Creating a Union Table

The first step is to open the schema that you are interested in in either Schema Modeler or Server Explorer.

 

 

Click on the Unions / UNION TABLES folder in the navigation tree and then the Add New Union Table button which will open a new view where you can set the basic details of the Union Table.

 

 

Set the details as follows:

  • Union Name as PhoneBook
  • Description Phonebook of staff
  • Public leave checked
  • Read-Only check this
  • Custom Attributes leave empty
  • Default Source Table leave empty

Next expand the PhoneBook union table so the Fields and Source Tables are visible.

 

 

There are two options for creating the Union Table Fields, the first is to generate them by hand adding each one one at time and configure all of the fields as you need. The other way to do it is to drag and drop a table onto the Source Tables folder which will cause Schema Modeler / Server Explorer to automatically generate Union Table Fields based on the fields of that Source Table.

NOTE This only applies to the first table dropped onto the Source Tables folder.

For the purposes of this article we are going to use the drag & drop method. So drag the "Deps" folder (in the Tables section) onto the Source Tables folder. This will generate three fields DepId, DepName and DepPhone which we will shortly rename.

 

 

To change the details of a field, simply click on the field in the Fields folder this swaps in a view where you can change finer details of the field from its type, whether its read-only or not, its defaults value, display format and many more. More information is available in the relevant section of each tools documentation.

For our purposes, simple select each of the three fields DepId, DepName and DepPhone in turn and remove the Dep from each of the names.

 

 

Next drag the Users table down from the Tables folder and drop it onto the Source Tables folder. This adds another Source Table to our Union Table, however before we can use it the mappings between the Union Table Fields and the Source Table Fields need to be changed as the fields don't match as we need. Select the new Users source table.

Changing a mapping is rather simple, just click on the on the the Source Table Field you are interested in which will cause a popup box of all of the fields in the Source Table to appear. Click on the one that is most appropriate for your needs. Here we will change the existing mapping of the Union Table Field "Phone" from the Source Table Field "Type" to "Phone" instead.

 

 

All that remains is to save your changes to the schema document.

NOTE: When you access the Union Table for the first time, a new Union Table Field will be created called "@SourceTable" which refers to which of the Source Tables the data was retrieved from.

Accessing the Union Table

Having created the "PhoneBook" Union Table Schema Modeler / Server Explorer, the next step is to retrieve the data from it.

Accessing the data from a Union Table is exactly the same as accessing the data in a normal data table. Rather than showing how you would do this with Xcode, we will instead demonstrate creating a console application using the Fire IDE.

Start Fire, it displays a splash screen from which you can load an existing project or create a new project. Click Start a new Project.

On the drop down dialog, select the platform (here Cocoa), the Language (here Swift) and the template that the project should be based on (here Console Application (OS X)) and the press OK.

Choose the location to save the project and click Create Project.

This opened the Project Window. The left side is a navigation view, the right side changes depending on what is selected on the left.

As we are working with Data Abstract we need to add a Reference to the data abstract library/framework to the project. Right click on References in the left view and click on the Add Reference button.

As the Data Abstract library isn't part of the system libraries, you need to click on Other References, then click on libDataAbstract.fx and finally click on the button Add 1 Reference.

After a momentary pause you will see a reference to libDataAbstract.fx in the left view. The figure below shows the completed Swift application with the added reference.

The next step is to add the code that will set up a connection to the Relativity server, log in, retrieve the data and print out the values received.

Sample Code

Available below is the sample code in all of the languages that the Cocoa version of Data Abstract supports. For the purposes of the example above, we used the Swift version of the code.

 

#import <Foundation/Foundation.h>
#import <DataAbstract/NSArray+DADataTableLog.h>
#import <DataAbstract/DataAbstract.h>

#define TARGET_URL @"http://localhost:7099/bin"
#define DATA_SERVICE_NAME @"DataService"
#define LOGIN_SERVICE_NAME @"LoginService"
#define LOGIN_STRING @"User=simple;Password=simple;Domain=DASamples;Schema=Simple"

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        // Initialise Adapter
        NSURL * url = [NSURL URLWithString:TARGET_URL];
        DARemoteDataAdapter * dataAdapter =
            [[DARemoteDataAdapter alloc] initWithTargetURL:url
                                           dataServiceName:DATA_SERVICE_NAME
                                          loginServiceName:LOGIN_SERVICE_NAME];

        // Attempt to log in
        BOOL logged = NO;
        logged = [dataAdapter loginWithString:LOGIN_STRING];

        if (!logged) {
            NSLog(@"Unsuccessful login. Please check your login and password. Exiting...");
            return 1;
        }

        // Access the Union Table
        DADataTable * table = [dataAdapter getDataTable:@"PhoneBook"];
        NSLog(@"Number of Rows in Union Table: %ld", (long)table.rowCount);
        DALogTable(table);
    }

    return 0;
}

 

import Foundation
import DataAbstract

let TARGET_URL       = "http://localhost:7099/bin"
let DATA_SERVICE_NAME  = "DataService"
let LOGIN_SERVICE_NAME = "LoginService"
let LOGIN_STRING       = "User=simple;Password=simple;Domain=DASamples;Schema=Simple"

// Initialise Adapter
let url:NSURL = NSURL(string: TARGET_URL)!
let dataAdapter:DARemoteDataAdapter =
          DARemoteDataAdapter(targetURL: url,
                        dataServiceName: DATA_SERVICE_NAME,
                       loginServiceName: LOGIN_SERVICE_NAME)

// Attempt to log in
var logged = false;
logged = dataAdapter.loginWithString(LOGIN_STRING)
if (!logged) {
    print("Unsuccessful login. Please check your login and password. Exiting...")
    exit(1)
}

// Access the Union Table
let table:DADataTable = dataAdapter.getDataTable("PhoneBook")
print("Number of Rows in Union Table: \(table.rowCount)")
//DALogTable(table);

for row in table.rows {
    let theRow:DADataTableRow = row
    for field in table.fields {
        print("\(field.name): \(theRow.valueForKey(field.name)!)\t", terminator:"");
    }
    print("")
}

 

namespace AccessingUnionTableOxygene;

interface

uses
  Foundation, DataAbstract;

type
  Program = public static class
  public
    method Main(aArguments: array of String): Int32;
  end;

implementation

method Program.Main(aArguments: array of String): Int32;
begin
  var TARGET_URL: String := "http://localhost:7099/bin";
  var DATA_SERVICE_NAME: String := "DataService";
  var LOGIN_SERVICE_NAME: String := "LoginService";
  var LOGIN_STRING: String :=
            "User=simple;Password=simple;Domain=DASamples;Schema=Simple";

  var url:NSURL := NSURL.URLWithString(TARGET_URL);
  var dataAdapter: DARemoteDataAdapter :=
            new DARemoteDataAdapter()
                  withTargetURL(url)
                  dataServiceName(DATA_SERVICE_NAME)
                  loginServiceName(LOGIN_SERVICE_NAME);

  var logged: BOOL := false;
  logged := dataAdapter.loginWithString(LOGIN_STRING);

  if logged = false then begin
    NSLog('Unsuccessful login. Please check your login and password. Exiting...');
    exit 1;
  end;

  var table : DADataTable := dataAdapter.getDataTable('PhoneBook');
  NSLog('Number of Rows in Union Table: %ld', table.rowCount);

  for each row: DADataTableRow in table.rows do begin
    for each field: DAFieldDefinition in table.fields do begin
      printf('%s: %s   ', field.name.UTF8String,
              row.valueForKey(field.name).description.UTF8String);
    end;

    writeLn();
  end;
end;

end.

 

using Foundation;
using DataAbstract;

namespace AccessingUnionTableCSharp
{
    static class Program
    {
        public static Int32 Main(string[] args)
        {
            using (__autoreleasepool)
            {
                String TARGET_URL = "http://localhost:7099/bin";
                String DATA_SERVICE_NAME  = "DataService";
                String LOGIN_SERVICE_NAME = "LoginService";
                String LOGIN_STRING    =
                  "User=simple;Password=simple;Domain=DASamples;Schema=Simple";

                NSURL url = NSURL.URLWithString(TARGET_URL);
                DARemoteDataAdapter dataAdapter =
                    DARemoteDataAdapter.adapterWithTargetURL(url)
                                dataServiceName(DATA_SERVICE_NAME)
                                loginServiceName(LOGIN_SERVICE_NAME);

                bool logged = false;
                logged = dataAdapter.loginWithString(LOGIN_STRING);

                if (!logged) {
                    printf("Unsuccessful login. Check you login details. Exiting...");
                    return 1;
                }

                DADataTable table = dataAdapter.getDataTable("PhoneBook");
                printf("Number of Rows: %ld\n", table.rowCount);

                foreach (DADataTableRow row in table.rows) {
                    foreach (DAFieldDefinition field in table.fields) {
                        printf("%s: %s\t", field.name.UTF8String,
                          row.valueForKey(field.name).description.UTF8String);
                    }
                    printf("\n");
                }

                return 0;
            }
        }
    }
}

Sample Output

This is a sample of the executed program's output. Note the additional column @SourceTable which indicates which of the source tables that the data was retrieved from based on the order that you defined in the schema. Note that there is no programatic way to identify which table is the source table.

Id: 1   Name: Sales Phone: (873)456-78-99   @SourceTable: 0
Id: 2   Name: Incomes   Phone: (873)456-78-88   @SourceTable: 0
Id: 1   Name: Mollie Bennett    Phone: (171) 555-1212   @SourceTable: 1
Id: 2   Name: Gale Dalton   Phone: 0221-0644327 @SourceTable: 1
Id: 3   Name: Matthew Decker    Phone: (503) 555-3612   @SourceTable: 1
Id: 4   Name: Joseph Henson234  Phone: (939)399-99-99   @SourceTable: 1
Id: 5   Name: Jennifer Kent Phone: (11) 555-7647    @SourceTable: 1
Id: 6   Name: Sandy Manning Phone: (1) 354-2534 @SourceTable: 1
Id: 7   Name: Glenn Cunningham  Phone: 0522-556721  @SourceTable: 1
Id: 8   Name: Marcy Collins Phone: (14) 555-8122    @SourceTable: 1
Id: 9   Name: Kirsten Rosario   Phone: (930)930-30-93   @SourceTable: 1
Id: 10  Name: Merle Frank   Phone: (415) 555-5938   @SourceTable: 1
Id: 11  Name: Will Smith    Phone: (714) 256-0552   @SourceTable: 1
Id: 12  Name: John Doe  Phone: (612) 276-0136   @SourceTable: 1
Id: 13  Name: Ian G. Kim    Phone: (612) 276-0136   @SourceTable: 1
Id: 14  Name: Jermaine M. Miller    Phone: (814) 343-0945   @SourceTable: 1
Id: 15  Name: Jean C. Gates Phone: (757) 382-4391   @SourceTable: 1
Id: 16  Name: David M. Lee  Phone: (704) 718-1664   @SourceTable: 1
Id: 17  Name: Jennifer K. Jones Phone: (859) 491-4222   @SourceTable: 1
Id: 18  Name: Brian L. Rowles 124   Phone: (908) 385-7809   @SourceTable: 1
Id: 19  Name: Angela W. Vanover Phone: (610) 463-9999   @SourceTable: 1
Id: 20  Name: Anna H. Kugler    Phone: (817) 249-9525   @SourceTable: 1
Id: 21  Name: Randy R. Howard   Phone: (234) 567-8909   @SourceTable: 1
Id: 22  Name: Kenny S. Lay  Phone: (817) 249-9525   @SourceTable: 1
Id: 23  Name: Maryann C. Bachmann   Phone: (907) 722-6777   @SourceTable: 1
Id: 24  Name: Lillie R. Schroeder   Phone: (312) 476-1404   @SourceTable: 1
Id: 25  Name: Samuel V. Gibbons Phone: (408) 747-3579   @SourceTable: 1