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
<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:
+-------+-------+------+------+-----------------+ |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| +-------+-------+------+------+-----------------+
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:
+-------+-------+------+------+-------+ |<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
.
<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:
+------------+----------+----------+------------+------------+ |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 | +------------+----------+----------+------------+------------+
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:
+------------+----------+---------+------------+------------+ |<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.
<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:
+----+------+------------+--------+ |code|amount|daterow |quantity| +----+------+------------+--------+ |1 |101 |Dec 24, 2020| | +----+------+------------+--------+
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:
+--------+-------+------------+--------+ |<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.
<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:
+----+-------+ |code|name | +----+-------+ |A1 |Name A1| +----+-------+ +----+-------+ |code|name | +----+-------+ |A2 |Name A2| +----+-------+ +----+-------+ |code|name | +----+-------+ |A1 |Name A1| |A2 |Name A2| +----+-------+
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:
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
.
<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>
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.
<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:
Code 2
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:
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 .
<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:
Solo estructura +------+------+ |codigo|nombre| +------+------+ Estructura y datos +------+---------+ |codigo|nombre | +------+---------+ |1 |Codigo 01| |2 |Codigo 02| +------+---------+
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:
+-------+-------+ |<null> |<null> | |code |name | |char(0)|char(0)| +-------+-------+ |01 |Code 01| |02 |Code 02| +-------+-------+