If a typedef is not in-memory only then part of its declaration is to bind it to an i/o mechanism. Inq supports a syntax to define a resource that can be referred to symbolically in a typedef's i/o binding.
A resource definition creates a symbol in the current package name space and takes the following form:
<resource-definition> = resource <identifier> "(" <resource-type> "," <resource-limit> "," <resource-info> ")" ";" <resource-limit> = <integer-literal>
where resource-type is a key word and resource-info is specific to the resource-type.
Configuring SQL Servers
Inq presently supports only SQL servers for typedef persistence. In this case, the resource-type is the keyword sqlserver, resource-limit is the maximum number of connections Inq will keep open to the SQL server and resource-info is a map of well-known keys to configure the connection parameters, string formatting requirements and any idiosyncrasies of the SQL server itself. These keys are as follows:
- the user name that Inq will use when connecting to the SQL server;
- the password for the given user;
- the JDBC URL to connect to;
- a map of data types specifying how a null value should be rendered when using parameterised textual SQL;
- a map of data types specifying how a non-null value should be delimited when using parameterised textual SQL;
- a boolean value to handle a row count idiosyncrasy when writing typedef instances.
These map elements are discussed further in the examples below.
When performing i/o to read or write typedef instances, Inq will allocate a handle to the resource specified in that typedef's i/o binding. If all the available handles up to the resource-limit are presently in use then the executing transaction will wait for one to be released before proceeding.
A MySql Example
Here is an example of a resource definition for a MySql server running on localhost.
resource xy ( sqlserver, 50, map( "user", "xy1", "password", "xy1", "url", "jdbc:mysql://localhost/xydev", "null", map(date.class, "NULL", string.class, "NULL", decimal.class, "NULL", double.class, "NULL", float.class, "NULL", int.class, "NULL" ), "delim", map(date.class, "'", string.class, "'"), "cardinality", false ) );
Delimiters and Null Mappings
When discussing the use of plain text SQL statements in key configurations we saw how formatting the parameterised string sometimes required the use of format patterns. In fact, the requirements extend beyond this since it is also necessary to cater for NULL. Inq supports a mapping between its value types and a string value that will be used when the Inq variable has the value null. In this case, no formatting takes place and the string value is used verbatim.
To express strings and when formatting dates as strings, SQL implementations require the value to be quoted. While this can be expressed in the format pattern it would mean that strings (and not just date and floating point values) would require their own pattern, repeated everywhere in the plain text SQL. Instead, the i/o configuration allows these to be expressed by data type. They are only used when parameterising a plain text SQL statement.
Standard SQL defines the separate statements insert and update to respectively create and modify table rows. As we saw in the primary key examples, many SQL implementations support their own way of combining these two possibilities into a single statement. The Inq primary key of an instance must be unique so Inq performs a check when reading and writing to SQL repositories that this is so.
Unfortunately, the MySql replace returns a row count of 2 when the row already exists. If cardinality is set to false then Inq ingores the row count on writing. The cardinality check is always enforced when reading.
An Oracle Example
Here is an Oracle example:
resource xy ( sqlserver, 50, map( "user", "xyuser", "password", "xyuser05", "url", "jdbc:oracle:thin:@host.in.domain.com:1521:myServer", "null", map(date.class, "NULL", string.class, "NULL", decimal.class, "NULL", double.class, "NULL", float.class, "NULL", int.class, "NULL" ), "delim", map(date.class, "'", string.class, "'") ) );
As we see, there is little difference between this and the MySql version.
Parsing The Resource Definition
A resource must be defined before it is referenced in any typedef iobind clause. It is common to place resource definitions in separate files referenced using a parameterised #include<...>, so that they can be selected using command line arguments on server invovation.
Any number of SQL resources can be defined in this way, allowing an Inq server application to easily integrate disparate data sources.