In XSQL vtables, are structures that simulates a table in memory, and allows inserting, modifying and deleting records, as well as performing operations between vtables. The alternativa in server side script are resulsets, because this data struct can operate like a table.

1 Create a vtable and insert values

The following example creates a vtable and insert records in a loop. A vtable named v_trigonometry is created, composed of five columns of decimal type: degrees, radians, sin, cos and tan. Subsequently, the vtable is loaded with the values ​​corresponding to a trigonometric table. This is done in a loop for

Javascript we use

Copy
<xsql-script>
    <body>
        <!-- ==================================================================== -->
        <!-- Crear tabla virtual vacía                                            -->
        <!-- ==================================================================== -->
        <vtable name='v_trigonometry'>
            <column name='degrees' type='integer' />
            <column name='radians' type='decimal' size='6,4' />
            <column name='sin'     type='decimal' size='6,4' />
            <column name='cos'     type='decimal' size='6,4' />
            <column name='tan'     type='decimal' size='6,4' />
        </vtable>

        <!-- ==================================================================== -->
        <!-- Se insertan datos en la tabla virtual                                -->
        <!-- ==================================================================== -->
        <for name='m_degrees' start='0' end='360' step='8'>
            <do>

                <!-- ============================================================ -->
                <!-- Calcular grados en radianes                                  -->
                <!-- ============================================================ -->
                <set name='m_radians' type='decimal'>
                    <math.round>
                        <mul><div><math.pi />180.0</div><m_degrees /></mul>
                        <number>10</number>
                    </math.round>
                </set>
                <vtable.insert name='v_trigonometry'>
                    <m_degrees />
                    <m_radians />
                    <math.sin><m_radians /></math.sin>
                    <math.cos><m_radians /></math.cos>
                    <math.tan><m_radians /></math.tan>
                </vtable.insert>
            </do>
        </for>

        <return><v_trigonometry /></return>
    </body>
</xsql-script>

Returns:

Copy
+-------+-------+------+------+-----------------+
|degrees|radians|sin   |cos   |tan              |
+-------+-------+------+------+-----------------+
|      0|  0,000| 0,000| 1,000|            0,000|
|      8|  0,140| 0,139| 0,990|            0,141|
|     16|  0,279| 0,276| 0,961|            0,287|
|     24|  0,419| 0,407| 0,914|            0,445|
|     32|  0,559| 0,530| 0,848|            0,625|
|     40|  0,698| 0,643| 0,766|            0,839|
|     48|  0,838| 0,743| 0,669|            1,111|
|     56|  0,977| 0,829| 0,559|            1,483|
|     64|  1,117| 0,899| 0,438|            2,050|
|     72|  1,257| 0,951| 0,309|            3,078|
|     80|  1,396| 0,985| 0,174|            5,671|
|     88|  1,536| 0,999| 0,035|           28,636|
|     96|  1,676| 0,995|-0,105|           -9,514|
|    104|  1,815| 0,970|-0,242|           -4,011|
|    112|  1,955| 0,927|-0,375|           -2,475|
|    120|  2,094| 0,866|-0,500|           -1,732|
|    128|  2,234| 0,788|-0,616|           -1,280|
|    136|  2,374| 0,695|-0,719|           -0,966|
|    144|  2,513| 0,588|-0,809|           -0,727|
|    152|  2,653| 0,469|-0,883|           -0,532|
|    160|  2,793| 0,342|-0,940|           -0,364|
|    168|  2,932| 0,208|-0,978|           -0,213|
|    176|  3,072| 0,070|-0,998|           -0,070|
|    184|  3,211|-0,070|-0,998|            0,070|
|    192|  3,351|-0,208|-0,978|            0,213|
|    200|  3,491|-0,342|-0,940|            0,364|
|    208|  3,630|-0,469|-0,883|            0,532|
|    216|  3,770|-0,588|-0,809|            0,727|
|    224|  3,910|-0,695|-0,719|            0,966|
|    232|  4,049|-0,788|-0,616|            1,280|
|    240|  4,189|-0,866|-0,500|            1,732|
|    248|  4,328|-0,927|-0,375|            2,475|
|    256|  4,468|-0,970|-0,242|            4,011|
|    264|  4,608|-0,995|-0,105|            9,514|
|    272|  4,747|-0,999| 0,035|          -28,636|
|    280|  4,887|-0,985| 0,174|           -5,671|
|    288|  5,027|-0,951| 0,309|           -3,078|
|    296|  5,166|-0,899| 0,438|           -2,050|
|    304|  5,306|-0,829| 0,559|           -1,483|
|    312|  5,445|-0,743| 0,669|           -1,111|
|    320|  5,585|-0,643| 0,766|           -0,839|
|    328|  5,725|-0,530| 0,848|           -0,625|
|    336|  5,864|-0,407| 0,914|           -0,445|
|    344|  6,004|-0,276| 0,961|           -0,287|
|    352|  6,144|-0,139| 0,990|           -0,141|
|    360|  6,283| 0,000| 1,000|            0,000|
+-------+-------+------+------+-----------------+
Copy
var mRsTrigonometry = new Ax.rs.Reader().memory(options => {
    options.setColumnNames([ "degrees", "radians", "sin", "cos", "tan" ]);
    options.setColumnTypes([
        Ax.sql.Types.INTEGER, 
        Ax.sql.Types.DOUBLE,
        Ax.sql.Types.DOUBLE,
        Ax.sql.Types.DOUBLE,
        Ax.sql.Types.DOUBLE
    ]);
    
    options.setColumnScales([ 0, 3, 3, 3, 3 ]);
}); 

for (var mIntDegrees = 0; mIntDegrees <= 360; mIntDegrees += 8) {
    var mBcRadians =  Ax.math.bc.scale(
            Ax.math.bc.mul(Ax.math.bc.div(Math.PI, 180), mIntDegrees),
            3,
            Ax.math.bc.RoundingMode.HALF_UP
    );
     mRsTrigonometry.rows().add(
        [mIntDegrees,
         mBcRadians, 
         Math.sin(mBcRadians),
         Math.cos(mBcRadians),
         Math.tan(mBcRadians)]);
    
}

console.log(mRsTrigonometry);

Returns:

Copy
+-------+-------+------+------+-------+
|<null> |<null> |<null>|<null>|<null> |
|degrees|radians|sin   |cos   |tan    |
|integer|double |double|double|double |
+-------+-------+------+------+-------+
|0      |0.000  |0.000 |1.000 |0.000  |
|8      |0.140  |0.140 |0.990 |0.141  |
|16     |0.279  |0.275 |0.961 |0.286  |
|24     |0.419  |0.407 |0.913 |0.445  |
|32     |0.559  |0.530 |0.848 |0.626  |
|40     |0.698  |0.643 |0.766 |0.839  |
|48     |0.838  |0.743 |0.669 |1.111  |
|56     |0.977  |0.829 |0.560 |1.481  |
|64     |1.117  |0.899 |0.438 |2.050  |
|72     |1.257  |0.951 |0.309 |3.081  |
|80     |1.396  |0.985 |0.174 |5.663  |
|88     |1.536  |0.999 |0.035 |28.727 |
|96     |1.676  |0.994 |-0.105|-9.470 |
|104    |1.815  |0.970 |-0.242|-4.013 |
|112    |1.955  |0.927 |-0.375|-2.473 |
|120    |2.094  |0.866 |-0.500|-1.734 |
|128    |2.234  |0.788 |-0.616|-1.280 |
|136    |2.374  |0.694 |-0.720|-0.965 |
|144    |2.513  |0.588 |-0.809|-0.727 |
|152    |2.653  |0.469 |-0.883|-0.532 |
|160    |2.793  |0.342 |-0.940|-0.363 |
|168    |2.932  |0.208 |-0.978|-0.213 |
|176    |3.072  |0.070 |-0.998|-0.070 |
|184    |3.211  |-0.069|-0.998|0.070  |
|192    |3.351  |-0.208|-0.978|0.213  |
|200    |3.491  |-0.342|-0.940|0.364  |
|208    |3.630  |-0.469|-0.883|0.531  |
|216    |3.770  |-0.588|-0.809|0.727  |
|224    |3.910  |-0.695|-0.719|0.967  |
|232    |4.049  |-0.788|-0.616|1.280  |
|240    |4.189  |-0.866|-0.500|1.733  |
|248    |4.328  |-0.927|-0.375|2.472  |
|256    |4.468  |-0.970|-0.242|4.010  |
|264    |4.608  |-0.995|-0.104|9.545  |
|272    |4.747  |-0.999|0.035 |-28.881|
|280    |4.887  |-0.985|0.174 |-5.669 |
|288    |5.027  |-0.951|0.309 |-3.073 |
|296    |5.166  |-0.899|0.438 |-2.051 |
|304    |5.306  |-0.829|0.559 |-1.482 |
|312    |5.445  |-0.743|0.669 |-1.112 |
|320    |5.585  |-0.643|0.766 |-0.839 |
|328    |5.725  |-0.530|0.848 |-0.624 |
|336    |5.864  |-0.407|0.913 |-0.446 |
|344    |6.004  |-0.276|0.961 |-0.287 |
|352    |6.144  |-0.139|0.990 |-0.140 |
|360    |6.283  |-0.000|1.000 |-0.000 |
+-------+-------+------+------+-------+

In server side script, can be used a memory resultset. In first sentence new Ax.rs.Reader().memory, defines the column names and data types of memory resultset. Later with a for loop are added the rows to resultset.

2 vtable.insert matrix

In XSQL can be created a vtable and using vtable.insert matrix, insert n rows in a single operation. In server side script, the resultset can be created with all rows with method build.

Copy
<xsql-script>
    <body>
      <vtable name='v_request_items'>
          <column name='local_office'   type='string' />
          <column name='department'     type='string' />
          <column name='item_coede'     type='string' />
          <column name='log_variable'   type='string' />
          <column name='req_quantity'   type='decimal' />
      </vtable>

      <vtable.insert name='v_request_items'>
          <matrix>
              { "D01", "P01", "024099", "0", "12" },
              { "D01", "P01", "024099", "0", "20" },
              { "D01", "P01", "026147", "0", "10" },
              { "D01", "P01", "026147", "0", "20" },
              { "D01", "P01", "026147", "2", "15" },
              { "D01", "P01", "026147", "2", "18" },
              { "D02", "0",   "024099", "0", "12" },
              { "D02", "0",   "024099", "0", "20" },
              { "D02", "0",   "024099", "0", "25" },
              { "D02", "0",   "024099", "0", "10" },
              { "D02", "0",   "026147", "0", "10" },
              { "D02", "0",   "026147", "3", "20" }
          </matrix>
      </vtable.insert>

      <println><v_request_items /></println>
    </body>
</xsql-script>

Returns:

Copy
+------------+----------+----------+------------+------------+
|local_office|department|item_coede|log_variable|req_quantity|
+------------+----------+----------+------------+------------+
|D01         |P01       |024099    |0           |12          |
|D01         |P01       |024099    |0           |20          |
|D01         |P01       |026147    |0           |10          |
|D01         |P01       |026147    |0           |20          |
|D01         |P01       |026147    |2           |15          |
|D01         |P01       |026147    |2           |18          |
|D02         |0         |024099    |0           |12          |
|D02         |0         |024099    |0           |20          |
|D02         |0         |024099    |0           |25          |
|D02         |0         |024099    |0           |10          |
|D02         |0         |026147    |0           |10          |
|D02         |0         |026147    |3           |20          |
+------------+----------+----------+------------+------------+
Copy
var mArrRows = [
    ["D01", "P01", "024099", "0", 12],
    ["D01", "P01", "024099", "0", 20],
    ["D01", "P01", "026147", "0", 10],
    ["D01", "P01", "026147", "0", 20],
    ["D01", "P01", "026147", "2", 15],
    ["D01", "P01", "026147", "2", 18],
    ["D02", "0",   "024099", "0", 12],
    ["D02", "0",   "024099", "0", 20],
    ["D02", "0",   "024099", "0", 25],
    ["D02", "0",   "024099", "0", 10],
    ["D02", "0",   "026147", "0", 10], 
    ["D02", "0",   "026147", "3", 20]
];
var mRsOutput = new Ax.rs.Reader().build(mArrRows, options => {
    options.setColumnNames(["local_office", "department",
                            "item_code",    "log_variable", "req_quantity"]);
    options.setColumnTypes([
        Ax.sql.Types.CHAR, 
        Ax.sql.Types.CHAR,
        Ax.sql.Types.CHAR,
        Ax.sql.Types.CHAR,
        Ax.sql.Types.DOUBLE
    ]);
});
console.log(mRsOutput);

Returns:

Copy
+------------+----------+---------+------------+------------+
|<null>      |<null>    |<null>   |<null>      |<null>      |
|local_office|department|item_code|log_variable|req_quantity|
|char(0)     |char(0)   |char(0)  |char(0)     |double      |
+------------+----------+---------+------------+------------+
|D01         |P01       |024099   |0           |12          |
|D01         |P01       |024099   |0           |20          |
|D01         |P01       |026147   |0           |10          |
|D01         |P01       |026147   |0           |20          |
|D01         |P01       |026147   |2           |15          |
|D01         |P01       |026147   |2           |18          |
|D02         |0         |024099   |0           |12          |
|D02         |0         |024099   |0           |20          |
|D02         |0         |024099   |0           |25          |
|D02         |0         |024099   |0           |10          |
|D02         |0         |026147   |0           |10          |
|D02         |0         |026147   |3           |20          |
+------------+----------+---------+------------+------------+

3 vtable.addColumns

Is posible to add columns to a vtable created previously and with rows inserted.

Copy
<xsql-script>
    <body>
        <vtable name='v_test'>
            <column name='code'    type='string'  unique='true' />
            <column name='amount'  type='decimal'               />
            <column name='daterow' type='date'                  />
        </vtable>

        <vtable.insert name='v_test'>
            <column name='code'>01</column>
            <column name='amount'>100.5</column>
            <column name='daterow'><date.current /></column>
        </vtable.insert>

        <vtable.addColumns name='v_test'>
            <column name='quantity'  type='integer' />
        </vtable.addColumns>

        <println><v_test /></println>
    </body>
</xsql-script>

Returns:

Copy
+----+------+------------+--------+
|code|amount|daterow     |quantity|
+----+------+------------+--------+
|1   |101   |Dec 24, 2020|        |
+----+------+------------+--------+
Copy
var mRsTest = new Ax.rs.Reader().memory(options => {
    options.setColumnNames([ "code", "amount", "daterow" ]);
    options.setColumnTypes([
        Ax.sql.Types.CHAR, 
        Ax.sql.Types.DOUBLE,
        Ax.sql.Types.DATE
    ]);
    
    options.setColumnScales([ 0, 3, 0 ]);
}); 

mRsTest.rows().add(['01', 100.5,  new Ax.util.Date()]);

mRsTest.cols().add("quantity", Ax.sql.Types.DOUBLE);

console.log(mRsTest);

Returns:

Copy
+--------+-------+------------+--------+
|<null>  |<null> |<null>      |<null>  |
|code    |amount |daterow     |quantity|
|char(40)|double |date        |double  |
+--------+-------+------------+--------+
|01      |100.500|Dec 24, 2020|        |
+--------+-------+------------+--------+

4 vtable.addVTable

Two vtables can be added. That is, add the content of first vtable to second one. In next example are created two vtables, v_test1 and v_test2 and is inserted one row in every vtable. Then, second vtable content is added to first.

In server side script, vtables are replaced by resulsets, rsTest1 and rsTest2. Then a cursor is opened on rsTest2 to copy its data to the other resultset.

Copy
<xsql-script>
    <body>
        <vtable name='v_test1'>
            <column name='code'   type='char' unique='true' />
            <column name='name'   type='char' size='25' />
        </vtable>

        <vtable name='v_test2'>
            <column name='code'   type='char' unique='true' />
            <column name='name'   type='char' size='25' />
        </vtable>

        <vtable.insert name='v_test1'>
            <column name='code'>A1</column>
            <column name='name'>Name A1</column>
        </vtable.insert>

        <vtable.insert name='v_test2'>
            <column name='code'>A2</column>
            <column name='name'>Name A2</column>
        </vtable.insert>

        <println><v_test1 />
<v_test2 /></println>

        <vtable.addVTable>
            <v_test1 />
            <v_test2 />
        </vtable.addVTable>

        <println><v_test1 /></println>
    </body>
</xsql-script>

Returns:

Copy
+----+-------+
|code|name   |
+----+-------+
|A1  |Name A1|
+----+-------+

+----+-------+
|code|name   |
+----+-------+
|A2  |Name A2|
+----+-------+

+----+-------+
|code|name   |
+----+-------+
|A1  |Name A1|
|A2  |Name A2|
+----+-------+
Copy
var mRsTest1 = new Ax.rs.Reader().memory(options => {
    options.setColumnNames([ "code", "name" ]);
    options.setColumnTypes([
        Ax.sql.Types.CHAR, 
        Ax.sql.Types.CHAR
    ]);
    options.setColumnScales([ 0, 25 ]);
}); 
mRsTest1.rows().add(['A1', 'Name A1']);

var mRsTest2 = new Ax.rs.Reader().memory(options => {
    options.setColumnNames([ "code", "name" ]);
    options.setColumnTypes([
        Ax.sql.Types.CHAR, 
        Ax.sql.Types.CHAR
    ]);
    options.setColumnScales([ 0, 25 ]);
});
mRsTest2.rows().add(['A2', 'Name A2']);

console.log('rsTest1');
console.log(mRsTest1);
          
console.log('rsTest2');
console.log(mRsTest2);

mRsTest2.cursor().forEach(row => {
    mRsTest1.rows().add(row);
});
   
console.log('rsTest1');
console.log(mRsTest1);

Returns:

Copy
rsTest1
+--------+--------+
|<null>  |<null>  |
|code    |name    |
|char(40)|char(40)|
+--------+--------+
|A1      |Name A1 |
+--------+--------+

rsTest2
+--------+--------+
|<null>  |<null>  |
|code    |name    |
|char(40)|char(40)|
+--------+--------+
|A2      |Name A2 |
+--------+--------+

rsTest1
+--------+--------+
|<null>  |<null>  |
|code    |name    |
|char(40)|char(40)|
+--------+--------+
|A1      |Name A1 |
|A2      |Name A2 |
+--------+--------+

5 vtable.clear

The content of a vtable can be removed with vtable.clear. In the same way a resultset can be removed with vtable.clear.

Copy
<xsql-script>
    <body>
        <vtable name='people'>
            <column name='dni'       	type='string' unique='true' />
            <column name='name'   	 	type='string'               />
            <column name='surname1' 	type='string'               />
            <column name='surname2' 	type='string'               />
        </vtable>

        <vtable.insert name='people'>
            <string>46352700Z</string>
            <string>John</string>
            <string>Smith</string>
            <string>Simpson</string>
        </vtable.insert>

        <println><vtable.clear name='people' /></println>
    </body>
</xsql-script>
Copy
var mRsPeople = new Ax.rs.Reader().memory(options => {
    options.setColumnNames([ "dni", "name", "surname1", "surname2" ]);
    options.setColumnTypes([
        Ax.sql.Types.CHAR, 
        Ax.sql.Types.CHAR,
        Ax.sql.Types.CHAR,
        Ax.sql.Types.CHAR
    ]);
}); 
mRsPeople.rows().add(['46352700Z', 'John', 'Smith', 'Simpson']);
console.log(mRsPeople);
mRsPeople.clear()
console.log(mRsPeople);

6 vtable.elementAt

Working with VTables in XSQL can be used vtable.elementAt to obtain a certain cell. This operation requires row number and and column name.

on the other hand, in server side script you have to make a loop to be able to position in a given row number.

Copy
<xsql-script>
    <body>
        <vtable name='v_test'>
            <column name='code' type='string' />
            <column name='name' type='string' />
        </vtable>

        <vtable.insert name='v_test'>
            <column name='code'>01</column>
            <column name='name'>Code 1</column>
        </vtable.insert>

        <vtable.insert name='v_test'>
            <column name='code'>02</column>
            <column name='name'>Code 2</column>
        </vtable.insert>

        <vtable.insert name='v_test'>
            <column name='code'>03</column>
            <column name='name'>Code 3</column>
        </vtable.insert>

        <return>
            <vtable.elementAt name='v_test' row='1' column='name' />
        </return>
    </body>
</xsql-script>

Returns:

Copy
Code 2
Copy
var mArrRows = [
	["01", "Code 1"],
	["02", "Code 2"],
	["03", "Code 3"]
]; 

var mRs = new Ax.rs.Reader().build(mArrRows, options => {
	options.setColumnNames(["code", "name"]);
	options.setColumnTypes([
		Ax.sql.Types.CHAR, 
		Ax.sql.Types.CHAR
	]);
});

var mIntIdx = 0;

for (var mRow of mRs) {
	mIntIdx++;
	if (mIntIdx == 2) {
	    console.log(mRow.name);
	}
}

Returns:

Copy
Code 2

Last row

Is posible to select first row or last row of a resulset. To select first row, the resuset method is rs.rows().first(1). To select last row , the resuset method is rs.rows().last(1).

7 vtable.clone

vtable.clone creates a clone of target vtable. That is creates a vtable with same columns, structure and data than target vtable.

To make this we use .

Copy
<xsql-script>
    <body>
        <vtable name='v_test_clone'>
            <column name='code' type='string' />
            <column name='name' type='string' />
         </vtable>

        <vtable.insert name='v_test_clone'>
            <column name='code'>01</column>
            <column name='name'>Code 01</column>
        </vtable.insert>

        <vtable.insert name='v_test_clone'>
            <column name='code'>02</column>
            <column name='name'>Code 02</column>
        </vtable.insert>

        <println>
            Solo estructura
            <vtable.clone name='v_test_clone' only-struct='true' />
            Estructura y datos
            <vtable.clone name='v_test_clone' />
        </println>

    </body>
</xsql-script>

Returns:

Copy
Solo estructura
            
+------+------+
|codigo|nombre|
+------+------+

            Estructura y datos
            
+------+---------+
|codigo|nombre   |
+------+---------+
|1     |Codigo 01|
|2     |Codigo 02|
+------+---------+
Copy
var mArrRows = [
	["01", "Code 01"],
	["02", "Code 02"],
]; 

var mRsTest = new Ax.rs.Reader().build(mArrRows, options => {
	options.setColumnNames(["code", "name"]);
	options.setColumnTypes([
		Ax.sql.Types.CHAR, 
		Ax.sql.Types.CHAR
	]);
});

const mRsTestClone = mRsTest.clone();

console.log(mRsTestClone);

Returns:

Copy
+-------+-------+
|<null> |<null> |
|code   |name   |
|char(0)|char(0)|
+-------+-------+
|01     |Code 01|
|02     |Code 02|
+-------+-------+