/*! @page ifrtrace SQLDBC Tracing and Logging
    @par
    @section ifrtrace1 Trace Features    
    @par 
    SQLDBC can generate trace output to support 
    defect analysis and debugging. The trace is usually written to a file,
    and the size of that file can be limited (and the trace starts writing
    at the beginning of the file when the size is exceeded). Also, the trace
    is multi-thread safe, and thread changes are detected and logged.

    There are several kinds of tracing some for normal users and some for 
    experts how know the source code or the internal architecture of SQLDBC.

    All trace kinds can be combined together.
    
    The following kinds of trace can be generated:

    @par SQL Trace
    The SQL trace shows all SQL commands sends from the application 
    to the database including the data of columns and parameters. 
    It also traces the metadata of the query and the parameter binding of the 
    application. The SQL trace is the normal trace for users to analyze what 
    the application does during runtime.

    @par Call Trace (short trace)
    The call trace is a hierarchical trace that
    shows the names of the internal methods as they get called. Only
    the names are shown, not the arguments of the calls. The function
    names are indented to show the call nesting level.
    
    @par Debug Trace (long trace)
    All explicit trace statements in the SQLDBC runtime fall into
    this category.  Thus you will see here all additional diagnostic
    output, to diagnose problems in using the interface runtime.

    @par Profile Trace
    In this trace, the entering and exiting of a profiling sections
    (which are usually, but are not necessarily required to be
    functions) is traced with a timestamp of high resolution. That
    output can be used to gather profiling data about the runtime
    behavior.

    @par Packet Trace
    In this trace, the content of the packets which are sent to and received
    from the database server is dumped. To read this trace you should be an 
    expert of the internal order interface of MaxDB.
    
    @section ifrtrace2 Controlling the Trace

    @par
    The trace can be enabled by using the <tt>sqldbc_cons</tt> utility.

    @par Trace Control using sqldb_cons

    The tool <tt>sqldbc_cons</tt> is called as follows:
<pre>          
sqldbc_cons [options] [command]
</pre>
    where <tt>[options]</tt> are:

    <table border=1>
      <tr>
        <td><b>Option</b></td>
        <td><b>Description</b></td>
      </tr>
      <tr>
        <td><tt>-h</tt></td>   
        <td>Help. Shows usage information, and ignore all commands.</td>
      </tr>
      <tr>
        <td><tt>-p &lt;pid&gt;</tt></td>   
        <td>Execute the command only for the specified process id <tt>&lt;pid&gt;</tt>.</td>
      </tr>
      <tr>
        <td><tt>-v</tt></td>   
        <td>Verbose operation.</td>
      </tr>
      <tr>
        <td><tt>-f</tt></td>   
        <td>Force tool execution, even if a lock file of another instance is 
        found.\n This feature should only used in critical situation like endless loops or 
        hanging processes.
        </td>
      </tr>
    </table>

    and <tt>[commands]</tt> are:

    <table border=1>
      <tr>
        <td><b>Command</b></td>
        <td><b>Description</b></td>
      </tr>
      <tr>
        <td><tt>[CONFIG] TRACE SQL | ON|OFF</tt></td>
        <td>Switches the SQL commando trace on or off or sets the call trace nesting level</td>
      </tr>
      <tr>
        <td><tt>[CONFIG] TRACE SHORT ON|OFF</tt></td>
        <td>Switches the short call trace (only function calls) on or off</td>
      </tr>
      <tr>
        <td><tt>[CONFIG] TRACE LONG ON|OFF</tt></td>
        <td>Switches the long call trace (includes function and arguments)  on or off</td>
      </tr>
      <tr>
        <td><tt>[CONFIG] TRACE PROFILE ON|OFF</tt></td>
        <td>Switches the profile trace on or off</td>
      </tr>
      <tr>
        <td><tt>[CONFIG] TRACE PACKET ON|OFF|&lt;limit&gt;</tt></td>
        <td>Switches the packet trace (like vtrace) on or off or sets the packet trace size.</td>
      </tr>
      <tr>
        <td><tt>[CONFIG] TRACE TIMESTAMP ON|OFF</tt></td>
        <td>Switches the time stamp prefix on or off</td>
      </tr>
      <tr>
        <td><tt>CONFIG TRACEFILENAME &lt;filename&gt;</tt></td>
        <td>Set the trace file name to where the commands are logged.\n
        A '%p' within the file name will be expanded to the process\n
        id of the application. File names started with a './' are placed\n
        relative to the run directory of the traced application</td>
      </tr>
      <tr>
        <td><tt>TRACE OFF</tt></td>
        <td>Switches all trace kinds off</td>
      </tr>
      <tr>
        <td><tt>SHOW CONFIG</tt></td>
        <td>Shows the trace configuration.</td>
      </tr>
      <tr>
        <td><tt>SHOW TRACESETTINGS</tt></td>
        <td>Shows the current trace settings done by this tool.</td>
      </tr>
      <tr>
        <td><tt>SHOW ALL</tt></td>
        <td>Shows the trace configuration and settings.</td>
      </tr>
    </table>

    @note
    - All command names are case insensitive. Also commands can be abbreviate to a length where 
    they can uniquely identified (e.g. 'S T' is same as 'SHOW TRACESETTINGS').

    - The trace types SQL, SHORT, LONG, PROFILE, PACKET can started with the CONFIG
    argument to make the trace settings persistent. Persistent means that all new
     started applications traces with the given setting.
*/    
 

/** @page pcache Implementation Details: ParseInfo Cache

    As it is expensive to parse commands again each time the parse infos are cached for each
    connection.

    An existing parse info can be used for a command if:
    - the command string is equal
    - the encoding of the command string is the same
    - the isolation level at parse time is the same

    A parse info is in shared use by several SQL statements, and must be therefore guarded
    against concurrent access. 

    @par Inserting a ParseInfo into the Cache
    
    A parse info is create by preparing a statement. Here, it is checked whether there
    is a parse info available, and if not the statement is parsed. Then, the parse info
    is inserted into the cache - hereby setting its flags appropriately.

    During this process the parse info is locked by the creator.

    @par Attaching to a ParseInfo

    When a matching parse info is found on prepare, the statement simply attaches to it.
    This means that the reference count of the parse info is increased. Attaching to a 
    parse info also propagates the parse info also to the top of the LRU list.

    @par Detaching from a ParseInfo

    When a statement is destroyed, it detaches from the parse info. If the parse info is
    cached, the reference count is simply decremented by one. 

    If it is not cached, it is checked whether this was the last referencee, and if yes,
    the resources are freed.

    @par Displacement of ParseInfo
    
    On the insertion of a new ParseInfo into the cache, the cache size is checked. If the
    cache is full, the ParseInfo at the end of the LRU list is displaced, hereby setting 
    its 'cached' flag to false. If its reference count is 0, it is deleted, otherwise that
    task is done by the last statement that detaches from the ParseInfo.    
    
*/

/** @page dataexec Implementation Details: Late Binding (DATA AT EXECUTE)

    ODBC provides the possibility to provide data for input parameters at
    execution time, and this feature is especially used for transferring 
    large objects into the database. Here, the indicator of a host variable
    signals that the data is available at execution time.   

    If at least one of these parameters is found, instead of consisting of
    a single call to <code>execute()</code> or <code>executeBatch</code>,
    the execution of a prepared statement proceeds according to the following 
    sequence:

    <ol>
      <li>Call <code>execute()</code>, it will return <code>IFR_NEED_DATA</code>.</li>
      <li>Call <code>nextParameter(index, address)</code>. Here, index and address 
          will be filled with the next parameter's details. The address here is set
          according to the parameter binding, the binding type, and the position in
          the row array, if batch execution is done. If the method returns 
          <code>IFR_OK</code>, you are finished, if it returns 
          <code>IFR_NEED_DATA</code>, 
      </li>
      <li>Call <code>putData(data, lengthindicator)</code> to actually provide the data.
          Take care that for integral data types, and the speciall NULL and DEFAULT
          values the data must be delivered in one call, otherwise subsequent calls 
          of <code>putData</code> append to the data. Continue with this step 
          until all data for that parameter has been transferred.   
      </li>
      <li>Continue with step 2 until finished.</li>
    </ol>        
    
    @par Internal Execution Sequence

    The calling sequence described above is translated into one EXECUTE message,
    and if necessary, one or more PUTVAL messages. 

    For doing this, the following measures are taken:

    <ol>
      <li>The parameters which are 'normal' bound are converted and inserted into 
          the message. If they are of LONG types, it is kept whether the long data
          did fit into the message, or was truncated.
      </li>
      <li>All non-LONG parameters which have late binding are collected, converted
          and inserted.
      </li>
      <li>If the LONG parameters that were not bound with late binding already  
          did not fit, now the EXECUTE message is sent, and if necessary,
          subsequent PUTVAL messages.
      </li>
      <li>The LONG parameters that were bound with late binding are collected,
          and inserted, hereby sending a PUTVAL message each time the space
          in the request packet is filled up. 
      </li>
    </ol>        
    
    The following example illustrates the behaviour:
    
<pre>
Consider a table TESTDATA defined as follows:

  CREATE TABLE TESTDATA(A INTEGER,
                        B CHAR(200),
                        C LONG BYTE,
                        D CHAR(30),
                        E LONG BYTE)

Assume an INSERT statement on this table, where the parameters for
column C and D are bound having an indicator value DATA AT EXECUTE,
and E is bound to an array of 1000 bytes. We assume also that the
order in the data part is A,B,C,D,E, for the ease of description.

The packet is filled as follows:

(1) execute
    
    The execute step does check whether there is DATA AT EXECUTE,
    and so returns almost immediately.

(2) nextParameter

    The execute step puts the parse id part into the segment, and then 
    all available data. The segment will then look as follows:

    +----------------+
    | ParseID Part   |
    +----------------+
    | Data Part      |   
    | A              |
    | B              |
    | C (Descriptor) |  <== Descriptor is set to 'no data' for now.
    |                |  <== Space for D is kept, but not filled with data.
    | E (Descriptor) |  <== Points to the data, has flag vm_alldata
    | E (Data)       |      to show there is no more data.
    +----------------+    
    
    Furthermore, the internal structures are laid out, and all DATA AT EXECUTE
    parameters are recorded. 

    Finally, the function returns pointing to D, as it is not a LONG column, 
    and non-LONGs are preferred.

(3) putData
   
    The application fills up D using putData, which fills up the value, 
    and eventually returns IFR_DATA_TRUNC when too much data is inserted.

    Now the segment looks like this:

    +----------------+
    | ParseID Part   |
    +----------------+
    | Data Part      |   
    | A              |
    | B              |
    | C (Descriptor) |  
    | D              | 
    | E (Descriptor) |  
    | E (Data)       |  
    +----------------+    

(4) nextParameter

    The next call to this method returns parameter C, and does not
    send any packet - or change anything, as it is not filled up.
    
(5) putData

    Subsequently, C will be filled with data. At some point, the
    segment will look like:

    +----------------+
    | ParseID Part   |
    +----------------+
    | Data Part      |   
    | A              |
    | B              |
    | C (Descriptor) |  
    | D              | 
    | E (Descriptor) |  
    | E (Data)       |  
    | D (Data)       |  
    +----------------+    
    
    and the packet is filled up completely. Then the packet is sent,
    and normal PUTVAL packets for this LONG are created, which are
    sent when they are filled up (which may happen in extreme even
    several times with one putData.

</pre>    


    @par Special Handling for Batch Execution
    
    When DATA AT EXECUTE is spotted during an <code>executeBatch()</code> operation,
    the control flow is similar to the case when this happen during <code>execute()</code>.
    
    The address returned by the <code>nextParameter</code> call will indicate the row, 
    as it would point to the place where the data would be normally expected, if no
    DATA AT EXECUTE would be present.
    
    In contrast to a single execute, the data from the rows accumulates in the packet
    until the packet is full.
    
 */


/*
 TODO fill this table.

 @page hostconv Implementation Details: Parameter Conversion

    The following table lists the implemented conversions for the host and SQL data types.

<table border="1">
<tr>
<td><b>Host Data Type</b></td>
<td><b>BINARY</b></td>
<td><b>ASCII</b></td>
<td><b>UCS2</b></td>
<td><b>UTF8</b></td>
<td><b>UINT1</b></td>
<td><b>INT1</b></td>
<td><b>UINT2</b></td>
<td><b>INT2</b></td>
<td><b>UINT4</b></td>
<td><b>INT4</b></td>
<td><b>UINT8</b></td>
<td><b>INT8</b></td>
<td><b>double</b></td>
<td><b>float</b></td>
<td><b>DATE_STRUCT</b></td>
<td><b>TIME_STRUCT</b></td>
<td><b>TIMESTAMP</b></td>
<td><b>NUMERIC</b></td>
<td><b>GUID</b></td>
</tr>
<tr>
<td><b>SQL Type</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>FIXED</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>FLOAT</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>CHAR ASCII</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>CHAR EBCDIC</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>CHAR BYTE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>LONG ASCII</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>LONG EBCDIC</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>LONG BYTE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>DATE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>TIME</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>TIMESTAMP</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>BOOLEAN</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>CHAR UNICODE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>SMALLINT</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>INTEGER</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>VARCHAR ASCII</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>VARCHAR EBCDIC</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>VARCHAR BYTE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>LONG UNICODE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>VARCHAR UNICODE</b></td>
<td colspan=19></td>
</tr>
<tr>
<td><b>ABAP STREAM</b></td>
<td colspan=19></td>
</tr>
</table>
 */

   
 
