Top  Previous  Next


The WRITE statement writes a record to a previously opened file. The WRITEU statement is identical but preserves any lock on the record.





WRITE var {ENCODING name} TO file.var, record.id {ON ERROR statement(s)}

WRITE var {ENCODING name} TO file.var CREATING.SEQKEY id.var {ON ERROR statement(s)}




varis the name of a variable containing the data to be written.


file.varis the file variable associated with the file.


record.idevaluates to the id of the record to be written.


id.varis the variable to receive the record id.


statement(s)are statements to be executed if the write fails.


The keyword ON may be used in place of TO.



In the first form of the WRITE statement, the contents of var are written to the file using the supplied record id. Any existing record of the same id is replaced by this action.


When writing to a directory file, field marks in the data to be written are replaced by newlines. This action may be suppressed by using the MARK.MAPPING statement after opening the file.


The optional ENCODING element to this statement sets the character encoding to be used, overriding any encoding set in the VOC F-type record or when the file was opened. This is relevant only to directory files and is ignored for other file types. A null string as the encoding name is equivalent to not having the ENCODING clause at all. To disable the default encoding, the encoding name should be specified as "NULL".


The WRITE statement releases any read or update lock on this record. The WRITEU statement preserves the lock. Within a transaction, the lock is retained until the transaction terminates and then released regardless of which statement is used. Attempting to write a record in a transaction will fail if the process does not hold an update lock on the record or the file.


The ON ERROR clause is executed for serious fault conditions such as errors in a file's internal control structures. It is also executed if the write operation is disallowed by a pre-write trigger function associated with the file. The STATUS() function will return an error number. If no ON ERROR clause is present, an abort would occur.


Although it is generally acceptable to assume that a WRITE that does not execute the ON ERROR clause or abort was successful, the WRITE operation normally returns zero from an immediately following use of the STATUS() function. On ECS mode systems, status value ER$ECS.DATA will be returned if a record containing ECS characters is written to a non-ECS mode hashed file or a directory file with no encoding. The write will have completed but only the low order byte of each character will have been written.


When writing a new record to a directory file on a Linux or Unix system, the operating system level file that represents the QM record is created using the current umask value. For sessions that connect directly to QM rather than from the operating system shell (direct telnet and QMClient), the umask value is specified by the UMASK configuration parameter or, if this parameter is not present, a default of 002. This behaviour can be modified by executing a UMASK command within the session.


Automatic Generation of Sequential Numeric Keys


The second form uses the CREATING.SEQKEY clause to create a sequentially numbered record id, returning this id in id.var. This form of write is only valid with hashed files, including those opened over a QMNet connection. Use with data replication is likely to fail as the internal sequence number will not be updated on the subscriber system.


Used inside a transaction, the record id is generated when the WRITE statement is executed, not at transaction commit. This could lead to gaps in sequential record numbering if a transaction does not commit. Gaps can also occur as a result of errors detected after the point when locking must be enforced such as rejection of the write by a trigger function. Because the record id is generated automatically, a program cannot lock it prior to the WRITE. Instead, an update lock is automatically applied for the duration of the internal processing of the write operation. Except when using WRITEU, this lock will be released before continuing with the next program statement.


By default, the sequential record numbering begins at 1 for a newly created file. The FCONTROL() function provides a way for an application to access and update the internal sequence number. The FILEINFO() function allows retrieval of the last used sequential record key. The sequence number can be updated using the CONFIGURE.FILE command.


Application developers should take great care when using automatic key generation. It is essential that all records are written using this method or by reserving a key value with the FC$GET.SEQ.KEY mode of the FCONTROL() function. Failure to comply with this rule could result in records being overwritten as there is no check whether a record with the automatically generated record id already exists. In addition, if the system suffers a power failure or similar condition in which a record may have been written but the file header (where the sequential counter is maintained) has not been flushed to disk. This situation is no different from that which would occur with other methods of allocating sequential numeric keys, however, the qmfix tool will detect and correct any inconsistency. It is good operational practice to run qmfix after a system failure regardless of whether automatic key generation is in use. Note that this issue applies only to system failures, not application errors or forced logout of a QM process.



Use of a THEN/ELSE Clause


For compatibility with the way in which triggers operate in some other multivalue products, the WRITE statement has an optional THEN/ELSE clause. Because this would otherwise lead to a syntactic ambiguity, compilation of programs that use this clause requires the WRITE.DELETE.THEN.ELSE option of the $MODE compiler directive to be enabled. Once this is done, the optional THEN/ELSE clauses can be included in their usual position, after the ON ERROR clause.


When a WRITE statement has a THEN/ELSE clause, a failure returned from a trigger function, typically as a result of a pre-write data validation error, will cause the ELSE clause to be executed instead of the ON ERROR clause.







This statement writes the content of ITEM to a record with the id in ITEM.ID on the file previously opened to file variable STOCK.





This statement writes the content of LOG.REC to the file opened to file variable LOG.F, using an automatically generated sequential record id that is returned in the LOG.ID variable.