.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 2000-2005 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $SQL$Project Distributed Database System$VAK640$
.tt 2 $$$
.TT 3 $ElkeZ$Execute_Factor$2000-11-16$
***********************************************************
.nf
 
 .nf
 
    ========== licence begin  GPL
    Copyright (c) 2000-2005 SAP AG
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
.fo
 
 
.fo
.nf
.sp
MODULE  : Execute_Factor
=========
.sp
Purpose : Processing of a factor of a value expression
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              a640factor (
                    VAR acv      : tak_all_command_glob;
                    VAR dmli     : tak_dml_info;
                    VAR colin    : tak00_scolinf;
                    VAR act_node : integer);
 
        PROCEDURE
              a640not_first_factor (
                    VAR acv      : tak_all_command_glob;
                    VAR dmli     : tak_dml_info;
                    VAR colin    : tak00_scolinf;
                    VAR act_node : integer);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01_i_new           : tsp00_KnlIdentifier;
              a01_i_old           : tsp00_KnlIdentifier;
              a01_i_tablekey      : tsp00_KnlIdentifier;
              a01_il_b_identifier : tsp00_KnlIdentifier;
 
      ------------------------------ 
 
        FROM
              AK_semantic_scanner_tools : VAK05;
 
        PROCEDURE
              a05identifier_get (
                    VAR acv     : tak_all_command_glob;
                    tree_index  : integer;
                    obj_len     : integer;
                    VAR moveobj : tsp00_KnlIdentifier);
 
      ------------------------------ 
 
        FROM
              AK_universal_semantic_tools : VAK06;
 
        PROCEDURE
              a06get_username (
                    VAR acv        : tak_all_command_glob;
                    VAR tree_index : integer;
                    VAR username   : tsp00_KnlIdentifier);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK07;
 
        PROCEDURE
              a07_b_put_error (
                    VAR acv : tak_all_command_glob;
                    b_err   : tgg00_BasisError;
                    err_code : tsp00_Int4);
 
        PROCEDURE
              a07_nb_put_error (
                    VAR acv  : tak_all_command_glob;
                    b_err    : tgg00_BasisError;
                    err_code : tsp00_Int4;
                    VAR n    : tsp00_KnlIdentifier);
 
      ------------------------------ 
 
        FROM
              AK_View_semantic : VAK16;
 
        PROCEDURE
              a16col_to_view_description (
                    VAR acv      : tak_all_command_glob;
                    VAR dmli     : tak_dml_info;
                    VAR col_info : tak00_columninfo;
                    use_extcolno : boolean);
 
      ------------------------------ 
 
        FROM
              Select_List : VAK61;
 
        PROCEDURE
              a61_search_table (
                    VAR acv  : tak_all_command_glob;
                    VAR dmli : tak_dml_info);
 
        PROCEDURE
              a61_search_table_by_columnindex (
                    VAR acv  : tak_all_command_glob;
                    VAR dmli : tak_dml_info);
 
        PROCEDURE
              a61get_column_expression (
                    VAR acv    : tak_all_command_glob;
                    VAR dmli   : tak_dml_info;
                    VAR colinf : tak00_columninfo;
                    errpos     : integer);
 
      ------------------------------ 
 
        FROM
              Execute_factor_col_function : VAK641;
 
        PROCEDURE
              a641col_function (
                    VAR acv   : tak_all_command_glob;
                    VAR dmli  : tak_dml_info;
                    VAR frec  : tak_factorrec;
                    VAR colin : tak00_scolinf;
                    act_node  : integer);
 
        PROCEDURE
              a641string_set_operator (
                    VAR acv      : tak_all_command_glob;
                    operator     : tgg00_StackOpBuildIn;
                    destlength   : integer;
                    sourcelength : integer;
                    tab1         : char;
                    tab2         : char);
 
        PROCEDURE
              a641stack_for_op_b_chr (
                    VAR acv           : tak_all_command_glob;
                    VAR dmli           : tak_dml_info;
                    VAR colin          : tak00_scolinf;
                    first_int          : tsp00_Int2;
                    keep_datatype      : tsp00_DataType);
 
        PROCEDURE
              a641_get_length (
                    VAR colin            : tak00_scolinf;
                    VAR output_length     : tsp00_Int2;
                    VAR wrong_datatype    : boolean);
 
        PROCEDURE
              a641check_datetime(
                    VAR acv  : tak_all_command_glob;
                    VAR dmli : tak_dml_info;
                    datatyp  : tsp00_DataType);
 
      ------------------------------ 
 
        FROM
              Execute_factor_constants : VAK642;
 
        PROCEDURE
              a642other_than_column (
                    VAR acv   : tak_all_command_glob;
                    VAR dmli  : tak_dml_info;
                    VAR frec  : tak_factorrec;
                    VAR colin : tak00_scolinf;
                    act_node  : integer);
 
      ------------------------------ 
 
        FROM
              Execute_Where_Part : VAK65;
 
        PROCEDURE
              a65ch_format (
                    VAR acv        : tak_all_command_glob;
                    VAR dmli       : tak_dml_info;
                    VAR startstack : integer;
                    VAR colin      : tak00_scolinf;
                    left_type      : tsp00_DataType;
                    d_type         : tsp00_DataType);
 
        PROCEDURE
              a65_val_expr (
                    VAR acv    : tak_all_command_glob;
                    VAR dmli   : tak_dml_info;
                    VAR colin  : tak00_scolinf;
                    first_node : integer);
 
        PROCEDURE
              a65_set_operator (
                    VAR acv  : tak_all_command_glob;
                    operator : tgg00_StackOpType);
 
        PROCEDURE
              a65subq_get_val (
                    VAR acv    : tak_all_command_glob;
                    first_node : integer;
                    iolen      : integer);
 
        PROCEDURE
              a65_term (
                    VAR acv        : tak_all_command_glob;
                    VAR dmli       : tak_dml_info;
                    VAR colin      : tak00_scolinf;
                    VAR first_node : integer);
 
      ------------------------------ 
 
        FROM
              Join_Select : VAK680;
 
        PROCEDURE
              a680multiplier_get (
                    VAR acv             : tak_all_command_glob;
                    base_ptr            : tak_sysbufferaddress;
                    VAR col_info        : tak00_columninfo;
                    jpropset            : tak_jcolpropset;
                    VAR jmultiplier     : tsp00_Int4;
                    VAR do_col_upd_stat : boolean);
 
      ------------------------------ 
 
        FROM
              SQLManager : vak101;
 
        PROCEDURE
              a101_MapSchemaName (
                    VAR acv        : tak_all_command_glob;
                    VAR schemaName : tsp00_KnlIdentifier;
                    pos            : integer);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01unicode        : boolean;
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01sname (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname);
 
        PROCEDURE
              t01int4 (
                    layer : tgg00_Debug;
                    nam : tsp00_Sname;
                    int : tsp00_Int4);
 
        PROCEDURE
              t01aptree (
                    layer         : tgg00_Debug;
                    VAR a_ap_tree : tak_ap_max_tree;
                    node_cnt      : integer;
                    hint_node     : tsp00_Int2);
 
        PROCEDURE
              t01colpropset (
                    debug : tgg00_Debug;
                    nam : tsp00_Sname;
                    s   : tak00_colpropset);
 
        PROCEDURE
              t01stackentry (
                    debug          : tgg00_Debug;
                    VAR st         : tgg00_StackEntry;
                    entry_index    : integer);
&       endif
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              a05identifier_get;
 
              tsp00_MoveObj tsp00_KnlIdentifier
 
        PROCEDURE
              t01aptree;
 
              tsp00_MoveObj tak_ap_max_tree
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : ElkeZ
.sp
.cp 3
Created : 1985-05-29
.sp
.cp 3
.sp
.cp 3
Release :      Date : 2000-11-16
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
.sp 2
A64_FACTOR
.sp
Processing of a factor that exists as a part-tree of the syntax tree and
creation of the corresponding postfix stack entries.
.sp
INPUT :
.in +11
.of 12
acv: especially ap_tree, mess_buf, part1
.sp
.of 12
act_node: Node at which the factor begins
.sp
.of 12
dmli: especially dm_datatype, d_first_tab, d_allowed
.sp
.in 0
OUTPUT :
.in +11
.of 12
acv: especially mess_buf, part1
.sp
.of 12
dmli: especially dm_datatype, d_first_tab, d_allowed, atbasetabno,
.sp
.of 12
colin: Description of the factor processed
.sp
.in -11
A factor that is to be checked is specified in the syntax tree by the parameter
act_node. It is checked first of all whether there is a monadic operator and
whether there is a nested expression. In the first case, a monadic minus is
recorded by an entry in 'fr_minus_symb' and 'fr_minus_n' is set to the corresponding
node. In the second case, A65_TERM and A65_VAL_EXPR are called recursively in
order to break up the nesting. If there is a labeled duration
DURATION_EXPRESSION is called, to process the specified duration.
In all other cases, 'normfac' is set to 'true',
since there is a normal factor.
.br
The specified data type (so far determined by a higher level) is stored in
'keep_datatype' in order, after the processing of the factor, to match the new
data type that may result with the old data type.
.br
If there is a column as a factor, the column name and any existing table name
and authid are entered in 'd_user', 'd_table' and 'd_column', so that a search
can be made for the associated system information in A61_SEARCH_TABLE (output:
'd_basetabno' ).
.br
With the result in 'd_basetabno' and the previous result ('d_first_tab',
'd_allowed'), the value expression is now described in greater detail:
.in 5
The entry in 'd_first_tab' is the table number of the first table in the
expression ('0' at the beginning). This checks whether there was
already another table in the expression. If not, 'd_first_tab' is set to the
current (possibly the old) table number.
.br
Otherwise, it is checked whether it is allowable for more
than one table to occur (normally yes, only in cases such as: SET F1 = F2 + F3,
where F1, F2, F3 are parts of a Joinview, but not of one base table it is
not allowed).
.br
For this purpose, 'd_allowed' is interrogated, which specifies,
firstly, whether more than one table is allowed (see above), but which also
specifies that more than one table occurs in the expression and whether
arithmetic is performed with these tables. If successful, a negative value is
entered in 'd_first_tab' (further sign of more than one table for other
modules) and 'are_more_tabs' is entered in 'd_allowed'. Otherwise, an error is
generated with 'only_one_recordtype_allowed '.
.br;
.in -5
If 'dm_join' is 'true' (is the case if the entire SELECT has to be processed as
JOIN, i.e. if there is more than one table or at least one JOIN VIEW in the
FROM-Part), the join conditions must be entered in 'jrc_joinarr'. If the left-hand
side of a condition is being handled, it is entered in 'jrecs[ 1 ]' and the
right-hand side in 'jrecs[ 2 ]' ('joinpartno' is appropriately set in VAK65).
'fr_jpos' then specifies which of the two possible sides has just had an entry
made in it.
.br
Because only one base
table may occur on each side of a join condition, so that this
condition can be used as a join condition, it is checked with the above-
described mechanism ( 'd_basetabno' and in this case
'jrecs[ jo_partno ].jop_tableno' ) whether this is the case. If not, by the
setting of 'jo_no_join', the condition is declared invalid and 'fr_jpos' is set to
'0'. With the calling of ANALYZE_COLUMN, the necessary information on the
factor is then determined and is entered in the stack or in 'jrc_joinarr'.
.br
If there was no column, A01_FUNCTION_SYMBOLS is checked and, if necessary,
COL_FUNCTION is called; otherwise, the set_functions are tested and, as
appropriate, SET_FUNCTION is called, or the remaining possibilities are checked
with OTHER_THAN_COLUMN.
.br
After a factor has been successfully processed, any existing monadic minus is
entered in the stack (if no_number is supplied as data type  =>
'incompatible_datatypes') and the matching of the old data type with the new
data type is checked. If the
new data type contains more information than the old one ( 'keep_datatype' in
(dunknown, dnonumber), the new one is returned; otherwise the old one is
returned.
.sp 2
ANALYZE_COLUMN
.sp
Analyzes a column as a factor.
.sp
INPUT :
.in +11
.of 12
acv: especially ap_tree
.sp
.of 12
dmli: especially d_allowed, atfieldlen, dm_join, dm_joins
.sp
.of 12
frec: Temporary description of the factor and of the processing status
.in -11
OUTPUT :
.in +11
.of 12
acv: especially mess_buf, part1
.sp
.of 12
dmli: especially d_allowed, dm_joins
.sp
.of 12
frec: Temporary description of the factor and of the processing status
.sp
.of 12
colin: Description of the factor processed
.sp
.in -11
.sp ??)
The column is analyzed on the basis of the system information that was
determined in A64_FACTOR by means of A61_SEARCH_TABLE. If the current column is
a view column and is composed of more than one stack entry (e.g. in the case of
arithmetic or character functions), the normal system information will not
contain the stack entries, but only references to them (into special view
information records). By means of A61_GET_COLUMN_EXPRESSION, they are fetched
and transferred to the 'mess_buf'.
.br
In order to be able to make a correct entry in 'd_allowed', the stack entries
that have been created are checked as to whether they have 'op_sum' or 'op_avg'
as operator and how far these set_functions extend (test of 'mfirst_free' - 1
). 'ctabno' > 'maxsources' specifies whether the column is composed of more
than one column of different base tables (see 'd_basetabno' in A64_FACTOR).
.br
In the case of a single column, it must also be tested whether there is a
complex SELECT. In this case it is necessary
to use single fields analyzed here as output fields for the split-up calls of
KB05. For this purpose, their output length is entered in  'ecol_tab[ 1 ]'.
The associated base-table number is entered in 'ecol_tab[ 2 ]'.
.br
The other parts of the column description are transferred to 'colin'. If
'ctopt' was already contained in 'ccolpropset', 'ctopt' is also inserted into
'colin.sci_cprops' in order to indicate to the PRECOMPILER that a null value may
occur and that an indicator must be used.
.br
If GROUP BY has been specified, it is tested with A61_GROUP_FIELD whether the
columns of the select list (without set_function) also occur as grouping
columns.
.br
In the case of 'progusage_add' (activated by the PRECOMPILER), it is recorded
which program uses which tables, columns etc.
.br
If there is a JOIN and if the join condition can be used (correct entries in
'dm_join' and 'fr_jpos', see above), the column description is entered in
'jrc_joinarr'. In order, for the evaluation of join, to have information on any key
fields or index fields, the information from 'ccolpropset' is transferred to
'jpropset'. Use is also made of information as to whether it is the first key
field, the only key field or a unique index ('op_unique', 'op_unique_desc').
.br
The entry in 'cdatatyp' is analyzed in conjunction with the so far determined
data type 'dm_datatype' and, if compatible, is transferred to 'dm_datatype'.
.sp 2
.cp 5
SET_FUNCTION
.sp
Processes a factor consisting of a set_function.
.sp
INPUT :
.in +11
.of 12
acv: especially ap_tree
.sp
.of 12
dmli: especially m_datatype
.sp
.of 12
frec: Temporary description of the factor and of the processing status
.sp
.of 12
act_node: Tree node at which the function begins
.sp;.in -11
OUTPUT :
.in +11
.of 12
acv: especially mess_buf, part1
.sp
.of 12
dmli: especially dm_datatype
.sp
.of 12
frec: Temporary description of the factor and of the processing status
.sp
.of 12
colin: Description of the factor processed
.sp
.in -11
Since the set_functions supply a numerical value as the result (with the
exception of 'MIN' and 'MAX'), it must first of all be clarified whether such a
data type is expected (dm_datatype in (dunknown, dnumber)). Otherwise, an
error is generated with 'incompatible_datatypes'.
.sp
If there is 's_all_count' ('COUNT(*)') as a symbol, it is not necessary for
an argument to be checked and 'colin.sci_typ' is set to 'dfixed'. In the case of
all other symbols, the argument is checked with A65_VAL_EXPR, with there
possibly being a parameter. In this case, a 'COUNT' is not possible, since no
information is available for the parameter. If the functions 'MIN' and 'MAX'
are specified, what happens depends on whether a special data type was already
expected before ('dm_datatype' <> 'dunknown'). Since numerical values must
have been specified for the functions 'SUM' and 'AVG', this information can be
used for the parameter.
.sp
After the argument has been successfully processed and the supplied data types
also match the function-specific data types (for 'SUM' and 'AVG'), the stack
entry is created: 'st_func' is entered in 'etype'; the appropriate operator is
entered in 'eop' and the remaining entries are made on a function-specific
basis:
.in +5
Entered in 'epos' is how many stack entries before the current set_function
entry (identified with stack type 'st_func') the next set_function entry comes.
The input/output length is entered in 'elen_var'; the s10fil byte is specified in
'ecol_tab[ 1 ]' ('ascii_blank', chr(0)),
and the number of stack
entries belonging to this set_function is specified in 'ecol_tab[ 2 ]'. The
entry of '[ ctopt ]' in 'sci_cprops' specifies that null values are possible as the
result.
.in -5
.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
 
.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
 
Code    :
 
 
(*------------------------------*) 
 
PROCEDURE
      ak640analyze_column (
            VAR acv       : tak_all_command_glob;
            VAR dmli      : tak_dml_info;
            VAR frec      : tak_factorrec;
            VAR colin     : tak00_scolinf;
            old_specified : boolean;
            errorpos      : integer);
 
VAR
      _multiplier      : tsp00_Int4;
      _res_len         : tsp00_Int2;
      _dummy           : boolean;
      _startstack      : integer;
      _do_upd_col_stat : boolean;
      _old_datatype    : tsp00_DataType;
 
BEGIN
IF  acv.a_returncode = 0
THEN
    BEGIN
    IF  acv.a_mblock.mb_qual^.mfirst_free - 1 = acv.a_mblock.mb_st_max
    THEN
        a07_b_put_error (acv, e_too_many_mb_stackentries, -acv.a_mblock.mb_st_max)
    ELSE
        BEGIN
        IF  dmli.d_colbuf^.ccolstack.etype = st_func
        THEN
            BEGIN
            a61get_column_expression (acv, dmli, dmli.d_colbuf^, dmli.d_vppos);
            IF  ((dmli.d_colbuf^.ccolstack.eop_func in
                [ op_f_sum, op_f_avg ]) AND
                ((acv.a_mblock.mb_st^ [acv.a_mblock.mb_qual^.mfirst_free-1].etype <> st_func) OR
                (NOT dmli.d_wherepart AND NOT dmli.d_having)))
            THEN
                dmli.d_allowed := tabs_with_arith
            ELSE
                IF  ((dmli.d_colbuf^.ctabno > cak00_maxsources) AND
                    (dmli.d_allowed <> tabs_with_arith))
                THEN
                    IF  dmli.d_allowed = only_one_tab
                    THEN
                        a07_b_put_error (acv,
                              e_only_one_recordtype_allowed, dmli.d_vppos)
                    ELSE
                        dmli.d_allowed := are_more_tabs
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            acv.a_mblock.mb_st^ [acv.a_mblock.mb_qual^.mfirst_free] :=
                  dmli.d_colbuf^.ccolstack;
            IF  old_specified
            THEN
                CASE dmli.d_colbuf^.ccolstack.etype OF
                    st_fixkey :
                        acv.a_mblock.mb_st^ [acv.a_mblock.mb_qual^.mfirst_free].
                              etype := st_old_fixkey;
                    st_varkey :
                        acv.a_mblock.mb_st^ [acv.a_mblock.mb_qual^.mfirst_free].
                              etype := st_old_varkey;
                    st_fixcol :
                        acv.a_mblock.mb_st^ [acv.a_mblock.mb_qual^.mfirst_free].
                              etype := st_old_fixcol;
                    st_varcol :
                        acv.a_mblock.mb_st^ [acv.a_mblock.mb_qual^.mfirst_free].
                              etype := st_old_varcol;
                    st_varlongchar :
                        acv.a_mblock.mb_st^ [acv.a_mblock.mb_qual^.mfirst_free].
                              etype := st_old_varlongchar;
                    OTHERWISE;
                    END;
                (*ENDCASE*) 
            (*ENDIF*) 
            acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mfirst_free ].
                  ecol_tab [2] := chr(dmli.d_basetabno);
            acv.a_mblock.mb_qual^.mfirst_free :=
                  succ(acv.a_mblock.mb_qual^.mfirst_free);
            acv.a_mblock.mb_qual^.mqual_cnt   :=
                  succ(acv.a_mblock.mb_qual^.mqual_cnt);
            END;
        (*ENDIF*) 
        colin.sci_len    := dmli.d_colbuf^.cdatalen;
        colin.sci_iolen  := dmli.d_colbuf^.cinoutlen;
        colin.sci_frac   := dmli.d_colbuf^.cdatafrac-cak_frac_offset;
        colin.sci_typ    := dmli.d_colbuf^.cdatatyp;
        colin.sci_udt_id := dmli.d_colbuf^.cudtdatatype;
        IF  ctopt in dmli.d_colbuf^.ccolpropset
        THEN
            colin.sci_cprops := [ ctopt ]
        ELSE
            colin.sci_cprops := [  ];
        (*ENDIF*) 
&       ifdef TRACE
        t01int4 (ak_sem, 'cdatatyp    ', ord(dmli.d_colbuf^.cdatatyp));
        t01int4 (ak_sem, 'ctabno      ', dmli.d_colbuf^.ctabno);
        t01colpropset (ak_sem, 'ccolpropset ', dmli.d_colbuf^.ccolpropset);
        t01stackentry( ak_sem, dmli.d_colbuf^.ccolstack, 1 );
        t01int4 (ak_sem, 'd_datatype  ', ord(dmli.d_datatype));
&       endif
        CASE dmli.d_colbuf^.cdatatyp OF
            dboolean :
                IF  dmli.d_datatype in [ dunknown, dboolean ]
                THEN
                    dmli.d_datatype := dboolean
                ELSE
                    frec.fr_error := true;
                (*ENDIF*) 
            dfixed, dfloat, dvfloat :
                IF  ((dmli.d_datatype = dunknown) OR (dmli.d_datatype = dnumber))
                THEN
                    dmli.d_datatype := dnumber
                ELSE
                    IF  (acv.a_sqlmode = sqlm_oracle) OR
                        (acv.a_comp_type = at_odbc) OR
                        (acv.a_comp_type = at_jdbc)
                    THEN
                        (* PTS 1117447 E.Z. *)
                        (* PTS 1128414 E.Z. *)
                        IF  dmli.d_datatype in [ dnonumber, dcha, dunicode ]
                        THEN
                            BEGIN
                            _old_datatype := dmli.d_datatype;
                            a641_get_length(colin, _res_len, _dummy);
                            a641stack_for_op_b_chr (acv, dmli, colin,
                                  _res_len, dcha);
                            colin.sci_typ   := dcha;
                            colin.sci_len   := _res_len;
                            colin.sci_frac  := 0;
                            colin.sci_iolen := succ(_res_len);
                            IF  _old_datatype = dunicode
                            THEN
                                BEGIN
                                a641string_set_operator (acv, op_b_uni_trans,
                                      succ(2*_res_len), 0, chr(csp_ascii),
                                      chr(csp_unicode));
                                (* PTS 1109069 E.Z. *)
                                dmli.d_datatype := dunicode;
                                colin.sci_typ   := dunicode;
                                colin.sci_iolen := (2*colin.sci_len) + 1;
                                END
                            (*ENDIF*) 
                            END
                        ELSE
                            frec.fr_error := true
                        (*ENDIF*) 
                    ELSE
                        frec.fr_error := true;
                    (*ENDIF*) 
                (*ENDIF*) 
            dcha, ddate, dtime, dtimestamp :
                BEGIN
                CASE dmli.d_colbuf^.cdatatyp OF
                    dcha :
                        IF  dmli.d_datatype in [ dunknown,
                            dcha, dnonumber, dtime, ddate, dtimestamp ]
                        THEN
                            dmli.d_datatype := dcha
                        ELSE
                            frec.fr_error := true;
                        (*ENDIF*) 
                    ddate :
                        IF  dmli.d_datatype in [ dunknown, ddate,
                            dduration, dnonumber, dcha ]
                        THEN
                            dmli.d_datatype := ddate
                        ELSE
                            frec.fr_error := true;
                        (*ENDIF*) 
                    dtime :
                        IF  dmli.d_datatype in [ dunknown, dtime,
                            dduration, dnonumber, dcha ]
                        THEN
                            dmli.d_datatype := dtime
                        ELSE
                            frec.fr_error := true;
                        (*ENDIF*) 
                    dtimestamp :
                        IF  dmli.d_datatype in [ dunknown, dtimestamp, dduration,
                            dnonumber, ddate, dtime, dcha ]
                        THEN
                            dmli.d_datatype := dtimestamp
                        ELSE
                            frec.fr_error := true;
                        (*ENDIF*) 
                    END;
                (*ENDCASE*) 
                IF  frec.fr_error AND
                    (dmli.d_datatype = dunicode)
                THEN
                    BEGIN
                    frec.fr_error := false;
                    IF  (dmli.d_colbuf^.cdatatyp in [ ddate, dtime, dtimestamp ]) AND
                        (*d_change_date_time AND*)
                        (acv.a_dt_format <> dtf_normal)
                    THEN
                        BEGIN
                        dmli.d_ch_datatype := dmli.d_colbuf^.cdatatyp;
                        _startstack := acv.a_mblock.mb_qual^.mfirst_free;
&                       ifdef TRACE
                        t01int4 (ak_sem, 'sci.len fact', colin.sci_len);
&                       endif
                        a65ch_format (acv, dmli, _startstack,
                              colin, dcha, dmli.d_colbuf^.cdatatyp);
&                       ifdef TRACE
                        t01int4 (ak_sem, 'sci.len   2 ', colin.sci_len);
&                       endif
                        colin.sci_iolen := colin.sci_len+1;
                        END;
                    (*ENDIF*) 
                    a641string_set_operator (acv, op_b_uni_trans,
                          2*colin.sci_len+1, 0, chr(csp_ascii), chr(csp_unicode));
                    (* PTS 1109069 E.Z. *)
                    dmli.d_datatype := dunicode;
                    colin.sci_typ   := dunicode;
                    colin.sci_iolen := (2*colin.sci_len) + 1;
                    END
                ELSE
                    IF  frec.fr_error AND
                        (dmli.d_datatype in [ dnumber, dfixed, dfloat ]) AND
                        (* PTS 1128414 E.Z. *)
                        (dmli.d_colbuf^.cdatatyp = dcha                          ) AND
                        ((acv.a_sqlmode = sqlm_oracle) OR
                        (acv.a_comp_type = at_odbc)    OR
                        (acv.a_comp_type = at_jdbc))
                    THEN
                        BEGIN
                        frec.fr_error := false;
                        a65_set_operator (acv, op_num);
                        colin.sci_typ   := dfloat;
                        colin.sci_len   := cak_default_precision;
                        colin.sci_frac  := csp_float_frac;
                        colin.sci_iolen := (colin.sci_len + 1) DIV 2 + 2;
                        END
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            dchb :
                IF  dmli.d_datatype in [ dunknown, dchb, dnonumber ]
                THEN
                    dmli.d_datatype := dchb
                ELSE
                    frec.fr_error := true;
                (*ENDIF*) 
            dunicode :
                IF  dmli.d_datatype in [ dunknown, dunicode, dnonumber ]
                THEN
                    dmli.d_datatype := dunicode
                ELSE
                    IF  dmli.d_datatype in [ dcha, ddate, dtime, dtimestamp ]
                    THEN
                        BEGIN
                        a641string_set_operator (acv, op_b_uni_trans,
                              dmli.d_colbuf^.cdatalen+1, 0, chr(csp_unicode),
                              chr(csp_ascii));
                        colin.sci_iolen := dmli.d_colbuf^.cdatalen + 1;
                        colin.sci_typ := dcha;
                        END
                    ELSE
                        IF  (dmli.d_datatype in [ dnumber, dfixed, dfloat ]) AND
                            ((acv.a_sqlmode = sqlm_oracle) OR
                            (acv.a_comp_type = at_odbc)    OR
                            (acv.a_comp_type = at_jdbc))
                        THEN
                            BEGIN
                            a641string_set_operator (acv, op_b_uni_trans,
                                  dmli.d_colbuf^.cdatalen+1, 0, chr(csp_unicode),
                                  chr(csp_ascii));
                            a65_set_operator (acv, op_num);
                            colin.sci_typ   := dfloat;
                            colin.sci_len   := cak_default_precision;
                            colin.sci_frac  := csp_float_frac;
                            colin.sci_iolen := (colin.sci_len + 1) DIV 2 + 2;
                            END
                        ELSE
                            frec.fr_error := true;
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
            dudt :
                BEGIN
&               ifdef trace
                t01int4 (ak_sem, 'd_udt_type  ',
                      ord (dmli.d_udt_datatype[1]) * 256 +
                      ord (dmli.d_udt_datatype[2]));
&               endif
                IF  dmli.d_datatype = dunknown
                THEN
                    BEGIN
                    dmli.d_datatype     := dudt;
                    dmli.d_udt_datatype := dmli.d_colbuf^.cudtdatatype
                    END
                ELSE
                    BEGIN
&                   ifdef trace
                    t01int4 (ak_sem, 'cudt_type   ',
                          ord (dmli.d_colbuf^.cudtdatatype[1]) * 256 +
                          ord (dmli.d_colbuf^.cudtdatatype[2]));
&                   endif
                    IF  (dmli.d_datatype <> dudt) OR
                        (dmli.d_udt_datatype <> dmli.d_colbuf^.cudtdatatype)
                    THEN
                        frec.fr_error := true;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            OTHERWISE
                IF  dmli.d_colbuf^.cdatatyp in [ dlonga, dlongb,
                    dlonguni, dstra, dstrb, dstruni ]
                THEN
                    IF  dmli.d_type_long_allowed
                    THEN
                        dmli.d_datatype := dmli.d_colbuf^.cdatatyp
                    ELSE
                        a07_b_put_error(acv,
                              e_command_for_string_not_allow, errorpos)
                    (*ENDIF*) 
                ELSE
                    frec.fr_error := true
                (*ENDIF*) 
            END;
        (*ENDCASE*) 
        IF  (dmli.d_join AND ( frec.fr_jpos in [ 1, 2 ] ))
        THEN
            BEGIN
            IF  ( dmli.d_colbuf^.ccolstack.etype = st_func ) AND
                ( dmli.d_colbuf^.ccolstack.eop_func = op_f_none ) AND
                ( dmli.d_colbuf^.ctabno = 0 )
            THEN
                (* constant expression *)
                BEGIN
&               ifdef trace
                t01sname(ak_sem, 'ins const ex');
&               endif
                dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                      jo_recs[ frec.fr_jpos ].jop_tableno := cak68_join_value;
                dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                      jo_recs[ frec.fr_jpos ].jop_fieldno := 0;
                END
            ELSE
                BEGIN
&               ifdef trace
                t01int4 (ak_sem, 'ins jop_tabn', dmli.d_basetabno );
                t01int4 (ak_sem, 'ins jop_fiel', dmli.d_colbuf^.creccolno );
&               endif
                dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                      jo_recs[ frec.fr_jpos ].jop_tableno := dmli.d_basetabno;
                dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                      jo_recs[ frec.fr_jpos ].jop_fieldno := dmli.d_colbuf^.creccolno;
                END;
            (*ENDIF*) 
            IF  dmli.d_datatype = dcha
            THEN
                dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                      jo_recs[ frec.fr_jpos ].jop_datatyp := dcha
            ELSE
                dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                      jo_recs[ frec.fr_jpos ].jop_datatyp := colin.sci_typ;
            (*ENDIF*) 
            dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                  jo_recs[ frec.fr_jpos ].jop_inoutlen := colin.sci_iolen;
            dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                  jo_recs[ frec.fr_jpos ].jop_propset := [  ];
            IF  ctkey in dmli.d_colbuf^.ccolpropset
            THEN
                BEGIN
                dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                      jo_recs[ frec.fr_jpos ].jop_propset := dmli.d_joins.
                      jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                      jo_recs[ frec.fr_jpos ].jop_propset + [ jtkey ];
                IF  dmli.d_colbuf^.ccolstack.epos = 1
                THEN
                    BEGIN
                    dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                          jo_recs[ frec.fr_jpos ].jop_propset := dmli.d_joins.
                          jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                          jo_recs[ frec.fr_jpos ].jop_propset + [ jtfirstkey ];
                    IF  dmli.d_colbuf^.ccolstack.etype = st_varkey
                    THEN
                        dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                              jo_recs[ frec.fr_jpos ].jop_propset := dmli.d_joins.
                              jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                              jo_recs[ frec.fr_jpos ].jop_propset + [ jtonlykey ]
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  ctmulti in dmli.d_colbuf^.ccolpropset
            THEN
                dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                      jo_recs[ frec.fr_jpos ].jop_propset := dmli.d_joins.
                      jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                      jo_recs[ frec.fr_jpos ].jop_propset + [ jtmulti ];
            (*ENDIF*) 
            a680multiplier_get (acv, dmli.d_sparr.pbasep, dmli.d_colbuf^,
                  dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                  jo_recs[ frec.fr_jpos ].jop_propset,
                  _multiplier, _do_upd_col_stat);
            IF  _do_upd_col_stat
            THEN
                BEGIN
                dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                      jo_col_upd_stat :=
                      dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                      jo_col_upd_stat + frec.fr_jpos;
                dmli.d_joins.jrc_col_upd := true;
                END;
            (*ENDIF*) 
            dmli.d_joins.jrc_joinarr^[ dmli.d_joins.jrc_cnt ].
                  jo_recs[ frec.fr_jpos ].jop_multiplier := _multiplier;
            END;
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak640duration_expression (
            VAR acv     : tak_all_command_glob;
            VAR dmli     : tak_dml_info;
            VAR colin    : tak00_scolinf;
            VAR act_node : integer);
 
VAR
      curr_n : integer;
 
BEGIN
WITH acv, dmli, a_ap_tree^[ act_node ] DO
    IF  (d_datatype <> dunknown)
    THEN
        a07_b_put_error (acv, e_incompatible_datatypes, n_pos)
    ELSE
        BEGIN
        curr_n := n_lo_level;
        IF  (a_sqlmode = sqlm_oracle)
        THEN
            d_datatype := dunknown
        ELSE
            d_datatype := dnumber;
        (*ENDIF*) 
        colin.sci_len := 0;
        a640factor (acv, dmli, colin, curr_n);
        IF  (a_returncode = 0) AND
            ((a_sqlmode <> sqlm_oracle) OR (d_datatype <> dtimestamp))
        THEN
            BEGIN
            d_datatype := dduration;
            CASE n_symb OF
                s_year :
                    colin.sci_dttyp := year;
                s_month :
                    colin.sci_dttyp := month;
                s_day :
                    colin.sci_dttyp := day;
                s_hour :
                    colin.sci_dttyp := hour;
                s_minute :
                    colin.sci_dttyp := minute;
                s_second :
                    colin.sci_dttyp := second;
                s_microsecond :
                    colin.sci_dttyp := microsecond
                END;
            (*ENDCASE*) 
            IF  a_sqlmode <> sqlm_oracle
            THEN (* In Oracle you can add fractions to a timestamp. *)
                WITH a_mblock, mb_qual^, mb_st^ [mfirst_free] DO
                    IF  mfirst_free >= mb_st_max
                    THEN
                        a07_b_put_error (acv,
                              e_too_many_mb_stackentries, -mb_st_max)
                    ELSE
                        BEGIN
                        WITH mb_st^ [mfirst_free] DO
                            BEGIN
                            etype         := st_op;
                            eop           := op_fixed;
                            epos          := csp_fixed;
                            elen_var      := 0;
                            ecol_tab[ 1 ] := chr(0);
                            ecol_tab[ 2 ] := chr(0)
                            END;
                        (*ENDWITH*) 
                        mqual_cnt   := succ (mqual_cnt);
                        mfirst_free := succ (mfirst_free)
                        END
                    (*ENDIF*) 
                (*ENDWITH*) 
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(* PTS 1115725 E.Z. *)
(*------------------------------*) 
 
PROCEDURE
      ak640error_if_col_found (
            VAR acv  : tak_all_command_glob;
            act_node : integer);
 
BEGIN
WITH acv.a_ap_tree^[act_node] DO
    BEGIN
    IF  n_symb in [ s_columnname, s_columnid, s_tablename, s_authid ]
    THEN (* PTS 1128197 D.T. *)
        a07_b_put_error (acv, e_invalid_mix_functions_columns, n_pos)
    ELSE
        BEGIN
        IF  n_lo_level <> 0
        THEN
            ak640error_if_col_found (acv, n_lo_level);
        (*ENDIF*) 
        IF  (acv.a_returncode = 0) AND
            (n_sa_level <> 0)
        THEN
            ak640error_if_col_found (acv, n_sa_level);
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak640subq_value (
            VAR acv   : tak_all_command_glob;
            VAR dmli  : tak_dml_info;
            VAR frec  : tak_factorrec;
            VAR colin : tak00_scolinf;
            act_node  : integer);
 
VAR
      datatype_n       : integer;
 
BEGIN
dmli.d_reuse := true;
dmli.d_param_st_index   := acv.a_mblock.mb_qual^.mfirst_free;
datatype_n := acv.a_ap_tree^[act_node].n_sa_level;
&ifdef TRACE
t01aptree (ak_sem, acv.a_ap_tree^, acv.a_scv_index,
      acv.a_first_hint_node);
t01int4 (ak_sem, 'datatype_n  ', datatype_n);
&endif
(* PTS 1120680 E.Z. *)
IF  datatype_n = 0
THEN
    BEGIN
    frec.fr_error := true;
    a07_b_put_error (acv, e_corelated_subquery_not_allowe,
          acv.a_ap_tree^[act_node].n_pos)
    END
ELSE
    WITH acv.a_ap_tree^[datatype_n], colin DO
        BEGIN
        sci_typ      := n_datatype;
        IF  n_datatype in [dfixed, dfloat, dvfloat]
        THEN
            dmli.d_datatype := dnumber
        ELSE
            dmli.d_datatype := n_datatype;
        (*ENDIF*) 
        IF  sci_typ = dfixed
        THEN
            BEGIN
            sci_len      := n_pos DIV 100;
            sci_frac     := (n_pos MOD 100) - cak_frac_offset;
            END
        ELSE
            BEGIN
            sci_len      := n_pos;
            IF  (sci_typ = dfloat) OR (sci_typ = dvfloat)
            THEN
                sci_frac := csp_float_frac
            ELSE
                sci_frac     := 0
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        sci_iolen    := n_length;
        sci_cprops   := [ ctopt ];
        (*
              sci_dttyp    :=
              sci_com_type :=
              sci_udt_id   :=
              *)
        a65subq_get_val (acv, act_node, sci_iolen);
        END
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak640set_function (
            VAR acv   : tak_all_command_glob;
            VAR dmli  : tak_dml_info;
            VAR colin : tak00_scolinf;
            act_node  : integer);
 
VAR
      md_group      : boolean;
      curr_n        : integer;
      i             : integer;
      j             : integer;
      m_mfirst_free : integer;
 
BEGIN
WITH acv, dmli, a_ap_tree^[ act_node ] DO
    BEGIN
    curr_n := n_lo_level;
    a_mblock.mb_type2 := mm_with_functions;
    d_reuse := true;
    d_const_value_expr := false;
    d_param_st_begin   := 0;
    d_param_st_index   := 0;
    IF  (NOT(d_datatype in [ dunknown, dnumber ]) AND
        (n_symb in
        [ s_avg   , s_dis_avg,
        s_sum     , s_dis_sum,
        s_count   , s_dis_count , s_all_count,
        s_stddev  , s_dis_stddev,
        s_variance, s_dis_variance ]))
    THEN
        a07_b_put_error (acv, e_incompatible_datatypes,
              a_ap_tree^[ curr_n ].n_pos)
    ELSE
        BEGIN
        m_mfirst_free := a_mblock.mb_qual^.mfirst_free;
        md_group := d_group;
        d_group := false;
        d_is_function_column := true;
        IF  n_symb <> s_all_count
        THEN
            BEGIN
            IF  n_symb in [ s_count, s_dis_count ]
            THEN
                d_datatype := dunknown;
            (*ENDIF*) 
            IF  n_symb = s_count
            THEN
                d_type_long_allowed := true;
            (*ENDIF*) 
            a65_val_expr (acv, dmli, colin, curr_n);
            d_type_long_allowed := false;
            IF  a_returncode = cak_e_parameter
            THEN
                (* PTS 1109261 E.Z. *)
                BEGIN
                a_returncode := 0;
                IF  n_symb in [ s_avg, s_dis_avg, s_sum, s_dis_sum,
                    s_stddev, s_dis_stddev, s_variance, s_dis_variance ]
                THEN
                    BEGIN
                    d_datatype := dnumber;
                    a65_val_expr (acv, dmli, colin, curr_n)
                    END
                ELSE
                    a07_b_put_error (acv, e_without_datatypes, n_pos);
                (*ENDIF*) 
                END;
            (* PTS 1115725 E.Z. *)
            (*ENDIF*) 
            IF  (a_returncode = 0) AND
                d_wherepart                          AND
                NOT d_prep_corr_cols
            THEN
                BEGIN
                curr_n := n_lo_level;
                ak640error_if_col_found (acv, curr_n);
                END;
            (*ENDIF*) 
            END
        ELSE
            IF  d_wherepart AND
                NOT d_prep_corr_cols
            THEN
                a07_b_put_error (acv, e_invalid_mix_functions_columns, n_pos)
            ELSE
                colin.sci_typ := dfixed;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (NOT (colin.sci_typ in [ dfixed, dfloat, dvfloat ]) AND
            (n_symb in [ s_sum, s_avg, s_dis_sum, s_dis_avg,
            s_stddev, s_dis_stddev, s_variance, s_dis_variance ]))
            (* PTS 1123645 E.Z. *)
            OR
            ((colin.sci_iolen > KEY_MXSP00) AND
            (n_symb in [ s_dis_avg, s_dis_count, s_dis_sum,
            s_dis_stddev, s_dis_variance] ))
        THEN
            a07_b_put_error (acv, e_function_not_allowed, n_pos)
        ELSE
            IF  a_returncode = 0
            THEN
                WITH a_mblock, mb_qual^ DO
                    BEGIN
                    i := mfirst_free-1;
                    IF  i = mb_st_max
                    THEN
                        a07_b_put_error (acv, e_too_many_mb_stackentries,
                              -mb_st_max)
                    ELSE
                        BEGIN
                        mqual_cnt := succ(mqual_cnt);
                        mfirst_free := succ(mfirst_free);
                        IF  (n_symb = s_sum)         AND
                            (colin.sci_typ = dfixed) AND
                            ( csa_short_sum_values in acv.a_sql_cmd_state )
                        THEN
                            BEGIN
                            WITH mb_st^ [i+1] DO
                                BEGIN
                                etype        := st_sum_length;
                                eop          := op_none;
                                epos         := colin.sci_len;
                                elen_var     := colin.sci_frac;
                                ecol_tab[1]  := chr(colin.sci_typ);
                                ecol_tab[2]  := chr(0);
                                END;
                            (*ENDWITH*) 
                            i := succ(i);
                            mqual_cnt := succ(mqual_cnt);
                            mfirst_free := succ(mfirst_free);
                            END;
                        (*ENDIF*) 
                        WITH mb_st^ [i+1] DO
                            BEGIN
                            etype := st_func;
                            CASE n_symb OF
                                s_count :
                                    eop_func := op_f_count;
                                s_dis_count :
                                    eop_func := op_f_dis_count;
                                s_all_count :
                                    eop_func := op_f_all_count;
                                s_avg :
                                    eop_func := op_f_avg;
                                s_dis_avg :
                                    eop_func := op_f_dis_avg;
                                s_sum :
                                    eop_func := op_f_sum;
                                s_dis_sum :
                                    eop_func := op_f_dis_sum;
                                s_min :
                                    eop_func := op_f_min;
                                s_max :
                                    eop_func := op_f_max;
                                s_stddev :
                                    eop_func := op_f_stddev;
                                s_dis_stddev :
                                    eop_func := op_f_dis_stddev;
                                s_variance :
                                    eop_func := op_f_variance;
                                s_dis_variance :
                                    eop_func := op_f_dis_variance;
                                END;
                            (*ENDCASE*) 
                            IF  n_symb <> s_all_count
                            THEN
                                elen_var := colin.sci_iolen;
                            (*ENDIF*) 
                            CASE n_symb OF
                                s_sum, s_dis_sum :
                                    BEGIN
                                    IF  (n_symb = s_sum)         AND
                                        (colin.sci_typ = dfixed) AND
                                        ( csa_short_sum_values in
                                        acv.a_sql_cmd_state )
                                    THEN
                                        BEGIN
                                        END
                                    ELSE
                                        WITH colin DO
                                            BEGIN
                                            sci_len   := csp_fixed;
                                            sci_frac  := csp_float_frac;
                                            sci_typ   := dvfloat;
                                            sci_iolen := NUMBER_MXGG04;
                                            elen_var  := sci_iolen;
                                            END;
                                        (*ENDWITH*) 
                                    (*ENDIF*) 
                                    colin.sci_cprops := [ ctopt ];
                                    END;
                                s_avg, s_dis_avg,
                                s_stddev, s_dis_stddev,
                                s_variance, s_dis_variance :
                                    BEGIN
                                    WITH colin DO
                                        BEGIN
                                        sci_len := csp_fixed;
                                        sci_frac := csp_float_frac;
                                        sci_typ := dvfloat;
                                        sci_iolen := NUMBER_MXGG04;
                                        elen_var := sci_iolen;
                                        sci_cprops := [ ctopt ];
                                        END;
                                    (*ENDWITH*) 
                                    END;
                                s_count, s_dis_count, s_all_count :
                                    BEGIN
                                    d_datatype := dnumber;
                                    WITH colin DO
                                        BEGIN
                                        sci_len := csp_resnum_deflen;
                                        sci_frac := 0;
                                        sci_typ := dfixed;
                                        IF  (elen_var > NUMBER_MXGG04) AND
                                            (n_symb = s_dis_count)     AND
                                            dmli.d_union
                                        THEN
                                            sci_iolen := elen_var
                                        ELSE
                                            sci_iolen := mxsp_resnum;
                                        (*ENDIF*) 
                                        sci_cprops := [  ];
                                        IF  n_symb = s_all_count
                                        THEN
                                            BEGIN
                                            d_all_count := true;
                                            elen_var := sci_iolen;
                                            END
                                        ELSE
                                            IF  elen_var < sci_iolen
                                            THEN
                                                elen_var := sci_iolen
                                            (*ENDIF*) 
                                        (*ENDIF*) 
                                        END
                                    (*ENDWITH*) 
                                    END;
                                OTHERWISE
                                    BEGIN
                                    END
                                END;
                            (*ENDCASE*) 
                            j := i;
                            WHILE ((j > 1) AND
                                  (mb_st^ [j].etype <> st_func)) DO
                                j := pred(j);
                            (*ENDWHILE*) 
                            epos          := i + 1 - j;
                            ecol_tab[ 1 ] := chr (0);
                            ecol_tab[ 2 ] := chr(mfirst_free-
                                  m_mfirst_free)
                            END
                        (*ENDWITH*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDWITH*) 
            (*ENDIF*) 
        (*ENDIF*) 
        d_group := md_group;
        d_is_function_column := false
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(* PTS 1123051 E.Z. *)
(*------------------------------*) 
 
PROCEDURE
      ak640reset_format (
            VAR acv      : tak_all_command_glob;
            VAR dmli     : tak_dml_info;
            VAR colin    : tak00_scolinf);
 
BEGIN
IF  ((colin.sci_typ = ddate) AND (colin.sci_iolen > succ(mxsp_date))) OR
    ((colin.sci_typ = dtime) AND (colin.sci_iolen > succ(mxsp_time))) OR
    ((colin.sci_typ = dtimestamp) AND (colin.sci_iolen > succ(mxsp_timestamp)))
THEN
    BEGIN
    a641check_datetime (acv, dmli, colin.sci_typ);
    CASE colin.sci_typ OF
        ddate:
            colin.sci_iolen := succ(mxsp_date);
        dtime:
            colin.sci_iolen := succ(mxsp_time);
        dtimestamp:
            colin.sci_iolen := succ(mxsp_timestamp);
        END;
    (*ENDCASE*) 
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a640factor (
            VAR acv      : tak_all_command_glob;
            VAR dmli     : tak_dml_info;
            VAR colin    : tak00_scolinf;
            VAR act_node : integer);
 
VAR
      is_old        : boolean;
      keep_concat   : boolean;
      keep_hex      : boolean;
      normfac       : boolean;
      schemaGiven   : boolean;
      keep_datatype : tsp00_DataType;
      node          : integer;
      frec          : tak_factorrec;
      startstack    : integer;
 
BEGIN
WITH acv, a_mblock, mb_qual^,
     a_ap_tree^[ act_node ], dmli, frec DO
    IF  a_returncode = 0
    THEN
        BEGIN
        normfac := false;
        fr_error := false;
        fr_describ := false;
        fr_minus_n := 0;
        fr_minus_symb := false;
        keep_datatype := d_datatype;
        keep_concat   := d_concat;
        keep_hex      := d_hex;
&       ifdef TRACE
        t01int4 (ak_sem, 'dm_datatype ', ord(d_datatype));
        t01int4 (ak_sem, 'act_node    ', act_node);
&       endif
        IF  ((n_proc = a64) AND (n_subproc = cak_x_mult_operator))
        THEN
            a65_term (acv, dmli, colin, act_node)
        ELSE
            IF  ((n_proc = a64) AND (n_subproc = cak_x_add_operator))
            THEN
                a65_val_expr (acv, dmli, colin, act_node)
            ELSE
                IF  ((n_proc = a64) AND (n_subproc = cak_x_duration))
                THEN
                    ak640duration_expression(acv, dmli, colin, act_node)
                ELSE
                    BEGIN
                    IF  n_symb in [ s_minus, s_plus ]
                    THEN
                        BEGIN
                        IF  n_symb = s_minus
                        THEN
                            BEGIN
                            fr_minus_symb := true;
                            fr_minus_n := act_node;
                            END
                        ELSE
                            fr_minus_n := act_node;
                        (*ENDIF*) 
                        fr_getnumb := false;
                        act_node := n_lo_level
                        END;
                    (*ENDIF*) 
                    WITH a_ap_tree^[ act_node ] DO
                        IF  ((n_proc = a64) AND (n_subproc = cak_x_mult_operator))
                        THEN
                            a65_term (acv, dmli, colin, act_node)
                        ELSE
                            IF  ((n_proc = a64) AND (n_subproc = cak_x_add_operator))
                            THEN
                                a65_val_expr (acv, dmli, colin, act_node)
                            ELSE
                                normfac := true;
                            (*ENDIF*) 
                        (*ENDIF*) 
                    (*ENDWITH*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
        IF  normfac
        THEN
            BEGIN
            is_old := false;
            WITH a_ap_tree^[ act_node ] DO
                IF  n_symb in [ s_columnname, s_columnid, s_tablename, s_authid ]
                THEN
                    BEGIN
                    node := act_node;
                    d_const_value_expr := false;
                    d_param_st_begin   := 0;
                    d_param_st_index   := 0;
                    d_user   := a01_il_b_identifier;
                    d_table  := a01_il_b_identifier;
                    d_column := a01_il_b_identifier;
                    d_vppos := a_ap_tree^[ act_node ].n_pos;
                    d_n_pos := d_vppos;
                    schemaGiven := a_ap_tree^[ act_node ].n_symb = s_authid;
                    a06get_username (acv, act_node, d_user);
                    IF  schemaGiven AND (dmli.d_view OR  (a_proc_compile <> pct_none))
                    THEN
                        a101_MapSchemaName (acv, d_user, d_vppos);
                    (*ENDIF*) 
                    WITH a_ap_tree^[ act_node ] DO
                        IF  n_symb = s_tablename
                        THEN
                            BEGIN
                            a05identifier_get (acv, act_node,
                                  sizeof (d_table), d_table);
                            IF  a_is_ddl = ddl_create_trigger
                            THEN
                                BEGIN
                                IF  (d_table = a01_i_old) AND
                                    (acv.a_proc_compile in [pct_delete_trigger, pct_update_trigger])
                                THEN
                                    is_old := true
                                ELSE
                                    IF  (d_table <> a01_i_new) OR
                                        NOT (acv.a_proc_compile in [pct_insert_trigger, pct_update_trigger])
                                    THEN
                                        a07_b_put_error (acv,
                                              e_unknown_columnname, n_pos);
                                    (*ENDIF*) 
                                (*ENDIF*) 
                                d_table := a01_il_b_identifier
                                END;
                            (*ENDIF*) 
                            act_node := n_sa_level;
                            END;
                        (*ENDIF*) 
                    (*ENDWITH*) 
                    WITH a_ap_tree^[ act_node ] DO
                        BEGIN
                        IF  n_symb = s_columnid (* PTS 1128197 D.T. *)
                        THEN
                            BEGIN (* s_columnid *)
                            d_fromtabnode := n_fromtabnode;
                            d_columnindex := n_columnindex;
                            a61_search_table_by_columnindex (acv, dmli);
                            END
                        ELSE
                            BEGIN (* s_columnname *)
                            a05identifier_get (acv, act_node,
                                  sizeof (d_column), d_column);
                            IF  ((a_is_ddl <> no_ddl) AND
                                (d_column = a01_i_tablekey))
                            THEN
                                a07_nb_put_error (acv, e_unknown_columnname,
                                      n_pos, d_column)
                            ELSE
                                a61_search_table (acv, dmli);
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        IF  a_returncode = 0
                        THEN
                            BEGIN
                            (* needed by complex-View-optimizer *)
                            IF  (NOT d_wherepart) AND (NOT d_having)
                            THEN
                                d_outcolno := succ(d_outcolno);
                            (*ENDIF*) 
                            a16col_to_view_description (acv, dmli,
                                  d_colbuf^,
                                  NOT(d_wherepart) AND NOT (d_subquery));
                            IF  (NOT d_wherepart) AND (NOT d_having)
                            THEN
                                d_outcolno := pred(d_outcolno);
                            (*ENDIF*) 
                            END;
&                       ifdef TRACE
                        (*ENDIF*) 
                        t01int4 (ak_sem, 'd_first_tab ', d_first_tab);
                        t01int4 (ak_sem, 'd_basetabno ', d_basetabno);
&                       endif
                        IF  (d_first_tab in [ 0, d_basetabno ])
                            AND (d_basetabno <= cak00_maxsources)
                        THEN
                            d_first_tab := d_basetabno
                        ELSE
                            IF  d_allowed in [ may_more_tabs,
                                are_more_tabs, tabs_with_arith ]
                            THEN
                                BEGIN
                                IF  d_first_tab = 0
                                THEN
                                    d_first_tab := -d_basetabno
                                ELSE
                                    IF  d_first_tab > 0
                                    THEN
                                        d_first_tab := -d_first_tab;
                                    (*ENDIF*) 
                                (*ENDIF*) 
                                IF  d_allowed = may_more_tabs
                                THEN
                                    d_allowed := are_more_tabs
                                (*ENDIF*) 
                                END
                            ELSE
                                a07_b_put_error (acv,
                                      e_only_one_recordtype_allowed, n_pos);
                            (*ENDIF*) 
                        (*ENDIF*) 
&                       ifdef TRACE
                        t01int4 (ak_sem, 'dm_datatype ', ord(d_datatype));
                        IF  fr_error
                        THEN
                            t01int4 (ak_sem, 'i_error     ', 1)
                        ELSE
                            t01int4 (ak_sem, 'no i_error  ', 0);
                        (*ENDIF*) 
&                       endif
                        IF  a_returncode = 0
                        THEN
                            BEGIN
&                           ifdef TRACE
                            IF  d_join
                            THEN
                                BEGIN
                                t01int4 (ak_sem, 'd_join ja   ', 1);
                                t01int4 (ak_sem, 'jrc_cnt     ', d_joins.jrc_cnt);
                                WITH d_joins.jrc_joinarr^[ d_joins.jrc_cnt ] DO
                                    BEGIN
                                    t01int4 (ak_sem, 'jo_partno   ', jo_partno);
                                    t01int4 (ak_sem, 'jop_tableno ', jo_recs[ jo_partno ].jop_tableno);
                                    END;
                                (*ENDWITH*) 
                                t01int4 (ak_sem, 'basetabno   ', d_basetabno);
                                END
                            ELSE
                                t01int4 (ak_sem, 'kein join   ', 0);
                            (*ENDIF*) 
&                           endif
                            IF  d_join
                            THEN
                                WITH d_joins.jrc_joinarr^[ d_joins.jrc_cnt ] DO
                                    IF  ((jo_recs[ jo_partno ].jop_tableno
                                        in [ 0, d_basetabno ]) AND
                                        (d_basetabno <= cak00_maxsources))
                                    THEN
                                        BEGIN
&                                       ifdef trace
                                        t01int4 (ak_sem, 'INS TABNO   ', d_basetabno);
                                        t01int4 (ak_sem, 'on side     ', jo_partno);
&                                       endif
                                        jo_recs[ jo_partno ].jop_tableno :=
                                              d_basetabno;
                                        fr_jpos := jo_partno;
                                        END
                                    ELSE
                                        BEGIN
                                        jo_no_join := true;
                                        fr_jpos := 0
                                        END;
                                    (*ENDIF*) 
                                (*ENDWITH*) 
                            (*ENDIF*) 
                            ak640analyze_column (acv, dmli, frec,
                                  colin, is_old, n_pos)
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDWITH*) 
&                   ifdef TRACE
                    t01int4 (ak_sem, 'dm_datatype ', ord(d_datatype));
                    IF  fr_error
                    THEN
                        t01int4 (ak_sem, 'i_error     ', 1)
                    ELSE
                        t01int4 (ak_sem, 'no i_error  ', 0);
                    (*ENDIF*) 
&                   endif
                    IF  fr_error
                    THEN
                        a07_b_put_error (acv,
                              e_incompatible_datatypes, n_pos)
                    (*ENDIF*) 
                    END
                ELSE
                    IF  n_proc = a641
                    THEN
                        a641col_function (acv, dmli, frec,
                              colin, act_node)
                    ELSE
                        IF  ((n_proc <> a67) AND
                            (n_symb in [ s_avg, s_sum, s_min, s_max,
                            s_count, s_all_count, s_dis_count,
                            s_dis_avg, s_dis_sum,
                            s_stddev, s_dis_stddev,
                            s_variance, s_dis_variance ]))
                        THEN
                            ak640set_function (acv, dmli, colin, act_node)
                        ELSE
                            (* PTS 1116169 E.Z. *)
                            (* PTS 1123051 E.Z. *)
                            IF  (n_proc = a63query_spec)
                            THEN
                                BEGIN
                                ak640subq_value (acv, dmli, frec, colin, act_node);
                                IF  NOT d_change_date_time
                                THEN
                                    ak640reset_format (acv, dmli, colin)
                                (*ENDIF*) 
                                END
                            ELSE
                                IF  (n_proc = a63) AND
                                    (n_subproc = cak_x_arith_with_subquery)
                                THEN
                                    BEGIN
                                    ak640subq_value (acv, dmli, frec,
                                          colin, a_ap_tree^[act_node].n_lo_level);
                                    IF  NOT d_change_date_time
                                    THEN
                                        ak640reset_format (acv, dmli, colin)
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    a642other_than_column (acv, dmli, frec,
                                          colin, act_node)
                                (*ENDIF*) 
                            (*ENDIF*) 
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDWITH*) 
            END;
        (*ENDIF*) 
        IF  fr_minus_n <> 0 (* monadic operator *)
        THEN
            IF  d_datatype <> dnumber
            THEN
                a07_b_put_error (acv, e_incompatible_datatypes, n_pos)
            ELSE
                IF  fr_minus_symb
                THEN
                    IF  ((a_returncode = 0) AND NOT fr_getnumb)
                    THEN
                        a65_set_operator (acv, op_minus_monad);
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
        IF  fr_minus_n <> 0
        THEN
            act_node := fr_minus_n;
&       ifdef TRACE
        (*ENDIF*) 
        t01int4 (ak_sem, 'dm_datatype ', ord(d_datatype));
        t01int4 (ak_sem, 'keep_datatyp', ord(keep_datatype));
        t01int4 (ak_sem, 'colin.sci_ty', ord(colin.sci_typ));
        IF  fr_error
        THEN
            t01int4 (ak_sem, 'i_error     ', 1)
        ELSE
            t01int4 (ak_sem, 'no i_error  ', 0);
        (*ENDIF*) 
&       endif
        IF  (d_datatype in [ ddate, dtime, dtimestamp ]) AND
            d_change_date_time
        THEN
            BEGIN
            d_ch_datatype := d_datatype;
            startstack := a_mblock.mb_qual^.mfirst_free;
&           ifdef TRACE
            t01int4 (ak_sem, 'sci.len fact', colin.sci_len);
&           endif
            a65ch_format (acv, dmli, startstack,
                  colin, keep_datatype, d_datatype);
&           ifdef TRACE
            t01int4 (ak_sem, 'sci.len   2 ', colin.sci_len);
&           endif
            colin.sci_iolen := colin.sci_len+1;
            END;
        (* PTS 1109069 E.Z. *)
        (*ENDIF*) 
        IF  (keep_datatype = dunicode) AND
            (d_datatype = dcha )
        THEN
            BEGIN
            colin.sci_typ   := dunicode;
            colin.sci_iolen := succ(2*colin.sci_len);
            a641string_set_operator (acv,
                  op_b_uni_trans, colin.sci_iolen, 0,
                  chr(csp_ascii), chr(csp_unicode));
            END
        ELSE (* PTS 1117494 E.Z. *)
            IF  (keep_datatype = dcha) AND
                (d_datatype = dunicode)
            THEN
                BEGIN
                colin.sci_typ   := keep_datatype;
                colin.sci_iolen := succ(colin.sci_len);
                a641string_set_operator (acv,
                      op_b_uni_trans, colin.sci_iolen, 0,
                      chr(csp_unicode), chr(csp_ascii));
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  NOT ( keep_datatype in [ dunknown, dnonumber ] )
            AND
            (NOT g01unicode OR
            (NOT (keep_datatype in [ ddate, dtime, dtimestamp ])))
        THEN
            d_datatype := keep_datatype;
        (*ENDIF*) 
        d_concat := keep_concat;
        d_hex    := keep_hex;
        END
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a640not_first_factor (
            VAR acv      : tak_all_command_glob;
            VAR dmli     : tak_dml_info;
            VAR colin    : tak00_scolinf;
            VAR act_node : integer);
 
VAR
      st_begin : integer;
      st_index : integer;
 
BEGIN
(* in the case SUBSTR (:p1,3,2) || chr(weekofyear(:p2)) *)
(* we had the problem that the second factor of concat  *)
(* prepares const_param_expression with all stackentries*)
(* except the 'concat'-Stackentry itself. Therefore we  *)
(* have to avoid that the second, third... factor will  *)
(* include the factors before if not the whole function *)
(* or arithmetic is in that const_expression            *)
(* compare a65not_first and ak641not_first              *)
st_begin := dmli.d_param_st_begin;
st_index := dmli.d_param_st_index;
dmli.d_param_st_begin := 0;
dmli.d_param_st_index := 0;
a640factor (acv, dmli, colin, act_node);
dmli.d_param_st_begin := st_begin;
IF  dmli.d_param_st_index = 0
THEN
    dmli.d_param_st_index := st_index;
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
