Writers are terminated components of graph that writes data to output source. The source can be for example a file placed on local disk, ftp, ldap, jms or database tables, etc. Graph must contain at least one of these components or more.
Common attributes
| Attribute | Description | Example |
|---|---|---|
id | component identification | string |
type | component type. This attribute is automatically generated from gui. | string |
File writers
| Attribute | Description | Example |
|---|---|---|
append | whether to append data at the end if output file exists or replace it | false | true |
bytesPerFile | max size of output files. To avoid splitting a record to two files, max size could be slightly | number |
charset | character encoding of the output file | see locales encoding |
fileURL | path to the output file | ( [zip: | gzip:] [path/] filename ) | ( ftp://user:password@server [/path] /filename ) |
outputFieldNames | print names of individual fields into output file - as a first row | false | true |
recordsPerFile | max number of records in one output file | number |
recordCount | specifies how many records/rows should be written to the output file. | number |
recordSkip | specifies how many records/rows should be skipped before of writting the first record to the output file. | number |
Database writers
| Attribute | Description | Example |
|---|---|---|
dbTable/table | table to store the records | employee |
Reads data from input port and writes them to binary file in Clover internal format. With records can be saved indexes of records in binary file (for reading not all records afterward) and metadata definition. If compress level is not set to zero, data are saved in zip file with the structure:
DATA/fileName, INDEX/fileName.idx, METADATA/fileName.fmt
Input ports:
Output ports: none
Xml attributes:
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
id | yes | component identification | ||
type | yes | component type | CLOVER_WRITER | |
fileURL | yes | path to the output file | ||
append | no | whether to append data at the end if output file exists or replace it | false | |
saveIndex | no | indicates if indexes to records in binary file are saved or not | false | |
saveMetadata | no | indicates if metadata definition is saved or not | false | |
compressLevel | no | sets the compression level. The compression level is 0-9. The default setting is to compress using default ZIP compression level. | -1 | |
recordSkip | no | specifies how many records/rows should be skipped before of writting the first record to the output file. | 0 | |
recordCount | no | specifies how many records/rows should be written to the output file. | ∞ | |
makeDirs | no | if true, creates directories to the output file if the directories don't exist | false | 2.8 |
Example:
<Node id="CLOVER_WRITER0" fileURL="customers.clv" type="CLOVER_WRITER"/> <Node id="CLOVER_WRITER0" type="CLOVER_WRITER" fileURL="customers.clv" compressLevel="0" saveIndex="true" saveMetadata="true" />
All records from input port [0] are formatted to the delimited or fixlen form and written to specified file. Type of formatting is taken from metadata specified for port[0] data flow.
Input ports:
Output ports:
* one optional output port defined/connected (port protocol see fileURL).
Xml attributes:
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
id | yes | component identification | ||
type | yes | component type | DATA_WRITER | |
fileURL | yes | path to the output file including the name. Example: path/out. Or: path/some#string.txt (an # serves as placeholder for numberFileTag or keyNameFileTag). If numberFileTag is set (the default value), number of # equals to the number of digits. Thus, ### can go from 000 to 999. | ||
append | no | whether to append data at the end if output file exists or replace it | false | |
charset | no | character encoding of the output file | ISO-8859-1 | |
outputFieldNames | no | print names of individual fields into output file - as a first row | false | |
bytesPerFile | no | max size of output files. To avoid splitting a record to two files, max size could be slightly overreached. | ∞ | |
recordsPerFile | no | max number of records in one output file | ∞ | |
recordSkip | no | specifies how many records/rows should be skipped before of writting the first record to the output file. | 0 | |
recordCount | no | specifies how many records/rows should be written to the output file. | ∞ | |
partitionKey | no | sequence of field names from incoming data flow (separated by semicolon). Data records with different partitionKey values are saved to different output files. The names of these different output files differ from each other by additional numbers or distinguishing names depending on the value of partitionFileTag attribute. Example of partitionKey: FirstName;SecondName. | ||
partition | if and only if partitionOutFields is set | name of the lookup table that will serve to group output data records and provide distinguishing names for output file names. | ||
partitionFileTag | no | possible values: numberFileTag or keyNameFileTag. If set to numberFileTag, output file names accept additional numbers appended to the base file name specified in the fileURL attribute (“out”, in the example mentioned above). If set to keyNameFileTag, output file names accept distinguishing names appended to the base file name specified in the fileURL attribute (the mentioned “out”). In case of the partitionKey mentioned above, all “John Smiths” are saved to one file, all “Peter Browns” to another. The names can be either “path/out27” and “path/out34”, for example, (partitionFileTag is set to numberFileTag), respectively, or they can be “path/outJohnSmith” and “path/outPeterBrown” (partitionFileTag is set to keyNameFiletag), respectively. | numberFileTag | |
partitionOutFields | if and only if partition is set | sequence of field names from the lookup table specified in the partition attribute (separated by semicolon). If user wants to group data records and/or give the output files different names than those specified in the partitionKey attribute, she needs to use a lookup table whose key values can be equal to the mentioned partitionKey. All records whose partitionKey values are not equal to the lookup table key values are saved together to a single file named according to the partitionUnassignedFileName value. If this file is not specified, such records are discarded. The other records are distributed to different output files according to different values of partitionKey (which are equal to the values of the lookup table key) and the values of the specified partitionOutFields serve as distinguishing names. Thus, the names of the other output files (those assigned) are as follows: “path/outpartitionOutFieldsvalues”. The values of individual fields of the partitionOutFields attribute are converted to strings and concatenated automatically to create the distinguishing names. | ||
partitionUnassignedFileName | no | user defined name of new file. The file will be created if a lookup table is specified and there is at least one record for which doesn't exist a key in the lookup table. These type of records will be written to the file. If the partitionUnassignedFileName is empty, the records will be discarded. | 2.8 | |
makeDirs | no | if true, creates directories to the output file if the directories don't exist | false | 2.8 |
excludeFields | no | sequence of field names from incoming data flow (separated by semicolon) to exclude from writing | 2.9 |
Example:
<Node id="Writer" type="DATA_WRITER" fileURL="/tmp/transfor.out" /> <Node id="Writer" type="DATA_WRITER" fileURL="/tmp/transfor.out" append="true" charset="UTF-8" outputFieldNames="true" bytesPerFile="1000000" recordsPerFile="10000" recordSkip="10" recordCount="100" /> Partition usage examples: - without lookup table <Node fileURL="${DATAOUT_DIR}/orders" id="DATA_WRITER0" partitionKey="ShippedDate" type="DATA_WRITER"/> - with lookup table <Metadata id="Metadata2"> <Record fieldDelimiter="|" name="data" recordDelimiter="\n" type="delimited"> <Field name="dataKey" type="integer"/> <Field name="data" type="string"/> </Record> </Metadata> <Metadata id="Metadata1"> <Record fieldDelimiter="|" name="lookup" recordDelimiter="\n" type="delimited"> <Field name="lookupKey" type="integer"/> <Field name="value" type="string"/> </Record> </Metadata> <LookupTable id="LookupTable0" key="lookupKey" metadata="Metadata1" name="Files" type="simpleLookup"/> . . . <Node fileURL="${DATAOUT_DIR}/" id="DATA_WRITER0" partition="LookupTable0" partitionFileTag="keyNameFileTag" partitionKey="dataKey" partitionOutFields="value" type="DATA_WRITER"/>
This component performs specified DML operation (insert/update/delete) on specified database table. The metadata describing data comming in through input port[0] must be in the same structure as the target table. Parameter placeholder in DML statemet is [?] - questionmark.
Input ports:
Output ports: * 0 - records rejected by database. If in this metadata there is more fields then in input metadata and last field is of type string, this field is filled by error message. Since 2.6 version component finds fields with autofilling=“ErrCode” and autofilling=“ErrText” and fills them with requested value.
Xml attributes:
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
id | yes | component identification | ||
type | yes | component type | DB_OUTPUT_TABLE | |
dbConnection | yes | id of the Database Connection object to be used to access the database | ||
dbTable | if no sqlQuery and no url | name of the DB table to populate data with | ||
sqlQuery | if no dbTable and no url | allows specification of SQL query/DML statement to be executed against database. It can consist of more then one query separated by semicolon [;]. Question marks [?] in the query text are placeholders which are filled with values from input fields specified in cloverFields attribute. If you have query in this form, cloverFields must be specified as well - it determines which input fields will be used/mapped onto target fields. From ver. 2.4 you can write query with direct mapping too: instead of placeholders use clover field's names predated by dollar char [$]. In such form you can use mapping between generated keys and output record with this keys too. Complete query should appear as follows:insert into mytable [(f1,f2,...,fn)] values (val1, $field2, ...,$fieldm ) returning $key := dbfield1, $field := dbfield2- where f1,f2,…,fn,dbfield1,dbfield2 are database fields; field2,.., fieldm are input record fields and key, field are key record fields. This is valid for databases which can return more then one columns in getGeneratedKeys() method (Oracle and db2 for the time beeing). insert into mytable [(f1,f2,...,fn)] values (val1, $field2, ...,$fieldm ) returning $key := auto_generated, $field := infield- where f1,f2,…,fn are database fields; field2,.., fieldm, infield are input record fields, auto_generated is auto genereted column value returned by database and key, field are key record fields. This is valid for databases which returns one auto generated column in getGeneratedKeys() method (MySql and Informix for the time being). delete from mytable where f1 = $field1 and ... fn = $fieldn- where f1,..,fn are database fields and field1,…,fieldn are input record fields update mytable set f1 = $field1,...,fn=$fieldn- where f1,..,fn are database fields and field1,…,fieldn are input record fields. Since 2.6 version it is possible to get number of records updated in database by current query (with current data record): update mytable set f1 = $field1,...,fn=$fieldn returning $outField:=update_countWhen db object name contains '$' it is possible to escape it by '$$' sice 2.7 ver. | ||
url | if no dbTable and no sqlQuery | url location of the query. The query will be loaded from file referenced by the url. Rules for extern query are the same as for sqlQuery parameter. | ||
charset | no | encoding of extern query. | ISO-8859-1 | |
fieldMap | no | pairs of clover fields and db fields (cloverField=dbField) separated by :;| {colon, semicolon, pipe}. It specifies mapping from source (Clover's) fields to DB table fields. It should be used instead of cloverFields and dbFields attributes, because it provides more clear mapping. If fieldMap attribute is found cloverFields and dbFields attributes are ignored. It is prescribed to use standard mapping syntax since 2.5 version: clover fields are preceded by $, mappings are separated by :;| {colon, semicolon, pipe} and assignment sign is :=, eg.: $field1:=dbField1;$field2:=dbField2 | ||
dbFields | no | delimited list of target table's fields to be populated. Input fields are mappend onto target fields (listed) in the order they are present in Clover's record. | ||
commit | no | determines how many records are in one db commit. Minimum 1. If MAX_INT is specified, it is considered as NEVER COMMIT - i.e. records are send to DB without every issuing commit. It can be called later from withing other component - for example DBExecute. | 100 | |
cloverFields | no | delimited list of input record's fields.Only listed fields (in the order they appear in the list) will be considered for mapping onto target table's fields. Combined with dbFields option you can specify mapping from source (Clover's) fields to DB table fields. If no dbFields are specified, then #of cloverFields must correspond to number of target DB table fields. | ||
batchMode | no | [Yes/No] determines whether to use batch mode for sending statemetns to DB. Note1:If your database/JDBC driver supports this feature, switch it on as it significantly speeds up table population. Note2: in batch mode number of records rejected by database can differ from number of records sent to rejected port - some db drivers mark all records in batch as rejected although some of them were inputted to database (eg. oracle driver puts to database all records before the invalid one, but all records in batch are marked as rejected). | No | |
batchSize | no | determines how many records will be sent to database in one batch update. | 25 | |
maxErrors | no | maximum number of allowed SQL errors. If exceeded, component stops with error. If set to -1(minus one) all errors are ignored. | 0 | |
SQLCode | no | Xml tag! This tag allows for embedding large SQL statement directly into graph. | ||
autoGeneratedColumns | deprecated - use sqlQuery extended form | This attribute can be used for obtaining auto generated columns, but only in case that sqlQuery consist of only one query. In other case construct queries with direct mapping.* For Oracle or Db2 database: names of database columns to be returned (for Db2 - entity columns) * For MySQL or Informix database: names of input record fields plus special field called "AUTO_GENERATED" to be returned | ||
errorAction | no | ROLLBACK or COMMIT (case sensitive!!!). Default: COMMIT. Action performed when exceeded maximum number of records or execution of the component is aborted. Behavior of this attribute may be platform dependent. Storage engine has to be innoDB on MySQL database, otherwise DB commits automatically each statement. MS SQL server performs automatic rollback after failed query. | COMMIT | |
atomicSQL | no | Sets atomicity of executing SQL queries. If set to true, all SQL queries for one record are executed as atomic operation, but value of commit attribute is ignored and commit is performed after each record. | 2.8.1 |
Examples:
<Node id="OUTPUT" type="DB_OUTPUT_TABLE" dbConnection="NorthwindDB" dbTable="employee_z"/> - example shows how to populate only selected fields within target DB table. It can be used for skipping target fields which are automatically populated by DB (such as autoincremented fields). <Node id="OUTPUT" type="DB_OUTPUT_TABLE" dbConnection="NorthwindDB" dbTable="employee_z" dbFields="f_name;l_name;phone"/> - example shows how to simply map Clover's LastName and FirstName fields onto f_name and l_name DB table fields. The order in which these fields appear in Clover data record is not important. <Node id="OUTPUT" type="DB_OUTPUT_TABLE" dbConnection="NorthwindDB" dbTable="employee_z" dbFields="f_name;l_name" cloverFields="LastName;FirstName"> </Node> <Node id="OUTPUT" type="DB_OUTPUT_TABLE" dbConnection="NorthwindDB" sqlQuery="insert into myemployee2 (FIRST_NAME,LAST_NAME,DATE,ID) values (?,?,sysdate,123)" cloverFields="FirstName;LastName"> </Node> <Node id="OUTPUT" type="DB_OUTPUT_TABLE" dbConnection="NorthwindDB" cloverFields="FirstName;LastName"> <attr name="SQLCode">insert into myemployee2 (FIRST_NAME,LAST_NAME,DATE,ID) values (?,?,sysdate,123)</attr> </Node> - example below shows how to delete records in table using DBOutputTable component <Node id="OUTPUT" type="DB_OUTPUT_TABLE" dbConnection="NorthwindDB" cloverFields="FirstName;LastName"> <attr name="SQLCode">delete from myemployee2 where FIRST_NAME = ? and LAST_NAME = ?</attr> </Node> - examples below show usage of "fieldMap" attribute <Node id="OUTPUT" type="DB_OUTPUT_TABLE" dbConnection="DBConnection0" dbTable="employee_tmp" fieldMap="EMP_NO=emp_no;FIRST_NAME=first_name;LAST_NAME=last_name;PHONE_EXT=phone_ext"> </Node> <Node id="OUTPUT" type="DB_OUTPUT_TABLE" dbConnection="DBConnection0" dbTable="employee_tmp" fieldMap="$EMP_NO:=emp_no;$FIRST_NAME:=first_name;$LAST_NAME:=last_name;$PHONE_EXT:=phone_ext"> </Node> - example below shows how to get aoutogenerated columns <Node dbConnection="Connection1" id="OUTPUT" maxErrors="10" sqlQuery= "INSERT INTO USER (U_ID,NAME ,CREATED) values ($EMP_NO, $FULL_NAME, $HIRE_DATE); INSERT INTO MYEMPLOYEE (EMP_NO, FIRST_NAME, LAST_NAME,COUNTRY, SALARY, FULL_NAME) VALUES ($EMP_NO, $FIRST_NAME, $LAST_NAME, $COUNTRY, $SALARY, $FULL_NAME) RETURNING $id:=auto_generated, $Field2:=full_name;" type="DB_OUTPUT_TABLE"/> <Node dbConnection="Connection1" id="OUTPUT" maxErrors="10" sqlQuery= "DELETE FROM USER WHERE U_ID = $EMP_NO; INSERT INTO MYEMPLOYEE (ID, EMP_NO, FIRST_NAME, LAST_NAME,COUNTRY, SALARY, FULL_NAME) VALUES (id_seq.nextval, $EMP_NO, $FIRST_NAME, $LAST_NAME, $COUNTRY, $SALARY, $FULL_NAME) RETURNING $id:=ID, $Field2:=FIRST_NAME;" type="DB_OUTPUT_TABLE" errorAction="ROLLBACK"/> <Node autoGeneratedColumns="ID;FIRST_NAME;" dbConnection="DBConnection2" id="OUTPUT" maxErrors="10" sqlQuery="INSERT INTO myemployee VALUES (id_seq.nextval, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" type="DB_OUTPUT_TABLE"> </Node>
since 2.8.0
This component can be used to send email messages from a graph. Messages to be sent are read as input records. Each message can have one or more attachments.
Input ports:
Output ports:
This component reads input records, extracts recipient address(es), subject and message body from the record and sends the message out. Default values for all headers can be specified so common e-mail attributes can be specified at design time. Successfully sent messages are passed through the component to port 0. Incomplete or rejected messages are sent to port 1 for debugging (see Debugging options).
Xml attributes:
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
id | yes | component identification | ||
type | yes | component type | EMAIL_SENDER | |
smtpServer | yes | SMTP server for outgoing mail | ||
smtpPort | no | SMTP port | 25 | |
smtpUser | no | SMTP username for authenticated servers | ||
smtpPassword | no | SMTP password for authenticated servers | ||
smtpTLS | no | SMTP server uses TLS | false | |
smtpSSL | no | Use SSL to connect to SMTP server | false | |
trustHost | no | Trust invalid certificate of SMTP server (expired, different name, etc.) | false | |
message | yes | Set of properties defining message headers and body | ||
attachments | no | Set of properites defining message attachments | ||
ignoreSendFail | no | When set to true, sending errors are logged but ignored | false |
Notes
message attribute is a set of header fields: From, To, Cc, Bcc, Subject, additional headers and MessageBody. All these properties can be set either as field values or static text which is used when field is not set or its value is empty. See Setting properties.attachments attribute is a list of attachments - either specified by file name or by triplet [ fieldName, name, mimeType ] for attachments whose data come from record field - in this case `name` a `mimeType` must to be specified.smtpTLS and/or smtpSSL, especially for self-signed SMTP server. You have two options - either add the server's certificate to Java default keystore which might be a lot of work or just name your smtpServer in trustedHosts attribute. This ways TLS/SSL layer will treat the server's certificate as valid even if it is not.Debugging options
EmailSender can detect messages that are rejected by the underlying transport layer and send notification about these failures to output port 1.
There can be arbitrary metadata on output port 1. However, an attempt to copy input record fields into output port 1 record is made. Additionally, if the metadata contain
special field errorMessage, then text of the error message is copied into this field.
Setting properties
Properties in message (and attachments) can contain static text and values extracted from record fields. A field value is denoted by $<field_name> construct.
For example: Let a property value be “I am $name” and field `name` in a record has a value “Peter”. Then resulting value
for that property would be “I am Peter”.
Property values can have alternatives. An alernative is used when previous one contains field values which resolve to empty or null strings.
Alternatives are separated by | (pipe) character (which can be escaped \| in which case it is treated as usually).
Let's see an example: Let a property be defined as “I am $name1|My other name is $name2”. If record field `name` resolves to “Peter” then
resulting value is again “I am Peter”. But if `name` is empty, then the other alternative is used (in case `name2` resolves to “Jones”) and
result is “My other name is Jones”. Good practise is to add a last alternative without field value so that it will always resolve to a meaningful value - e.g. “I am $name1|My other name is $name2|I don't know my name”
Attachments
Attachments are specified as a list separated by ; semicolon) of files or record fields which hold attachment data.
Each entry in the list can be either a filename (e.g. /home/peter/myfile.pdf) or a triplet containing field name, attachment file name and its mime type. Example show how attachments might look like:
Examples
Attachments Example 1 - two files from a file system attachments="/home/peter/myfile.pdf;/tmp/generatedfile.txt" Attachments Example 2 - two files from a file system, one being passed as a record field value attachments="/home/peter/myfile.pdf;$recordFileNameField" Attachments Example 3 - two files from a file system, one being passed as a record field value with an alternative (see Setting properties) attachments="/home/peter/myfile.pdf;$recordFileNameField|/share/defaultFile.pdf" Attachments Example 4 - using data in record field `recordFileData`, specify file name as static text "myfile.pdf" and appropriate mime type attachments="[$recordFileData,myfile.pdf,application/pdf]" Attachments Example 5 - using data in record field - specify all attachment properties in record field attachments="[$attachmentDataField,$attachmentNameField,$attachmentMimeTypeField]" Attachments Example 6 - combined example attachments="/share/staticAttachment.pdf;$fileSystemFileField,[$attachmentDataField,$attachmentNameField,$attachmentMimeTypeField]" Simple example - possibly insecure password, To: and message body are read from record, other parts are static <Node id="EMAIL_SENDER0" type="EMAIL_SENDER" smtpServer="smtp.yourisp.com" smtpUser="yourid@yourisp.com" smtpPassword="mypass" message="From=CloverETL test <mytest@yourisp.com> To=$fieldRecipient Subject=Hello, this is a test message body=$fieldMessageBody"/> Advanced example - with password in a parameter and default values for missing record field values <Node id="EMAIL_SENDER1" type="EMAIL_SENDER" smtpServer="smtp.yourisp.com" smtpUser="yourid@yourisp.com" smtpPassword="${SMTP_PASSWORD}" message="From=$fieldFrom|CloverETL test <mytest@yourisp.com> To=$fieldRecipient Subject=$fieldSubject|This is default subject body=$fieldMessageBody|Message body seems empty"/>
Transforms incoming data records to JMS messages using user-specified transformation class (so-called processor). The processor is supposed to implement interface DataRecord2JmsMsg. The processor implements a DataRecord2JmsMsg interface or inherits from a DataRecord2JmsMsgBase class. The processor may be specified either by class name or by inline Java code.
Default implementation of the processor org.jetel.component.jms.DataRecord2JmsMsgProperties is sufficient in most cases. It produces javax.jms.TextMessage. Body of the message is filled by content of field which is specified by bodyField component attribute. The other fields from input record are added to the message as properties.
Properties have the same names as fields.
Input ports:
Output ports: none
Xml attributes:
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
id | yes | component identification | ||
type | yes | component type | JMS_WRITER | |
connection | yes | JMS connection ID | ||
processorClass | no | Name of processor class. Default value is applied only if processorCode and processorURL aren't specified | org.jetel.component.jms.DataRecord2JmsMsgProperties | |
processorCode | no | Inline Java code defining processor class. It's applied only if processorClass isn't specified. | ||
processorURL | no | URL to file with java code defining processor class. It's applied only if processorClass and processorCode aren't specified | ||
charset | no | Charset of processor code, if it's specified by processorURL attribute. | Default is taken from CloverETL engine defaults | |
bodyField | no | Name of field in output record metadata, which should be filled by body of incoming JMS message. This attribute is used by default processor implementation (JmsMsg2DataRecordProperties). If value of “bodyField” attribute is specified, there must be such field in metadata. If value isn't specified, processor tries to set field named “bodyField”, but it's silently ignored if such field doesn't exist in output record metadata. | bodyField (since 2.8 - older versions don't have any default) |
Example:
<Node id="JmsWriter" type="JMS_WRITER" connection="dest" />
Provides the logic to update information on an LDAP directory. An update can be add/delete entries, add/replace/remove attributes. Metadata MUST match LDAP object attribute name. “DN” metadata attribute is mandatory. String and byte are the only metadata type supported. Most of the LDAP tpyes are compatible with clover string, however for instance the userPassword LDAP type is necessary to populate from byte data field. LDAP rules are applied : to add an entry, mandatory attribute (even object classe) are requiered in metadata.
Comment:
LDAP attribute may be multivaluated. Default value separator is “|” and is reasonable only for string data fields.
Input ports:
Output ports:
* one optional port defined/connected, for rejected records.
Xml attributes:
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
id | yes | component identification | ||
type | yes | component type | LDAP_WRITER | |
ldapUrl | yes | Ldap url of the directory, on the form “ldap://host:port/” | ||
action | yes | Choose one of these options: add_entry, remove_entry, replace_attributes, remove_attributes | ||
user | no | The user DN to used when connecting to directory. | ||
password | no | The password to used when connecting to directory. | ||
multiValueSeparator | no | multi-value separator, __none__ is special escape value to turn off multi-value separating | | |
Example:
<Node enabled="enabled" id="LdapWriter" type="LDAP_WRITER" action="add_entry" />
commercial component since 2.8.0
Batch data record writer to QuickBase online database (http://quickbase.intuit.com/). This component wrapps the API_ImportFromCSV HTTP interaction (https://www.quickbase.com/up/6mztyxu8/g/rc7/en/#_Toc126580055).
Input ports:
Output ports:
Xml attributes:
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
id | yes | component identification | ||
type | yes | component type | QUICKBASE_RECORD_WRITER | |
connection | yes | QuickBase connection identifier | ||
tableId | yes | QuickBase table identifier | ||
batchSize | no | number of records committed at once (in one batch) | 100 | |
clist | yes | A period delimited list of field IDs to which the input fields map. This means that the first field ID in the list maps to the first input field, the second field ID maps to the second input field, and so forth. To prevent an input field from being imported, enter a 0 in the field ID list. | ||
errorCodeField | no | field name of error metadata where error code will be stored | ||
errorMessageField | no | field name of error metadata where error message will be stored | ||
batchNumberField | no | field name of error metadata where sequence number of currupted batch will be stored |
Example:
<Node id="QUICKBASE_RECORD_WRITER0" type="QUICKBASE_RECORD_WRITER" connection="QuickBaseConnection0" tableId="begz47brm" batchSize="10" errorCodeField="errorCode" errorMessageField="errorMessage" batchNumberField="batchNumber"/>
commercial component since 2.8.0
Simple data record writer to QuickBase online database (http://quickbase.intuit.com/). This component wrapps the API_AddRecord HTTP interaction (https://www.quickbase.com/up/6mztyxu8/g/rc7/en/#_Toc126579962).
Input ports:
Output ports:
Xml attributes:
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
id | yes | component identification | ||
type | yes | component type | QUICKBASE_RECORD_WRITER | |
connection | yes | QuickBase connection identifier | ||
tableId | yes | QuickBase table identifier | ||
mapping | yes | semicolon separated list of field identifiers of output table (names or ids) | ||
errorCodeField | no | field name of error metadata where error code will be stored | ||
errorMessageField | no | field name of error metadata where error message will be stored |
Example:
<Node id="QUICKBASE_RECORD_WRITER0" type="QUICKBASE_RECORD_WRITER" connection="QuickBaseConnection0" tableId="begz47brm" mapping="7;9;13;6;10;8" errorCodeField="errorCode" errorMessageField="errorMessage"/>
All records from input port [0] are formatted due to given mask and written to specified file. Records can be preceded by some text (header) or be trailed by a text (footer)
Input ports:
Output ports:
Xml attributes:
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
id | yes | component identification | ||
type | yes | component type | STRUCTURE_WRITER | |
fileURL | yes | Output files mask. Use wildcard '#' to specify where to insert sequential number of file. Number of consecutive wildcards specifies minimal length of the number. Name without wildcard specifies only one file. When some partitioning of the output is defined, fileURL serves as base file name to which a distinguishing name is added. Example: path/out. Or: path/some#string.txt (an # serves as placeholder for numberFileTag or keyNameFileTag). If numberFileTag is set (the default value), number of # equals to the number of digits. Thus, ### can go from 000 to 999. | ||
mask | yes | template for formating records. Every occurrence of $fieldName will be replaced by value of the fieldName. The rest of text will be unchanged. If not given there is used default mask: <recordName field1=$field1 field2=$field2 … fieldn=$fieldn /> where field1 ,.., fieldn are record's fields from metadata | ||
append | no | whether to append data at the end if output file exists or replace it (true/false) | false | |
charset | no | character encoding of the output file (if not specified, then ISO-8859-1 is used) | ISO-8859-1 | |
header | no | text to write before records | ||
footer | no | text to write after records | ||
bytesPerFile | no | max size of output files. To avoid splitting a record to two files, max size could be slightly overreached. | ∞ | |
recordsPerFile | no | max number of records in one output file | ∞ | |
recordSkip | no | specifies how many records/rows should be skipped before of writting the first record to the output file. | 0 | |
recordCount | no | specifies how many records/rows should be written to the output file. | ∞ | |
partitionKey | no | sequence of field names from incoming data flow (separated by semicolon). Data records with different partitionKey values are saved to different output files. The names of these different output files differ from each other by additional numbers or distinguishing names depending on the value of partitionFileTag attribute. Example of partitionKey: FirstName;SecondName. | ||
partition | if and only if partitionOutFields is set | name of the lookup table that will serve to group output data records and provide distinguishing names for output file names. | ||
partitionFileTag | no | possible values: numberFileTag or keyNameFileTag. If set to numberFileTag, output file names accept additional numbers appended to the base file name specified in the fileURL attribute (“out”, in the example mentioned above). If set to keyNameFileTag, output file names accept distinguishing names appended to the base file name specified in the fileURL attribute (the mentioned “out”). In case of the partitionKey mentioned above, all “John Smiths” are saved to one file, all “Peter Browns” to another. The names can be either “path/out27” and “path/out34”, for example, (partitionFileTag is set to numberFileTag), respectively, or they can be “path/outJohnSmith” and “path/outPeterBrown” (partitionFileTag is set to keyNameFiletag), respectively. | numberFileTag | |
partitionOutFields | if and only if partition is set | sequence of field names from the lookup table specified in the partition attribute (separated by semicolon). If user wants to group data records and/or give the output files different names than those specified in the partitionKey attribute, she needs to use a lookup table whose key values can be equal to the mentioned partitionKey. All records whose partitionKey values are not equal to the lookup table key values are saved together to a single file named according to the partitionUnassignedFileName value. If this file is not specified, such records are discarded. The other records are distributed to different output files according to different values of partitionKey (which are equal to the values of the lookup table key) and the values of the specified partitionOutFields serve as distinguishing names. Thus, the names of the other output files (those assigned) are as follows: “path/outpartitionOutFieldsvalues”. The values of individual fields of the partitionOutFields attribute are converted to strings and concatenated automatically to create the distinguishing names. | ||
partitionUnassignedFileName | no | user defined name of new file. The file will be created if a lookup table is specified and there is at least one record for which doesn't exist a key in the lookup table. These type of records will be written to the file. If the partitionUnassignedFileName is empty, the records will be discarded. | 2.8 | |
makeDirs | no | if true, creates directories to the output file if the directories don't exist | false | 2.8 |
Example:
<Node id="STRUCTURE_WRITER0" type="STRUCTURE_WRITER" fileURL="structured_customers.txt"> <Node id="STRUCTURE_WRITER0" type="STRUCTURE_WRITER" fileURL="structured_customers.txt" append="true"> <attr name="header">$Filedname0; $Filedname1;</attr> <attr name="mask"> <![CDATA[ <Customer id=$customer_id> <last name = $lname> <first name = $fname> </Customer> ]]> </attr> <attr name="footer">end of file</attr> </Node>
All records from input port [0] are formatted to table and written to specified file or on screen.
Input ports:
Output ports:
Xml attributes:
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
id | yes | component identification | ||
type | yes | component type | TEXT_TABLE_WRITER | |
fileURL | yes | Output files mask. Use wildcard '#' to specify where to insert sequential number of file. Number of consecutive wildcards specifies minimal length of the number. Name without wildcard specifies only one file. | ||
mask | no | template for selected fields. Mask for fields is: field1;field2;…fieldn, where field1,.., fieldn are record's fields from metadata | ||
outputFieldNames | no | print names of individual fields into output file - as a first row | false | |
append | no | whether to append data at the end if output file exists or replace it (true/false) | false | |
charset | no | character encoding of the output file (if not specified, then ISO-8859-1 is used) | ISO-8859-1 | |
bytesPerFile | no | max size of output files. To avoid splitting a record to two files, max size could be slightly overreached. | ∞ | |
recordsPerFile | no | max number of records in one output file | ∞ | |
recordSkip | no | specifies how many records/rows should be skipped before of writting the first record to the output file. | 0 | |
recordCount | no | specifies how many records/rows should be written to the output file. | ∞ |
Example:
<Node id="TEXT_TABLE_WRITER0" type="TEXT_TABLE_WRITER" fileURL="customers.txt" mask="Field0;Field1"/>
All records from input port:0 are discarded. This component is deemed for debugging !
Input ports:
Output ports: none
Xml attributes:
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
id | yes | component identification | ||
type | yes | component type | TRASH | |
debugPrint | no | indicates whether input records should be printed to stdout. | false (no print) | |
debugFilename | no | filename - if defined, debugging output is sent to this file. | ||
printTrashID | no | if true, prints trash ID | false | 2.8 |
makeDirs | no | if true, creates directories to the output file if the directories don't exist | false | 2.8 |
Example:
<Node id="TRASH0" type="TRASH"/> <Node id="TRASH0" type="TRASH" debugPrint="true" debugFilename="file.log" />
Reads data from input port and writes them to given xls sheet in xls file. If in one graph you want to write to the same file but to different sheets each XLSWriter has to have another phase
JExcel can handle with files up to ~5.7MB in flat file - for more data you have to set more memory for jvm.
Input ports:
Output ports:
Xml attributes:
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
id | yes | component identification | ||
type | yes | component type | XLS_WRITER | |
formatter | no | The type of a XLS(X) formatter. Possible values: 'auto' for automatic selection of a formatter based on a file extension, 'XLS' for a classic XLS formatter, 'XLSX' for a XLSX formatter. | auto | |
fileURL | yes | path to the output file. When some partitioning of the output is defined, fileURL serves as base file name to which a distinguishing name is added. Example: path/out. Or: path/some#string.xls, path/somestring#.xlsx (an # serves as placeholder for numberFileTag or keyNameFileTag). If numberFileTag is set (the default value), number of # equals to the number of digits. Thus, ### can go from 000 to 999. | ||
namesRow | no | index of row, where to write metadata names | 0 | |
firstDataRow | no | index of row, where to write first data record | 1 | |
firstColumn | no | code of column from which data will be written | A | |
sheetName | no | name of sheet for writing data. If it is not set new sheet with default name is created. From ver. 2.4 it can be list of input metadata field's names preceded by dollar [$] and separated by :;| {colon, semicolon, pipe}. Then for different key values there are created separated sheets. | ||
sheetNumber | no | number of sheet for writing data (starting from 0). If it is not set new sheet with default name is created. If sheetName and sheetNumber are both set, sheetNumber is ignored | ||
append | no | indicates if given sheet exist new data are append to the sheet or old data are deleted and rewritten by new ones | false | |
removeSheets | no | indicates if all sheets are to be removed from a file | false | |
recordsPerFile | no | max number of records in one output file new sheet with default name is created | ∞ | |
recordSkip | no | specifies how many records/rows should be skipped before of writting the first record to the output file. | 0 | |
recordCount | no | specifies how many records/rows should be written to the output file. | ∞ | |
partitionKey | no | sequence of field names from incoming data flow (separated by semicolon). Data records with different partitionKey values are saved to different output files. The names of these different output files differ from each other by additional numbers or distinguishing names depending on the value of partitionFileTag attribute. Example of partitionKey: FirstName;SecondName. | ||
partition | if and only if partitionOutFields is set | name of the lookup table that will serve to group output data records and provide distinguishing names for output file names. | ||
partitionFileTag | no | possible values: numberFileTag or keyNameFileTag. If set to numberFileTag, output file names accept additional numbers appended to the base file name specified in the fileURL attribute (“out”, in the example mentioned above). If set to keyNameFileTag, output file names accept distinguishing names appended to the base file name specified in the fileURL attribute (the mentioned “out”). In case of the partitionKey mentioned above, all “John Smiths” are saved to one file, all “Peter Browns” to another. The names can be either “path/out27” and “path/out34”, for example, (partitionFileTag is set to numberFileTag), respectively, or they can be “path/outJohnSmith” and “path/outPeterBrown” (partitionFileTag is set to keyNameFiletag), respectively. | numberFileTag | |
partitionOutFields | if and only if partition is set | sequence of field names from the lookup table specified in the partition attribute (separated by semicolon). If user wants to group data records and/or give the output files different names than those specified in the partitionKey attribute, she needs to use a lookup table whose key values can be equal to the mentioned partitionKey. All records whose partitionKey values are not equal to the lookup table key values are saved together to a single file named according to the partitionUnassignedFileName value. If this file is not specified, such records are discarded. The other records are distributed to different output files according to different values of partitionKey (which are equal to the values of the lookup table key) and the values of the specified partitionOutFields serve as distinguishing names. Thus, the names of the other output files (those assigned) are as follows: “path/outpartitionOutFieldsvalues”. The values of individual fields of the partitionOutFields attribute are converted to strings and concatenated automatically to create the distinguishing names. | ||
partitionUnassignedFileName | no | user defined name of new file. The file will be created if a lookup table is specified and there is at least one record for which doesn't exist a key in the lookup table. These type of records will be written to the file. If the partitionUnassignedFileName is empty, the records will be discarded. | 2.8 | |
makeDirs | no | if true, creates directories to the output file if the directories don't exist | false | 2.8 |
Example:
<Node id="XLS_WRITER0" type="XLS_WRITER" fileURL="orders.xls"/> <Node id="XLS_WRITER0" type="XLS_WRITER" fileURL="orders.xls" firstColumn="f" namesRow="2" sheetName="via1" /> <Node id="XLS_WRITER0" type="XLS_WRITER" fileURL="orders.xls" firstColumn="f" namesRow="2" sheetName="via1" /> <Node id="XLS_WRITER1" type="XLS_WRITER" fileURL="orders.xls" firstDataRow="10" sheetName="via2" /> <Node id="XLS_WRITER2" type="XLS_WRITER" append="true" fileURL="orders.xls" namesRow="1" firstDataRow="3" sheetName="via3" /> <Node append="true" fileURL="out.xls" firstDataRow="3" id="XLS_WRITER0" namesRow="1" sheetName="$Field1;$Field2" type="XLS_WRITER" />
Since version 2.4
Reads data records from any number of input ports and creates structured XML file(s),
according to ports mapping definition. Overwrites existing files.
Input ports: * any number of input port defined/connected. Output ports:
Xml attributes:
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
id | yes | component identification | ||
type | yes | component type | XML_WRITER | |
mappingURL | !mapping | file containing complex XML definition of hierarchical relations between data on input ports. Detail description bellow. | 2.8 | |
mapping | !mappingURL | Complex XML definition of hierarchical relations between data on input ports. Detail description bellow. | ||
fileURL | yes | Path to the output file. If you want to divide records to more out files, this attribute will be used as mask for out file names. Use “$” characters as replacement for file index. i.e. mask “out_$$.xml” will generate file names “out_00.xml”, “out_01.xml” etc. | ||
charset | no | charset of out file | UTF-8 | |
recordsPerFile | no | max number of records in one output file; 0 value means infinity | ∞ | |
recordSkip | no | specifies how many records/rows should be skipped before of writting the first record to the output file. | 0 | |
recordCount | no | Specifies how many records/rows should be written to the output file. 0 value means infinity | ∞ | |
rootElement | no | Name of root element in out XML file. It can be with or without namespace prefix. | root | |
useRootElement | no | If this switch is set to false, no extra root element will be used in the output. Thus top level mapping becomes root element and if there are more records of top level mapping in single file, XML which is technically invalid will be created. | true | 2.5 |
rootInfoAttributes | no | If this switch is set to false, root won't contain any attributes. By default it's set to true and root element (if used) contains attributes: nodeId - ID of XmlWriter node, created - current system time formated according to default locale, graphId - id of graph. | true | 2.7 |
singleRow | no | If this switch is set to true, whole XML body is written to single line. XML header and DTD are on the first line, XML body is on the second line. | false | 2.5 |
rootDefaultNamespace | no | URI of default namespace for root element (useRootElement should be true). | 2.5 | |
rootNamespaces | no | List of pairs prefix-URI for root element (useRootElement should be true). Format is like this: [prefix1]=[URI1];[prefix2]=[URI2];… | 2.5 | |
dtdPublicId | no, but if specified, dtdSystemId has to be specified too | If dtdSystemId attribute is specified together with dtdPublicId attribute, DTD will be created in the output XML: <!DOCTYPE [rootElement] PUBLIC "[dtdPublicId]" "[dtdSystemId]">
(useRootElement should be true) | 2.5 | |
dtdSystemId | no, but if specified, dtdPublicId has to be specified too | see dtdPublicId | 2.5 | |
xsdSchemaLocation | no | Content of attribute “xsi:schemaLocation” for root element (useRootElement should be true). Don't forget to specify namespace with “xsi” prefix (use rootNamespaces attribute, i.e. like this: rootNamespaces=“xsi="http://www.w3.org/2001/XMLSchema-instance "” ). | 2.5 | |
makeDirs | no | if true, creates directories to the output file if the directories don't exist | false | 2.8 |
compressLevel | no | sets the compression level. The compression level is 0-9. The default setting is to compress using default ZIP compression level. | -1 | 2.8 |
“mapping” attribute itself contains hierarchically organized XML elements “Mapping” which describe relations between data from input ports in output XML.
Child element has field which is primary key of parent element. In this example, element “customer” will contain 0..n elements “order”.
<Mapping inPort="1" element="customer" > <Mapping inPort="0" element="order" key="CustomerID" parentKey="CUSTOMERID" > ... </Mapping> ... </Mapping>
Parent element has field which is primary key of child element. In this example, element “order” will contain 0..1 element “employee”.
<Mapping inPort="0" element="order" > <Mapping inPort="1" element="employee" key="EmployeeID" parentKey="EmployeeID" > ... </Mapping> ... </Mapping>
| Attribute | Mandatory | Description | Default | ETL Version since |
|---|---|---|---|---|
element | yes | Name of element of record in out XML file. May be specified with or without namespace prefix. | ||
inPort | yes | Index of input file, where will be records read from | ||
key | no | Semicolon, pipe, or colon separated list of fields which represent relation key of this input port. | ||
parentKey | no | Semicolon, pipe, or colon separated list of fields from parent port, which will be mapped to key fields from this input port | ||
keyToParent | no | Deprecated(use key+parentKey instead) Semicolon, pipe, or colon separated list of fields from this port, which represent primary key of records from parent input port | ||
keyFromParent | no | Deprecated(use key+parentKey instead) Semicolon, pipe, or colon separated list of fields from parent port, which represent primary key of records from this input port | ||
fieldsAs | no | There are two possible values:“elements”, “attributes”. Defines way how records fields will be generated to XML out file. | elements | |
fieldsAsExcept | no | Semicolon, pipe, or colon separated list of fields which won't be generated in a way specified by fieldsAs attribute. i.e. if fieldsAd has “elements” value, all fields specified in fieldsAsExcept will be generated as attributes | ||
fieldsIgnore | no | Semicolon, pipe, or colon separated list of fields which will be completely excluded from out XML file | ||
namespaces | no | List of pairs prefix-URI. Format is like this: [prefix1]="[URI1]";[prefix2]="[URI2]";… | 2.5 | |
defaultNamespace | no | URI of default namespace for this element. | 2.5 | |
fieldsNamespacePrefix | no | Namespace prefix which will be used for fields' elements or attributes. | 2.5 |
Examples
Only 1 input port and single “flat” output XML file.
<Node id="XML_OUT" type="XML_WRITER" fileUrl="output/xmlOut.xml" > <attr name="mapping"><![CDATA[ <Mapping inPort="0" element="customer" > </Mapping> ]]></attr> </Node>
4 input ports and structured output XML files (for each record from input port 2 (root mapping) will be created its own XML out file). Using attributes key, parentKey:
<Node id="XML_OUT" type="XML_WRITER" recordsPerFile="1" recordSkip="0" recordCount="100" rootElement="root" fileUrl="output/xmlOut_$$.xml" charset="UTF-8" rootDefaultNamespace="http://cloveretl.org/ns/def/" rootNamespaces="data="http://cloveretl.org/ns/data/";cust="http://cloveretl.org/ns/cust/"" > <attr name="mapping"><![CDATA[ <Mapping inPort="2" element="cust:customer" fieldsAs="elements" fieldsAsExcept="CUSTOMERID;CompanyName" fieldsIgnore="CompanyName;State" > <Mapping inPort="0" element="data:order" parentKey="CUSTOMERID" key="CustomerID" fieldsAs="elements" fieldsAsExcept="OrderID"> <Mapping inPort="3" element="data:address" parentKey="OrderID" key="OrderID" fieldsAs="attributes" > </Mapping> <Mapping inPort="1" element="data:employee" parentKey="EmployeeID" key="EmployeeID" fieldsAs="elements" > </Mapping> </Mapping> </Mapping> ]]></attr> </Node>
Deprecated way … using attributes key, keyToParent, keyFromParent
<Node id="XML_OUT" type="XML_WRITER" recordsPerFile="1" recordSkip="0" recordCount="100" rootElement="root" fileUrl="output/xmlOut_$$.xml" charset="UTF-8" rootDefaultNamespace="http://cloveretl.org/ns/def/" rootNamespaces="data="http://cloveretl.org/ns/data/";cust="http://cloveretl.org/ns/cust/"" > <attr name="mapping"><![CDATA[ <Mapping inPort="2" element="cust:customer" key="CUSTOMERID" fieldsAs="elements" fieldsAsExcept="CUSTOMERID;CompanyName" fieldsIgnore="CompanyName;State" > <Mapping inPort="0" element="data:order" key="OrderID" keyToParent="CustomerID" fieldsAs="elements" fieldsAsExcept="OrderID"> <Mapping inPort="3" element="data:address" key="AddressID" keyToParent="OrderID" fieldsAs="attributes" > </Mapping> <Mapping inPort="1" element="data:employee" key="EmployeeID" keyFromParent="EmployeeID" fieldsAs="elements" > </Mapping> </Mapping> </Mapping> ]]></attr> </Node>
| Value | Description |
|---|---|
| /path/filename.out | path to the data output file. |
| /path/filename$.out | path to the data output file(s). The wildcard '$' will be replaced by sequential number of the file. Count of wildcards specifies minimal length of the sequential number. |
| /path/filename$$.out | path to the data output file(s). |
| zip:/path/filename$.zip | path to the data zip output file(s). Component writes a file in zip file. |
| zip:/path/filename$.zip#name.txt | path to the data zip output file(s). Component writes one file marked after '#'. |
| gzip:/path/filename$.gz | path to the data gzip output file(s). |
| ftp://user:password@server/path/name.txt | ftp address to the data output file. |
| port:$0.field1:discrete | output/formatted data are written to output port 0, field 'field1'. Number of output records depends on the same count of created files (files are sent to the output port/field instead of file). *1) |
| port:$0.field1:stream | the same as the discrete mode except each file is sent to multiple records and the last field value is null which is mark of end of file. The count of records depends on PortReadingWriting.DATA_LENGTH parameter of default property file. Default value is 2048B. This mode is convenient to use if the output file is too big. Since CloverETL 2.10 *1) |
| dict:keyName:discrete | writes data to dictionary. Creates ArrayList<byte[]>. *2). |
| dict:keyName:stream | writes data to dictionary - WritableByteChannel. *2). |
| - | stdout is the data output file. |
Proxy specification for a URL in the fileURL attribute. The URL can have three proxy protocols:
| Value | Description |
|---|---|
| ftp:(proxy://proxyserver:443)//user:password@server/path/file.dat | proxy for ftp protocol |
| sftp:(proxy://66.11.122.193:443)//user:password@server/path/file.dat | proxy for sftp protocol |
| bytes/records per file | footer/header | skip/num records | charset | zip | gzip | ftp | sftp | stdout | |
|---|---|---|---|---|---|---|---|---|---|
| CloverDataWriter | - | - | yes | - | yes | yes | yes | yes | yes |
| DataWriter | yes | yes | yes | yes | yes | yes | yes | yes | yes |
| DBOutputTable | - | - | - | - | - | - | - | - | - |
| DelimitedDataWriter | yes | yes | yes | yes | yes | yes | yes | yes | yes |
| FixLenDataWriter | yes | yes | yes | yes | yes | yes | yes | yes | yes |
| JmsWriter | - | - | - | - | - | - | - | - | - |
| LdapWriter | - | - | - | - | - | - | - | - | - |
| LookupTableReaderWriter | - | - | - | - | - | - | - | - | - |
| MysqlDataWriter | - | - | - | - | - | - | - | - | - |
| OracleDataWriter | - | - | - | - | - | - | - | - | - |
| StructureWriter | yes | yes | yes | yes | yes | yes | yes | yes | yes |
| TextTableWriter | yes | yes | yes | yes | yes | yes | yes | yes | yes |
| Trash | yes | - | - | yes | yes | yes | yes | yes | yes |
| XLSWriter | yes | yes | yes | - | yes | yes | yes | yes | - |
| XmlWriter | yes | yes | yes | yes | yes | yes | yes | yes | - |