Developer ToolsFree generatorPDF, Excel, Word exportBaan IV / Infor LNAll Infor LN and Baan tools

Infor LN 4GL Database Insert and Update Transaction Generator

This generator writes a Baan IV / Infor LN 3GL function that changes one record safely: it sets a retry point, selects the row for update, applies your assignments, calls db.update, db.delete or db.insert with db.retry, and commits or aborts the transaction. Fill in the table, key and fields and paste the result into a program script or library in your VRC.

Fill in

Logical table code without the leading t and company number.

Generated code
Download:

Declaration

|******************************************************************************
|* Safe write to tdsls400 (operation: update)
|* Compile in your own VRC with the table declared below.
|******************************************************************************
declaration:

	table	ttdsls400		| table pointer used by db.* calls

	extern domain tcorno	i.orno	| key value supplied by the caller

Update or delete an existing record

functions:

function long update.tdsls400.record()
{
	long	ret

	db.retry.point()

	select	tdsls400.*
	from	tdsls400 for update
	where	tdsls400.orno = :i.orno
	selectdo
		| assignments are ignored for a delete
		tdsls400.refa = "CHECKED"
tdsls400.refb = "BATCH01"
		ret = db.update(ttdsls400, db.retry)
		if ret <> 0 then
			abort.transaction()
			return(ret)
		endif
	selectempty
		return(111)	| 111 ENOREC: no record found
	endselect

	ret = commit.transaction()
	return(ret)
}

Insert a new record

function long insert.tdsls400.record()
{
	long	ret

	db.retry.point()

	tdsls400.orno = i.orno
	tdsls400.ofbp = i.ofbp
tdsls400.sotp = i.sotp
tdsls400.odat = date.num()

	ret = db.insert(ttdsls400, db.retry)
	if ret <> 0 then
		abort.transaction()
		return(ret)	| 100 EDUPL: key already exists
	endif

	ret = commit.transaction()
	return(ret)
}

Check against the Programmer's Guide for your Enterprise Server version: the db.* argument list, whether your release expects extra error-handling flags, and the domain of the key. db.update, db.insert and db.delete write directly to the table; DAL business logic of the table runs only through the DAL calls (dal.new, dal.update, dal.destroy), so use those when the table has a DAL. Fill every mandatory field before db.insert, and test in a non-production company.

Want a second pair of eyes on a database write?

Send us the function and the table and we will review locking, retry and DAL use for your LN version.

Optional. The tool and every export work without this. No spam.

Was this tool useful?

How the pattern works

db.retry.point() marks where the bshell restarts the transaction when a retryable database error occurs, such as a row that was changed or locked by another user after a delayed lock. The select with for update locks the record inside the transaction. Inside selectdo you assign the new values and call db.update(t<table>, db.retry), where t<table> is the table pointer created by the table declaration. A non-zero return means the write failed, so the function calls abort.transaction() and returns the error number. If nothing matched, selectempty returns 111 (ENOREC). When all writes succeed, commit.transaction() makes them permanent.

  • One retry point at the start of each transaction
  • Lock with for update before you change a row
  • Always end in commit.transaction() or abort.transaction()

Worked example

With the defaults, the update function locks the sales order header tdsls400 where orno equals i.orno, sets Reference A and Reference B and calls db.update(ttdsls400, db.retry). The insert function sets tdsls400.orno, the sold-to business partner, order type and order date and calls db.insert. In practice you should not insert sales orders directly: LN fills many fields and related records through the standard sessions and the DAL. Use direct inserts for your own customer tables, and use the DAL or a standard API for application tables. Rename the generated functions to match your naming convention.

Error numbers you will meet

The return values are Enterprise Server error numbers. 100 EDUPL means a duplicate key on insert. 107 ELOCKED and 113 EFLOCKED mean a record or table lock. 111 ENOREC means no record matched. 201 EROWCHANGED means the record changed after a delayed lock, which db.retry handles by going back to the retry point. 205 ENOTINRANGE means a value does not fit the field's domain. Log the number with the key so support can trace it in the bshell log. Return the number to the caller rather than showing a message inside the function, so batch jobs and sessions can each decide how to report it. The full list is in the error codes reference linked below.

DAL and upgrade notes

Direct db.* writes skip the DAL logic of the table, including checks and defaults that the standard sessions rely on. For standard LN tables with a DAL, write through the DAL functions instead, or call a standard session or API. Keep this code in your customer VRC and document it in a change header, so an upgrade does not overwrite it and reviewers can find every direct write. Before an upgrade, search your VRC for db.insert, db.update and db.delete on standard tables and check each one against the new data model, because added mandatory fields or new DAL rules can make an old direct write leave inconsistent data.

Frequently Asked Questions

What is the Baan 4GL language?

Baan 4GL is the event-driven script layer of Baan and Infor LN sessions, with sections such as before.program and field events. It sits on the Baan 3GL language, which provides variables, functions, embedded SQL (select, selectdo, endselect) and the db.* database calls used in this generator.

What does db.retry do in db.update?

Passing db.retry tells the bshell that when a retryable error occurs, it should roll back and restart from the last db.retry.point() rather than return the error. That is why the retry point must come before the select for update, so the record is read again with fresh values.

Do I need commit.transaction after db.update?

Yes. The select for update and the db.* calls run inside a transaction that is only made permanent by commit.transaction(). If any step fails, call abort.transaction() to roll back all writes made since the transaction started. Leaving a transaction open keeps locks on the rows.

Where is the Infor LN development guide for these functions?

The Infor Enterprise Server Programmer's Guide and the Enterprise Server online manual on docs.infor.com describe the 3GL language, embedded SQL and the db.* and transaction functions. Error numbers are listed in the Enterprise Server Technical Manual. Check the guide for your exact Enterprise Server version before relying on an argument list.

If you are reviewing legacy Baan or LN code for direct database writes before an upgrade, we can help your team scan and document them with a private AI assistant on your own servers.

ArchRay builder
Design the on-prem AI stack for Infor LN and Baan: model, GPUs, RAG pipeline, guardrails
See memory, speed and cost as you swap parts, then export the diagram. Free, in your browser.
Open the builder

Keep exploring

Free tools

ERP fixes and how-tos

Guides

AI on your ERP

Integrations

Comparisons

Software