Example: Working with VARIANT data type variables
- Alexandr Kudentsov (Unlicensed)
LYCIA
VARIANT is a data type intended to store values of different scalar data types. It is not a built-in 4gl data type - it was implemented specifically for Lycia and Lycia users. Variables defined as VARIANT take the type of a variable or a constant assigned to this VARIANT variable.
Full article about this data type is available here:
Below you can find a simple 4GL application which demonstrates the VARIANT variable dynamically changing its data type.
4GL:
MAIN DEFINE var_char CHAR(40), var_datetime DATETIME YEAR TO FRACTION(5), var_integer INTEGER, var_variant VARIANT ##### VARIANT as CHAR ##### LET var_char = "abc" CALL my_func(var_char) RETURNING var_char DISPLAY "main: var_char = ", var_char ##### VARIANT as INT ##### CALL my_func(123) RETURNING var_integer DISPLAY "main: var_integer = ", var_integer ##### VARIANT as DATETIME ##### LET var_datetime = "9999-12-31 23:59:59.99999" CALL my_func(var_datetime)RETURNING var_datetime DISPLAY "main: var_datetime = ", var_datetime CALL fgl_getkey() END MAIN FUNCTION my_func(p_variant) DEFINE p_variant VARIANT DISPLAY "my_func(): p_variant is ", p_variant.gettypefullname() RETURN p_variant END FUNCTION
Using VARIANT variable as a parameter for functions.
4GL:
MAIN DEFINE var_char CHAR(40), var_datetime DATETIME YEAR TO FRACTION(5), var_integer INTEGER, var_variant VARIANT ##### VARIANT as CHAR ##### LET var_char = "abc" CALL my_func(var_char) RETURNING var_char DISPLAY "main: var_char = ", var_char ##### VARIANT as INT ##### CALL my_func(123) RETURNING var_integer DISPLAY "main: var_integer = ", var_integer ##### VARIANT as DATETIME ##### LET var_datetime = "9999-12-31 23:59:59.99999" CALL my_func(var_datetime)RETURNING var_datetime DISPLAY "main: var_datetime = ", var_datetime CALL fgl_getkey() END MAIN FUNCTION my_func(p_variant) DEFINE p_variant VARIANT DISPLAY "my_func(): p_variant is ", p_variant.gettypefullname() RETURN p_variant END FUNCTION
Using VARIANT variables with databases. (Note: Currently, you can use VARIANT variables only with the Informix databases.)
4GL:
DATABASE stores MAIN DEFINE var_char CHAR(40), var_datetime DATETIME YEAR TO FRACTION(5), var_date DATE, var_integer INTEGER, var_decimal DECIMAL(16,2), var_variant VARIANT WHENEVER ERROR CONTINUE DROP TABLE table_test CREATE TABLE table_test ( col_char CHAR(40), col_datetime DATETIME YEAR TO FRACTION(5), col_date DATE, col_integer INTEGER, col_decimal DECIMAL(16,2) ) ##### VARIANT as CHAR ##### LET var_char = "abc" LET var_variant = var_char INSERT INTO table_test(col_char) VALUES(var_variant) IF SQLCA.SQLCODE <> 0 THEN DISPLAY "SQLCA.SQLCODE = ", SQLCA.SQLCODE END IF SELECT col_char INTO var_variant FROM table_test WHERE col_char = var_variant IF SQLCA.SQLCODE <> 0 THEN DISPLAY "SQLCA.SQLCODE = ", SQLCA.SQLCODE END IF DISPLAY "var_variant is ",var_variant.gettypefullname(),", var_variant = ",var_variant ##### VARIANT as DATETIME ##### LET var_datetime = "9999-12-31 23:59:59.99999" LET var_variant = var_datetime INSERT INTO table_test(col_datetime) VALUES(var_variant) IF SQLCA.SQLCODE <> 0 THEN DISPLAY "SQLCA.SQLCODE = ",SQLCA.SQLCODE END IF SELECT col_datetime INTO var_variant FROM table_test WHERE col_datetime = var_variant IF SQLCA.SQLCODE <> 0 THEN DISPLAY "SQLCA.SQLCODE = ",SQLCA.SQLCODE END IF DISPLAY "var_variant is ",var_variant.gettypefullname(),", var_variant = ",var_variant ##### VARIANT as DATE ##### LET var_date = "12/31/9999" LET var_variant = var_date INSERT INTO table_test(col_date) VALUES(var_variant) IF SQLCA.SQLCODE <> 0 THEN DISPLAY "SQLCA.SQLCODE = ",SQLCA.SQLCODE END IF SELECT col_date INTO var_variant FROM table_test WHERE col_date = var_variant IF SQLCA.SQLCODE <> 0 THEN DISPLAY "SQLCA.SQLCODE = ",SQLCA.SQLCODE END IF DISPLAY "var_variant is ",var_variant.gettypefullname(),", var_variant = ",var_variant ##### VARIANT as INT ##### LET var_integer = 123 LET var_variant = var_integer INSERT INTO table_test(col_integer) VALUES(var_variant) IF SQLCA.SQLCODE <> 0 THEN DISPLAY "SQLCA.SQLCODE = ",SQLCA.SQLCODE END IF SELECT col_integer INTO var_variant FROM table_test WHERE col_integer = var_variant IF SQLCA.SQLCODE <> 0 THEN DISPLAY "SQLCA.SQLCODE = ",SQLCA.SQLCODE END IF DISPLAY "var_variant is ",var_variant.gettypefullname(),", var_variant = ",var_variant ##### VARIANT as DECIMAL ##### LET var_decimal = 123.45 LET var_variant = var_decimal INSERT INTO table_test(col_decimal) VALUES(var_variant) IF SQLCA.SQLCODE <> 0 THEN DISPLAY "SQLCA.SQLCODE = ",SQLCA.SQLCODE END IF SELECT col_decimal INTO var_variant FROM table_test WHERE col_decimal = var_variant IF SQLCA.SQLCODE <> 0 THEN DISPLAY "SQLCA.SQLCODE = ",SQLCA.SQLCODE END IF DISPLAY "var_variant is ",var_variant.gettypefullname(),", var_variant = ",var_variant END MAIN
Using DYNAMIC ARRAY of VARIANT (Display array).
4GL:
MAIN DEFINE DisplArr DYNAMIC ARRAY OF VARIANT DEFINE str STRING DEFINE tm DATETIME HOUR TO SECOND DEFINE dt DATE LET str = "string value" LET tm = "15:22:35" LET dt = "01.05.2018" OPEN WINDOW w WITH FORM "variant_04_display_dynamic_array" ATTRIBUTE(BORDER) LET DisplArr[1]= str LET DisplArr[2]= tm LET DisplArr[3]= dt DISPLAY DisplArr TO rec.* CALL fgl_getkey() DISPLAY "ARRAY:",DisplArr END MAIN
Form:
<?xml version="1.0" encoding="UTF-8"?> <form xmlns="http://namespaces.querix.com/2015/fglForms" title="New Form 1"> <form.rootContainer> <GridPanel identifier="rootContainer" visible="true"> <GridPanel.gridColumnDefinitions> <GridColumnDefinition gridLengthValue=""/> <GridColumnDefinition gridLengthValue=""/> <GridColumnDefinition gridLengthValue=""/> <GridColumnDefinition gridLengthValue=""/> <GridColumnDefinition gridLengthValue=""/> <GridColumnDefinition gridLengthValue=""/> </GridPanel.gridColumnDefinitions> <GridPanel.gridRowDefinitions> <GridRowDefinition gridLengthValue=""/> </GridPanel.gridRowDefinitions> <Label text="Text" isDynamic="true" visible="true" identifier="lb4" gridItemLocation="0,0,1,1" verticalAlignment="Center"/> <TextField visible="true" identifier="f1" gridItemLocation="1,0,1,1"/> <Label text="Time" isDynamic="true" visible="true" identifier="lb5" gridItemLocation="2,0,1,1" verticalAlignment="Center"/> <TimeEditField dataType="DateTime,Hour,Minute,," visible="true" identifier="f2" gridItemLocation="3,0,1,1"/> <Label text="Date" isDynamic="true" visible="true" identifier="lb6" gridItemLocation="4,0,1,1" verticalAlignment="Center"/> <Calendar dataType="Date,,,," visible="true" identifier="f3" gridItemLocation="5,0,1,1" verticalAlignment="Center"/> </GridPanel> </form.rootContainer> <form.screenRecords> <ScreenRecord identifier="rec" fields="f1,f2,f3"/> </form.screenRecords> </form>
Using DYNAMIC ARRAY of VARIANT (Input array).
4GL:
MAIN DEFINE tableRec DYNAMIC ARRAY OF DYNAMIC ARRAY OF VARIANT DEFINE numCol, numRow INTEGER DEFINE f1 BOOL, f2 STRING, f3 DATE, f4 SMALLINT, f5 INT, f6 INT, f7 INT, f8 INT, f9 CHAR(20), f10 DATETIME HOUR TO SECOND LET f1 = 1 LET f2 = "functionfield" LET f3 ="12.12.2012" LET f4 = 20 LET f5 = 5 LET f6 = 50 LET f7 = 50 LET f8 = 50 LET f9 = "textfield" LET f10 = "15:22:33" OPEN WINDOW w WITH FORM "variant_05_input_dynamic_array" ATTRIBUTE(BORDER) FOR numRow=1 TO 5 FOR numCol=1 TO 10 CASE numCol WHEN 1 LET tableRec[numRow][numCol]=f1 WHEN 2 LET tableRec[numRow][numCol]=f2||" "||numRow WHEN 3 LET tableRec[numRow][numCol]=f3 WHEN 4 LET tableRec[numRow][numCol]=f4 WHEN 5 LET tableRec[numRow][numCol]=f5 WHEN 6 LET tableRec[numRow][numCol]=f6 WHEN 7 LET tableRec[numRow][numCol]=f7 WHEN 8 LET tableRec[numRow][numCol]=f8 WHEN 9 LET tableRec[numRow][numCol]=f9 WHEN 10 LET tableRec[numRow][numCol]=f10 END CASE END FOR END FOR INPUT ARRAY tableRec FROM tarr.* ATTRIBUTE (WITHOUT DEFAULTS) DISPLAY "INPUT ARRAY:",tableRec END MAIN
Form:
<?xml version="1.0" encoding="UTF-8"?> <form xmlns="http://namespaces.querix.com/2015/fglForms"> <form.rootContainer> <Table preferredSize="1000,300.0" visible="true" fieldTable="" identifier="tarr"> <TableColumn text="CheckBox" resizable="true" visible="true" fieldTable="" identifier="tc_f1"> <TableColumn.columnLength> <GridLength gridLengthValue=""/> </TableColumn.columnLength> <CheckBox title="CheckBox" visible="true" fieldTable="" identifier="f1"> <CheckBox.checkedValue> <IntegerLiteral integerValue="1"/> </CheckBox.checkedValue> <CheckBox.uncheckedValue> <IntegerLiteral/> </CheckBox.uncheckedValue> </CheckBox> </TableColumn> <TableColumn text="FunctionField" resizable="true" visible="true" fieldTable="" identifier="tc_f2"> <TableColumn.columnLength> <GridLength gridLengthValue=""/> </TableColumn.columnLength> <FunctionField visible="true" fieldTable="" identifier="f2"/> </TableColumn> <TableColumn text="Calendar" resizable="true" visible="true" fieldTable="" identifier="tc_f3"> <TableColumn.columnLength> <GridLength gridLengthValue=""/> </TableColumn.columnLength> <Calendar dataType="Date,,,," visible="true" fieldTable="" identifier="f3"/> </TableColumn> <TableColumn text="ListBox" resizable="true" visible="true" fieldTable="" identifier="tc_f4"> <TableColumn.columnLength> <GridLength gridLengthValue=""/> </TableColumn.columnLength> <ListBox visible="true" fieldTable="" identifier="f4"> <ListBoxItem text="value1" identifier="f4_1"/> <ListBoxItem text="value2" identifier="f4_2"> <ListBoxItem.value> <IntegerLiteral integerValue="20"/> </ListBoxItem.value> </ListBoxItem> </ListBox> </TableColumn> <TableColumn text="RadioButtonList" resizable="true" visible="true" fieldTable="" identifier="tc_f5"> <TableColumn.columnLength> <GridLength gridLengthValue=""/> </TableColumn.columnLength> <RadioGroup orientation="Vertical" visible="true" fieldTable="" identifier="f5"> <Radio title="value0" identifier="f5_0"> <Radio.value> <IntegerLiteral integerValue="3"/> </Radio.value> </Radio> <Radio title="value1" identifier="f5_1"> <Radio.value> <IntegerLiteral integerValue="5"/> </Radio.value> </Radio> </RadioGroup> </TableColumn> <TableColumn text="Slider" resizable="true" visible="true" fieldTable="" identifier="tc_f6"> <TableColumn.columnLength> <GridLength gridLengthValue=""/> </TableColumn.columnLength> <Slider maxValue="100" dataType="Integer,,,," visible="true" fieldTable="" identifier="f6"/> </TableColumn> <TableColumn text="Spinner" resizable="true" visible="true" fieldTable="" identifier="tc_f7"> <TableColumn.columnLength> <GridLength gridLengthValue=""/> </TableColumn.columnLength> <Spinner step="1" maxValue="100" visible="true" fieldTable="" identifier="f7"> <Spinner.defaultValue> <IntegerLiteral/> </Spinner.defaultValue> </Spinner> </TableColumn> <TableColumn text="ScrollBar" resizable="true" visible="true" fieldTable="" identifier="tc_f8"> <TableColumn.columnLength> <GridLength gridLengthValue=""/> </TableColumn.columnLength> <ScrollBar largeStep="10" smallStep="1" maxValue="100" dataType="SmallInt,,,," visible="true" fieldTable="" identifier="f8"/> </TableColumn> <TableColumn text="TextField" resizable="true" visible="true" fieldTable="" identifier="tc_f9"> <TableColumn.columnLength> <GridLength gridLengthValue=""/> </TableColumn.columnLength> <TextField visible="true" fieldTable="" identifier="f9"/> </TableColumn> <TableColumn text="TimeEditField" resizable="true" visible="true" fieldTable="" identifier="tc_f10"> <TableColumn.columnLength> <GridLength gridLengthValue=""/> </TableColumn.columnLength> <TimeEditField visible="true" fieldTable="" identifier="f10"/> </TableColumn> </Table> </form.rootContainer> <form.screenRecords> <ScreenRecord identifier="tarr" fields="f1,f2,f3,f4,f5,f6,f7,f8,f9,f10"/> </form.screenRecords> </form>
Please find below the link to our Gitlab repository which contains 4GL applications examples.
Follow instructions in this article to add the above-mentioned repository to your Lycia IDE. Feel free to contact us in case if any additional information or assistance is needed.