Dynamic arrays

Defining dynamic arrays

Dynamic arrays are defined with the DYNAMIC ARRAY syntax and specify an array with a variable size. Dynamic arrays have no theoretical size limit. The elements of dynamic arrays are allocated automatically by the runtime system, based on the indexes used.
MAIN
  DEFINE a1 DYNAMIC ARRAY OF INTEGER
  LET a2[5000] = 12456  -- Automatic allocation for element 5000
END MAIN

Element types

The elements of a dynamic array variable are typically defined as a structured record:
MAIN
  DEFINE arr DYNAMIC ARRAY OF RECORD
               key INTEGER,
               name VARCHAR(30),
               address VARCHAR(200),
               contacts DYNAMIC ARRAY OF VARCHAR(20)
       END RECORD
  LET arr[1].key = 12456
  LET arr[1].name = "Scott"
  LET arr[1].contacts[1] = "Bryan COX"
  LET arr[1].contacts[2] = "Mike FLOWER"
END MAIN

Automatic element allocation

When a dynamic array element does not exist, it is automatically allocated before it is used. For example, when you assign an array element with the LET instruction by specifying an array index greater than the current length of the array, the new element is created automatically before assigning the value. This is also true when using a dynamic array in aFOREACH loop or when dynamic array elements are used as r-values, for example in a DISPLAY.

MAIN
  DEFINE a DYNAMIC ARRAY OF INTEGER
  LET a[50] = 33 -- Extends array size to 50 and assigns 33 to element #50
  DISPLAY a[100] -- Extends array size to 100 and displays NULL
END MAIN
Important:
Pay attention to automatic element allocation in dynamic arrays. The following code example creates an additional element because at each iteration, the runtime system must allocate a new element to fetch the row from the database. As result, you need to remove the last element of the array after the FOREACH loop:
DEFINE arr DYNAMIC ARRAY OF RECORD
               key INTEGER,
               name VARCHAR(30)
       END RECORD,
       x INTEGER
DECLARE c1 CURSOR FOR SELECT ckey, cname FROM mytable
LET x=1
FOREACH c1 INTO arr[x].*
   LET x=x+1
END FOREACH
CALL arr.deleteElement(x)

-- A more elegant way to fetch rows into an array:
TYPE my_type RECORD LIKE mytable.*
DEFINE arr DYNAMIC ARRAY OF my_type,
       rec my_type,
       x INTEGER
DECLARE c1 CURSOR FOR SELECT * FROM mytable
LET x=1
FOREACH c1 INTO rec.*
   LET arr[x:=x+1].* = rec.*
END FOREACH

Passing and returning dynamic arrays to functions

Dynamic arrays are passed (or returned) by reference to/from functions.

The dynamic array can be modified inside the called function, and the caller will see the modifications.
MAIN
  DEFINE a DYNAMIC ARRAY OF INTEGER
  CALL fill(a)
  DISPLAY a.getLength() -- shows 2
END MAIN

FUNCTION fill(x)
  DEFINE x DYNAMIC ARRAY OF INTEGER
  CALL x.appendElement()
  CALL x.appendElement()
END FUNCTION

Using multidimensional dynamic arrays

Multidimensional dynamic arrays can be defined by using the WITH DIMENSION syntax.

Array methods can be used on multidimensional arrays with the brackets notation:
MAIN
  DEFINE a2 DYNAMIC ARRAY WITH DIMENSION 2 OF INTEGER
  DEFINE a3 DYNAMIC ARRAY WITH DIMENSION 3 OF INTEGER
  LET a2[50,100]  = 12456
  LET a2[51,1000] = 12456
  DISPLAY a2.getLength()         -- shows 51
  DISPLAY a2[50].getLength()     -- shows 100
  DISPLAY a2[51].getLength()     -- shows 1000
  LET a3[50,100,100]  = 12456
  LET a3[51,101,1000] = 12456
  DISPLAY a3.getLength()         -- shows 51
  DISPLAY a3[50].getLength()     -- shows 100
  DISPLAY a3[51].getLength()     -- shows 101
  DISPLAY a3[50,100].getLength() -- shows 100
  DISPLAY a3[51,101].getLength() -- shows 1000
  CALL a3[50].insertElement(10)  -- inserts at 50,10
  CALL a3[50,10].insertElement(1)-- inserts at 50,10,1
END MAIN