Qore TableMapper Module Reference  1.1
TableMapper Module

TableMapper Module Introduction

Classes provided by this module:

TableMapper Examples

The following is an example map hash with comments:

1 const DataMap = (
2  # output column: "id" mapper from the "Id" element of any "^attributes^" hash in the input record
3  "id": "^attributes^.Id",
4  # output column: "name": maps from an input field with the same name (no translations are made)
5  "name": True,
6  # output column: "explicit_count": maps from the input "Count" field
7  "explicit_count": "Count",
8  # output column: "implicit_count": runs the given code on the input record and retuns the result, the code returns the number of "Products" sub-records
9  "implicit_count": int sub (any ignored, hash rec) { return rec.Products.size(); },
10  # output column: "order_date": converts the "OrderDate" string input field to a date in the specified format
11  "order_date": ("name": "OrderDate", "date_format": "DD.MM.YYYY HH:mm:SS.us"),
12  # output column: order_type: given as a constant value
13  "order_type": ("constant": "NEW"),
14 );

If this map is applied in the following way:

1 Table table(ds, "order_table");
2 InboundTableMapper map1(table, DataMap);
3 {
4  on_success map1.commit();
5  on_error map1.rollback();
6  # apply the map and insert the mapped data for each input record
7  map map1.insertRow($1), input;
8 }
9 printf("%d record%s inserted\n", map.getCount(), map.getCount() == 1 ? "" : "s");

This will insert all the mapped input data into data into the ORDER_TABLE table and then print out the number of rows inserted.

This is an example for TableMapper::SqlStatementOutboundMapper. It selects data from the ORDER_DATE and it transforms rows regarding mapping used.

1 # SqlUtil Table object
2 Table table(ds, "order_table");
3 # mapping definition
4 const DataMap = (
5  "id" : True,
6  "foo" : "name",
7  "bar" : ("code" : string sub (any ignored, hash rec) { return format_date("YYYYMMDD", rec."order_table"); } ),
8  );
9 # SqlUgtil select hash
10 hash sh = (
11  "columns" : ("id", "name", "order_date"),
12  "where" : ( "id" : op_gt(1000) ),
13  );
14 
15 SqlStatementOutboundMapper m(table, sh, DataMap);
16 on_exit m.commit();
17 
18 while (*hash h = m.getData()) {
19  do_something_with_data(h);
20 }

InboundTableMapper Bulk Insert API

InboundTableMapper Bulk Insert API Introduction

The bulk insert API allows for multiple rows to be mapped and inserted in a single server round trip for high-performance applications. This requires bulk DML support in the underlying DBI driver and also in SqlUtil (to determine if bulk DML support is available, call SqlUtil::AbstractTable::hasArrayBind() on the SqlUtil::AbstractTable object).

The bulk insert API consists of the following methods:

The behavior of the bulk insert API can be modified or tuned with the following options:

  • "insert_block": the number of rows inserted in a single block (default: 1000)
Note
The bulk insert API is only used when "unstable_input" is False and bulk DML is supported in the SqlUtil::AbstractTable object

InboundTableMapper Bulk Insert API Usage

To queue data for bulk insert, call TableMapper::InboundTableMapper::queueData() instead of TableMapper::InboundTableMapper::insert(). To perform per-row actions, the TableMapper::InboundTableMapper::setRowCode() method should be called with a closure that accepts a hash representing a single row; whenever data is flushed to the database, this closure will be called with the row actually inserted (including sequence values used, etc).

Before committing the transaction, ensure that TableMapper::InboundTableMapper::flush() is called for each TableMapper::InboundTableMapper object participating in the transaction. This ensures that all data has been flushed to the database before committing the transaction.

If there are any errors, call TableMapper::InboundTableMapper::discard() before rolling the transaction back.

Note
If an error occurs flushing data, the count is reset by calling Mapper::resetCount()

InboundTableMapper Bulk Insert API Examples

Consider the following example:

1 # table1 and table2 must use the same @ref Qore::SQL::Datasource "Datasource" or @ref Qore::SQL::DatasourcePool "DatasourcePool" to participate in the same transaction
2 TableMapper::InboundTableMapper map1(table1, maph1);
3 TableMapper::InboundTableMapper map2(table2, maph2);
4 
5 # the transaction only needs to be committed once
6 on_success table1.commit();
7 on_error table1.rollback();
8 
9 # ensure that data for each mapper is inserted and flushed before committing the transaction
10 {
11  on_success map1.flush();
12  on_error map1.discard();
13 
14  map map1.queueData($1), data1.iterator();
15 }
16 {
17  on_success map2.flush();
18  on_error map2.discard();
19 
20  map map2.queueData($1), data2.iterator();
21 }

TableMapper Specification Format

The mapper hash is made up of target (ie output) column names as the key values assigned to field specifications as specified in Mapper Specification Format, plus the following hash options:

  • "sequence": a name of a sequence to use to populate the column; the output buffers for this option are bound as type number, so the output type depends on the database driver's number option setting (for example, with "optimal-numbers", the values here are generally returned as strings)
  • "sequence_currval": a name of a sequence to use to return the current value of the sequence; this is useful when assigning the same sequence value to multiple columns; the output buffers for this option are bound as type number, so the output type depends on the database driver's number option setting (for example, with "optimal-numbers", the values here are generally returned as strings)

In both cases, the actual value inserted in the table is available in the following APIs:

Additionally, the value is provided to any row code set with TableMapper::InboundTableMapper::setRowCode(); see InboundTableMapper Bulk Insert API for more information.

Release Notes

TableMapper v1.1

TableMapper v1.0

  • Initial release.