Get information of debug.

1 debug

The debug tag is used to obtain the activity log and usage statistics and SQL response times of the execution of a program XSQL-Script. The debuf can be:

  • Sent by e-mail: indicating the e-mail using the attribute mailto.
  • Sent to file: indicating the file path using the attribute file. The file is located in the application server in the indicated file path that should be configurated as server work directory in the configuration database.
  • Sent to the standard console: If the e-mail or the file is not specified, the debug is issued in the standard console or in the application error console DBStudio if it is executed from it.

It exist differents levels of debug that allows to the programmer determine which type of log wants to obtain. By default, if not indicated the database logs are issued as connections, queries and performed transactions.

The option dump is independent of the level of defined debug. This option is used to issue with the debug, the summary of usage statistics and SQL response times. This option is very useful to obtain the total of performed operations and totals of time.

Dump de estadísticas globales sin debug

To indicate that only global statistics without debug are desired, the following values should be indicated.

Copy
dump='true' level='none'

<debug
    mailto='mailto'
    smtphost='smtphost'
    file='file'
    disk='true|false'
    mode='local|calls'
    level='none|soft|eval|attr|conv|dbms|dump|args|file|hard'
    dump='true|false'
    explain='true|false'
/>

Exceptions

unsupported mode [...]

The specified value in the mode attribute is not valid.

no smtp host defined for sending debug file by mail, user= [...]

The mail server has not been indicated and it is not deductible by the user.

unknown SMTP host: [...]

The informed value as mail server is not valid.

could not connect to SMTP host: [...]

It is not possible to establish communication with the specified mail server.

Remarks

The compiled debug information can be visualized by console, sent to the specified email address in the mailto attribute (through the server of the Outgoing mail indicated in the smtphost attribute, or dumped to file using the attribute file. There is a possibility that the debug is propagated to functions (subroutines). Indicating the value calls to the attribute mode, the debug will affect to the possible subroutines, informing the local value (default option), we will get only information of the main routine.

Example

Get debug information by console of certain lines of code.

Copy
<xsql-script name='debug_sample1'>
	<body>
	    <debug />
	    <set name='word1'>hello</set>
	    <set name='word2'>world</set>
	    <set name='sentence'>
	        <string><word1/><string.space /><word2/></string>
	    </set>
	    <println><sentence/></println>
	</body>
</xsql-script>

The result shown on the screen would be:

Copy
00:00.000:    4 p:\tmp\test:.
00:00.000:    4 p:\tmp\test:.. req
00:00.000:    4 p:\tmp\test:.. get all args
00:00.016:    4 p:\tmp\test:.. = java.lang.String[hello]
00:00.016:      p:\tmp\test:. Variable(java.lang.String)[hello]
00:00.016:    4 p:\tmp\test:.
00:00.016:    5 p:\tmp\test:.
00:00.016:    5 p:\tmp\test:.. req
00:00.016:    5 p:\tmp\test:.. get all args
00:00.016:    5 p:\tmp\test:.. = java.lang.String[world]
00:00.016:      p:\tmp\test:. Variable(java.lang.String)[world]
00:00.016:    5 p:\tmp\test:.
hello world

Where the different columns show the following information (from left to right):

Copy
Execution time.
Number of code line.
XSQL-Script route.
Nesting level of the tag.
Label and information of the interpreter.

Example:

Copy
00:00.016:    4 p:\tmp\dvt\test:..</set> = java.lang.String[hello]

The instruction has been processed in the second 16 from the beginning of the execution of the script, the code line is 4, the XML file route is p:\tmp\test, the tag end mark </set> is in the level 2 of nesting and the value 'hello' is interpreted as Java string type (clase java.lang.String).

Example

Get debug information from e-mail.

Copy
<xsql-script name='debug_sample2'>
    <body>
        <debug mailto='destinatario@deister.es' smtphost='mail.deister.net' />
        <set name='word1'>hello</set>
        <set name='word2'>world</set>
        <set name='sentence'>
            <string><word1/><string.space /><word2/></string>
        </set>
        <println><sentence/></println>
    </body>
</xsql-script>

The headboard from the e-mail who would receive the recipient is shown below:

Copy
Subject:  debug file generated at p:\tmp\test
     Date:  Mon Oct 31 14:51:37 CET 2005
     From:  xsqlscript.debug@deister.net
       To:   destinatario@deister.es
 Attached:  debug.txt  debug.xml


XSQLScript debug from script p:\tmp\test

user=null
pool=null
host=camelot
addr=192.168.10.104

This is an automatic generated message from DEISTER Axional Studio application server.
Please, do not respond!

Where debug.txt contains the debuf information and debug.xml includes the code of the script.

Example

Get debug information from disktool.

Copy
<xsql-script name='debug_sample2'>
    <body>
        <debug disk='true' />
        <set name='word1'>hello</set>
        <set name='word2'>world</set>
        <set name='sentence'>
            <string><word1/><string.space /><word2/></string>
        </set>
        <println><sentence/></println>
    </body>
</xsql-script>

A ZIP file in the user's disktool will be created with the name file-{dbms}-{timestamp} where dbms is the database code of execution and timestamp is the current date in milliseconds

Example

Get the debug information for file.

Copy
<xsql-script name='debug_sample3'>
    <body>
        <set name='file_debug'>debug.log</set>
        <debug file='#file_debug' />
        <set name='word1'>hello</set>
        <set name='word2'>world</set>
        <set name='sentence'>
            <string><word1/><string.space /><word2/></string>
        </set>
        <println><sentence/></println>

        <println></println>
        <println>Debug:</println>
        <println></println>
        <println>
            <file.bytes.read>
                <file name='#file_debug' type='absolute'/>
            </file.bytes.read>
        </println>
    </body>
</xsql-script>

The debug information is stored in the file of new creation debug.txt.

Example

Only get information of debug and statistics.

Copy
<xsql-script name='debug_sample4'>
   <body>
       <debug dump='true' level='none' />
       <set name='word1'>hello</set>
       <set name='word2'>world</set>
       <set name='sentence'>
           <string><word1/><string.space /><word2/></string>
       </set>
       <println><sentence/></println>
   </body>
</xsql-script>

In this case, the result only shows statistic information, because the debug level is disabled:

Copy
< SCRIPT (p:\tmp\dvt\debug_test) >
User........................: null
Current tag.................: [sentence: null]
Current line................: 9
Execution time..............: 00:00.031
Local module functions......: 0

< SQL SELECT >
Cached ResultSets...........: 0 (0 / 0) 0,00 (N/A)
Instructions of type select.: 0 (cached = 0, direct = 0, prepared = 0)
Physically executed fetch...: 0

< SQL STATEMENTS >
Cached Statements...........: 0 (0 / 0) 0,00 (N/A)
Physically Prepared.........: 0 (cached = 0, direct = 0)
Physically executed insert..: 0 / 0
Physically executed delete..: 0 / 0
Physically executed update..: 0 / 0
Physically executed exec-f..: 0
Physically executed exec-p..: 0
Physically executed other...: 0
Physically executed total...: 0 (direct = 0, prepared = 0)

< SPL FUNCTIONS >
Cached function calls.......: (0 / 0) 0,00 (N/A)

< SPL PROCEDURES >
Cached procedures calls.....: (0 / 0) 0,00 (N/A)

< SCRIPT FUNCTIONS >
Cached script calls.........: (0 / 0) 0.00,00 (N/A)

< LOCAL VARIABLES (3) >
+--------+-+--------+-------------------------+--------+-----------+
|name    |P|recycles|Type XML                 |Type SQL|Data       |
+--------+-+--------+-------------------------+--------+-----------+
|sentence| |       0|string (java.lang.String)|CHAR    |hello world|
|word1   | |       0|string (java.lang.String)|CHAR    |hello      |
|word2   | |       0|string (java.lang.String)|CHAR    |world      |
+--------+-+--------+-------------------------+--------+-----------+
Example

Get the SQL Explain of the performed SQL query and recover the file from an e-mail.

Copy
<xsql-script name='debug_sample2'>
   <body>
       <debug explain='true' mailto='destinatario@deister.es' smtphost='mail.deister.net' />

       <file.out.open id='out1'>
           <file name='z:\yy' type='absolute' />
       </file.out.open>

       <file.out.print.sql id='out1' head='false'>
           <select>
               <columns>*</columns>
               <from table='cdiarios'>
                   <join table='cdiarios' type='left' alias='b'>
                       <on>cdiarios.codigo = b.codigo</on>
                   </join>
               </from>
               <where>
                   cdiarios.nomdia like '%b%'
               </where>
               <group>1,2,3,4</group>
               <order>1</order>
           </select>
       </file.out.print.sql>
   </body>
</xsql-script>

The headboard from the e-mail who would receive the recipient is shown below:

Copy
Subject:  debug file generated at p:\tmp\test
     Date:  Mon Oct 31 14:51:37 CET 2005
     From:  xsqlscript.debug@deister.net
       To:  destinatario@deister.es
 Attached:  debug.txt.gz  debug.xml.gz   sqlexplain.txt.gz


XSQLScript debug from script p:\tmp\test

user=null
pool=null
host=camelot
addr=192.168.10.104

This is an automatic generated message from DEISTER Axional Studio application server.
Please, do not respond!

Where sqlexplain.txt the SQL Explain of the performed SQL query.

2 Main cases

The main uses of debugging are a query performance test or tracking variables in a script.

2.1 Query performance

In this case, we make two queries and analyze the times in the table TOP SQL STATEMENTS

Example

The debug attributes required in this case are dump = true and level = none. These attributes are the ones that are by default.

Copy
<xsql-script>
   <body>
        <debug mailto='destinatario@deister.es' smtphost='mail.deister.net'/>

        <select prefix='m_'>
            <columns>
                the_year the_year1, 
                SUM(store_sales) total_sales1, 
                SUM(store_cost) total_cost1
            </columns>
            <from table='sales_fact'>
                <join table='time_by_day'>
                    <on>sales_fact.time_id = time_by_day.time_id</on>
                </join>
            </from>
            <where>
                the_year = 1998
            </where>
            <group>1</group>
        </select>

        <select prefix='m_'>
            <columns>
                the_year the_year2, 
                SUM(sales) total_sales2, 
                SUM(cost) total_cost2
            </columns>
            <from table='sales_fact_yearmonth_store'/>
            <where>
                the_year = 1998
            </where>
            <group>1</group>
        </select>
        <println>
            ok <m_the_year1/>
            total_sales: <m_total_sales2/>
        </println>
   </body>
</xsql-script>

The headboard from the e-mail who would receive the recipient is shown below:

Copy
< FUNCTION CALLS >
+--------+----+----+----+-----+----+----+----+
|Function|Rank|Self|Acum|Count|Min |Max |Avg |
+--------+----+----+----+-----+----+----+----+
|select  |   1|0.24|0.24|    2|0.01|0.23|0.12|
|println |   2|0.00|0.24|    1|0.00|0.00|0.00|
+--------+----+----+----+-----+----+----+----+

< TOP SQL STATEMENTS >
+-------+----+----+----+-----+----+-------------+---------------+-----------------------------------------------+
|Script |Rank|Self|Acum|Count|Line|User         |Dbms           |SQL                                            |
+-------+----+----+----+-----+----+-------------+---------------+-----------------------------------------------+
|<embed>|   1|0.23|0.23|    1|   6|user.deister |sample_foodmart|                                               |
|       |    |    |    |     |    |             |               |SELECT                                         |
|       |    |    |    |     |    |             |               |                the_year the_year1,            |
|       |    |    |    |     |    |             |               |                SUM(store_sales) total_sales1, |
|       |    |    |    |     |    |             |               |                SUM(store_cost) total_cost1    |
|       |    |    |    |     |    |             |               |                                               |
|       |    |    |    |     |    |             |               |  FROM sales_fact                              |
|       |    |    |    |     |    |             |               |      ,time_by_day                             |
|       |    |    |    |     |    |             |               | WHERE                                         |
|       |    |    |    |     |    |             |               |       sales_fact.time_id = time_by_day.time_id|
|       |    |    |    |     |    |             |               |[ 5 line(s) more ]                             |
|<embed>|   2|0.01|0.23|    1|  23|user.deister |sample_foodmart|                                               |
|       |    |    |    |     |    |             |               |SELECT                                         |
|       |    |    |    |     |    |             |               |                the_year the_year2,            |
|       |    |    |    |     |    |             |               |                SUM(sales) total_sales2,       |
|       |    |    |    |     |    |             |               |                SUM(cost) total_cost2          |
|       |    |    |    |     |    |             |               |                                               |
|       |    |    |    |     |    |             |               |  FROM sales_fact_yearmonth_store              |
|       |    |    |    |     |    |             |               | WHERE                                         |
|       |    |    |    |     |    |             |               |                                               |
|       |    |    |    |     |    |             |               |                the_year = 1998                |
|       |    |    |    |     |    |             |               |[ 3 line(s) more ]                             |
+-------+----+----+----+-----+----+-------------+---------------+-----------------------------------------------+

< ALL(2) SQL STATEMENTS (ACUMULATED TIME AND COUNT) >
+-------+----+----+----+-----+----+-------------+---------------+-----------------------------------------------+
|Script |Rank|Self|Acum|Count|Line|User         |Dbms           |SQL                                            |
+-------+----+----+----+-----+----+-------------+---------------+-----------------------------------------------+
|<embed>|   1|0.23|0.23|    1|   6|user.deister |sample_foodmart|                                               |
|       |    |    |    |     |    |             |               |SELECT                                         |
|       |    |    |    |     |    |             |               |                the_year the_year1,            |
|       |    |    |    |     |    |             |               |                SUM(store_sales) total_sales1, |
|       |    |    |    |     |    |             |               |                SUM(store_cost) total_cost1    |
|       |    |    |    |     |    |             |               |                                               |
|       |    |    |    |     |    |             |               |  FROM sales_fact                              |
|       |    |    |    |     |    |             |               |      ,time_by_day                             |
|       |    |    |    |     |    |             |               | WHERE                                         |
|       |    |    |    |     |    |             |               |       sales_fact.time_id = time_by_day.time_id|
|       |    |    |    |     |    |             |               |[ 5 line(s) more ]                             |
|<embed>|   2|0.01|0.23|    1|  23|user.deister |sample_foodmart|                                               |
|       |    |    |    |     |    |             |               |SELECT                                         |
|       |    |    |    |     |    |             |               |                the_year the_year2,            |
|       |    |    |    |     |    |             |               |                SUM(sales) total_sales2,       |
|       |    |    |    |     |    |             |               |                SUM(cost) total_cost2          |
|       |    |    |    |     |    |             |               |                                               |
|       |    |    |    |     |    |             |               |  FROM sales_fact_yearmonth_store              |
|       |    |    |    |     |    |             |               | WHERE                                         |
|       |    |    |    |     |    |             |               |                                               |
|       |    |    |    |     |    |             |               |                the_year = 1998                |
|       |    |    |    |     |    |             |               |[ 3 line(s) more ]                             |
+-------+----+----+----+-----+----+-------------+---------------+-----------------------------------------------+

< DATABASE SESSION STATISTICS >

< MEMORY POOLS STATUS >
+-----+--------------------------------+--------+-------------------------+-----------+-----------+-----------+------------+-----------+-----------+-----------+----------+--------+---------+
 Memory pools
+-----+--------------------------------+--------+-------------------------+-----------+-----------+-----------+------------+-----------+-----------+-----------+----------+--------+---------+
|                                                                         |Usage                                           |Peak                   |Threshold                                |
+-----+--------------------------------+--------+-------------------------+-----------+-----------+-----------+------------+-----------+-----------+-----------+----------+--------+---------+
|rowid|poolname                        |pooltype|jvm_flags                |used       |commited   |max        |percent_used|peak_used  |peak_max   |th_max     |th_percent|th_count|th_exceed|
+-----+--------------------------------+--------+-------------------------+-----------+-----------+-----------+------------+-----------+-----------+-----------+----------+--------+---------+
|0    |G1 Eden Space                   |HEAP    |-Xmx,-XX:MaxNewSize      |     251 MB|     482 MB|      -1  b|            |     902 MB|       0  b|           |          |        |         |
|1    |G1 Old Gen                      |HEAP    |-Xmx                     |    1.11 GB|    1.46 GB|       2 GB|     55.43 %|    1.62 GB|       2 GB|    1.60 GB|        80|       5|false    |
|2    |G1 Survivor Space               |HEAP    |-Xmx                     |      73 MB|      73 MB|      -1  b|            |      84 MB|       0  b|           |          |        |         |
|3    |CodeHeap 'non-nmethods'         |NON_HEAP|-XX:ReservedCodeCacheSize|    1.56 MB|    2.44 MB|    5.56 MB|     28.12 %|    1.68 MB|    5.56 MB|       0  b|          |       0|false    |
|4    |Metaspace                       |NON_HEAP|                         |  193.68 MB|  239.92 MB|      -1  b|            |  210.83 MB|       0  b|       0  b|          |       0|false    |
|5    |CodeHeap 'profiled nmethods'    |NON_HEAP|-XX:ReservedCodeCacheSize|   71.70 MB|   73.88 MB|  117.22 MB|     61.17 %|   72.02 MB|  117.22 MB|       0  b|          |       0|false    |
|6    |CodeHeap 'non-profiled nmethods'|NON_HEAP|-XX:ReservedCodeCacheSize|   58.71 MB|   59.19 MB|  117.22 MB|     50.09 %|   59.01 MB|  117.22 MB|       0  b|          |       0|false    |
+-----+--------------------------------+--------+-------------------------+-----------+-----------+-----------+------------+-----------+-----------+-----------+----------+--------+---------+

Where sqlexplain.txt the SQL Explain of the performed SQL query.

2.2 Script tracking

In this example we can track the use of three local functions.

Example

The debug attributes required in this case are level = 'soft' and dump = 'true' (default attribute)

Copy
<xsql-script>
   <body>
        <debug mailto='destinatario@deister.es' smtphost='localhost' level='soft' />
        
        <function name='get_sales_year'>
            <args>
                <arg name='p_year'/>
            </args>
            <body>
                <select prefix='m_'>
                    <columns>
                        SUM(store_sales) total_sales
                    </columns>
                    <from table='sales_fact'>
                        <join table='time_by_day'>
                            <on>sales_fact.time_id = time_by_day.time_id</on>
                        </join>
                    </from>
                    <where>
                        the_year = <p_year/>
                    </where>
                </select>
                <return><m_total_sales/></return>
            </body>
        </function>

        <function name='get_cost_year'>
            <args>
                <arg name='p_year'/>
            </args>
            <body>
                <select prefix='m_'>
                    <columns>
                        SUM(cost) total_cost
                    </columns>
                    <from table='sales_fact_yearmonth_store'/>
                    <where>
                        the_year = <p_year/>
                    </where>
                </select>
                <return><m_total_cost/></return>
            </body>
        </function>

        <function name='get_gain_year'>
            <args>
                <arg name='p_year'/>
            </args>
            <body>

                <set name='m_total_sales'><get_sales_year><p_year/></get_sales_year></set>
                <set name='m_total_cost'><get_cost_year><p_year/></get_cost_year></set>
                <return><mul><sub><div><ifnull><m_total_sales/>0</ifnull><ifnull><m_total_cost/>1</ifnull></div>1</sub>100</mul></return>
            </body>
        </function>

        <println>
            total gain : <get_gain_year>1998</get_gain_year>%
        </println>
   </body>
</xsql-script>
Copy
:..</debug> 
:..<function/> 
:..</function> 
:..<function/> 
:..</function> 
:..<function/> 
:..</function> 
:..<println/> 
:..<get_gain_year/> internal
:...<get_gain_year/> call attribute p_year=java.lang.Integer[1998] type=null
->get_gain_year:<function/> 
->get_gain_year:.<body/> 
->get_gain_year:..<set/> 
->get_gain_year:...<get_sales_year/> internal
->get_gain_year:....</p_year> var=Variable 'p_year' java.lang.Integer[1998]
->get_gain_year:....<get_sales_year/> call attribute p_year=java.lang.Integer[1998] type=null
->get_gain_year->get_sales_year:<function/> 
->get_gain_year->get_sales_year:.<body/> 
->get_gain_year->get_sales_year:..<select/> 
->get_gain_year->get_sales_year:..</p_year> var=Variable 'p_year' java.lang.Integer[1998]
<RUN sample_foodmart transaction='false' tag='select' method='__prepareStatement'>

SELECT
                        SUM(store_sales) total_sales

  FROM sales_fact
      ,time_by_day
 WHERE
       sales_fact.time_id = time_by_day.time_id
 AND
                        the_year = ?
</RUN>
->get_gain_year->get_sales_year:..<select/> prepared statement stored in cache, size=1 ps=JDBCPreparedStatement[00000008][JDBCConnection[
<PREPAREDSTATEMENT hold='HOLD_CURSORS_OVER_COMMIT' class='deister.axional.server.jdbc.impl.JDBCPreparedStatement'>
->get_gain_year->get_sales_year:..<select/> setUpdateParameter(1) sqltype=4 (INTEGER) value=[1998] class=java.lang.Integer
<RESULTSET hold='HOLD_CURSORS_OVER_COMMIT' type='FORWARD_ONLY' class='deister.axional.server.jdbc.impl.JDBCResultSet'>
->get_gain_year->get_sales_year:   <resultset-autovars prefix='m_' struct='' preserve-case='false'> 
->get_gain_year->get_sales_year:     set rs variable m_total_sales = [1079147.4700] sqltype(3, DECIMAL) isnull(false) java.math.BigDecimal
->get_gain_year->get_sales_year:   </resultset-autovars> 
->get_gain_year->get_sales_year:..</select> data=java.math.BigDecimal[1079147.4700]
->get_gain_year->get_sales_year:..<return/> 
->get_gain_year->get_sales_year:....</m_total_sales> var=Variable 'm_total_sales' java.math.BigDecimal[1079147.4700]
->get_gain_year->get_sales_year:..</return> 
->get_gain_year->get_sales_year:.</body> return=java.math.BigDecimal[1079147.4700]
->get_gain_year->get_sales_year:</function> 
->get_gain_year:..</set> data=Variable 'm_total_sales' java.math.BigDecimal[1079147.4700]
->get_gain_year:..<set/> 
->get_gain_year:...<get_cost_year/> internal
->get_gain_year:....</p_year> var=Variable 'p_year' java.lang.Integer[1998]
->get_gain_year:....<get_cost_year/> call attribute p_year=java.lang.Integer[1998] type=null
->get_gain_year->get_cost_year:<function/> 
->get_gain_year->get_cost_year:.<body/> 
->get_gain_year->get_cost_year:..<select/> 
->get_gain_year->get_cost_year:..</p_year> var=Variable 'p_year' java.lang.Integer[1998]
<RUN sample_foodmart transaction='false' tag='select' method='__prepareStatement'>

SELECT
                        SUM(cost) total_cost

  FROM sales_fact_yearmonth_store
 WHERE

                        the_year = ?
</RUN>
->get_gain_year->get_cost_year:..<select/> prepared statement stored in cache, size=2 ps=JDBCPreparedStatement[00000009][JDBCConnection[
<PREPAREDSTATEMENT hold='HOLD_CURSORS_OVER_COMMIT' class='deister.axional.server.jdbc.impl.JDBCPreparedStatement'>
->get_gain_year->get_cost_year:..<select/> setUpdateParameter(1) sqltype=4 (INTEGER) value=[1998] class=java.lang.Integer
<RESULTSET hold='HOLD_CURSORS_OVER_COMMIT' type='FORWARD_ONLY' class='deister.axional.server.jdbc.impl.JDBCResultSet'>
->get_gain_year->get_cost_year:..<select/> resultset returned from query, rs=JDBCResultSet[rs134426:st9][refc=1/1][JDBCPreparedStatement[00000009][JDBCConnection[
->get_gain_year->get_cost_year:   <resultset-autovars prefix='m_' struct='' preserve-case='false'> 
->get_gain_year->get_cost_year:     set rs variable m_total_cost = [432565.7289] sqltype(3, DECIMAL) isnull(false) java.math.BigDecimal
->get_gain_year->get_cost_year:   </resultset-autovars> 
->get_gain_year->get_cost_year:..</select> data=java.math.BigDecimal[432565.7289]
->get_gain_year->get_cost_year:..<return/> 
->get_gain_year->get_cost_year:....</m_total_cost> var=Variable 'm_total_cost' java.math.BigDecimal[432565.7289]
->get_gain_year->get_cost_year:..</return> 
->get_gain_year->get_cost_year:.</body> return=java.math.BigDecimal[432565.7289]
->get_gain_year->get_cost_year:</function> 
->get_gain_year:..</set> data=Variable 'm_total_cost' java.math.BigDecimal[432565.7289]
->get_gain_year:..<return/> 
->get_gain_year:....<mul/> 
->get_gain_year:.....<sub/> 
->get_gain_year:......<div/> 
->get_gain_year:.......<ifnull/> 
->get_gain_year:........</m_total_sales> var=Variable 'm_total_sales' java.math.BigDecimal[1079147.4700]
->get_gain_year:.......</ifnull> data=java.math.BigDecimal[1079147.4700]
->get_gain_year:.......<ifnull/> 
->get_gain_year:........</m_total_cost> var=Variable 'm_total_cost' java.math.BigDecimal[432565.7289]
->get_gain_year:.......</ifnull> data=java.math.BigDecimal[432565.7289]
->get_gain_year:......</div> data=java.math.BigDecimal[2.4947595195399216]
->get_gain_year:.....</sub> data=java.math.BigDecimal[1.4947595195399216]
->get_gain_year:....</mul> data=java.math.BigDecimal[149.4759519539921600]
->get_gain_year:..</return> 
->get_gain_year:.</body> return=java.math.BigDecimal[149.4759519539921600]
->get_gain_year:</function> 
:..</println> data=java.lang.String[
            total gain : 149.4759519539921600%
        ]