.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
*****************************************************
Copyright (c) 2000-2005 SAP AG
SAP Database Technology
 
Release :      Date : 2000-09-11
*****************************************************
modname : VAK65
changed : 2000-09-11
module  : Execute_Where_Part
 
Author  : ElkeZ
Created : 1987-09-22
*****************************************************
 
Purpose : Processing of the search condition and every value expression
 
Define  :
 
        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_search_condition (
                    VAR acv        : tak_all_command_glob;
                    VAR dmli       : tak_dml_info;
                    VAR first_node : integer);
 
        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
              a65_convert (
                    VAR acv   : tak_all_command_glob;
                    operator  : tak_convert_type;
                    maxlength : integer);
 
        PROCEDURE
              a65_term (
                    VAR acv        : tak_all_command_glob;
                    VAR dmli       : tak_dml_info;
                    VAR colin      : tak00_scolinf;
                    VAR first_node : integer);
 
        PROCEDURE
              a65_look_for_datatypes (
                    VAR acv    : tak_all_command_glob;
                    VAR dmli   : tak_dml_info;
                    first_node : integer);
 
        FUNCTION
              a65_datatypes_ok (
                    VAR acv        : tak_all_command_glob;
                    VAR dmli       : tak_dml_info;
                    VAR dm_type    : tsp00_DataType;
                    VAR dm_iolen   : tsp00_Int2;
                    ctype          : tsp00_DataType;
                    is_subquery    : boolean;
                    first_node     : integer;
                    error_pos      : tsp00_Int4;
                    convert        : boolean;
                    VAR convert_t  : tak_convert_type) : boolean;
 
        PROCEDURE
              a65subq_get_val (
                    VAR acv    : tak_all_command_glob;
                    first_node : integer;
                    iolen      : integer);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01_i_new             : tsp00_KnlIdentifier;
              a01_i_old             : tsp00_KnlIdentifier;
              a01_il_b_identifier   : tsp00_KnlIdentifier;
 
        PROCEDURE
              a01_dt_put_datatype_node (
                    VAR acv    : tak_all_command_glob;
                    VAR curr_n : tsp00_Int2;
                    data_type  : tsp00_DataType;
                    datalen    : tsp00_Int2;
                    datafrac   : tsp00_Int2;
                    inoutlen   : integer);
 
        PROCEDURE
              a01_call_put (
                    VAR acv  : tak_all_command_glob;
                    proc     : tak_procs;
                    subproc  : tsp00_Int2;
                    VAR curr_n : tsp00_Int2);
 
        PROCEDURE
              a01_function_put (
                    VAR acv    : tak_all_command_glob;
                    VAR curr_n : tsp00_Int2);
 
        PROCEDURE
              a01_put_same_node (
                    VAR acv    : tak_all_command_glob;
                    input_node : tsp00_Int2;
                    VAR curr_n : tsp00_Int2);
 
      ------------------------------ 
 
        FROM
              AK_semantic_scanner_tools : VAK05;
 
        PROCEDURE
              a05dfts_date_from_timestamp (
                    VAR sbuf   : tsp00_MoveObj;
                    VAR dbuf   : tsp00_C28;
                    spos       : tsp00_Int4;
                    dpos       : tsp00_Int4;
                    dbufsize   : tsp00_Int4;
                    actlen     : integer;
                    format     : tgg00_DateTimeFormat;
                    language   : tsp00_C3;
                    ch_code    : boolean;
                    VAR b_err  : tgg00_BasisError);
 
        PROCEDURE
              a05tfts_time_from_timestamp (
                    VAR sbuf   : tsp00_MoveObj;
                    VAR dbuf   : tsp00_C28;
                    spos       : tsp00_Int4;
                    dpos       : tsp00_Int4;
                    dbufsize   : tsp00_Int4;
                    actlen     : integer;
                    format     : tgg00_DateTimeFormat;
                    language   : tsp00_C3;
                    ch_code    : boolean;
                    VAR b_err  : tgg00_BasisError);
 
        PROCEDURE
              a05tsfdt_timestamp_from_dattim (
                    VAR sbuf   : tsp00_MoveObj;
                    VAR dbuf   : tsp00_C28;
                    spos       : tsp00_Int4;
                    dpos       : tsp00_Int4;
                    dbufsize   : tsp00_Int4;
                    actlen     : integer;
                    format     : tgg00_DateTimeFormat;
                    stype      : tsp00_DataType;
                    ch_code    : boolean;
                    VAR b_err  : tgg00_BasisError);
 
        PROCEDURE
              a05identifier_get (
                    VAR acv     : tak_all_command_glob;
                    tree_index  : integer;
                    obj_len     : integer;
                    VAR moveobj : tsp00_KnlIdentifier);
 
        PROCEDURE
              a05timestamp_get (
                    VAR acv   : tak_all_command_glob;
                    VAR src   : tsp00_MoveObj;
                    src_pos   : tsp00_Int4;
                    VAR dest  : tsp00_C28;
                    dest_pos  : tsp00_Int4;
                    check_len : tsp00_Int4;
                    ch_code   : boolean;
                    VAR b_err : tgg00_BasisError);
 
        PROCEDURE
              a05get_digit (
                    VAR num_buf  : tsp00_MoveObj;
                    pos          : integer;
                    length       : integer;
                    VAR dig_len  : integer;
                    VAR dig_frac : integer);
 
      ------------------------------ 
 
        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);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK071;
 
        FUNCTION
              a07_return_code (
                    b_err   : tgg00_BasisError;
                    sqlmode : tsp00_SqlMode) : tsp00_Int2;
 
      ------------------------------ 
 
        FROM
              AK_Domain : VAK12;
 
        FUNCTION
              a12dbfunc_exist (
                    VAR acv         : tak_all_command_glob;
                    VAR owner       : tsp00_KnlIdentifier;
                    VAR dbfunc_name : tsp00_KnlIdentifier;
                    dstate          : tak_directory_state;
                    VAR method_buf  : tak_sysbufferaddress) : boolean;
 
        PROCEDURE
              a12describe_param  (
                    VAR acv      : tak_all_command_glob;
                    method_buf   : tak_sysbufferaddress;
                    param_no     : integer;
                    VAR colinf   : tak00_scolinf);
 
      ------------------------------ 
 
        FROM
              AK_View_semantic : VAK16;
 
        PROCEDURE
              a16inc_vdesc_cnt (
                    VAR acv       : tak_all_command_glob;
                    VAR dmli      : tak_dml_info;
                    VAR vdesc_ptr : tak_sysbufferaddress);
 
      ------------------------------ 
 
        FROM
              DML_Parts : VAK55;
 
        PROCEDURE
              a55realloc_parsinfo (
                    VAR acv          : tak_all_command_glob;
                    VAR parsinfo_ptr : tak_sysbufferaddress);
 
      ------------------------------ 
 
        FROM
              AK_Insert : VAK56;
 
        PROCEDURE
              a56_datatype (
                    in_datatype      : char;
                    VAR out_datatype : tsp00_DataType);
 
      ------------------------------ 
 
        FROM
              Select_List : VAK61;
 
        PROCEDURE
              a61_search_table (
                    VAR acv  : tak_all_command_glob;
                    VAR dmli : tak_dml_info);
 
        PROCEDURE
              a61_set_jump (
                    VAR mblock : tgg00_MessBlock;
                    stentrynr : integer;
                    operator  : tgg00_StackEntryType);
 
        PROCEDURE
              a61_format_change (
                    VAR acv     : tak_all_command_glob;
                    VAR dmli    : tak_dml_info;
                    stackpos    : integer;
                    cdatatyp    : tsp00_DataType;
                    VAR datalen : tsp00_Int2);
 
        PROCEDURE
              a61_is_group_field (
                    VAR acv       : tak_all_command_glob;
                    VAR dmli      : tak_dml_info;
                    VAR fieldname : tsp00_KnlIdentifier;
                    extcolno      : tsp00_Int2;
                    is_expression : boolean;
                    expression_n  : tsp00_Int2;
                    errorpos      : integer);
 
      ------------------------------ 
 
        FROM
              Execute_Factor : VAK640;
 
        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);
 
      ------------------------------ 
 
        FROM
              Execute_factor_col_function : VAK641;
 
        PROCEDURE
              a641check_datetime(
                    VAR acv  : tak_all_command_glob;
                    VAR dmli : tak_dml_info;
                    datatyp  : tsp00_DataType);
 
        PROCEDURE
              a641s_literal_value (
                    VAR acv           : tak_all_command_glob;
                    act_node           : integer;
                    keep_datatype      : tsp00_DataType;
                    string_allowed     : boolean;
                    VAR string_found   : boolean;
                    VAR letter         : char;
                    VAR wrong_datatype : boolean);
 
        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
              a641u_literal_value (
                    VAR acv            : tak_all_command_glob;
                    act_node           : integer;
                    VAR c2             : tsp00_C2;
                    VAR wrong_datatype : boolean);
 
      ------------------------------ 
 
        FROM
              Const_Expression : VAK651;
 
        PROCEDURE
              a651const_between_expression (
                    VAR acv     : tak_all_command_glob;
                    VAR dmli    : tak_dml_info;
                    st_begin    : integer;
                    operator    : tgg00_StackOpType);
 
        PROCEDURE
              a651in_const_expression (
                    VAR acv     : tak_all_command_glob;
                    VAR dmli    : tak_dml_info;
                    st_begin    : tsp00_Int2;
                    st_end      : tsp00_Int2);
 
        PROCEDURE
              a651code_for_const_param_expr
                    (VAR acv : tak_all_command_glob;
                    VAR dmli    : tak_dml_info;
                    st_begin    : tsp00_Int2;
                    expr_st_cnt : tsp00_Int2);
 
        PROCEDURE
              a651value_calculate (
                    VAR acv  : tak_all_command_glob;
                    st_begin : integer;
                    st_end   : integer;
                    byte_str : boolean;
                    like     : boolean;
                    iolen    : tsp00_Int2;
                    err_pos  : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              Execute_Select_Expression : VAK660;
 
        PROCEDURE
              a660construct_subtree (
                    VAR acv      : tak_all_command_glob;
                    VAR sub_tree : tgg00_FileId;
                    sub_count    : integer);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              join_trace_routines : VAK683;
 
        PROCEDURE
              a683_output (
                    debug    : tgg00_Debug;
                    VAR dmli : tak_dml_info);
 
        PROCEDURE
              a683_one_join_entry(
                    debug    : tgg00_Debug;
                    VAR joins: tak_joinrec;
                    index    : integer;
                    trace_all: boolean);
&       endif
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01code           : tgg04_CodeGlobals;
              g01unicode        : boolean;
 
        FUNCTION
              g01userstackoverflow : boolean;
 
        FUNCTION
              g01mb_data_size : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              Check-Date-Time : VGG03;
 
        PROCEDURE
              g03fdcheck_date (
                    VAR sbuf : tsp00_MoveObj;
                    VAR dbuf : tsp00_C28;
                    spos     : tsp00_Int4;
                    dpos     : tsp00_Int4;
                    actlen   : integer;
                    format   : tgg00_DateTimeFormat;
                    ch_code  : boolean;
                    VAR e    : tgg00_BasisError);
 
        PROCEDURE
              g03ftcheck_time (
                    VAR sbuf : tsp00_MoveObj;
                    VAR dbuf : tsp00_C28;
                    spos     : tsp00_Int4;
                    dpos     : tsp00_Int4;
                    actlen   : integer;
                    format   : tgg00_DateTimeFormat;
                    ch_code  : boolean;
                    VAR e    : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalMove   (
                    mod_id         : tsp00_C6;
                    mod_intern_num : tsp00_Int4;
                    size1          : tsp00_Int4;
                    size2          : tsp00_Int4;
                    val1           : tsp00_MoveObjPtr;
                    p1             : tsp00_Int4;
                    val2           : tsp00_MoveObjPtr;
                    p2             : tsp00_Int4;
                    cnt            : tsp00_Int4;
                    VAR e          : tgg00_BasisError);
 
        PROCEDURE
              SAPDB_PascalOverlappingMove  (
                    mod_id         : tsp00_C6;
                    mod_intern_num : tsp00_Int4;
                    size1          : tsp00_Int4;
                    size2          : tsp00_Int4;
                    val1           : tsp00_MoveObjPtr;
                    p1             : tsp00_Int4;
                    val2           : tsp00_MoveObjPtr;
                    p2             : tsp00_Int4;
                    cnt            : tsp00_Int4;
                    VAR e          : tgg00_BasisError);
 
        PROCEDURE
              SAPDB_PascalFill  (
                    mod_id         : tsp00_C6;
                    mod_intern_num : tsp00_Int4;
                    size           : tsp00_Int4;
                    m              : tsp00_MoveObjPtr;
                    pos            : tsp00_Int4;
                    len            : tsp00_Int4;
                    fillchar       : char;
                    VAR e          : tgg00_BasisError);
 
        PROCEDURE
              SAPDB_PascalUnicodeFill  (
                    mod_id         : tsp00_C6;
                    mod_intern_num : tsp00_Int4;
                    size           : tsp00_Int4;
                    m              : tsp00_MoveObjPtr;
                    pos            : tsp00_Int4;
                    len            : tsp00_Int4;
                    filluchar      : tsp00_C2;
                    VAR e          : tgg00_BasisError);
 
        PROCEDURE
              SAPDB_PascalForcedFill (
                    size     : tsp00_Int4;
                    m        : tsp00_MoveObjPtr;
                    pos      : tsp00_Int4;
                    len      : tsp00_Int4;
                    fillchar : char);
 
        PROCEDURE
              g10mv (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    source_upb  : tsp00_Int4;
                    dest_upb    : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    src_pos     : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    dest_pos    : tsp00_Int4;
                    length      : tsp00_Int4;
                    VAR e       : tgg00_BasisError);
 
        PROCEDURE
              s10mv (
                    source_upb  : tsp00_Int4;
                    destin_upb  : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    source_pos  : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    destin_pos  : tsp00_Int4;
                    length      : tsp00_Int4);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01stackdesc (
                    debug          : tgg00_Debug;
                    nam            : tsp00_Sname;
                    stack_addr     : tgg00_StackListPtr;
                    VAR stack_desc : tgg00_StackDesc);
 
        PROCEDURE
              t01name (
                    debug : tgg00_Debug;
                    nam   : tsp00_Name);
 
        PROCEDURE
              t01sname (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname);
 
        PROCEDURE
              t01bool (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    curr_bool: boolean);
 
        PROCEDURE
              t01p2int4 (
                    debug : tgg00_Debug;
                    nam_1 : tsp00_Sname;
                    int_1 : tsp00_Int4;
                    nam_2 : tsp00_Sname;
                    int_2 : tsp00_Int4);
 
        PROCEDURE
              t01op (
                    debug  : tgg00_Debug;
                    nam    : tsp00_Sname;
                    op     : tgg00_StackOpType);
 
        PROCEDURE
              t01int4 (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01messblock (
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    VAR m         : tgg00_MessBlock);
 
        PROCEDURE
              t01moveobj (
                    level     : tgg00_Debug;
                    VAR buf   : tsp00_MoveObj;
                    pos_start : tsp00_Int4;
                    pos_end   : tsp00_Int4);
 
        PROCEDURE
              t01aptree (
                    level       : tgg00_Debug;
                    VAR ap_tree : tak_ap_max_tree;
                    cntnodes    : integer;
                    hint_node   : tsp00_Int2);
&       endif
 
.CM *-END-* use -----------------------------------------
***********************************************************
 
Synonym :
 
        PROCEDURE
              a56_datatype;
 
              tsp00_DataType char
 
        PROCEDURE
              a05dfts_date_from_timestamp ;
 
              tsp00_MoveObj tsp00_C28
 
        PROCEDURE
              a05tfts_time_from_timestamp ;
 
              tsp00_MoveObj tsp00_C28
 
        PROCEDURE
              a05tsfdt_timestamp_from_dattim ;
 
              tsp00_MoveObj tsp00_C28
 
        PROCEDURE
              g03fdcheck_date ;
 
              tsp00_MoveObj tsp00_C28
 
        PROCEDURE
              g03ftcheck_time ;
 
              tsp00_MoveObj tsp00_C28
 
        PROCEDURE
              a05timestamp_get;
 
              tsp00_MoveObj tsp00_C28
 
        PROCEDURE
              a05identifier_get;
 
              tsp00_MoveObj tsp00_KnlIdentifier
&             ifdef trace
 
        PROCEDURE
              t01aptree;
 
              tsp00_MoveObj tak_ap_max_tree
&             endif
 
.CM *-END-* synonym -------------------------------------
***********************************************************
 
Specification:
 
Analysis of a search_condition or of an expression having the following
structure. The individual steps also reflect the corresponding procedures that
are run through in the course of the analysis.
 
 
    search_condition
          |
          |           (or_term)
          |
          |
     boolean_term
          |
          |        (and_predicate)
          |
          |
       predicate
          |
        val_expr
          |
          |     (plus_minus_term)
          |
          |
          term
          |
          |     (mult_div_factor)
          |
          |
         factor
 
 
.CM *-END-* specification -------------------------------
***********************************************************
 
Description:
 
A65_SEARCH_CONDITION
---------------------------------
 
Highest call in order to analyze a search_condition.
 
INPUT :
acv         : especially ap_tree
dmli        : especially dm_join
first_node  : Node in the syntax tree at which the search_condition begins.
 
OUTPUT :
acv     : especially mess_buf, part1
dmli    : dm_join, dm_arith_where
 
The actual semantic analysis and checking takes place in AK65SE_CONDITION, which is
called here. Before this, however, various parts of 'dmli' and 'acv' are set or
interrogated in order to clarify the type of search_condition and its
significance, e.g. 'dm_first_tab' in the case of JOINS, 'rowno_allowed' in
order to be able to handle 'ROWNO' etc.
 
AK65SE_CONDITION
---------------------------------
 
Processes the highest level of a  search_condition : an or_term
 
INPUT :
acv         : especially ap_tree
dmli        : especially atfieldlen, dm_join, dm_joins, dm_arith_where,
              dm_datatype, atcolbuf
first_node  : Node in the syntax tree at which the or_term begins.
mtabs_allowed : Boolean value that specifies whether more than one table may be
                specified in the part of the search_condition.
 
OUTPUT :
acv     : especially mess_buf, part1
dmli    : especially atfieldlen, dm_join, dm_joins, dm_arith_where,
          dm_datatype, atcolbuf
 
First of all, it is tested whether the current tree node contains a 'NOT' and
an appropriate entry is made in 'snot' and the tree pointer is moved on.
 
A distinction is then made as to whether there is an or_term or not ('n_symb'
<> 's_or'). If not, the now following and_term is processed with BOOLEAN_TERM.
However, a distinction must also be made as to whether this term is negated or
not (interrogation of 'snot'). If it is, the severity code of the Select is
determined depending on 'mtabs_allowed' (specifies whether more than one
base table can
be accessed), 'atfieldlen' (complex Select) or 'ap_tree[ xxx ].n_pos =
cak_complex_select'. After analysis by BOOLEAN_TERM, if 'dm_first_tab' < 0 (see
VAK64), entries are made in 'dm_arith_where' and 'n_pos' in order to indicate,
firstly, that there is a complex Select and, secondly, that more than one table
has occurred in an AND part. In the case of a JOIN, the necessary values are
then also entered in 'dm_joins'.
 
If there is an or_term, a distinction is once again made as to whether there is
a JOIN and the appropriate sequence of actions is adopted. The clearing of the
or_term is, however, analogous in both cases: the first operand is processed
with BOOLEAN_TERM, the next free stack position is stored, the second operand
is processed (again with BOOLEAN_TERM) and the operator OR is entered with
A65_SET_OPERATOR. Finally, an 'st_jump_true', which branches behind the
associated operator, is entered in the previously marked position. If again one
of the operands is an or_term, the recursion contained in BOOLEAN_TERM or in
PREDICATE ensures that the remainder of the current or_term is not processed
until after the complete processing of the expression. This results in a
postfix notation in the stack.
 
If there is a single and_term without negation, the entry in 'mtabs_allowed' is
passed on directly to BOOLEAN_TERM; in all other cases, 'mtabs_allowed' =
'false'  is passed on.
 
Finally, the 'NOT' operator is also entered if there was one.
 
AK65BOOLEAN_TERM
---------------------------------
 
Processes the second level of a search_condition, an and_term.
 
INPUT :
acv             : especially ap_tree
dmli            : especially atfieldlen, dm_join, dm_joins, dm_arith_where,
                  dm_datatype, atcolbuf
first_node      : Node in the syntax tree at which the and_term begins.
mtabs_allowed   : Boolean value that specifies whether more than one table
                  may be specified in the part of the search_condition.
 
OUTPUT :
acv     : especially mess_buf, part1
dmli    : especially atfieldlen, dm_join, dm_joins, dm_arith_where,
          dm_datatype, atcolbuf
 
Is comparable in the sequence of actions with SE_CONDITION. After the
recognition of a negation and the nesting of an or_term (then recursive call of
SE_CONDITION), a distinction is made as to whether there is a single predicate
or not. If there is, it is processed with PREDICATE. Any 'NOT' is passed on,
since it is partially included in the predicate (see COMPARE_PREDICATE). In the
case of an and_term, a distinction is made as in SE_CONDITION as to whether
there is a negation or a JOIN or not, with the result that the appropriate
course of action is adopted. Otherwise, an and_term is analyzed in a manner
comparable with an or_term, i.e. first operand, marking of the position, second
operand, entering of operator and entering of 'st_jump_false'. Nesting is
handled recursively in PREDICATE.
 
Finally, any 'NOT' is then entered.
 
AK65PREDICATE
---------------------------------
 
Processes the last stage of a search_condition : a single predicate.
 
INPUT :
acv             : especially ap_tree
dmli            : especially atfieldlen, dm_join, dm_joins, dm_arith_where
first_node      : Node in the syntax tree at which the predicate begins.
mtabs_allowed   : Boolean value that specifies whether more than one table may be
                  specified in the part of the search_condition.
 
OUTPUT :
acv     : especially mess_buf, part1
dmli    : especially atfieldlen, dm_join, dm_joins, dm_arith_where
 
After initialization of 'dm_joins' and recognition of a 'NOT', first of all, a
nest is broken up and, if necessary, AK65SE_CONDITION or AK65BOOLEAN_TERM is called
recursively. In the case of an and_term, a distinction is also made as to
whether there was a negation, with the result that 'mtabs_allowed' is specified
with 'false', or not, with the result that the entry is passed on.
 
In all other cases, there is a normal predicate ('normpred' is 'true'). Then,
after the handling of JOIN and 'mtabs_allowed', it is tested whether there is
's_exists' as a symbol. In this case, with SUB_OP_SET, the operator 'op_eq' is
entered in the stack and it is tested whether the subquery has already been
evaluated or not ('atuse_sub'). If not, entries are created for a node, which
is then entered in the tree as the 'sa_level' of the 'exists' node. This node
serves to provide information on the data type to be supplied by the subquery.
 
If there was no 'EXISTS', the first expression is evaluated with A65_VAL_EXPR.
In the case of a parameter ('a_returncode' = 'par_error') which was not
possible to analyze, an attempt is first made with A65_LOOK_FOR_DATATYPES to
obtain some data-type information from the tree (see
A65_LOOK_FOR_DATATYPES). If successful, another attempt is made to evaluate
the expression (the parameter); otherwise, an error is generated.
 
After the first expression has been processed (if there is a JOIN, the
necessary information is entered in 'dm_joins'), a distinction is made as to
whether there is a comparison predicate and COMPARE_PREDICATE is called or any
other predicate, which is processed with DIFF_PREDICATE.
 
Finally, a 'NOT' is entered (if it 'still' exists) and it is checked whether
there is a JOIN (left-hand table <> right-hand table) and whether there are not
already too many JOINs.
 
AK65COMPARE_PREDICATE
---------------------------------
 
Processes a comparison predicate.
 
INPUT :
acv         : especially ap_tree
dmli        : especially atcolbuf, dm_datatype
first_node  : Node in the syntax tree at which the predicate begins.
snotpred    : Boolean value that specifies whether there was a NOT in front of the
              predicate.
field_found : Integer value that specifies whether a column was found
              (then the stackentry-no, where it can be found) or not (= 0) as the
              first expression.
 
OUTPUT :
acv     : especially mess_buf, part1
dmli    : especially atcolbuf, dm_datatype
 
First of all, the stack operator is determined depending on the entry in
'snotpred', with a negation meaning that the operators are turned round.
'snotpred' is set to 'false', so that a further negation is not entered in
PREDICATE. Then, a specification of 'authid' or 'tablename', if there is one,
is skipped and it is tested whether 'ALL' or 'ANY' or a subquery has been
specified. In all cases, it is checked whether information already exists for
this subquery ('atuse_sub') or not and an additional node is appropriately
entered in the tree containing the data type (see PREDICATE in
the case of 'EXISTS'). If information exists, it is checked with
A65_DATATYPES_OK whether the expected data type matches the data type supplied
by the subquery. In either case, depending on the specification of 'ALL' or
'ANY', the operator and the remaining stack entry are created with SUB_OP_SET.
 
If there is no subquery, first of all, a multiple index on a column is
considered (ecol_tab[ 2 ] set > 100). For a Join condition, an entry is made
in the operator and the right-hand side is entered in 'dm_joins'. In addition,
the overall length of the columns concerned (expressions) is determined.
.br;Otherwise, with A65_VAL_EXPR, the second expression is read and then the
operator is entered in the stack (with A65_SET_OPERATOR).
 
If 'ROWNO' occurred in this expression and was allowed ('a_returncode' = 0),
an entry is made in 'atrowno' depending on the operator ('op_le' or 'op_lt')
as well as in 'etype', 'eop' and 'epos'. The stack entries belonging to this
rowno condition are not needed any more and are destroyed.
 
AK65DIFF_PREDICATES
---------------------------------
 
The predicates 'BETWEEN', 'LIKE', 'IN', 'SOUNDS' and their negations are
processed.
 
INPUT :
acv         : especially ap_tree
dmli        : especially atcolbuf, dm_datatype
first_node  : Node in the syntax tree at which the predicate begins.
field_found : Integer value that specifies whether a column was found
              (then the stackentry-no, where it can be found) or not (= 0) as the
              first expression.
 
OUTPUT :
acv     : especially mess_buf, part1
dmli    : especially atcolbuf, dm_datatype
 
A distinction is made between the individual predicates on the basis of the
current symbol, with basically the same steps being performed: processing of
the next (i.e. second expression) with A65_VAL_EXPR and entry of the
corresponding operator in the stack. If the next expression contains a function
(interrogation of 'n_symb'), the previous found column
information is destroyed ('atcolbuf'
:= NIL), because it cannot be used for functions.
 
The following special cases with regard to the individual predicates must also
be considered:
 
between     : since a 'BETWEEN' condition can be used for deciding on the strategy,
              a multiple index on a column, if there is one, is entered in 'ecol_tab'. Then,
              two further expressions are evaluated.
 
in          : Is processed in IN_PREDICATE.
like        : To be able to use a 'LIKE' condition for the strategy, an attempt is
              made to convert it in TRY_LIKE_OPTIMIZATION into a 'BETWEEN' or 'EQUAL'
              condition. This is not possible if a function has been specified.
              Therefore this case is processed directly
              with A64_FACTOR. Otherwise, first of all, a multiple index is considered and
              then TRY_LIKE_OPTIMIZATION is called. After it has been called, the entry in
              'dm_like' specifies whether an optimization has taken place or not, with the
              result that the operator has already been entered or not.
 
sounds : No special features.
 
AK65IN_PREDICATE
---------------------------------
 
Processes the predicate 'IN' and its negation.
 
INPUT :
acv         : especially ap_tree
dmli        : especially atcolbuf, dm_datatype
first_node  : Node in the syntax tree at which the IN predicate begins.
symbol      : Current predicate symbol, either 's_in' or 's_notin'
 
OUTPUT :
acv     : especially mess_buf, part1
dmli    : especially atcolbuf, dm_datatype
 
Either a subquery (node is identified by a63 , 4) or a list of values is
specified as the second argument of the 'IN' predicate.
 
In the first case, the subquery is handled in the usual manner, i.e.
distinction as to whether something is known about the subquery or not
('atuse_sub').
 
In the second case, each value in the list is handled with A64_FACTOR by a
WHILE loop. Then, the operator 'op_in' or 'op_notin' is entered in the stack.
If there is a test of a single value in a list of values, then the number of
values is entered in 'elen_var' and a 1 (for one element per list) is written
in 'epos'. If a list is tested versus a list of lists, then the count of lists
is stored in 'elen_var' and the number of values per list in 'epos'.
Zero is entered in almost all of the other values of the stack entry.
 
Ak65TRY_LIKE_OPTIMIZATION
---------------------------------
 
Attempts an optimization of a 'LIKE' predicate.
 
For this purpose, the value is entered three times in the Mess-Buffer, twice
with the stack entry st_dummy, once as st_value with the correct operator.
Normally, this means that nothing changes for KB irrespective of the Like
value, except that 2 stack entries have to be jumped. For the strategy,
however, the two st_dummy stack entries are visible and may possibly contain a
Between condition ('00'h or 'ff'h is subsequently used for padding starting at
the first place-holder).
 
INPUT:
acv         : especially ap_tree
dmli        : especially dm_like
first_node  : Node in the syntax tree at which the LIKE predicate begins
symbol      : Current predicate symbol, either 's_in' or 'snotin'
keep_part_pos : Pointer to the valueposition in the SQL_PACKET during execution
 
OUTPUT :
acv     : especially mess_buf, part1
dmli    : especially dm_like
 
To be able to perform an optimization, it is checked whether only parsing is to
be performed and there is a parameter or whether a value has already been
entered in the command.
In the first case, two dummy entries are created in the
stack and the operator is entered, with the result that optimization can be
performed during execution.
 
In the second case, an attempt is made on the basis of the value in
the command
to obtain a 'BETWEEN' or 'EQUAL' condition from the
'LIKE' condition. For this purpose, the position of the wildcard is determined
and it is checked whether a lower set bound can be created by leaving out the
remainder or whether an upper set bound can be created by entering binary 255
in the remainder. If no wildcards are found ('star_or_any_found' is 'false'),
an EQUAL condition can be created.
 
According to the result of the optimization, an entry is then made in the
stack.
 
A65_LOOK_FOR_DATATYPES
---------------------------------
 
Looks for information on data types.
 
INPUT :
acv         : especially ap_tree
first_node  : Node in the syntax tree at which the expression begins.
 
OUTPUT :
dmli    : especially dm_datatype, atuser, attable, atcolumn
 
On the basis of the current symbol in the syntax tree, an attempt is made to
obtain information on the data type. The simple cases can be transferred
directly. If a column is specified, first of all, 'authid', 'tablename' and
'columnname' are transferred to the corresponding parts of 'dmli' and then the
system information for the table and column is fetched with A61_SEARCH_TABLE.
The data type 'dm_datatype' that is being searched for is determined on the
basis of the column data type 'cdatatype'.
 
If the case is not one of the recognizable ones, an attempt is made to obtain
information (by a recursive call) at least in the environs of the current node
('n_lo_level' or 'n_sa_level' <> 0).
 
A65_DATATYPES_OK
---------------------------------
 
Compares the compatibility of the two specified data types of the
output column of the subquery and of the corresponding expression or column.
 
INPUT :
acv         : especially ap_tree
ord_dm_type : Data type of the expression
ord_ctype   : Data type of the column
first_node  : Node in the syntax tree at which the expression begins.
 
OUTPUT :
RESULT : Boolean result of the comparison
 
On the basis of the possibilities for the data type (dnumber (1), dchb
(2), dcha (3), ddate (5), dtime (6)), it is
checked whether the data type of the column matches it. If not, an ERROR is
generated with 'incompatible_datatypes'.
 
AK65SUB_OP_SET
---------------------------------
 
In the case of a subquery, this procedure
enters in the stack the operator, the subquery name
and the specification of 'ALL' or 'ANY'.
 
INPUT :
acv         : especially ap_tree
all         : Boolean value that identifies the existence of 'ALL'
any         : Boolean value that identifies the existence of 'ANY'
operator    : Operator that is to be entered
first_node  : Node at which the expression begins
 
OUTPUT :
acv : especially mess_buf, part1, part2
 
The subquery name is formed with the aid of 'ap_tree[ xxx ].n_length and is
entered in 'part2' ('info'). The operator and the specification of 'ALL' or
'ANY' are entered in 'part1' (in 'ecol_tab[ 1 ]' or 'ecol_tab[ 2 ]').
 
A65_VAL_EXPR
---------------------------------
 
Processes the highest level of an expression : an additive expression.
 
INPUT :
acv         : especially ap_tree
dmli        : especially dm_datatype
first_node  : Node in the tree at which the expression begins
 
OUTPUT :
acv         : especially mess_buf, part1
dmli        : especially dm_datatype
colin       : Description of the expression
 
The analysis of an additive expression is basically the same as the analysis of
the search_condition, since, in both cases, there are operators with
arity two.
 
After it has been tested whether there is an additive expression at all, it is
identified in 'keep_plus' whether there is an addition or a subtraction and
then the first term is processed with A65_TERM. In accordance of the  data
type this term supplies the following actions takes place :
In case of 'ddate', 'dtime', 'dtimestamp', 'dcha'
a date_time arithmetik has been found. In dependence on the datatype and
the operator 'dt_expected' is set und 'datetimearith' is set to true. If
the processed term is a string specification ( dcha )
A65_LOOK_FOR_DATATYPES is called to determine whether date or time
values must be tested ( with A64_CHECK_DATETIME ). Timestamp values
can not be given via a string specifiation inside timestamp arithmetic.
In all other cases it is tested whether th datatype is <> dnumber and
otherwise, the tree pointer is moved on one and the
an error ( 'function_not_allowed' ) is created.
Now the second term is handled. After it has been successfully processed,
depending on 'keep_plus', the 'colin' for the expression is created with
AK65NEW_COLINFO and the corresponding operator is entered in the stack.
If datetimearith has been set before, the processing of the date-time
arithmetic takes place.
By this way it is guaranteed that the processing of normal additiv
expression is not influenced by the occurance of date-time arithmetic.
 
If again one of the operands is an additive expression, it is ensured by
recursion in A65_TERM or A64_FACTOR that, first of all, all lower expressions
are entered in the stack before the highest operator is entered. Therefore, a
postfix notation is created.
 
A65_TERM
---------------------------------
 
Processes the second level of an arithmetic expression: a multiplicative term.
 
INPUT :
acv         : especially ap_tree
dmli        : especially dm_datatype
first_node  : Node in the tree at which the term begins
 
OUTPUT :
acv         : especially mess_buf, part1
dmli        : especially dm_datatype
colin       : Description of the term
 
Sequence of actions precisely as in A65_VAL_EXPR, only that the multiplicative
operators '*', '/', 'MOD' and 'DIV' are handled.
 
A65_SET_OPERATOR
---------------------------------
 
Enters an operator in the stack.
 
INPUT :
operator : Operator that is to be entered.
 
OUTPUT :
acv     : especially mess_buf, part1
 
 
The operator that is to be entered is either inserted into the current stack
entry if it does not yet contain one ('eop' = 'op_none'); otherwise, a new
stack entry consisting only of the operator is created.
 
 
AK65NEW_COLINFO :
---------------------------------
 
Creates the 'colin' for the arithmetic expressions.
 
INPUT :
col1    : Colinfo of the first operand
col2    : Colinfo of the second operand
n_symb  : Operator symbol of the expression under consideration
 
 
OUTPUT :
col1 : Description of the entire expression
 
The 'colin' for the entire arithmetic expression is formed on the basis of the
information of the two operands contained in 'col1' and 'col2'. The different
arithmetic operators are taken into account.
 
.CM *-END-* description ------------------------
***********************************************************
.CM -lll-
Code    :
 
 
CONST
      date_duration_len   = 8;
      date_duration_iolen = 6;
      time_duration_len   = 6;
      time_duration_iolen = 5;
      timestamp_duration_len   = 20;
      timestamp_duration_iolen = 12;
      c_is_expression     = true (* a61_is_group_field *);
      c_ignore_sa_level   = true;
      c_mtabs_allowed     = true (* ak65boolean_term *);
      (*                            ak65predicate *)
      (*                            ak65se_condition *)
      c_like_expression   = true (* ak65set_like_operator *);
      c_escape            = true (* ak65set_like_operator *);
      c_all               = true (* ak65sub_op_set *);
      c_any               = true (* ak65sub_op_set *);
      c_look_for_dtype    = true (* ak65is_datetime_arith *);
      c_convert           = true (* a65_datatypes_ok *);
      c_is_subquery       = true (* a65_datatypes_ok *);
      c_ch_code           = true (* g03fdcheck_date *);
      c_string_allowed    = true (* a641s_literal_value *);
 
TYPE
      expected_datetime_value =
            (date_duration,
            date_or_date_duration,
            time_duration,
            time_or_time_duration,
            timestamp_duration);
 
      list_elem_info_entry = RECORD
            is_field  : boolean;
            datatype  : tsp00_DataType;
            datalen   : tsp00_Int2;
            datafrac  : tsp00_Uint1;
            filler    : boolean;
            inout_len : tsp00_Int2;
            pos       : tsp00_Int4;
      END;
 
 
      list_elem_info = RECORD
            count : integer;
            elem  : ARRAY [ 1 .. MAX_COL_PER_TAB_GG00 ] OF list_elem_info_entry;
      END;
 
 
 
(*------------------------------*) 
 
PROCEDURE
      ak65analyze_joinarr (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            first_node     : integer;
            act_node       : integer);
 
CONST
      c_found = csp_maxint2;
 
VAR
      _ix           : integer;
      _curr_n       : integer;
      _const_expr   : boolean;
 
BEGIN
(* dmli.d_joins.jrc_cnt used as index in jrc_joinarr is *)
(* first free/unused aray element                       *)
(* precondition: dmli.d_joins.jrc_cnt is valid index    *)
&ifdef trace
t01p2int4 (ak_sem, 'jrc_cnt     ', dmli.d_joins.jrc_cnt,
      'jop_tableno ', dmli.d_joins.jrc_joinarr
      [ dmli.d_joins.jrc_cnt ].jo_recs[ 1 ].jop_tableno);
t01name(ak_sem, 'entry to proof   :');
a683_one_join_entry( ak_sem, dmli.d_joins, dmli.d_joins.jrc_cnt, true );
t01bool(ak_sem, 'jo_no_join  ', dmli.d_joins.jrc_joinarr
      [ dmli.d_joins.jrc_cnt ].jo_no_join);
&endif
IF  ( NOT dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_no_join )
    AND
    ( dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_recs[ 1 ].
    jop_tableno > 0 )
THEN
    BEGIN
    IF  ( dmli.d_joins.jrc_cnt = MAX_JOINS_GG04 )
    THEN
        BEGIN
&       ifdef trace
        t01sname(ak_sem, 'overflow    ');
&       endif
        (* end of jrc_joinarr reached, test if *)
        (* a real join predicate has to be *)
        (* inserted                        *)
        IF  NOT ( acv.a_outer_join OR dmli.d_outer_join )
        THEN
            BEGIN
            IF  ( dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                jo_recs[ 2 ].jop_tableno <> 0 )
            THEN
                BEGIN
                (* join predicate, try to remove a *)
                (* value predicate                 *)
                _ix := 0;
                WHILE _ix < MAX_JOINS_GG04 DO
                    IF  ( dmli.d_joins.jrc_joinarr[ _ix ].jo_recs[ 2 ].
                        jop_tableno = cak68_join_value )
                    THEN
                        BEGIN
                        dmli.d_joins.jrc_joinarr[ _ix ] :=
                              dmli.d_joins.jrc_joinarr[ MAX_JOINS_GG04 ];
                        _ix := c_found;
                        END
                    ELSE
                        _ix := _ix + 1;
                    (*ENDIF*) 
                (*ENDWHILE*) 
                IF  ( _ix <> c_found )
                THEN
                    a07_b_put_error (acv, e_too_many_joins,
                          acv.a_ap_tree^[ act_node ].n_pos)
                ELSE
                    BEGIN
                    ak65init_one_join(dmli.d_joins.jrc_joinarr[ MAX_JOINS_GG04 ]);
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END
        ELSE
            a07_b_put_error (acv, e_too_many_joins,
                  acv.a_ap_tree^[ act_node ].n_pos)
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        _curr_n := acv.a_ap_tree^[ act_node ].n_sa_level;
        (* move to next column node *)
        IF  (_curr_n > 0)
        THEN
            IF  (acv.a_ap_tree^[ _curr_n ].n_symb = s_tablename)
            THEN
                _curr_n := acv.a_ap_tree^[ _curr_n ].n_sa_level;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (_curr_n > 0)
        THEN
            IF  (acv.a_ap_tree^[ _curr_n ].n_symb = s_columnname)
            THEN
                _curr_n := acv.a_ap_tree^[ _curr_n ].n_sa_level;
            (* h.b. PTS 1000329 *)
&           ifdef TRACE
            (*ENDIF*) 
        (*ENDIF*) 
        t01int4 (ak_sem, 'first_node^^', first_node); (* operator node *)
        t01int4 (ak_sem, 'act_nodepred', act_node);   (* operand node  *)
        t01int4 (ak_sem, '_curr_n     ', _curr_n);
&       endif
        IF  (_curr_n > 0)
            AND
            (* first operand is column *)
            (dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
            jo_recs[ 1 ].jop_tableno <> 0)
            AND
            (* second operand isn't column *)
            (dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
            jo_recs[ 2 ].jop_tableno =  0)
            AND
            (* no functions *)
            (acv.a_ap_tree^[ act_node ].n_symb IN
            [ s_authid, s_tablename, s_columnname ])
            AND
            (* insert all local outer join predicates *)
            (* PTS 1113327 *)
            (( (acv.a_outer_join OR dmli.d_outer_join) AND (dmli.d_joins.
            jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_op <> op_none))
            (* insert local join predicates with equal condition *)
            OR ((acv.a_ap_tree^[ first_node ].n_symb = s_equal) AND
            (dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
            jo_op = op_eq)))
        THEN
            BEGIN
            (* found "col <op> noncol" predicate *)
            _const_expr := true;
            ak65is_const_expr( acv.a_ap_tree, _curr_n,
                  NOT c_ignore_sa_level, _const_expr );
&           ifdef trace
            t01bool(ak_sem, '_const_expr ', _const_expr );
&           endif
            IF  ( _const_expr )
            THEN
                BEGIN
                IF  ((acv.a_mblock.mb_st^[dmli.d_joins.jrc_joinarr
                    [ dmli.d_joins.jrc_cnt ].jo_recs[ 1 ].
                    jop_startstack + 1 ].etype in [st_value, st_subquery]) OR
                    (( dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                    jo_op = op_like ) AND
                    ( acv.a_mblock.mb_st^[dmli.d_joins.jrc_joinarr
                    [ dmli.d_joins.jrc_cnt ].jo_recs[ 1 ].
                    jop_startstack + 1 ].etype = st_dummy )))
                    AND
                    (dmli.d_joins.jrc_joinarr
                    [ dmli.d_joins.jrc_cnt ].jo_recs[ 1 ].
                    jop_inoutlen <> 0)
                THEN
                    BEGIN
                    IF   dmli.d_joins.jrc_joinarr
                        [ dmli.d_joins.jrc_cnt ].jo_recs[ 2 ].jop_outer_join
                    THEN
                        a07_b_put_error (acv,
                              e_outer_join_not_allowed,
                              acv.a_ap_tree^[ _curr_n ].n_pos)
                    ELSE
                        BEGIN
                        dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                              jo_recs[ 2 ].jop_tableno    :=
                              cak68_join_value;
                        dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ]
                              .jo_recs[ 2 ].jop_fieldno    := 0;
                        dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                              jo_recs[ 2 ].jop_startstack :=
                              dmli.d_joins.jrc_joinarr
                              [ dmli.d_joins.jrc_cnt ].jo_recs[ 1 ].
                              jop_startstack +
                              dmli.d_joins.jrc_joinarr
                              [ dmli.d_joins.jrc_cnt ].jo_recs[ 1 ].
                              jop_cntstack;
                        dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                              jo_recs[ 2 ].jop_cntstack   :=
                              acv.a_mblock.mb_qual^.mfirst_free -
                              dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                              jo_recs[ 2 ].jop_startstack;
                        dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                              jo_recs[ 2 ].jop_datatyp    := dmli.d_joins.
                              jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                              jo_recs[ 1 ].jop_datatyp;
                        IF  ( acv.a_mblock.mb_st^[ dmli.d_joins.jrc_joinarr
                            [ dmli.d_joins.jrc_cnt ].jo_recs[ 1 ].
                            jop_startstack + 1 ].etype = st_value )
                            AND
                            ( acv.a_mblock.mb_st^[ dmli.d_joins.jrc_joinarr
                            [ dmli.d_joins.jrc_cnt ].jo_recs[ 1 ].
                            jop_startstack + 1 ].elen_var  > dmli.d_joins.
                            jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                            jo_recs[ 1 ].jop_inoutlen )
                        THEN
                            dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                                  jo_recs[ 2 ].jop_inoutlen :=
                                  acv.a_mblock.mb_st^[ dmli.d_joins.jrc_joinarr
                                  [ dmli.d_joins.jrc_cnt ].jo_recs[ 1 ].
                                  jop_startstack + 1 ].elen_var
                        ELSE
                            dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                                  jo_recs[ 2 ].jop_inoutlen   := dmli.d_joins.
                                  jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                                  jo_recs[ 1 ].jop_inoutlen;
                        (*ENDIF*) 
                        dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                              jo_recs[ 2 ].jop_propset    := [  ];
                        dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                              jo_recs[ 2 ].jop_outer_join := false;
                        dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                              jo_recs[ 2 ].jop_outpos     := 0;
                        dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                              jo_recs[ 2 ].jop_multiplier :=
                              csp_maxint4;
&                       ifdef TRACE
                        t01int4 (ak_sem, 'value_found ',
                              ord (acv.a_ap_tree^[ _curr_n ].n_symb));
&                       endif
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            (* *** PTS 2801 multiple Indexfelder              *)
            (*     werden von a70_strategy nicht erkannt  *** *)
            IF  (dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                jo_recs[ 2 ].jop_startstack > 0) AND
                (dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                jo_recs[ 2 ].jop_startstack <=
                acv.a_mblock.mb_qual^.mfirst_free) AND
                (dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                jo_recs[ 2 ].jop_tableno <> 0)
            THEN
                BEGIN
                IF  (jtmulti in dmli.d_joins.
                    jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_recs[ 2 ].
                    jop_propset)
                    AND
                    (ord (acv.a_mblock.
                    mb_st^[dmli.d_joins.
                    jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_recs[ 2 ].
                    jop_startstack ].ecol_tab[ 2 ]) < 100)
                    AND
                    (acv.a_mblock.
                    mb_st^[dmli.d_joins.
                    jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_recs[ 2 ].
                    jop_startstack ].etype in
                    [ st_fixkey, st_varkey, st_fixcol, st_varcol ])
                THEN
                    acv.a_mblock.
                          mb_st^[dmli.d_joins.
                          jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_recs[ 2 ].
                          jop_startstack ].ecol_tab[ 2 ] :=
                          chr( ord (acv.a_mblock.mb_st^[ dmli.d_joins.
                          jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_recs[ 2 ].
                          jop_startstack ].ecol_tab[ 2 ]) + 100);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        ;
&       ifdef TRACE
        IF  ( dmli.d_join )
        THEN
            BEGIN
            dmli.d_joins.jrc_cnt := succ (dmli.d_joins.jrc_cnt);
            a683_output (ak_sem, dmli);
            dmli.d_joins.jrc_cnt := pred (dmli.d_joins.jrc_cnt);
            END;
        (*ENDIF*) 
        t01stackdesc (ak_join, 'ak65analyze ', acv.a_mblock.mb_st,
              acv.a_mblock.mb_qual^.mstack_desc);
&       endif
        IF  (dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
            jo_recs[ 2 ].jop_tableno = 0)
            OR
            (
            (dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
            jo_recs[ 1 ].jop_tableno = cak68_join_value) AND
            (dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
            jo_recs[ 2 ].jop_tableno = cak68_join_value)
            )
        THEN
            BEGIN
            dmli.d_joins.jrc_cnt := pred (dmli.d_joins.jrc_cnt);
&           ifdef trace
            t01name(ak_sem, 'reject this entry ');
&           endif
            END
        ELSE
            BEGIN
&           ifdef trace
            t01name(ak_sem, 'accept this entry ');
&           endif
            IF  ((dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                jo_recs[ 1 ].jop_inoutlen = 0) OR
                ( dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                jo_recs[ 2 ].jop_inoutlen = 0))
            THEN
                a07_b_put_error (acv, e_join_fields_too_long,
                      acv.a_ap_tree^[ act_node ].n_pos);
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        ;
        dmli.d_joins.jrc_cnt := succ(dmli.d_joins.jrc_cnt);
        (* prepare next entry or reject actual entry *)
        ak65init_one_join(dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ]);
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65between_predicate (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR colin      : tak00_scolinf;
            sel_start_n    : integer;
            first_node     : integer;
            operator       : tgg00_StackOpType;
            field_found    : tsp00_Int2;
            VAR e          : tgg00_BasisError);
 
VAR
      _nochange        : boolean;
      _no_check        : boolean;
      _startstack      : integer;
      _i               : integer;
      _sel_n           : integer;
      _dummy_iolen     : tsp00_Int2;
      _st_begin        : tsp00_Int2;
      _st_begin1       : tsp00_Int2;
      _both_const_expr : boolean;
      _check_type      : tsp00_DataType;
      _helpbuf         : tak00_colinfo_ptr;
      _keep_dtype      : ARRAY [ 1.. 3 ] OF tsp00_DataType;
      _node            : ARRAY [ 1.. 3 ] OF integer;
      _val_const       : ARRAY [ 1.. 3 ] OF boolean;
      _cchange         : ARRAY [ 1.. 3 ] OF boolean;
      _startstck       : ARRAY [ 1.. 3 ] OF integer;
      _ccolin          : ARRAY [ 1.. 3 ] OF tak00_scolinf;
      _convert_t       : tak_convert_type;
 
BEGIN
_sel_n := sel_start_n;
_both_const_expr := false;
_node [ 1 ]      := first_node;
_no_check        := false;
_startstack      := acv.a_mblock.mb_qual^.mfirst_free;
_val_const[ 1 ]  := acv.a_ap_tree^[ _node[ 1 ] ].n_symb in
      [ s_string_literal, s_uid, s_user, s_usergroup,
      (* PTS 1111797 E.Z. *)
      s_sysdba, s_parameter_name ];
_check_type := dunknown;
IF  field_found > 0
THEN
    IF  ctmulti in dmli.d_colbuf^.ccolpropset
    THEN
        WITH acv.a_mblock.mb_st^ [field_found] DO
            ecol_tab[ 2 ] := chr( ord (ecol_tab[ 2 ]) + 100);
        (*ENDWITH*) 
    (*ENDIF*) 
(*ENDIF*) 
_helpbuf      := dmli.d_colptr;
_i            := 1;
_cchange[ _i ] := dmli.d_datatype in [ ddate,dtime,dtimestamp ];
IF  _cchange[ _i ]
THEN
    _check_type := dmli.d_datatype
ELSE
    IF  NOT _val_const[ _i ]
    THEN
        _no_check := true;
    (*ENDIF*) 
(*ENDIF*) 
_startstck[ _i ]  := _startstack;
_keep_dtype[ _i ] := dmli.d_datatype;
_ccolin[ _i ]     := colin;
&ifdef trace
t01int4 (ak_sem, 'node       1', _node[ _i ]);
t01int4 (ak_sem, 'd_datatype 1', ord (dmli.d_datatype));
t01int4 (ak_sem, 'startstack 1', _startstck[ _i ]);
t01int4 (ak_sem, 'colin.typ  1', ord(_ccolin[ _i ].sci_typ));
&endif
_i         := succ(_i);
_node[ _i ] := _sel_n;
(* PTS 1103903 E.Z.  x weitere Stellen entsprechend *)
IF  (((acv.a_ap_tree^[ _sel_n ].n_symb in
    [ s_plus, s_minus, s_mult, s_divide,
    s_div, s_mod ]) AND (acv.a_ap_tree^[_sel_n ].n_proc = a64))
    OR
    (acv.a_ap_tree^[ _sel_n ].n_proc = a641)) OR
    (_check_type <> dunknown)
THEN
    dmli.d_colptr := NIL;
(*ENDIF*) 
colin.sci_len      := 0;
IF  (g01unicode AND
    (dmli.d_datatype in [ ddate, dtime, dtimestamp ]) AND
    (acv.a_ap_tree^[ _sel_n ].n_symb = s_string_literal))
THEN
    dmli.d_datatype := dcha
ELSE
    IF  NOT (
        ((acv.a_ap_tree^[ _sel_n ].n_proc = a641) AND
        ( acv.a_ap_tree^[ _sel_n ].n_symb in [s_addtime, s_subtime, s_adddate, s_subdate]))
        OR
        ((acv.a_ap_tree^[ _sel_n ].n_proc = no_proc) AND
        ( acv.a_ap_tree^[ _sel_n ].n_symb = s_now))
        )
    THEN
        dmli.d_datatype := dunknown;
    (*ENDIF*) 
(*ENDIF*) 
dmli.d_change_date_time := false;
_st_begin           := acv.a_mblock.mb_qual^.mfirst_free;
dmli.d_single_expr      := true;
a65_val_expr (acv, dmli, colin, _sel_n);
IF  dmli.d_const_value_expr
THEN
    IF  acv.a_mblock.mb_qual^.mfirst_free - _st_begin > 1
    THEN
        IF  acv.a_mblock.mb_st^[ _st_begin ].ecol_tab[ 2 ] = chr(0)
        THEN
            dmli.d_const_value_expr := false;
        (*ENDIF*) 
    (*ENDIF*) 
(*ENDIF*) 
_both_const_expr    := dmli.d_const_value_expr AND (acv.a_is_ddl = no_ddl);
IF  acv.a_returncode = cak_e_parameter
THEN
    BEGIN
    _val_const[ _i ]        := true;
    dmli.d_datatype            := _keep_dtype[ _i-1 ];
    acv.a_returncode := 0;
    dmli.d_colptr              := _helpbuf;
    a65_val_expr (acv, dmli, colin, _sel_n);
    END
ELSE
    _val_const[ _i ] := acv.a_ap_tree^[ _node[ _i ] ].n_symb
          in [ s_string_literal, s_uid, s_user,
          (* PTS 1111797 E.Z. *)
          s_usergroup, s_sysdba ];
(*ENDIF*) 
(* PTS 1120680 E.Z. *)
IF  acv.a_returncode = cak_e_parameter
THEN
    BEGIN
    acv.a_returncode := 0;
    a07_b_put_error (acv, e_without_datatypes,
          acv.a_ap_tree^[ _sel_n ].n_pos);
    END;
(*ENDIF*) 
IF  acv.a_ap_tree^[ _sel_n ].n_symb = s_authid
THEN
    _sel_n := acv.a_ap_tree^[ _sel_n ].n_sa_level;
(*ENDIF*) 
IF  acv.a_ap_tree^[ _sel_n ].n_symb = s_tablename
THEN
    _sel_n := acv.a_ap_tree^[ _sel_n ].n_sa_level;
(*ENDIF*) 
_sel_n := acv.a_ap_tree^[ _sel_n ].n_sa_level;
_nochange := false;
dmli.d_single_expr := false;
(* PTS 1000985/1001162 E.Z. *)
_dummy_iolen := 0;
IF  a65_datatypes_ok (acv, dmli, _keep_dtype[ _i-1 ], _dummy_iolen,
    dmli.d_datatype, NOT c_is_subquery, _node[ _i ],
    acv.a_ap_tree^[ _node[ _i ]].n_pos, c_convert, _convert_t)
THEN
    BEGIN
    dmli.d_single_expr := true;
    _cchange[ _i ] := (dmli.d_datatype in [ ddate,dtime,dtimestamp ]);
    IF  _cchange[ _i ] AND (_check_type = dunknown)
    THEN
        _check_type := dmli.d_datatype
    ELSE
        IF  NOT _cchange[ _i ] AND NOT _val_const[ _i ]
        THEN
            _no_check := true;
        (*ENDIF*) 
    (*ENDIF*) 
    _startstck[ _i ]  := acv.a_mblock.mb_qual^.mfirst_free;
    _keep_dtype[ _i ] := dmli.d_datatype;
    _ccolin[ _i ]     := colin;
&   ifdef trace
    t01int4 (ak_sem, 'node       2', _node[ _i ]);
    t01int4 (ak_sem, 'd_datatype 2', ord (dmli.d_datatype));
    t01int4 (ak_sem, 'startstack 2', _startstck[ _i ]);
    t01int4 (ak_sem, 'colin.typ  2', ord(_ccolin[ _i ].sci_typ));
&   endif
    _i         := succ(_i);
    _node[ _i ] := _sel_n;
    IF  (((acv.a_ap_tree^[ _sel_n ].n_symb in
        [ s_plus, s_minus, s_mult, s_divide,
        s_div, s_mod ]) AND (acv.a_ap_tree^[_sel_n ].n_proc = a64))
        OR
        (acv.a_ap_tree^[ _sel_n ].n_proc = a641)) OR
        (_check_type <> dunknown)
    THEN
        dmli.d_colptr := NIL;
    (*ENDIF*) 
    colin.sci_len      := 0;
    IF  (g01unicode AND
        (_keep_dtype[ 1 ] in [ ddate, dtime, dtimestamp ]) AND
        (acv.a_ap_tree^[ _sel_n ].n_symb = s_string_literal))
    THEN
        dmli.d_datatype := dcha
    ELSE
        IF  NOT (
            ((acv.a_ap_tree^[ _sel_n ].n_proc = a641) AND
            ( acv.a_ap_tree^[ _sel_n ].n_symb in [s_addtime, s_subtime, s_adddate, s_subdate]))
            OR
            ((acv.a_ap_tree^[ _sel_n ].n_proc = no_proc) AND
            ( acv.a_ap_tree^[ _sel_n ].n_symb = s_now))
            )
        THEN
            dmli.d_datatype := dunknown;
        (*ENDIF*) 
    (*ENDIF*) 
    dmli.d_change_date_time := false;
    dmli.d_param_st_index   := 0;
    dmli.d_param_st_begin   := 0;
    _st_begin1          := acv.a_mblock.mb_qual^.mfirst_free;
    a65_val_expr (acv, dmli, colin, _sel_n);
    IF  dmli.d_const_value_expr
    THEN
        IF  acv.a_mblock.mb_qual^.mfirst_free - _st_begin1 > 1
        THEN
            IF  acv.a_mblock.mb_st^[ _st_begin1 ].ecol_tab[ 2 ] = chr(0)
            THEN
                dmli.d_const_value_expr := false;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    _both_const_expr := _both_const_expr AND dmli.d_const_value_expr;
    IF  acv.a_returncode = cak_e_parameter
    THEN
        BEGIN
        _val_const[ _i ]        := true;
        dmli.d_datatype            := _keep_dtype[ _i-2 ];
        acv.a_returncode := 0;
        dmli.d_colptr              := _helpbuf;
        a65_val_expr (acv, dmli, colin, _sel_n);
        END
    ELSE
        _val_const[ _i ] :=
              acv.a_ap_tree^[ _node[ _i ] ].n_symb in
              [ s_string_literal, s_uid, s_user,
              (* PTS 1111797 E.Z. *)
              s_usergroup, s_sysdba ];
    (*ENDIF*) 
    (* PTS 1120680 E.Z. *)
    IF  acv.a_returncode = cak_e_parameter
    THEN
        BEGIN
        acv.a_returncode := 0;
        a07_b_put_error (acv, e_without_datatypes,
              acv.a_ap_tree^[ _sel_n ].n_pos);
        END;
    (*ENDIF*) 
    dmli.d_single_expr := false;
    (* PTS 1000985/1001162 E.Z. *)
    IF  a65_datatypes_ok (acv, dmli, _keep_dtype[ _i-2 ], _dummy_iolen,
        dmli.d_datatype, NOT c_is_subquery, _node[ _i ],
        acv.a_ap_tree^[ _node[ _i ]].n_pos, c_convert, _convert_t)
    THEN
        IF  a65_datatypes_ok (acv, dmli, _keep_dtype[ _i-1 ], _dummy_iolen,
            dmli.d_datatype, NOT c_is_subquery, _node[ _i ],
            acv.a_ap_tree^[ _node[ _i ]].n_pos, NOT c_convert, _convert_t)
        THEN
            BEGIN
            _keep_dtype[ _i ] := dmli.d_datatype;
            _cchange[ _i ] := (dmli.d_datatype in [ ddate,dtime,dtimestamp ]);
            IF  _cchange[ _i ] AND
                (_check_type = dunknown)
            THEN
                _check_type := dmli.d_datatype
            ELSE
                IF  NOT _cchange[ _i ] AND
                    NOT _val_const[ _i ]
                THEN
                    _no_check := true;
                (*ENDIF*) 
            (*ENDIF*) 
            _ccolin[ _i ] := colin;
&           ifdef trace
            t01int4 (ak_sem, 'node       3', _node[ _i ]);
            t01int4 (ak_sem, 'd_datatype 3', ord (dmli.d_datatype));
            t01int4 (ak_sem, 'colin.typ  3', ord(_ccolin[ _i ].sci_typ));
&           endif
            _nochange := (_cchange[ 1 ] AND
                  _cchange[ 2 ] AND
                  _cchange[ 3 ]);
            _nochange := (_cchange[ 1 ]  OR
                  _cchange[ 2 ]  OR
                  _cchange[ 3 ]) AND
                  (NOT _nochange);
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    END
ELSE
    dmli.d_single_expr := true;
(*ENDIF*) 
IF  _nochange AND (acv.a_returncode = 0)
THEN
    BEGIN
    _i := 0;
    e := e_ok;
    REPEAT
        BEGIN
        _i := succ(_i);
        IF  _i = 3
        THEN
            _startstck[ _i ] := acv.a_mblock.mb_qual^.mfirst_free;
        (*ENDIF*) 
        IF  _no_check
        THEN
            BEGIN
            IF  NOT _cchange[ _i ] AND _val_const[ _i ]
            THEN
                _cchange[ _i ] := _val_const[ _i ]
            (*ENDIF*) 
            END
        ELSE
            IF  _val_const[ 1 ] OR _val_const[ 2 ] OR
                _val_const[ 3 ]
            THEN
                _cchange[ _i ] := false;
            (*ENDIF*) 
        (*ENDIF*) 
        ak65check_change (acv, dmli, _check_type,
              _cchange[ _i ], _node[ _i ],
              _startstck[ _i ], _ccolin[ _i ],
              _keep_dtype[ _i ], _keep_dtype[ 1 ], e);
        IF  _i = 1
        THEN
            _startstck[ _i+1 ] := _startstck[ _i+1 ] +
                  _startstck[ _i ] - _startstack;
        (*ENDIF*) 
        END;
    UNTIL
        (e <> e_ok) OR (_i = 3);
    (*ENDREPEAT*) 
    END;
&ifdef trace
(*ENDIF*) 
t01int4(ak_sem, 'operator    ',ord(operator));
t01int4(ak_sem, 'first_node  ',first_node);
&endif
IF  _both_const_expr AND (dmli.d_param_st_index <> 0) AND
    (acv.a_mblock.mb_qual^.mfirst_free - _st_begin > 2)
THEN
    a651const_between_expression( acv, dmli, _st_begin, operator)
ELSE
    a65_set_operator (acv, operator);
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65boolean_term (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR first_node : integer;
            mtabs_allowed  : boolean;
            VAR list_info  : list_elem_info);
 
VAR
      _snot_bool     : boolean;
      _act_node      : integer;
      _oldjoincnt    : integer;
      _stentryno     : integer;
 
BEGIN
IF  g01userstackoverflow
THEN
    a07_b_put_error (acv, e_program_stack_overflow, 1);
(*ENDIF*) 
IF  acv.a_returncode = 0
THEN
    BEGIN
    _act_node := first_node;
    _snot_bool := ak65subq_se (acv, first_node);
    WITH acv.a_ap_tree^[ first_node ] DO
        IF  n_symb = s_or
        THEN
            BEGIN
            IF  mtabs_allowed
            THEN
                dmli.d_first_tab := 0;
            (*ENDIF*) 
            ak65se_condition (acv, dmli, first_node,
                  NOT c_mtabs_allowed, list_info)
            END
        ELSE
            IF  n_symb <> s_and
            THEN
                BEGIN
                ak65predicate (acv, dmli, _act_node, mtabs_allowed,
                      list_info);
                _snot_bool  := false;
                first_node := _act_node
                END
            ELSE
                BEGIN
                _act_node := n_lo_level;
                IF  (dmli.d_join AND _snot_bool)
                THEN
                    WITH dmli DO
                        BEGIN
                        IF  mtabs_allowed
                        THEN
                            d_first_tab := 0;
                        (*ENDIF*) 
                        _oldjoincnt := d_joins.jrc_cnt;
                        ak65predicate (acv, dmli, _act_node,
                              NOT c_mtabs_allowed, list_info);
                        _stentryno := acv.a_mblock.mb_qual^.mfirst_free;
                        IF  _stentryno >= 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
                            acv.a_mblock.mb_qual^.mqual_cnt   :=
                                  succ(acv.a_mblock.mb_qual^.mqual_cnt);
                            acv.a_mblock.mb_qual^.mfirst_free :=
                                  succ(acv.a_mblock.mb_qual^.mfirst_free);
                            _act_node := acv.a_ap_tree^[ _act_node ].n_sa_level;
                            ak65predicate (acv, dmli, _act_node,
                                  NOT c_mtabs_allowed, list_info);
                            a65_set_operator (acv, op_and);
                            a61_set_jump (acv.a_mblock, _stentryno, st_jump_false)
                            END;
                        (*ENDIF*) 
                        IF  d_joins.jrc_cnt > _oldjoincnt
                        THEN
                            BEGIN
                            d_joins.jrc_cnt     := _oldjoincnt;
                            WITH d_joins, jrc_joinarr[ jrc_cnt ] DO
                                BEGIN
                                ak65init_one_join(jrc_joinarr[ jrc_cnt ]);
                                END
                            (*ENDWITH*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDWITH*) 
                ELSE
                    BEGIN
                    ak65predicate (acv, dmli, _act_node, mtabs_allowed,
                          list_info);
                    _stentryno := acv.a_mblock.mb_qual^.mfirst_free;
                    IF  _stentryno >= 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
                        acv.a_mblock.mb_qual^.mqual_cnt   :=
                              succ(acv.a_mblock.mb_qual^.mqual_cnt);
                        acv.a_mblock.mb_qual^.mfirst_free :=
                              succ(acv.a_mblock.mb_qual^.mfirst_free);
                        _act_node := acv.a_ap_tree^[ _act_node ].n_sa_level;
                        IF  dmli.d_join
                        THEN
                            WITH dmli.d_joins, jrc_joinarr[ jrc_cnt ] DO
                                IF  jo_no_join
                                THEN
                                    BEGIN
                                    ak65init_one_join(jrc_joinarr[ jrc_cnt ]);
                                    END;
                                (*ENDIF*) 
                            (*ENDWITH*) 
                        (*ENDIF*) 
                        ak65predicate (acv, dmli, _act_node,
                              mtabs_allowed, list_info);
                        a65_set_operator (acv, op_and);
                        a61_set_jump (acv.a_mblock, _stentryno, st_jump_false);
                        IF  dmli.d_join
                        THEN
                            WITH dmli.d_joins, jrc_joinarr[ jrc_cnt ] DO
                                IF  jo_no_join
                                THEN
                                    BEGIN
                                    jo_no_join             := false;
                                    jo_partno              := 1;
                                    jo_recs[ 1 ].jop_tableno    := 0;
                                    jo_recs[ 2 ].jop_tableno    := 0;
                                    jo_recs[ 1 ].jop_outer_join := false;
                                    jo_recs[ 2 ].jop_outer_join := false;
                                    END;
                                (*ENDIF*) 
                            (*ENDWITH*) 
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDWITH*) 
    IF  _snot_bool
    THEN
        a65_set_operator (acv, op_not)
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65compare_predicate (
            VAR acv       : tak_all_command_glob;
            VAR dmli      : tak_dml_info;
            VAR colin     : tak00_scolinf;
            first_node    : integer;
            VAR snot_pred : boolean;
            field_found   : tsp00_Int2;
            VAR list_info : list_elem_info);
 
VAR
      _any             : boolean;
      _all             : boolean;
      _s_special_expr  : boolean;
      _sel_n           : integer;
      _expr_n          : integer;
      _cnt_expr        : integer;
      _dummy_iolen     : tsp00_Int2;
      _convert_t       : tak_convert_type;
      _operator        : tgg00_StackOpType;
      _check_type      : tsp00_DataType;
      _ix              : integer;
      _keep_dtype      : ARRAY[ 1..2 ] OF tsp00_DataType;
      _startstck       : ARRAY[ 1..2 ] OF integer;
      _node            : ARRAY[ 1..2 ] OF integer;
      _ccolin          : ARRAY[ 1..2 ] OF tak00_scolinf;
      _cchange         : ARRAY[ 1..2 ] OF boolean;
      _nochange        : boolean;
      _types_ok        : boolean;
      _helpbuf         : tak00_colinfo_ptr;
      _e               : tgg00_BasisError;
      _val_const       : boolean;
      _level_node      : tsp00_Int2;
      _list_node       : tsp00_Int2;
      _list_cnt        : integer;
      _dm_datatype     : tsp00_DataType;
      _st_begin        : tsp00_Int2;
      _expr_st_cnt     : tsp00_Int2;
 
BEGIN
&ifdef trace
t01int4(ak_sem, 'field_found ', field_found );
&endif
WITH acv.a_ap_tree^[ first_node ] DO
    BEGIN
    IF  snot_pred
    THEN
        CASE n_symb OF
            s_equal :
                BEGIN
                _operator := op_ne;
                (* *** PTS 2302
                      IF  (n_subproc = cak_x_left_outer_join) OR
                      (n_subproc = cak_x_full_outer_join) OR
                      (n_subproc = cak_x_right_outer_join)
                      THEN
                      n_subproc := 0;
                      *** *)
                END;
            s_greater :
                _operator := op_le;
            s_greater_or_eq :
                _operator := op_lt;
            s_less :
                _operator := op_ge;
            s_less_or_eq :
                _operator := op_gt;
            s_unequal :
                _operator := op_eq;
            s_is_null :
                _operator := op_not_null;
            s_is_not_null :
                _operator := op_null;
            s_is_true :
                _operator := op_false;
            s_is_false :
                _operator := op_true;
            END
        (*ENDCASE*) 
    ELSE
        CASE n_symb OF
            s_equal :
                _operator := op_eq;
            s_greater :
                _operator := op_gt;
            s_greater_or_eq :
                _operator := op_ge;
            s_less :
                _operator := op_lt;
            s_less_or_eq :
                _operator := op_le;
            s_unequal :
                _operator := op_ne;
            s_is_null :
                _operator := op_null;
            s_is_not_null :
                _operator := op_not_null;
            s_is_true :
                _operator := op_true;
            s_is_false :
                _operator := op_false;
            END;
        (*ENDCASE*) 
    (*ENDIF*) 
    _s_special_expr := acv.a_special_expr;
    IF  dmli.d_join AND ((acv.a_outer_join OR dmli.d_outer_join) OR dmli.d_view)
    THEN
        WITH dmli.d_joins, jrc_joinarr[ jrc_cnt ] DO
            BEGIN
            CASE acv.a_ap_tree^[ first_node ].n_subproc OF
                cak_x_left_outer_join,
                cak_x_right_outer_join,
                cak_x_full_outer_join :
                    (* compare a65_set_operator *)
                    acv.a_special_expr := true;
                OTHERWISE
                    BEGIN
                    END;
                END;
            (*ENDCASE*) 
&           ifdef trace
            t01int4 (ak_sem, 'first_node  ', first_node);
            t01int4 (ak_sem, 'jrc_cnt     ', jrc_cnt);
            t01int4 (ak_sem, 'acv_outer_jo', ord (acv.a_outer_join));
            t01int4 (ak_sem, 'dm_outer_joi', ord (dmli.d_outer_join));
            WITH  jo_recs[ 1 ] DO
                t01int4 (ak_sem, 'jop_tablen 1', jop_tableno);
            (*ENDWITH*) 
            WITH  jo_recs[ 2 ] DO
                t01int4 (ak_sem, 'jop_tablen 2', jop_tableno);
            (*ENDWITH*) 
            CASE acv.a_ap_tree^[ first_node ].n_subproc OF
                cak_x_left_outer_join :
                    t01int4 (ak_syn, 'l OUTER JOIN', cak_x_left_outer_join);
                cak_x_right_outer_join :
                    t01int4 (ak_syn, 'r OUTER JOIN', cak_x_right_outer_join);
                cak_x_full_outer_join :
                    t01int4 (ak_syn, 'f OUTER JOIN', cak_x_full_outer_join);
                OTHERWISE
                    BEGIN
                    END;
                END;
            (*ENDCASE*) 
&           endif
            IF  (jo_recs[ 2 ].jop_tableno <> cak68_join_value)
            THEN
                CASE acv.a_ap_tree^[ first_node ].n_subproc OF
                    cak_x_left_outer_join :
                        BEGIN
                        jo_recs[ 1 ].jop_outer_join := true;
                        jo_recs[ 2 ].jop_outer_join := false;
                        END;
                    cak_x_right_outer_join :
                        BEGIN
                        jo_recs[ 1 ].jop_outer_join := false;
                        jo_recs[ 2 ].jop_outer_join := true;
                        END;
                    cak_x_full_outer_join :
                        BEGIN
                        jo_recs[ 1 ].jop_outer_join := true;
                        jo_recs[ 2 ].jop_outer_join := true;
                        END;
                    OTHERWISE
                        BEGIN
                        jo_recs[ 1 ].jop_outer_join := false;
                        jo_recs[ 2 ].jop_outer_join := false;
                        END;
                    END
                (*ENDCASE*) 
            ELSE
                CASE acv.a_ap_tree^[ first_node ].n_subproc OF
                    cak_x_left_outer_join,
                    cak_x_right_outer_join,
                    cak_x_full_outer_join :
                        BEGIN
                        jo_recs[ 1 ].jop_outer_join := true;
                        jo_recs[ 2 ].jop_outer_join := false;
                        END;
                    OTHERWISE
                        BEGIN
                        jo_recs[ 1 ].jop_outer_join := false;
                        jo_recs[ 2 ].jop_outer_join := false;
                        END;
                    END;
                (*ENDCASE*) 
            (*ENDIF*) 
            acv.a_outer_join  := acv.a_outer_join OR
                  jo_recs[ 1 ].jop_outer_join OR
                  jo_recs[ 2 ].jop_outer_join;
            IF  NOT dmli.d_outer_join
            THEN
                dmli.d_outer_join := acv.a_outer_join;
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
    (*ENDIF*) 
    _val_const     := false;
    _check_type    := dunknown;
    _ix            := 1;
    _sel_n         := acv.a_ap_tree^[ first_node ].n_lo_level;
    _node[ _ix ]    := _sel_n;
    _cchange[ _ix ] := (dmli.d_datatype in [ ddate,dtime,dtimestamp ]);
    IF  _cchange[ _ix ]
    THEN
        _check_type := dmli.d_datatype;
    (*ENDIF*) 
    _startstck[ _ix ]  := acv.a_mblock.mb_qual^.mfirst_free;
    _keep_dtype[ _ix ] := dmli.d_datatype;
    _helpbuf          := dmli.d_colptr;
    _ccolin[ _ix ]     := colin;
    IF  (dmli.d_datatype <> dboolean) AND (n_symb in [s_is_false, s_is_true])
    THEN
        a07_b_put_error (acv, e_incompatible_datatypes,
              acv.a_ap_tree^[ _sel_n ].n_pos);
    (*ENDIF*) 
    IF  acv.a_ap_tree^[ _node[ _ix ] ].n_symb in [ s_string_literal,
        (* PTS 1111797 E.Z. *)
        s_uid, s_user, s_usergroup, s_sysdba ]
    THEN
        _val_const := true;
    (*ENDIF*) 
    IF  acv.a_ap_tree^[ _sel_n ].n_symb = s_authid
    THEN
        _sel_n := acv.a_ap_tree^[ _sel_n ].n_sa_level;
    (*ENDIF*) 
    IF  acv.a_ap_tree^[ _sel_n ].n_symb = s_tablename
    THEN
        _sel_n := acv.a_ap_tree^[ _sel_n ].n_sa_level;
    (*ENDIF*) 
    _sel_n := acv.a_ap_tree^[ _sel_n ].n_sa_level;
&   ifdef trace
    t01int4 (ak_sem, 'node       4', _node[ _ix ]);
    t01int4 (ak_sem, 'd_datatype 4', ord (dmli.d_datatype));
    t01int4 (ak_sem, 'startstack 4', _startstck[ _ix ]);
    t01int4 (ak_sem, 'colin.typ  4', ord(_ccolin[ _ix ].sci_typ));
&   endif
    _ix                 := succ(_ix);
    _node[ _ix ]         := _sel_n;
    _st_begin           := acv.a_mblock.mb_qual^.mfirst_free;
    dmli.d_const_value_expr := ( acv.a_is_ddl = no_ddl);
    IF  (acv.a_ap_tree^[ _sel_n ].n_proc = a63query_spec)
        OR
        ((acv.a_ap_tree^[ _sel_n ].n_proc = a63) AND
        (acv.a_ap_tree^[ _sel_n ].n_subproc = cak_x_start_union))
        OR
        (acv.a_ap_tree^[ _sel_n ].n_symb = s_all)
        OR
        (acv.a_ap_tree^[ _sel_n ].n_symb = s_any)
        OR
        ((acv.a_ap_tree^[ _sel_n ].n_proc = a56) AND
        ( acv.a_ap_tree^[ _sel_n ].n_subproc = cak_x_value_list))
    THEN
        BEGIN
        IF  dmli.d_join
        THEN
            WITH dmli.d_joins, jrc_joinarr[ jrc_cnt ] DO
                IF  jo_no_join
                THEN
                    dmli.d_arith_where := true;
                (*ENDIF*) 
            (*ENDWITH*) 
        (*ENDIF*) 
        IF  acv.a_ap_tree^[ _sel_n ].n_symb = s_all
        THEN
            BEGIN
            _all   := true;
            _any   := false;
            _sel_n := acv.a_ap_tree^[ _sel_n ].n_sa_level;
            END
        ELSE
            IF  acv.a_ap_tree^[ _sel_n ].n_symb = s_any
            THEN
                BEGIN
                _all := false;
                _any := true;
                _sel_n := acv.a_ap_tree^[ _sel_n ].n_sa_level
                END
            ELSE
                BEGIN
                _all := false;
                _any := false;
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  snot_pred AND (_all OR _any) AND (list_info.count > 1)
        THEN
            BEGIN
            _all := NOT _all;
            _any := NOT _any;
            END;
        (*ENDIF*) 
        IF  (acv.a_ap_tree^[ _sel_n ].n_proc = a63query_spec)
            OR
            ((acv.a_ap_tree^[ _sel_n ].n_proc = a63) AND
            ( acv.a_ap_tree^[ _sel_n ].n_subproc = cak_x_start_union))
        THEN (* the right side of the compare operation is a subquery. *)
            BEGIN
&           ifdef TRACE
            t01int4 (ak_sem, 'd_use_sub 65', ord(dmli.d_use_sub));
            t01int4 (ak_sem, 'd_datatype  ', ord(dmli.d_datatype));
&           endif
            (* The datatypes of the selected columns are stored in a *)
            (* node list starting at the same_level of first_node.   *)
            IF  NOT dmli.d_use_sub
            THEN      (* In a corelated subquery (or the like) we  *)
                BEGIN (* have to construct the datatype list here. *)
                _list_node := _sel_n;
                _list_cnt  := 0;
                WHILE _list_cnt < list_info.count DO
                    BEGIN
                    _list_cnt  := succ (_list_cnt);
                    IF  _cchange[ 1 ]
                    THEN
                        BEGIN
                        a65ch_format (acv, dmli, _startstck[ 1 ],
                              _ccolin[1], dcha, dmli.d_datatype);
                        list_info.elem[_list_cnt].inout_len :=
                              succ (_ccolin[1].sci_len) (* incl. def-byte *)
                        END;
                    (* PTS 1000985/1001162 E.Z. *)
                    (*ENDIF*) 
                    IF  acv.a_ap_tree^[ _list_node ].n_sa_level > 0
                    THEN
                        BEGIN
                        _level_node  := acv.a_ap_tree^[ _list_node ].n_sa_level;
                        _dm_datatype := list_info.elem[_list_cnt].datatype;
&                       ifdef TRACE
                        t01int4 (ak_sem, 'd_datatype  ', ord(_keep_dtype[_ix]));
                        t01int4 (ak_sem, 'dm_datatype ', ord(_dm_datatype));
&                       endif
                        _types_ok := a65_datatypes_ok (acv, dmli,
                              acv.a_ap_tree^[ _level_node ].n_datatype,
                              acv.a_ap_tree^[ _level_node ].n_length,
                              _dm_datatype,
                              c_is_subquery, _sel_n, list_info.elem[ _list_cnt ].pos,
                              (list_info.count = 1), _convert_t);
                        IF  (_convert_t <> conv_none) AND
                            (list_info.count <> 1)
                        THEN
                            a07_b_put_error (acv, e_incompatible_datatypes,
                                  list_info.elem[ _list_cnt ].pos);
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        WITH list_info.elem[_list_cnt] DO
                            a01_dt_put_datatype_node (acv, _level_node,
                                  datatype, datalen, datafrac, inout_len);
                        (*ENDWITH*) 
                        acv.a_ap_tree^[ _list_node  ].n_sa_level := _level_node;
                        END;
                    (*ENDIF*) 
&                   ifdef trace
                    WITH acv.a_ap_tree^[ _level_node ] DO
                        BEGIN
                        t01int4 (ak_sem, 'list#       ', _list_cnt);
                        t01int4 (ak_sem, 'type(list#) ', ord (n_datatype));
                        t01int4 (ak_sem, 'len(list#)  ', n_length)
                        END;
                    (*ENDWITH*) 
&                   endif
                    _list_node := _level_node
                    END;
                (*ENDWHILE*) 
                _types_ok := true
                END
            ELSE      (* In an ordinary subquery we can use the information *)
                BEGIN (* of the datatype list for checking of column types. *)
                _list_node := acv.a_ap_tree^[ _sel_n ].n_sa_level;
                _list_cnt  := 0;
                WHILE (_list_node <> 0) AND (acv.a_returncode = 0) DO
                    WITH acv.a_ap_tree^[ _list_node ] DO
                        BEGIN
                        _list_cnt       := succ (_list_cnt);
                        _dm_datatype    := list_info.elem[_list_cnt].datatype;
&                       ifdef TRACE
                        t01int4 (ak_sem, 'd_datatype  ', ord(_keep_dtype[_ix]));
                        t01int4 (ak_sem, 'dm_datatype ', ord(_dm_datatype));
&                       endif
                        (* PTS 1000985/1001162 E.Z. *)
                        _types_ok := a65_datatypes_ok (acv, dmli,
                              n_datatype, n_length, _dm_datatype,
                              c_is_subquery,
                              _sel_n, list_info.elem[ _list_cnt ].pos,
                              (list_info.count = 1), _convert_t);
                        IF  _types_ok AND _cchange[ 1 ] AND (list_info.count = 1)
                        THEN
                            a65ch_format (acv, dmli, _startstck[ 1 ],
                                  _ccolin[1], _keep_dtype[1], _dm_datatype);
                        (*ENDIF*) 
                        _list_node := acv.a_ap_tree^[ _list_node ].n_sa_level
                        END
                    (*ENDWITH*) 
                (*ENDWHILE*) 
                END;
            (*ENDIF*) 
            IF  (acv.a_returncode = 0) AND _types_ok
            THEN
                BEGIN
                IF  ((field_found > 0) AND
                    (_operator =  op_eq))
                THEN
                    IF  ctmulti in dmli.d_colbuf^.ccolpropset
                    THEN
                        WITH acv.a_mblock.mb_qual^, acv.a_mblock.mb_st^ [field_found] DO
                            ecol_tab[ 2 ] :=
                                  chr( ord (ecol_tab[ 2 ]) + 100);
                        (*ENDWITH*) 
                    (*ENDIF*) 
                (*ENDIF*) 
                IF  (list_info.count = 1) AND NOT _all AND NOT _any
                THEN
                    BEGIN
                    a65subq_get_val (acv, _sel_n, _ccolin[1].sci_iolen);
                    a65_set_operator (acv, _operator);
                    END
                ELSE
                    ak65sub_op_set (acv, _all, _any, _operator, _sel_n);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            _expr_n := _sel_n;
&           ifdef TRACE
            t01int4 (ak_sem, 'expr_n      ', _expr_n);
            t01int4 (ak_sem, '.n_proc     ', ord (n_proc));
            t01int4 (ak_sem, '.n_subproc  ', ord (n_subproc));
&           endif
            WITH acv.a_ap_tree^[ _expr_n ] DO
                IF  (n_proc = a56) AND (n_subproc = cak_x_value_list)
                THEN      (* Here comes a list of lists, and each *)
                    BEGIN (* elem can have a different datatype.  *)
                    _list_node := n_sa_level;
                    _expr_n    := n_lo_level;
                    _list_cnt  := 1
                    END
                ELSE      (* Here comes a list of expressions, *)
                    BEGIN (* and all are of the same datatype. *)
                    _list_cnt  := 0;
                    _list_node := 0
                    END;
                (*ENDIF*) 
            (*ENDWITH*) 
            _cnt_expr := 0;
            _helpbuf  := dmli.d_colptr;
            REPEAT
                colin.sci_len := 0;
                IF  _list_cnt > 0
                THEN      (* In a list each value can have its own   *)
                    BEGIN (* datatype, which is stored in list_info. *)
                    dmli.d_datatype := list_info.elem[ _list_cnt ].datatype;
                    dmli.d_colptr   := NIL (* Here we don't know anything. *)
                    END
                ELSE
                    dmli.d_colptr := _helpbuf;
                (*ENDIF*) 
                a65_val_expr (acv, dmli, colin,
                      acv.a_ap_tree^[ _expr_n ].n_lo_level);
                _cnt_expr := succ (_cnt_expr);
                _expr_n   := acv.a_ap_tree^[ _expr_n ].n_sa_level;
                IF  (_expr_n  = 0) AND (_list_node <> 0)
                THEN (* There is still another list of lists. *)
                    WITH acv.a_ap_tree^[ _list_node ] DO
                        BEGIN
                        _expr_n    := n_lo_level;
                        _list_node := n_sa_level;
                        _list_cnt  := 1
                        END
                    (*ENDWITH*) 
                ELSE
                    IF  (_list_cnt > 0) AND (_expr_n > 0)
                    THEN (* next elem of a list of lists. *)
                        _list_cnt := succ (_list_cnt);
                    (*ENDIF*) 
                (*ENDIF*) 
            UNTIL
                _expr_n = 0;
            (*ENDREPEAT*) 
            ak65set_mass_cmp (acv, _operator, _all, _cnt_expr, list_info.count)
            END;
        (*ENDIF*) 
        IF  dmli.d_join
        THEN
            WITH dmli.d_joins, jrc_joinarr[ jrc_cnt ], jo_recs[ 2 ], acv.a_mblock.mb_qual^ DO
                BEGIN
                IF  acv.a_outer_join OR dmli.d_outer_join
                THEN
                    BEGIN
                    (* create an entry in join_arr for outer join handling *)
                    jo_partno      := 2;
                    jo_op          := op_ne;
                    jop_tableno    := 0;
                    jop_startstack := _st_begin;
                    jop_cntstack   := mfirst_free-jop_startstack;
                    jop_propset    := [];
                    jop_inoutlen   := 0;
                    END;
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  ((field_found > 0) AND
            (_operator in [ op_eq, op_ne, op_null, op_gt, op_ge, op_lt, op_le ]))
        THEN
            IF  ctmulti in dmli.d_colbuf^.ccolpropset
            THEN
                WITH acv.a_mblock.mb_st^[ field_found ] DO
                    ecol_tab[ 2 ] := chr (ord (ecol_tab[ 2 ]) + 100);
                (*ENDWITH*) 
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (((acv.a_ap_tree^[ _sel_n ].n_symb in
            [ s_plus, s_minus, s_mult, s_divide,
            s_div, s_mod ]) AND (acv.a_ap_tree^[_sel_n ].n_proc = a64))
            OR
            (acv.a_ap_tree^[ _sel_n ].n_proc = a641))
            OR
            ((_check_type <> dunknown) AND
            ((acv.a_ap_tree^[ _sel_n ].n_proc <> no_proc) OR
            ( acv.a_ap_tree^[ _sel_n ].n_symb <> s_default)))
        THEN
            dmli.d_colptr := NIL;
        (*ENDIF*) 
        colin.sci_len := 0;
        IF  dmli.d_datatype <> dunicode
        THEN
            (* otherwise unicode = timestamp will not do format_change *)
            dmli.d_change_date_time := false;
        (*ENDIF*) 
        IF  (g01unicode AND
            (dmli.d_datatype in [ ddate, dtime, dtimestamp ]) AND
            (acv.a_ap_tree^[ _sel_n ].n_symb = s_string_literal))
        THEN
            dmli.d_datatype := dcha
        ELSE
            IF  NOT (
                ((acv.a_ap_tree^[ _sel_n ].n_proc = a641) AND
                ( acv.a_ap_tree^[ _sel_n ].n_symb in [s_addtime, s_subtime, s_adddate, s_subdate]))
                OR
                ((acv.a_ap_tree^[ _sel_n ].n_proc = no_proc) AND
                ((acv.a_ap_tree^[ _sel_n ].n_symb = s_now) OR (acv.a_ap_tree^[ _sel_n ].n_symb = s_null)))
                )
            THEN
                dmli.d_datatype := dunknown;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  dmli.d_join (* PTS 1113327 *)
        THEN
            WITH dmli.d_joins, jrc_joinarr[ jrc_cnt ], jo_recs[ 2 ], acv.a_mblock.mb_qual^ DO
                BEGIN
                jo_op          := _operator;
                jop_startstack := mfirst_free;
                jo_partno      := 2;
&               ifdef trace
                t01op(ak_sem, 'set join op ', _operator );
                t01int4 (ak_sem, 'jop_startsta', mfirst_free);
                t01sname(ak_sem, 'next side   ');
&               endif
                IF  (((acv.a_ap_tree^[ _sel_n ].n_symb in
                    [ s_plus, s_minus, s_mult, s_divide,
                    s_div, s_mod ]) AND (acv.a_ap_tree^[_sel_n ].n_proc = a64))
                    OR
                    (acv.a_ap_tree^[ _sel_n ].n_proc = a641))
                THEN
                    dmli.d_colptr := NIL;
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        a65_val_expr (acv, dmli, colin, _sel_n);
        IF  acv.a_returncode = cak_e_parameter
        THEN
            BEGIN
            _val_const := true;
            dmli.d_datatype := _keep_dtype[ _ix-1 ];
            acv.a_returncode := 0;
            dmli.d_colptr := _helpbuf;
            a65_val_expr (acv, dmli, colin, _sel_n);
            END
        ELSE
            IF  acv.a_ap_tree^[ _node[ _ix ] ].n_symb in [ s_string_literal,
                (* PTS 1111797 E.Z. *)
                s_uid, s_user, s_usergroup, s_sysdba ]
            THEN
                _val_const := true;
            (* PTS 1120680 E.Z. *)
            (*ENDIF*) 
        (*ENDIF*) 
        IF  acv.a_returncode = cak_e_parameter
        THEN
            BEGIN
            acv.a_returncode := 0;
            a07_b_put_error (acv, e_without_datatypes,
                  acv.a_ap_tree^[ _sel_n ].n_pos);
            END;
        (*ENDIF*) 
        _cchange[ _ix ] := (dmli.d_datatype in [ ddate,dtime,dtimestamp ]);
        IF  _cchange[ _ix ]
        THEN
            IF  _check_type = dunknown
            THEN
                _check_type := dmli.d_datatype
            ELSE
                IF  _check_type <> dmli.d_datatype
                THEN
                    a07_b_put_error (acv, e_incompatible_datatypes,
                          acv.a_ap_tree^[ _node[ _ix ] ].n_pos);
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
        _keep_dtype[ _ix ] := dmli.d_datatype;
        _ccolin[ _ix ] := colin;
        _startstck[ _ix ] := acv.a_mblock.mb_qual^.mfirst_free;
&       ifdef trace
        t01int4 (ak_sem, 'node       5', _node[ _ix ]);
        t01int4 (ak_sem, 'd_datatype 5', ord (dmli.d_datatype));
        t01int4 (ak_sem, 'startstack 5', _startstck[ _ix ]);
        t01int4 (ak_sem, 'colin.typ  5', ord(_ccolin[ _ix ].sci_typ));
&       endif
        _nochange := false;
        _nochange := (_cchange[ 1 ] AND _cchange[ 2 ]);
        _nochange := (_cchange[ 1 ] OR _cchange[ 2 ]) AND
              (NOT _nochange);
        _dummy_iolen := 0;
        IF  acv.a_returncode = 0
        THEN
            (* PTS 1000985/1001162 E.Z. *)
            IF  NOT a65_datatypes_ok (acv, dmli, _keep_dtype[ 1 ], _dummy_iolen,
                _keep_dtype[ 2 ], NOT c_is_subquery,
                _node[ 2 ], acv.a_ap_tree^[ _node[ 2 ]].n_pos,
                NOT _nochange, _convert_t)
            THEN
                _nochange := false
                      (* PTS 1124037 E.Z. *)
            ELSE
                IF  (_convert_t <> conv_none) AND
                    (dmli.d_param_st_index = 0)
                THEN
                    BEGIN
                    CASE _convert_t OF
                        conv_ascii_to_num, conv_unicode_to_num :
                            colin.sci_iolen := succ(mxsp_number);
                        conv_num_to_ascii :
                            colin.sci_iolen := succ(colin.sci_len + 6);
                        conv_num_to_unicode :
                            colin.sci_iolen := succ(2 * (colin.sci_len + 6));
                        conv_ascii_to_unicode :
                            colin.sci_iolen := succ(2 * colin.sci_len);
                        conv_unicode_to_ascii  :
                            colin.sci_iolen := succ(colin.sci_len);
                        OTHERWISE
                            BEGIN
                            END
                        END;
                    (*ENDCASE*) 
                    IF  dmli.d_const_value_expr AND NOT dmli.d_group AND
                        (acv.a_returncode = 0)
                    THEN
                        a651value_calculate ( acv, _st_begin,
                              acv.a_mblock.mb_qual^.mfirst_free - 1,
                              colin.sci_typ = dchb, dmli. d_like,
                              colin.sci_iolen,
                              acv.a_ap_tree^[ _node[ _ix ] ].n_pos);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (dmli.d_datatype = dudt) AND (acv.a_returncode = 0)
        THEN
            a07_b_put_error (acv, e_incompatible_datatypes,
                  acv.a_ap_tree^[ _node[ _ix ] ].n_pos);
        (*ENDIF*) 
        IF  _nochange AND (acv.a_returncode = 0)
        THEN
            BEGIN
            _ix := 0;
            _e  := e_ok;
            REPEAT
                BEGIN
                _ix    := succ(_ix);
                IF  _ix = 2
                THEN
                    _startstck[ _ix ] := acv.a_mblock.mb_qual^.mfirst_free;
                (*ENDIF*) 
                IF  _val_const
                THEN
                    _cchange[ _ix ] := false;
                (*ENDIF*) 
                ak65check_change (acv, dmli, _check_type, _cchange[ _ix ], _node[ _ix ],
                      _startstck[ _ix ], _ccolin[ _ix ], _keep_dtype[ _ix ], _keep_dtype[ 1 ], _e);
                END;
            UNTIL
                (_e <> e_ok) OR (_ix = 2);
            (*ENDREPEAT*) 
            IF  _convert_t <> conv_none
            THEN
                a65_convert (acv, _convert_t, _ccolin[ _ix ].sci_iolen);
            (*ENDIF*) 
            IF  (_cchange[ 1 ] AND dmli.d_join) AND
                NOT(_operator in [ op_null, op_not_null ])
            THEN
                WITH dmli.d_joins, jrc_joinarr[ jrc_cnt ], jo_recs[ 1 ] DO
                    BEGIN
                    jop_cntstack := succ(jop_cntstack);
                    jop_propset  := [  ];
                    WITH _ccolin[ 1 ] DO
                        BEGIN
                        jop_datatyp  := sci_typ;
                        IF  sci_iolen >= mxsp_key - sizeof (tsp00_Int4)
                        THEN
                            BEGIN
                            jop_inoutlen := 0;
                            END
                        ELSE
                            BEGIN
                            jop_inoutlen := sci_iolen;
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDWITH*) 
                    END;
                (*ENDWITH*) 
            (*ENDIF*) 
            END;
        (* PTS 1113318 E.Z. *)
        (*ENDIF*) 
        IF  dmli.d_join AND dmli.d_outer_join AND (_operator in [ op_null, op_not_null ])
            (* PTS 1113327 *)
            AND NOT dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_recs[ 1 ].jop_outer_join
        THEN
            dmli.d_arith_where := true;
        (*ENDIF*) 
        IF  dmli.d_join AND NOT(_operator in [ op_null, op_not_null ])
        THEN
            WITH dmli.d_joins, jrc_joinarr[ jrc_cnt ], jo_recs[ 2 ], acv.a_mblock.mb_qual^ DO
                BEGIN
                IF  jo_no_join
                THEN
                    dmli.d_arith_where := true
                ELSE
                    IF  ((jop_tableno <> 0) AND
                        (jo_recs[ 1 ].jop_tableno <> 0) AND
                        NOT jo_no_join)
                    THEN
                        IF  (jo_recs[ 1 ].jop_inoutlen <> 0)
                        THEN
                            BEGIN
                            jop_cntstack := mfirst_free-jop_startstack;
                            jop_outpos   := 0;
                            IF  ((jop_cntstack > 1) OR
                                NOT (acv.a_mblock.mb_st^ [jop_startstack].eop in
                                [ op_none, op_unique, op_unique_desc,
                                op_order_asc, op_order_desc ]))
                            THEN
                                BEGIN
                                IF  NOT ((jop_cntstack = 1) AND
                                    (acv.a_mblock.mb_st^ [jop_startstack].eop
                                    = op_ascii))
                                THEN
                                    jop_propset := [  ];
                                (*ENDIF*) 
                                WITH _ccolin[ 2 ] DO
                                    BEGIN
                                    CASE _convert_t OF
                                        conv_unicode_to_ascii:
                                            sci_typ := dcha;
                                        conv_ascii_to_unicode:
                                            BEGIN
                                            sci_typ := dunicode;
                                            sci_iolen := (2*sci_len) + 1
                                            END;
                                        OTHERWISE
                                            BEGIN
                                            END
                                        END;
                                    (*ENDCASE*) 
                                    jop_datatyp  := sci_typ;
                                    IF  sci_iolen >= mxsp_key -
                                        sizeof (tsp00_Int4)
                                    THEN
                                        BEGIN
                                        jop_inoutlen := 0;
                                        a07_b_put_error (acv, e_join_fields_too_long, 1);
                                        END
                                    ELSE
                                        BEGIN
                                        jop_inoutlen := sci_iolen;
                                        END;
                                    (*ENDIF*) 
                                    END;
                                (*ENDWITH*) 
                                IF  jop_datatyp in [ dfixed,
                                    dfloat, dvfloat ]
                                THEN
                                    BEGIN
                                    jop_datatyp  := dfloat;
                                    jop_inoutlen := NUMBER_MXGG04;
                                    END
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                            END
                        ELSE
                            a07_b_put_error (acv, e_join_fields_too_long, 1);
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        IF  (acv.a_returncode = 0)
        THEN
            BEGIN
            _expr_st_cnt := acv.a_mblock.mb_qual^.mfirst_free - _st_begin;
&           ifdef trace
            t01int4 (ak_sem,'st_begin 999',_st_begin);
            t01int4 (ak_sem,'expr_st_cnt ',_expr_st_cnt);
            t01int4 (ak_sem,'d_param_st_i',dmli.d_param_st_index);
            t01int4 (ak_sem,'d_const_valu',ord(dmli.d_const_value_expr));
            t01int4 (ak_sem,'true        ',ord(true));
            t01int4 (ak_sem,'mb_data_len ',acv.a_mblock.mb_data_len );
            t01int4 (ak_sem,'epos        ',
                  acv.a_mblock.mb_st^ [_st_begin].epos);
&           endif
            IF  dmli.d_const_value_expr AND
                (acv.a_mblock.mb_st^ [_st_begin].etype = st_value) AND
                (acv.a_mblock.mb_st^[ _st_begin ].ecol_tab [2] <> chr(0))
            THEN
                acv.a_mblock.mb_st^ [_st_begin].eop := _operator
            ELSE
                a65_set_operator (acv, _operator);
            (*ENDIF*) 
            (* PTS 1128637 E.Z. *)
            IF  ((NOT acv.a_rowno_allowed) AND
                (acv.a_returncode = 0) AND
                (acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mfirst_free-2 ].
                etype = st_rowno))
            THEN
                BEGIN
                WITH acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mfirst_free-1 ] DO
                    BEGIN
                    (* h.b. PTS 1001366 *)
                    IF  eop in [ op_lt, op_le ]
                    THEN
                        BEGIN
                        IF  eop = op_le
                        THEN
                            dmli.d_rowno := epos
                        ELSE
                            dmli.d_rowno := -epos;
                        (*ENDIF*) 
                        END;
                    (* Destroy Rowno- and Value-Stackentries *)
                    (*ENDIF*) 
                    acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mfirst_free-1 ].
                          etype := st_bool;
                    acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mfirst_free-1 ].
                          eop   := op_none;
                    acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mfirst_free-1 ].
                          epos  := 1;
                    acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mfirst_free-2 ].
                          etype := st_dummy;
                    acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mfirst_free-2 ].
                          eop   := op_none;
                    (* PTS 1104018 E.Z. *)
                    acv.a_mblock.mb_data_len :=
                          acv.a_mblock.mb_data_len - colin.sci_iolen + RESNUM_MXSP00;
                    END;
                (*ENDWITH*) 
                acv.a_rowno_allowed := true
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  ((_operator = op_ne) AND NOT _nochange)
        THEN
            ak65ne_handle (acv, dmli, colin, _sel_n);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    acv.a_special_expr := _s_special_expr;
    END;
(*ENDWITH*) 
snot_pred := false; (* We reverted the operator already. *)
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65ne_handle (
            VAR acv       : tak_all_command_glob;
            VAR dmli      : tak_dml_info;
            VAR colin     : tak00_scolinf;
            sel_node      : tsp00_Int4);
 
BEGIN (* h.b. PTS 1106859 *)
IF  (acv.a_mblock.mb_qual^.mfirst_free + 4 <= acv.a_mblock.mb_st_max)
    AND
    (acv.a_mblock.mb_st^[acv.a_mblock.mb_qual^.mfirst_free - 1].
    etype = st_value)
    AND
    (acv.a_mblock.mb_st^[acv.a_mblock.mb_qual^.mfirst_free - 1].eop   = op_ne)
    AND
    (acv.a_mblock.mb_st^[acv.a_mblock.mb_qual^.mfirst_free - 2].etype IN
    [ st_fixkey, st_varkey, st_fixcol, st_varcol ])
    AND
    (acv.a_mblock.mb_st^[acv.a_mblock.mb_qual^.mfirst_free - 2].eop IN
    [ op_order_asc, op_order_desc, op_none ])
    AND
    ((acv.a_mblock.mb_st^[acv.a_mblock.mb_qual^.mfirst_free - 2].
    ecol_tab[ 1 ] > chr(0))   OR
    (acv.a_mblock.mb_st^[acv.a_mblock.mb_qual^.mfirst_free - 2].
    ecol_tab[ 2 ] > chr(100)) OR
    (acv.a_mblock.mb_st^[acv.a_mblock.mb_qual^.mfirst_free - 2].etype in
    [st_fixkey, st_varkey]))
THEN
    BEGIN
    acv.a_mblock.mb_st^[acv.a_mblock.mb_qual^.mfirst_free - 1].eop := op_lt;
    acv.a_mblock.mb_qual^.mfirst_free :=
          succ(acv.a_mblock.mb_qual^.mfirst_free);
    acv.a_mblock.mb_st^[acv.a_mblock.mb_qual^.mfirst_free] :=
          acv.a_mblock.mb_st^[acv.a_mblock.mb_qual^.mfirst_free - 3];
    acv.a_mblock.mb_qual^.mfirst_free :=
          succ(acv.a_mblock.mb_qual^.mfirst_free);
    colin.sci_len               := 0;
    a640not_first_factor (acv, dmli, colin, sel_node);
    acv.a_mblock.mb_st^[acv.a_mblock.mb_qual^.mfirst_free - 1].eop := op_gt;
    acv.a_mblock.mb_qual^.mqual_cnt := acv.a_mblock.mb_qual^.mqual_cnt + 2;
    a65_set_operator (acv, op_or);
    a61_set_jump (acv.a_mblock,
          acv.a_mblock.mb_qual^.mfirst_free - 4, st_jump_true);
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
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);
 
VAR
      _entry_cnt : integer;
 
BEGIN
IF  acv.a_returncode = 0
THEN
    BEGIN
    IF  (acv.a_dt_format = dtf_oracle_date) AND (d_type = dtimestamp)
    THEN
        _entry_cnt := 3
    ELSE
        _entry_cnt := 1;
    (*ENDIF*) 
    IF  acv.a_mblock.mb_qual^.mfirst_free+_entry_cnt-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
        acv.a_date_time_used := true;
        IF  (acv.a_dt_format <> dtf_normal)
        THEN
            BEGIN
            IF  (startstack < acv.a_mblock.mb_qual^.mfirst_free)
            THEN
                SAPDB_PascalOverlappingMove ('VAK65 ',   1,    
                      acv.a_mblock.mb_st_size, acv.a_mblock.mb_st_size,
                      @acv.a_mblock.mb_st^, (startstack-1)*STACK_ENTRY_MXGG00+1,
                      @acv.a_mblock.mb_st^, (startstack+_entry_cnt-1)*STACK_ENTRY_MXGG00+1,
                      (acv.a_mblock.mb_qual^.mfirst_free - startstack) * STACK_ENTRY_MXGG00,
                      acv.a_returncode);
            (*ENDIF*) 
            a61_format_change (acv, dmli, startstack, d_type, colin.sci_len);
            startstack := startstack + _entry_cnt
            END
        ELSE
            CASE d_type OF
                ddate :
                    colin.sci_len := mxsp_date ;
                dtime :
                    colin.sci_len := mxsp_time ;
                dtimestamp :
                    colin.sci_len := mxsp_timestamp ;
                END;
            (*ENDCASE*) 
        (*ENDIF*) 
        colin.sci_iolen := succ(colin.sci_len);
        colin.sci_typ := dcha;
        dmli.d_datatype := dcha;
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65check_change (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            c_type         : tsp00_DataType;
            change         : boolean;
            VAR act_node   : integer;
            VAR startstack : integer;
            VAR colin      : tak00_scolinf;
            d_type         : tsp00_DataType;
            left_type      : tsp00_DataType;
            VAR e          : tgg00_BasisError);
 
VAR
      _alen          : integer;
      _curr_data_pos : tsp00_Int4;
      _re_buf        : tsp00_C28;
 
BEGIN
IF  acv.a_ap_tree^[ act_node ].n_symb IN
    [ s_string_literal, s_uid, s_user,
    (* PTS 1111797 E.Z. *)
    s_usergroup, s_sysdba ]
THEN
    BEGIN
    _alen := acv.a_ap_tree^[ act_node ].n_length;
&   ifdef TRACE
    t01messblock (ak_sem, 'ak65check_c1', acv.a_mblock);
    t01int4 (ak_sem, 'alen        ', _alen);
    t01int4 (ak_sem, 'startstack  ', startstack);
    t01int4 (ak_sem, 'c_type      ', ord (c_type));
    t01int4 (ak_sem, 'n_datatype  ',
          ord (acv.a_ap_tree^[ act_node ].n_datatype));
&   endif
    IF  (acv.a_is_ddl = ddl_create_view) AND
        (c_type in [ ddate, dtime, dtimestamp ])
    THEN
        BEGIN
        a16inc_vdesc_cnt (acv, dmli, acv.a_ptr10);
        IF  acv.a_returncode = 0
        THEN
            WITH acv.a_ptr10^.sviewdesc, vdescription[ vdesc_cnt ] DO
                BEGIN
                vfromtabno    := _alen;
                vfromextcolno := 0;
                vn_pos        := acv.a_ap_tree^[ act_node ].n_pos;
                vextcolno     := 0;
                vdatatype     := c_type
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  g01unicode
    THEN
        _alen := _alen DIV 2;
    (*ENDIF*) 
    CASE c_type OF
        ddate :
            BEGIN
            IF  acv.a_ap_tree^[ act_node ].n_datatype = dtimestamp
            THEN
                a05dfts_date_from_timestamp (acv.a_mblock.mb_data^.mbp_buf, _re_buf,
                      acv.a_mblock.mb_st^ [startstack-1].epos+ 1, sizeof(_re_buf),
                      1, _alen, acv.a_dt_format, acv.a_ak_language,
                      c_ch_code, e)
            ELSE
                g03fdcheck_date (acv.a_mblock.mb_data^.mbp_buf, _re_buf,
                      acv.a_mblock.mb_st^ [startstack-1].epos+ 1,
                      1, _alen, acv.a_dt_format, c_ch_code, e);
            (*ENDIF*) 
            _alen := mxsp_date + 1;
            END;
        dtime :
            BEGIN
            IF  acv.a_ap_tree^[ act_node ].n_datatype = dtimestamp
            THEN
                a05tfts_time_from_timestamp (acv.a_mblock.mb_data^.mbp_buf, _re_buf,
                      acv.a_mblock.mb_st^ [startstack-1].epos+ 1, sizeof(_re_buf),
                      1, _alen, acv.a_dt_format, acv.a_ak_language,
                      c_ch_code, e)
            ELSE
                g03ftcheck_time (acv.a_mblock.mb_data^.mbp_buf, _re_buf,
                      acv.a_mblock.mb_st^ [startstack-1].epos+ 1,
                      1, _alen, acv.a_dt_format, c_ch_code, e);
            (*ENDIF*) 
            _alen := mxsp_time + 1;
            END;
        dtimestamp :
            BEGIN
            IF  acv.a_ap_tree^[ act_node ].n_datatype in [ddate, dtime]
            THEN
                a05tsfdt_timestamp_from_dattim (acv.a_mblock.mb_data^.mbp_buf, _re_buf,
                      acv.a_mblock.mb_st^ [startstack-1].epos+ 1,
                      1,sizeof(_re_buf), _alen, acv.a_dt_format,
                      acv.a_ap_tree^[ act_node ].n_datatype,
                      c_ch_code, e)
            ELSE
                a05timestamp_get (acv, acv.a_mblock.mb_data^.mbp_buf,
                      acv.a_mblock.mb_st^[ startstack-1 ].epos,
                      _re_buf, 1, _alen, c_ch_code, e);
            (*ENDIF*) 
            _alen := mxsp_timestamp + 1;
            END
        OTHERWISE;
        END;
    (*ENDCASE*) 
    IF  e <> e_ok
    THEN
        a07_b_put_error (acv, e, acv.a_ap_tree^[ act_node ].n_pos)
    ELSE
        WITH acv.a_mblock.mb_data^ DO
            IF  acv.a_mblock.mb_data_len + _alen <= acv.a_mblock.mb_data_size
            THEN
                BEGIN
                acv.a_mblock.mb_st^ [startstack-1].epos :=
                      acv.a_mblock.mb_data_len + 1;
                acv.a_mblock.mb_st^ [startstack-1].elen_var := _alen;
                acv.a_mblock.mb_data_len :=
                      succ(acv.a_mblock.mb_data_len);
                _curr_data_pos := acv.a_mblock.mb_data_len;
                mbp_buf [_curr_data_pos] := csp_ascii_blank;
                g10mv ('VAK65 ',   2,    
                      sizeof(_re_buf), acv.a_mblock.mb_data_size,
                      @_re_buf, 1,
                      @mbp_buf, _curr_data_pos+1, _alen-1,
                      acv.a_returncode);
                acv.a_mblock.mb_data_len :=
                      acv.a_mblock.mb_data_len+_alen-1;
                d_type := c_type;
                END
            ELSE
                a07_b_put_error (acv , e_too_many_mb_data, 1);
            (*ENDIF*) 
        (*ENDWITH*) 
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  change AND (e = e_ok)
THEN
    BEGIN
&   ifdef trace
    t01int4 (ak_sem, 'format_chang', act_node);
    t01int4 (ak_sem, 'startstack  ', startstack);
&   endif
    a65ch_format (acv, dmli, startstack, colin,
          left_type, d_type);
&   ifdef TRACE
    t01messblock (ak_sem, 'ak65check_c2', acv.a_mblock);
&   endif
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65diff_predicates (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR colin      : tak00_scolinf;
            VAR first_node : integer;
            VAR snot_pred  : boolean;
            field_found    : tsp00_Int2;
            VAR list_info  : list_elem_info);
 
CONST
      (* h.b. PTS 1105535 *)
      c_like_mult       = 3;
      c_reserve_mbsize  = 1024;
 
VAR
      _escape_char_found : boolean;
      _wrong_datatype    : boolean;
      _c2                : tsp00_C2;
      _keep_part_pos     : integer;
      _left_side         : integer;
      _right_side        : integer;
      _escape_n          : integer;
      _i                 : integer;
      _strat_size        : integer;
      _dummy_iolen       : tsp00_Int2;
      _helpbuf           : tak00_colinfo_ptr;
      _check_type        : tsp00_DataType;
      _startstack        : integer;
      _keep_dtype        : ARRAY[ 1..3 ] OF tsp00_DataType;
      _startstck         : ARRAY[ 1..3 ] OF integer;
      _node              : ARRAY[ 1..3 ] OF integer;
      _ccolin            : ARRAY[ 1..3 ] OF tak00_scolinf;
      _cchange           : ARRAY[ 1..3 ] OF boolean;
      _convert_t         : tak_convert_type;
      _operator          : tgg00_StackOpType;
      _nochange          : boolean;
      _e                 : tgg00_BasisError;
      _val_const         : ARRAY[ 1..3 ] OF boolean;
      _no_check          : boolean;
      _dont_care         : boolean;
      _const_expr_l      : boolean;
      _const_expr_r      : boolean;
 
BEGIN
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    _strat_size := sizeof( tgg07_StrategyInfo );
    IF  snot_pred
    THEN
        BEGIN
        CASE acv.a_ap_tree^[ first_node ].n_symb OF
            s_sounds :
                _operator := op_not_sounds;
            s_notsounds :
                _operator := op_sounds;
            s_like :
                _operator := op_not_like;
            s_notlike :
                _operator := op_like;
            s_between :
                _operator := op_not_between;
            s_notbetween :
                _operator := op_between;
            s_in :
                _operator := op_not_in;
            s_notin :
                _operator := op_in;
            OTHERWISE
                _operator := op_none
            END;
        (*ENDCASE*) 
        snot_pred := false;
        END
    ELSE
        CASE acv.a_ap_tree^[ first_node ].n_symb OF
            s_sounds :
                _operator := op_sounds;
            s_notsounds :
                _operator := op_not_sounds;
            s_like :
                _operator := op_like;
            s_notlike :
                _operator := op_not_like;
            s_between :
                _operator := op_between;
            s_notbetween :
                _operator := op_not_between;
            s_in :
                _operator := op_in;
            s_notin :
                _operator := op_not_in;
            OTHERWISE
                _operator := op_none
            END;
        (*ENDCASE*) 
    (*ENDIF*) 
    dmli.d_const_value_expr := ( acv.a_is_ddl = no_ddl);
    dmli.d_param_st_index   := 0;
    dmli.d_param_st_begin   := 0;
    _no_check           := false;
    _left_side          := acv.a_ap_tree^[ first_node ].n_lo_level;
    IF  ((acv.a_ap_tree^[ _left_side ].n_proc = a64) AND
        (acv.a_ap_tree^[ _left_side ].n_subproc  = cak_x_escape))
    THEN
        BEGIN
        dmli.d_escape := true;
        _escape_n := acv.a_ap_tree^[ _left_side ].n_sa_level;
        _left_side:= acv.a_ap_tree^[ _left_side ].n_lo_level
        END;
    (*ENDIF*) 
    _node[ 1 ]      := _left_side;
    _val_const[ 1 ] := acv.a_ap_tree^[ _node[ 1 ] ].n_symb in
          [ s_string_literal, s_uid, s_user, s_usergroup,
          (* PTS 1111797 E.Z. *)
          s_sysdba, s_parameter_name ];
    IF  acv.a_ap_tree^[ _left_side ].n_symb = s_authid
    THEN
        _left_side := acv.a_ap_tree^[ _left_side ].n_sa_level;
    (*ENDIF*) 
    IF  acv.a_ap_tree^[ _left_side ].n_symb = s_tablename
    THEN
        _left_side := acv.a_ap_tree^[ _left_side ].n_sa_level;
    (*ENDIF*) 
    _right_side := acv.a_ap_tree^[ _left_side ].n_sa_level;
&   ifdef trace
    IF  ( dmli.d_join )
    THEN
        BEGIN
        t01int4(ak_sem, 'jrc_cnt     ', dmli.d_joins.jrc_cnt );
        a683_one_join_entry( ak_sem, dmli.d_joins, dmli.d_joins.jrc_cnt, true );
        t01int4(ak_sem, '_right_side ', _right_side );
        END;
&   endif
    (*ENDIF*) 
    IF  ( dmli.d_join )
    THEN
        BEGIN
        _const_expr_l := true;
        _const_expr_r := false;
        ak65is_const_expr( acv.a_ap_tree, _left_side,
              c_ignore_sa_level, _const_expr_l );
        IF  ( NOT _const_expr_l )
        THEN
            BEGIN
            _const_expr_r := true;
            ak65is_const_expr( acv.a_ap_tree, _right_side,
                  c_ignore_sa_level, _const_expr_r );
            END;
        (*ENDIF*) 
        IF  ((( acv.a_ap_tree^[ _right_side ].n_symb in
            [ s_authid, s_tablename, s_columnname ] ) AND
            NOT dmli.d_escape AND
            (_operator in [ op_sounds, op_not_sounds, op_like, op_not_like ]) AND
            NOT (acv.a_outer_join OR dmli.d_outer_join))
            OR
            (( NOT _const_expr_l AND _const_expr_r ) AND
            ( acv.a_outer_join OR dmli.d_outer_join )))
        THEN
            BEGIN
            dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_op := _operator;
            dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                  jo_recs[ 2 ].jop_startstack := acv.a_mblock.mb_qual^.mfirst_free;
            dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_partno := 2;
&           ifdef trace
            t01op(ak_sem, 'set join op ', _operator );
            t01sname(ak_sem, 'next side   ');
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    _startstack := acv.a_mblock.mb_qual^.mfirst_free;
    WITH acv.a_ap_tree^[ first_node ] DO
        CASE n_symb OF
            s_between, s_notbetween : (*between*)
                ak65between_predicate (acv, dmli, colin, _right_side,
                      first_node, _operator, field_found, _e);
            s_in, s_notin : (*in*)
                ak65in_predicate (acv, dmli, _right_side, _operator,
                      field_found, list_info);
            s_like, s_notlike :
                IF  dmli.d_datatype = dnumber
                THEN
                    a07_b_put_error (acv, e_incompatible_datatypes,
                          acv.a_ap_tree^[ _right_side ].n_pos)
                ELSE
                    BEGIN (*like*)
                    _i            := 0;
                    _check_type   := dunknown;
                    _i            := succ(_i);
                    _cchange[ _i ] := (dmli.d_datatype in [ ddate,dtime,dtimestamp ]);
                    IF  _cchange[ _i ]
                    THEN
                        _check_type  := dmli.d_datatype;
                    (*ENDIF*) 
                    _startstck[ _i ]  := _startstack;
                    _keep_dtype[ _i ] := dmli.d_datatype;
                    _ccolin[ _i ]     := colin;
&                   ifdef trace
                    t01int4 (ak_sem, 'node       6', _node[ _i ]);
                    t01int4 (ak_sem, 'd_datatype 6', ord (dmli.d_datatype));
                    t01int4 (ak_sem, 'startstack 6', _startstck[ _i ]);
                    t01int4 (ak_sem, 'colin.typ  6', ord(_ccolin[ _i ].sci_typ));
&                   endif
                    dmli.d_like          := true;
                    dmli.d_like_optimize := false;
                    _keep_part_pos := acv.a_input_data_pos;
                    (* keep_part_pos is pointer to     *)
                    (* data-part where parameter       *)
                    (* from user is expected at exe-   *)
                    (* cution time                     *)
                    IF  (((acv.a_ap_tree^[ _right_side ].n_symb in
                        [ s_plus, s_minus, s_mult, s_divide,
                        s_div, s_mod ]) AND
                        (acv.a_ap_tree^[_right_side ].n_proc = a64))
                        OR
                        (acv.a_ap_tree^[ _right_side ].n_symb in
                        [ s_authid, s_tablename, s_columnname ]) OR
                        (acv.a_ap_tree^[ _right_side ].n_proc = a641))
                    THEN
                        dmli.d_like_expression := true;
                    (*ENDIF*) 
                    _escape_char_found := false;
                    IF  dmli.d_escape
                    THEN
                        WITH acv.a_ap_tree^[ _escape_n ] DO
                            IF  ((n_symb   = s_string_literal) OR
                                ( n_symb   = s_byte_string)   )
                                AND NOT dmli.d_like_expression
                            THEN
                                BEGIN
                                _wrong_datatype := false;
                                IF  (dmli.d_datatype = dunicode) AND
                                    g01unicode
                                THEN
                                    a641u_literal_value (acv, _escape_n,
                                          _c2, _wrong_datatype)
                                ELSE
                                    BEGIN
                                    _c2 := csp_unicode_blank;
                                    a641s_literal_value (acv,
                                          _escape_n, dmli.d_datatype,
                                          NOT c_string_allowed, _dont_care,
                                          _c2[ 2 ], _wrong_datatype);
                                    END;
                                (*ENDIF*) 
                                IF  _wrong_datatype
                                THEN
                                    a07_b_put_error (acv,
                                          e_invalid_escape_char, n_pos);
                                (*ENDIF*) 
                                dmli.d_escape_char     := _c2;
                                _escape_char_found := true;
                                END
                            ELSE
                                BEGIN
                                dmli.d_like := false;
                                IF  acv.a_ap_tree^[ _escape_n ].n_symb <>
                                    s_parameter_name
                                THEN
                                    dmli.d_like_expression := true
                                ELSE
                                    IF  acv.a_ap_tree^[ _right_side ].n_symb <>
                                        s_parameter_name
                                    THEN
                                        dmli.d_like_expression := true;
                                    (*ENDIF*) 
                                (*ENDIF*) 
                                IF  acv.a_ap_tree^[ _escape_n ].n_symb =
                                    s_parameter_name
                                THEN
                                    BEGIN
                                    dmli.d_expand := 1;
                                    IF  acv.a_ap_tree^[ _right_side ].n_symb =
                                        s_parameter_name
                                    THEN
                                        dmli.d_like_expression := false;
                                    (*ENDIF*) 
                                    END;
                                (*ENDIF*) 
                                _helpbuf            := dmli.d_colptr;
                                dmli.d_colptr           := NIL;
                                dmli.d_const_value_expr := dmli.d_like_expression;
&                               ifdef trace
                                t01int4 (ak_sem, 'a640factor  ', 1);
&                               endif
                                a640factor (acv, dmli, colin, _escape_n);
                                IF  NOT dmli.d_like_expression
                                THEN
                                    BEGIN
                                    acv.a_mblock.mb_qual^.mqual_cnt   :=
                                          acv.a_mblock.mb_qual^.mqual_cnt - 1;
                                    acv.a_mblock.mb_qual^.mfirst_free :=
                                          acv.a_mblock.mb_qual^.mfirst_free-1
                                    END;
                                (*ENDIF*) 
                                dmli.d_colptr := _helpbuf;
                                IF  acv.a_ap_tree^[ _escape_n ].n_symb =
                                    s_parameter_name
                                THEN
                                    dmli.d_expand := 0
                                ELSE
                                    IF  dmli.d_datatype = dunicode
                                    THEN
                                        a641string_set_operator ( acv,
                                              op_b_expand, 3, 1, chr(0), chr(0))
                                    ELSE
                                        a641string_set_operator ( acv,
                                              op_b_expand, 2, 1, chr(0), chr(0));
                                    (*ENDIF*) 
                                (*ENDIF*) 
                                dmli.d_like        := true;
                                colin.sci_len := 0
                                END;
                            (*ENDIF*) 
                        (*ENDWITH*) 
                    (*ENDIF*) 
                    IF  dmli.d_like_expression
                    THEN
                        BEGIN
                        (* ======================== *)
                        (* like cannot be used for  *)
                        (* optimization or strategy *)
                        (* ======================== *)
                        IF  (((acv.a_ap_tree^[ _right_side ].n_symb in
                            [ s_plus, s_minus, s_mult, s_divide,
                            s_div, s_mod ]) AND (acv.a_ap_tree^[_right_side ].n_proc = a64))
                            OR
                            (acv.a_ap_tree^[ _right_side ].n_proc = a641)) OR
                            (_check_type <> dunknown)
                        THEN
                            dmli.d_colptr := NIL;
                        (*ENDIF*) 
                        IF  (acv.a_ap_tree^[ _right_side ].n_symb <>
                            s_parameter_name)
                        THEN
                            BEGIN
                            colin.sci_len      := 0;
                            dmli.d_change_date_time := false;
                            IF  (g01unicode AND
                                (dmli.d_datatype in [ ddate, dtime, dtimestamp ]) AND
                                (acv.a_ap_tree^[ _right_side ].n_symb = s_string_literal))
                            THEN
                                dmli.d_datatype := dcha
                            ELSE
                                IF  NOT (
                                    ((acv.a_ap_tree^[ _right_side ].n_proc = a641) AND
                                    ( acv.a_ap_tree^[ _right_side ].n_symb in [s_addtime, s_subtime, s_adddate, s_subdate]))
                                    OR
                                    ((acv.a_ap_tree^[ _right_side ].n_proc = no_proc) AND
                                    ( acv.a_ap_tree^[ _right_side ].n_symb = s_now))
                                    )
                                THEN
                                    dmli.d_datatype := dunknown;
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END;
&                       ifdef trace
                        (*ENDIF*) 
                        t01int4 (ak_sem, 'a640factor  ', 2);
&                       endif
                        a640factor (acv, dmli, colin, _right_side);
                        IF  acv.a_returncode = cak_e_parameter
                        THEN
                            BEGIN
                            acv.a_returncode := 0;
                            dmli.d_datatype := _keep_dtype[ 1 ];
                            a640factor (acv, dmli, colin, _right_side);
                            END;
                        (* PTS 1120680 E.Z. *)
                        (*ENDIF*) 
                        IF  acv.a_returncode = cak_e_parameter
                        THEN
                            BEGIN
                            acv.a_returncode := 0;
                            a07_b_put_error (acv, e_without_datatypes,
                                  acv.a_ap_tree^[ _right_side ].n_pos);
                            END;
                        (*ENDIF*) 
                        IF  (dmli.d_escape AND
                            ((acv.a_ap_tree^[ _right_side ].n_symb = s_authid)
                            OR
                            (acv.a_ap_tree^[ _right_side ].n_symb = s_tablename)
                            OR
                            (acv.a_ap_tree^[ _right_side ].n_symb =
                            s_columnname)
                            OR
                            (acv.a_ap_tree^[ _right_side ].n_symb =
                            s_string_literal)
                            OR
                            (acv.a_ap_tree^[ _right_side ].n_symb =
                            s_byte_string)
                            OR
                            (acv.a_ap_tree^[ _right_side ].n_symb =
                            s_parameter_name)))
                        THEN
                            a641string_set_operator ( acv,
                                  op_b_expand,
                                  colin.sci_iolen, colin.sci_len,
                                  chr(0),chr(0));
                        (* it seems superfluos, but we need *)
                        (* the like value in a result_buffer*)
                        (* otherwise the like-value will be *)
                        (* changed after the first row has  *)
                        (* been checked                     *)
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        IF  ((field_found > 0) AND
                            (_operator = op_like))
                        THEN
                            WITH acv.a_mblock.mb_st^[ field_found ] DO
                                IF  ctmulti in dmli.d_colbuf^.ccolpropset
                                THEN
                                    BEGIN
                                    ecol_tab[ 2 ]   :=
                                          chr( ord (ecol_tab[ 2 ]) + 100);
                                    (* h.b. PTS 1105535 *)
                                    IF  ((acv.a_no_of_likes *
                                        c_like_mult *
                                        dmli.d_colbuf^.cinoutlen)
                                        + _strat_size
                                        + c_reserve_mbsize
                                        < g01mb_data_size)
                                    THEN
                                        dmli.d_like_optimize := true;
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    BEGIN
                                    (* h.b. PTS 1105535 *)
                                    IF  ((etype in [ st_fixkey, st_varkey ]) OR
                                        (ord(ecol_tab[ 1 ]) > 0 ))
                                        AND
                                        ((acv.a_no_of_likes *
                                        c_like_mult *
                                        dmli.d_colbuf^.cinoutlen)
                                        + _strat_size
                                        + c_reserve_mbsize
                                        < g01mb_data_size)
                                    THEN
                                        dmli.d_like_optimize := true;
                                    (*ENDIF*) 
                                    END;
                                (*ENDIF*) 
                            (*ENDWITH*) 
                        (*ENDIF*) 
                        IF  ((acv.a_ap_tree^[ _right_side ].n_symb =
                            s_parameter_name) AND _escape_char_found)
                        THEN
                            ak65fix_escape (acv, dmli);
&                       ifdef trace
                        (*ENDIF*) 
                        t01int4 (ak_sem, 'a640factor  ', 3);
&                       endif
                        IF  (((acv.a_ap_tree^[ _right_side ].n_symb in
                            [ s_plus, s_minus, s_mult, s_divide,
                            s_div, s_mod ]) AND (acv.a_ap_tree^[_right_side ].n_proc = a64))
                            OR
                            (acv.a_ap_tree^[ _right_side ].n_proc = a641))
                            OR
                            (_check_type <> dunknown)
                        THEN
                            dmli.d_colptr := NIL;
                        (*ENDIF*) 
                        IF  (acv.a_ap_tree^[ _right_side ].n_symb <>
                            s_parameter_name)
                        THEN
                            BEGIN
                            colin.sci_len      := 0;
                            dmli.d_change_date_time := false;
                            IF  (g01unicode AND
                                (dmli.d_datatype in [ ddate, dtime, dtimestamp ]) AND
                                (acv.a_ap_tree^[ _right_side ].n_symb = s_string_literal))
                            THEN
                                dmli.d_datatype := dcha
                            ELSE
                                IF  NOT (
                                    ((acv.a_ap_tree^[ _right_side ].n_proc = a641) AND
                                    ( acv.a_ap_tree^[ _right_side ].n_symb in [s_addtime, s_subtime, s_adddate, s_subdate]))
                                    OR
                                    ((acv.a_ap_tree^[ _right_side ].n_proc = no_proc) AND
                                    ( acv.a_ap_tree^[ _right_side ].n_symb = s_now))
                                    )
                                THEN
                                    dmli.d_datatype := dunknown;
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END
                        ELSE
                            IF  _cchange[ _i ]
                            THEN
                                dmli.d_datatype := dcha;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        dmli.d_like_part := 1;
                        a640factor (acv, dmli, colin, _right_side);
                        IF  ( acv.a_returncode = 0 ) AND
                            dmli.d_like_optimize
                        THEN
                            ak65try_like_optimization (acv, dmli,
                                  _right_side, _operator,
                                  _ccolin[ 1 ].sci_iolen, _keep_part_pos);
                        (* =============================== *)
                        (* ak65try_like_optimization returns   *)
                        (* dm_like = false if optimization *)
                        (* has taken place                 *)
                        (* =============================== *)
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    _i            := succ(_i);
                    _node[ _i ]    := _right_side;
                    _cchange[ _i ] := (dmli.d_datatype in [ ddate,dtime,dtimestamp ]);
                    IF  _cchange[ _i ]
                    THEN
                        IF  _check_type = dunknown
                        THEN
                            _check_type := dmli.d_datatype
                        ELSE
                            IF  _check_type <> dmli.d_datatype
                            THEN
                                a07_b_put_error (acv, e_incompatible_datatypes,
                                      acv.a_ap_tree^[ _node[ _i ] ].n_pos);
                            (*ENDIF*) 
                        (*ENDIF*) 
                    (*ENDIF*) 
                    _keep_dtype[ _i ] := dmli.d_datatype;
                    _ccolin[ _i ]     := colin;
                    _startstck[ _i ]  := acv.a_mblock.mb_qual^.mfirst_free;
&                   ifdef trace
                    t01int4 (ak_sem, 'node       7', _node[ _i ]);
                    t01int4 (ak_sem, 'd_datatype 7', ord (dmli.d_datatype));
                    t01int4 (ak_sem, 'startstack 7', _startstck[ _i ]);
                    t01int4 (ak_sem, 'colin.typ  7', ord(_ccolin[ _i ].sci_typ));
&                   endif
                    _nochange := false;
                    IF  acv.a_returncode = 0
                    THEN
                        (* PTS 1000985/1001162 E.Z. *)
                        IF  a65_datatypes_ok (acv, dmli, _keep_dtype[ 1 ], _dummy_iolen,
                            _keep_dtype[ 2 ],  NOT c_is_subquery, _node[ 2 ],
                            acv.a_ap_tree^[ _node[ 2 ]].n_pos,
                            c_convert, _convert_t)
                        THEN
                            _nochange := _cchange[ 1 ] OR _cchange[ 2 ];
                        (*ENDIF*) 
                    (*ENDIF*) 
                    IF  _nochange AND (acv.a_returncode = 0)
                    THEN
                        BEGIN
                        _e := e_ok;
                        IF  _val_const[ 1 ]
                        THEN
                            BEGIN
                            _cchange[ 1 ] := false;
                            _cchange[ 2 ] := false;
                            END;
                        (*ENDIF*) 
                        ak65check_change (acv, dmli, _check_type,
                              _cchange[ 1 ], _node[ 1 ],
                              _startstck[ 1 ], _ccolin[ 1 ],
                              _keep_dtype[ 1 ], _keep_dtype[ 1 ], _e);
                        _startstck[ 2 ] := acv.a_mblock.mb_qual^.mfirst_free;
                        IF  (_e = e_ok) AND _cchange[ 2 ]
                        THEN
                            a65ch_format (acv, dmli, _startstck[ 2 ],
                                  _ccolin[ 2 ], _keep_dtype[ 1 ],
                                  _keep_dtype[ 2 ]);
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  dmli.d_like
                    THEN
                        BEGIN
                        (* ================================ *)
                        (* no previous optimization         *)
                        (* -> attach standard like-operator *)
                        (* ================================ *)
                        dmli.d_like    := false;
                        ak65set_like_operator (acv, _operator,
                              dmli.d_like_expression,
                              ord(colin.sci_typ), dmli.d_escape);
                        dmli.d_like_expression := false;
                        END;
                    (*ENDIF*) 
                    dmli.d_escape := false;
                    END;
                (*ENDIF*) 
            s_sounds, s_notsounds :
                IF  ((dmli.d_datatype = dnumber)     OR
                    (dmli.d_datatype = ddate)        OR
                    (dmli.d_datatype = dtime)        OR
                    (dmli.d_datatype = dunicode))
                THEN
                    a07_b_put_error (acv, e_incompatible_datatypes,
                          acv.a_ap_tree^[ _right_side ].n_pos)
                ELSE
                    BEGIN (*sounds*)
                    IF  (((acv.a_ap_tree^[ _right_side ].n_symb in
                        [ s_plus, s_minus, s_mult, s_divide,
                        s_div, s_mod ]) AND (acv.a_ap_tree^[_right_side ].n_proc = a64))
                        OR
                        (acv.a_ap_tree^[ _right_side ].n_proc = a641))
                    THEN
                        dmli.d_colptr := NIL;
                    (*ENDIF*) 
                    a640factor (acv, dmli, colin, _right_side);
                    a65_set_operator (acv, _operator)
                    END
                (*ENDIF*) 
            END;
        (*ENDCASE*) 
    (*ENDWITH*) 
    IF  ( dmli.d_join ) AND
        ( dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_partno = 2 )
    THEN
        BEGIN
        IF  ( dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_no_join )
        THEN
            dmli.d_arith_where := true
        ELSE
            IF  ((dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                jo_recs[ 2 ].jop_tableno <> 0) AND
                (dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                jo_recs[ 1 ].jop_tableno <> 0) AND
                NOT dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                jo_no_join)
            THEN
                BEGIN
                IF  (dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                    jo_recs[ 1 ].jop_inoutlen <> 0)
                THEN
                    BEGIN
                    FOR _i := 0 TO dmli.d_joins.jrc_cnt - 1 DO
                        IF  (dmli.d_joins.jrc_joinarr[ _i ].jo_op = op_like)       OR
                            (dmli.d_joins.jrc_joinarr[ _i ].jo_op = op_not_like)   OR
                            (dmli.d_joins.jrc_joinarr[ _i ].jo_op = op_sounds)     OR
                            (dmli.d_joins.jrc_joinarr[ _i ].jo_op = op_not_sounds)
                        THEN
                            BEGIN
                            dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_no_join := true;
                            dmli.d_arith_where := true
                            END;
                        (*ENDIF*) 
                    (*ENDFOR*) 
                    IF  NOT dmli.d_arith_where
                    THEN
                        BEGIN
                        IF  acv.a_mblock.
                            mb_st^[ acv.a_mblock.mb_qual^.mfirst_free - 1 ].
                            etype = st_op (* op_(not_)like *)
                        THEN
                            dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                                  jo_recs[ 2 ].jop_cntstack :=
                                  acv.a_mblock.mb_qual^.mfirst_free -
                                  dmli.d_joins.
                                  jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                                  jo_recs[ 2 ].jop_startstack - 1
                        ELSE
                            dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                                  jo_recs[ 2 ].jop_cntstack :=
                                  acv.a_mblock.mb_qual^.mfirst_free -
                                  dmli.d_joins.jrc_joinarr
                                  [ dmli.d_joins.jrc_cnt ].jo_recs[ 2 ].
                                  jop_startstack;
                        (*ENDIF*) 
                        dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                              jo_recs[ 2 ].jop_outpos   := 0;
                        IF  ((dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                            jo_recs[ 2 ].jop_cntstack > 1)
                            OR
                            NOT (acv.a_mblock.mb_st^[ dmli.d_joins.
                            jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_recs[ 2 ].
                            jop_startstack ].eop in
                            [ op_none, op_unique, op_unique_desc,
                            op_order_asc, op_order_desc, op_ascii ]))
                        THEN
                            BEGIN
                            dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                                  jo_recs[ 2 ].jop_propset := [  ];
                            WITH colin DO
                                BEGIN
                                dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                                      jo_recs[ 2 ].jop_datatyp  := sci_typ;
                                IF  sci_iolen >= mxsp_key -
                                    sizeof (tsp00_Int4)
                                THEN
                                    a07_b_put_error (acv,
                                          e_join_fields_too_long, 1)
                                ELSE
                                    BEGIN
                                    dmli.d_joins.
                                          jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                                          jo_recs[ 2 ].jop_inoutlen := sci_iolen;
                                    END
                                (*ENDIF*) 
                                END;
                            (*ENDWITH*) 
                            IF  dmli.d_joins.
                                jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                                jo_recs[ 2 ].jop_datatyp in
                                [ dfixed, dfloat, dvfloat ]
                            THEN
                                BEGIN
                                dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                                      jo_recs[ 2 ].jop_datatyp  := dfloat;
                                dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                                      jo_recs[ 2 ].jop_inoutlen := NUMBER_MXGG04;
                                END
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                ELSE
                    a07_b_put_error (acv, e_join_fields_too_long, 1);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65fix_escape (
            VAR acv  : tak_all_command_glob;
            VAR dmli : tak_dml_info);
 
VAR
      _parsinfo_ptr : ^tak_parsinforecord;
 
BEGIN
_parsinfo_ptr := @dmli.d_sparr.pparsp^.sparsinfo;
IF  _parsinfo_ptr^.p_cnt_infos >= _parsinfo_ptr^.p_max_infos
THEN
    BEGIN
    a55realloc_parsinfo (acv, dmli.d_sparr.pparsp);
    IF  acv.a_returncode = 0
    THEN
        _parsinfo_ptr := @dmli.d_sparr.pparsp^.sparsinfo
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  acv.a_returncode = 0
THEN
    BEGIN
    _parsinfo_ptr^.p_cnt_infos := _parsinfo_ptr^.p_cnt_infos + 1;
    WITH _parsinfo_ptr^.p_pars_infos[_parsinfo_ptr^.p_cnt_infos] DO
        BEGIN
        fp_kind         := fp_escape_val;
        fp_etype        := st_dummy;
        fp_datatyp      := dunknown;
        fp_colset       := [  ];
        fp_fill_101     := 0;
        fp_fill_102     := 0;
        fp_fill_103     := 0;
        fp_escape_char  := dmli.d_escape_char
        END
    (*ENDWITH*) 
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65in_predicate (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR first_node : integer; (* node of the expr after IN *)
            VAR operator   : tgg00_StackOpType;
            field_found    : tsp00_Int2;
            VAR list_info  : list_elem_info);
 
VAR
      _cnt_fac     : integer;
      _be_q_cnt    : integer;
      _convert_t   : tak_convert_type;
      _colin       : tak00_scolinf;
      _help_buf    : tak00_colinfo_ptr;
      _types_ok    : boolean;
      _startstack  : integer;
      _level_node  : tsp00_Int2;
      _list_node   : integer;
      _in_check    : boolean;
      _in_strat    : boolean;
      _first_entry : tsp00_Int2;
      _first_free  : tsp00_Int2;
      _list_cnt    : integer;
      _dm_datatype : tsp00_DataType;
 
BEGIN
dmli.d_const_value_expr := false;
dmli.d_param_st_index   := 0;
dmli.d_param_st_begin   := 0;
dmli.d_single_expr      := true;
_first_entry        := acv.a_mblock.mb_qual^.mfirst_free;
_cnt_fac            := 0;
_in_check           := true;
_be_q_cnt           := acv.a_mblock.mb_qual^.mqual_cnt;
IF  (acv.a_ap_tree^[ first_node ].n_proc = a63query_spec)
    OR
    ((acv.a_ap_tree^[ first_node ].n_proc = a63) AND
    (acv.a_ap_tree^[ first_node ].n_subproc = cak_x_start_union))
THEN (* IN SELECT ... *)
    BEGIN
    IF  operator = op_not_in
    THEN
        operator := op_ne
    ELSE
        operator := op_eq;
    (*ENDIF*) 
    (* The datatypes of the selected columns are stored in a *)
    (* node list starting at the same_level of first_node.   *)
    IF  NOT dmli.d_use_sub
    THEN      (* In a corelated subquery (or the like) we  *)
        BEGIN (* have to construct the datatype list here. *)
        _list_node := first_node;
        _list_cnt  := 0;
        WHILE _list_cnt < list_info.count DO
            BEGIN
            _list_cnt  := succ (_list_cnt);
            (* PTS 1000985/1001162 E.Z. *)
            IF  acv.a_ap_tree^[ _list_node ].n_sa_level > 0
            THEN
                BEGIN
                _level_node  := acv.a_ap_tree^[ _list_node ].n_sa_level;
                _dm_datatype := list_info.elem[_list_cnt].datatype;
&               ifdef TRACE
                t01int4 (ak_sem, 'dm_datatype ', ord(_dm_datatype));
&               endif
                _types_ok := a65_datatypes_ok (acv, dmli,
                      acv.a_ap_tree^[ _level_node ].n_datatype,
                      acv.a_ap_tree^[ _level_node ].n_length, _dm_datatype,
                      c_is_subquery,
                      first_node, list_info.elem[ _list_cnt ].pos,
                      (list_info.count = 1), _convert_t);
                IF  (_convert_t <> conv_none) AND
                    (list_info.count <> 1)
                THEN
                    a07_b_put_error (acv, e_incompatible_datatypes,
                          list_info.elem[ _list_cnt ].pos);
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                WITH list_info.elem[_list_cnt] DO
                    a01_dt_put_datatype_node (acv, _level_node,
                          datatype, datalen, datafrac, inout_len);
                (*ENDWITH*) 
                acv.a_ap_tree^[ _list_node  ].n_sa_level := _level_node;
                END;
            (*ENDIF*) 
&           ifdef trace
            WITH acv.a_ap_tree^[ _level_node ] DO
                BEGIN
                t01int4 (ak_sem, 'list#       ', _list_cnt);
                t01int4 (ak_sem, 'type(list#) ', ord (n_datatype));
                t01int4 (ak_sem, 'len(list#)  ', n_length)
                END;
            (*ENDWITH*) 
&           endif
            _list_node := _level_node
            END;
        (*ENDWHILE*) 
        _types_ok := true
        END
    ELSE      (* In an ordinary subquery we can use the information *)
        BEGIN (* of the datatype list for checking of column types. *)
        _list_node := acv.a_ap_tree^[ first_node ].n_sa_level;
        _list_cnt  := 0;
        WHILE (_list_node <> 0) AND (acv.a_returncode = 0) DO
            WITH acv.a_ap_tree^[ _list_node ] DO
                BEGIN (* in sub_query *)
&               ifdef trace
                t01int4 (ak_sem, 'dtype_node  ', _list_node);
&               endif
                _list_cnt    := succ (_list_cnt);
                _dm_datatype := list_info.elem[_list_cnt].datatype;
                (* *** null value in subquery select list *** *)
                _startstack  := acv.a_mblock.mb_qual^.mfirst_free;
                _types_ok    := n_datatype = dunknown;
                IF  NOT _types_ok
                THEN
                    (* PTS 1000985/1001162 E.Z. *)
                    _types_ok := a65_datatypes_ok (acv, dmli, n_datatype, n_length,
                          _dm_datatype, c_is_subquery, first_node,
                          list_info.elem[_list_cnt].pos,
                          (list_info.count = 1), _convert_t);
                (*ENDIF*) 
                IF  _types_ok AND (list_info.count = 1) AND
                    (_dm_datatype in [ ddate,dtime,dtimestamp ])
                THEN (* For expression lists this is already done. *)
                    a65ch_format (acv, dmli, _startstack, _colin,
                          n_datatype, _dm_datatype);
                (*ENDIF*) 
                _list_node := acv.a_ap_tree^[ _list_node ].n_sa_level
                END;
            (*ENDWITH*) 
        (*ENDWHILE*) 
        IF  (acv.a_returncode = 0) AND
            (_list_cnt <> list_info.count)
        THEN      (* The given select list on the right side has a   *)
            BEGIN (* different number of columns than the left side. *)
            _list_node := first_node;
            WHILE (acv.a_ap_tree^[ _list_node ].n_proc <> no_proc) AND
                  (acv.a_ap_tree^[ _list_node ].n_lo_level <> 0) DO
                _list_node := acv.a_ap_tree^[ _list_node ].n_lo_level;
            (*ENDWHILE*) 
            IF  _list_cnt < list_info.count
            THEN (* fewer columns in select list than on left side. *)
                a07_b_put_error (acv, e_too_few_columns,
                      acv.a_ap_tree^[ _list_node ].n_pos)
            ELSE
                IF  _list_cnt > list_info.count
                THEN (* more columns in select list than on left side. *)
                    a07_b_put_error (acv, e_select_col_list_too_long,
                          acv.a_ap_tree^[ _list_node ].n_pos)
                (*ENDIF*) 
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (acv.a_returncode = 0) AND _types_ok
    THEN
        IF  operator = op_ne
        THEN
            ak65sub_op_set (acv, c_all, NOT c_any, op_ne, first_node)
        ELSE
            BEGIN
            IF  field_found > 0
            THEN
                IF  ctmulti in dmli.d_colbuf^.ccolpropset
                THEN
                    WITH acv.a_mblock.mb_qual^, acv.a_mblock.mb_st^ [field_found] DO
                        ecol_tab[ 2 ] :=
                              chr( ord (ecol_tab[ 2 ]) + 100);
                    (*ENDWITH*) 
                (*ENDIF*) 
            (*ENDIF*) 
            ak65sub_op_set (acv, NOT c_all, c_any, op_eq, first_node)
            END
        (*ENDIF*) 
    (*ENDIF*) 
    END
ELSE (* IN (expr, expr, ... *)
    BEGIN
    (* set first_node to 1. list elem *)
    first_node    := acv.a_ap_tree^[ first_node ].n_lo_level;
    _colin.sci_len := 0;
    _help_buf      := dmli.d_colptr;
    IF  field_found > 0
    THEN
        IF  ctmulti in dmli.d_colbuf^.ccolpropset
        THEN
            WITH acv.a_mblock.mb_st^[ field_found ] DO
                ecol_tab[ 2 ] := chr (ord (ecol_tab[ 2 ]) + 100);
            (*ENDWITH*) 
        (*ENDIF*) 
    (*ENDIF*) 
    IF  (acv.a_sqlmode = sqlm_internal) OR (acv.a_sqlmode = sqlm_oracle)
    THEN
        BEGIN
        _in_strat := true;
        WITH acv.a_ap_tree^[ first_node ] DO
            IF  (n_proc = a56) AND (n_subproc = cak_x_value_list)
            THEN      (* Here comes a list of lists, and each *)
                BEGIN (* elem can have a different datatype.  *)
                _list_node  := n_sa_level;
                first_node := n_lo_level;
                _list_cnt   := 1
                END
            ELSE      (* Here comes a list of expressions, *)
                BEGIN (* and all are of the same datatype. *)
                _list_cnt  := 0;
                _list_node := 0
                END;
            (*ENDIF*) 
        (*ENDWITH*) 
        REPEAT
            _first_free := acv.a_mblock.mb_qual^.mfirst_free;
            IF  _list_cnt > 0
            THEN      (* In a list each value can have its own   *)
                BEGIN (* datatype, which is stored in list_info. *)
                dmli.d_datatype := list_info.elem[_list_cnt].datatype;
                dmli.d_colptr   := NIL (* Here we don't know anything. *)
                END;
&           ifdef trace
            (*ENDIF*) 
            t01int4 (ak_sem, 'list_cnt    ', _list_cnt);
            t01int4 (ak_sem, 'dm_datatype ', ord (dmli.d_datatype));
&           endif
            a65_val_expr (acv, dmli, _colin,
                  acv.a_ap_tree^[ first_node ].n_lo_level);
            IF  acv.a_returncode <> 0
            THEN
                first_node := 0 (* signal to exit loop. *)
            ELSE
                BEGIN
                IF  acv.a_mblock.mb_st^ [ acv.a_mblock.mb_qual^.mfirst_free-1 ].etype <> st_value
                THEN
                    _in_check := false;
                (*ENDIF*) 
                _in_strat := _in_strat AND
                      (acv.a_mblock.mb_st^ [_first_free].etype = st_value) AND
                      ((acv.a_mblock.mb_st^[ _first_free ].ecol_tab [2] <> chr(0)) OR
                      (_first_free = acv.a_mblock.mb_qual^.mfirst_free - 1));
                _cnt_fac    := succ(_cnt_fac);
                first_node := acv.a_ap_tree^[ first_node ].n_sa_level;
                IF  (first_node = 0) AND (_list_node <> 0)
                THEN (* There is still another list of lists. *)
                    WITH acv.a_ap_tree^[ _list_node ] DO
                        BEGIN
                        first_node := n_lo_level;
                        _list_node  := n_sa_level;
                        _list_cnt   := 1
                        END
                    (*ENDWITH*) 
                ELSE
                    IF  (_list_cnt > 0) AND (first_node > 0)
                    THEN (* next elem of a list of lists. *)
                        _list_cnt := succ (_list_cnt);
                    (*ENDIF*) 
                (*ENDIF*) 
                IF  first_node > 0
                THEN
                    BEGIN
                    _colin.sci_len      := 0;
                    dmli.d_colptr           := _help_buf;
                    dmli.d_const_value_expr := false;
                    dmli.d_param_st_index   := 0;
                    dmli.d_param_st_begin   := 0;
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
        UNTIL
            first_node = 0
        (*ENDREPEAT*) 
        END
    ELSE (* sqlmode is ansi or db2. *)
        BEGIN
        _in_strat := false;
        _list_cnt := 0;
        a640factor (acv, dmli, _colin, first_node);
        _cnt_fac  := succ(_cnt_fac);
        WHILE acv.a_ap_tree^[ first_node ].n_sa_level <> 0 DO
            BEGIN
            first_node := acv.a_ap_tree^[ first_node ].n_sa_level;
            _colin.sci_len := 0;
            dmli.d_colptr := _help_buf;
            a640not_first_factor (acv, dmli, _colin, first_node);
            _cnt_fac := succ(_cnt_fac);
            END
        (*ENDWHILE*) 
        END;
    (*ENDIF*) 
    IF  _cnt_fac = 1
    THEN
        IF  operator = op_not_in
        THEN
            a65_set_operator (acv, op_ne)
        ELSE
            a65_set_operator (acv, op_eq)
        (*ENDIF*) 
    ELSE
        WITH acv.a_mblock, acv.a_mblock.mb_qual^ DO
            BEGIN
            IF  mfirst_free > 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
                mqual_cnt := succ(mqual_cnt);
                WITH acv.a_mblock.mb_st^ [mfirst_free] DO
                    BEGIN
                    etype := st_op;
                    eop   := operator;
                    IF  _list_cnt = 0
                    THEN      (* The 'cnt_fac' expressions could be   *)
                        BEGIN (* seen as lists with one element each. *)
                        epos     := 1;
                        elen_var := _cnt_fac
                        END
                    ELSE      (* Multiple lists with 'list_cnt' elems   *)
                        BEGIN (* each and 'cnt_fac' elems all together. *)
                        epos     := _list_cnt;
                        elen_var := _cnt_fac DIV _list_cnt;
                        _in_check := false;
                        _in_strat := false;
                        END;
                    (*ENDIF*) 
                    IF  _in_strat AND _in_check
                    THEN
                        ecol_tab[ 1 ] := chr(0) (* g04_incheck not done *)
                    ELSE
                        ecol_tab[ 1 ] := chr(2);(* no g04_incheck *)
                    (*ENDIF*) 
                    ecol_tab[ 2 ] := chr(0)
                    END;
                (*ENDWITH*) 
                mfirst_free := succ(mfirst_free)
                END
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
    (*ENDIF*) 
    IF  _in_strat AND (acv.a_returncode = 0)
    THEN
        a651in_const_expression (acv, dmli, _first_entry,
              acv.a_mblock.mb_qual^.mfirst_free - 1);
    (*ENDIF*) 
    dmli.d_single_expr := false;
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65new_colinfo (
            VAR acv  : tak_all_command_glob;
            VAR col1 : tak00_scolinf;
            VAR col2 : tak00_scolinf;
            n_symb   : tak_sc_symbol);
 
VAR
      diff1  : integer;
      diff2  : integer;
      first  : integer;
      second : integer;
 
BEGIN
IF  ((col1.sci_cprops = [ ctopt ]) OR (col2.sci_cprops = [ ctopt ]))
THEN
    col1.sci_cprops := [ ctopt ];
&ifdef TRACE
(*ENDIF*) 
t01int4 (ak_sem, 'col1 frac > ', col1.sci_frac);
t01int4 (ak_sem, 'col2 frac > ', col2.sci_frac);
t01int4 (ak_sem, 'col1 len  > ', col1.sci_len);
t01int4 (ak_sem, 'col2 len  > ', col2.sci_len);
t01int4 (ak_sem, 'col1 typ  > ', ord(col1.sci_typ));
t01int4 (ak_sem, 'col2 typ  > ', ord(col2.sci_typ));
&endif
IF  ((col1.sci_frac = csp_float_frac) OR
    (col2.sci_frac = csp_float_frac)) OR
    (acv.a_recursive_state = rs_check_select_list)
THEN
    BEGIN
    col1.sci_len   := csp_fixed;
    col1.sci_frac  := csp_float_frac;
    col1.sci_iolen := NUMBER_MXGG04;
    col1.sci_typ   := dvfloat
    END
ELSE
    BEGIN
    IF  col1.sci_len = 0
    THEN
        col1 := col2
    ELSE
        BEGIN
        IF  col1.sci_frac = csp_float_frac
        THEN
            diff1 := col1.sci_len
        ELSE
            diff1 := col1.sci_len - col1.sci_frac;
        (*ENDIF*) 
        IF  col2.sci_frac = csp_float_frac
        THEN
            diff2 := col2.sci_len
        ELSE
            diff2 := col2.sci_len - col2.sci_frac;
        (*ENDIF*) 
        CASE n_symb OF
            s_plus, s_minus :
                BEGIN
                IF  diff1 > diff2
                THEN
                    first := diff1
                ELSE
                    first := diff2;
                (*ENDIF*) 
                IF  col1.sci_frac > col2.sci_frac
                THEN
                    second := col1.sci_frac
                ELSE
                    second := col2.sci_frac;
                (*ENDIF*) 
                IF  first + second + 1 <= csp_fixed
                THEN
                    BEGIN
                    col1.sci_len  := first + second + 1;
                    col1.sci_frac := second
                    END
                ELSE
                    BEGIN
                    col1.sci_len := csp_fixed;
                    col1.sci_typ := dvfloat
                    END;
                (*ENDIF*) 
                END;
            s_mult :
                IF  col1.sci_len + col2.sci_len > csp_fixed
                THEN
                    BEGIN
                    col1.sci_len := csp_fixed;
                    col1.sci_typ := dvfloat
                    END
                ELSE
                    BEGIN
                    col1.sci_len  := col1.sci_len  + col2.sci_len;
                    col1.sci_frac := col1.sci_frac + col2.sci_frac
                    END;
                (*ENDIF*) 
            s_divide :
                IF  ((diff1 + col2.sci_frac >= csp_fixed) AND
                    (col2.sci_frac <> csp_float_frac))
                THEN
                    BEGIN
                    col1.sci_len := csp_fixed;
                    col1.sci_typ := dvfloat
                    END
                ELSE
                    BEGIN
                    col1.sci_frac := csp_fixed -
                          col1.sci_len + col1.sci_frac - col2.sci_frac;
                    col1.sci_len := csp_fixed
                    END
                (*ENDIF*) 
            END;
        (*ENDCASE*) 
        col1.sci_iolen := ((col1.sci_len + 1) DIV 2) + 2;
        IF  ((col1.sci_typ in [ dfloat, dvfloat ]) OR
            (col2.sci_typ in [ dfloat, dvfloat ]))
        THEN
            BEGIN
            col1.sci_frac := csp_float_frac;
            col1.sci_typ := dvfloat
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDIF*) 
END;
 
(* PTS 1116838 E.Z. *)
(*------------------------------*) 
 
PROCEDURE
      ak65copy_expression (
            VAR acv  : tak_all_command_glob;
            source   : tsp00_Int2;
            VAR dest : tsp00_Int2);
 
BEGIN
a01_put_same_node (acv, source, dest);
IF  acv.a_returncode = 0
THEN
    IF  acv.a_ap_tree^[source].n_lo_level > 0
    THEN
        ak65copy_expression (acv, acv.a_ap_tree^[source].n_lo_level,
              acv.a_ap_tree^[dest].n_lo_level);
    (*ENDIF*) 
(*ENDIF*) 
IF  acv.a_returncode = 0
THEN
    IF  acv.a_ap_tree^[source].n_sa_level > 0
    THEN
        ak65copy_expression (acv, acv.a_ap_tree^[source].n_sa_level,
              acv.a_ap_tree^[dest].n_sa_level);
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65split_in_clause (
            VAR acv    : tak_all_command_glob;
            first_node : integer);
 
VAR
      second_in     : tsp00_Int2;
      first_left    : tsp00_Int2;
      second_left   : tsp00_Int2;
      new_first_node: tsp00_Int2;
      first_list    : tsp00_Int2;
      second_list   : tsp00_Int2;
      curr_listelem : tsp00_Int2;
 
BEGIN
(* split one 'x in (a, b, c)' into 'x in (a,c) or x in (b)' *)
(*
      ------11------
      | a64|__|Symb|
      |in  |  |colu|
      ------  ------
      |
      13------14------15------
      | a64|__| a64|__|Symb|
      |   8|  |  17|  |uns_|
      ------  ------  ------
      |
      16------17------
      | a64|__|Symb|
      |  17|  |stri|
      ------  ------
      |
      18------19------
      | a64|__|Symb|
      |  17|  |uns_|
      ------  ------
      |
      20------21------
      | a64|__|Symb|
      |  17|  |stri|
      ------  ------
      INTO
      ------  ------  ------
      | a64|__| a64|__|Symb|
      | or |  |in  |  |colu|
      ------  ------  ------
      |       |
      |  13------14------15------
      |    | a64|__| a64|__|Symb|
      |    |   8|  |  17|  |stri|
      |    ------  ------  ------
      |               |
      |          16------17------
      |            | a64|__|Symb|
      |            |  17|  |stri|
      |            ------  ------
      |
      21------19------20------
      | a64|__| 641|__|Symb|
      |in  |  |user|  |colu|
      ------  ------  ------
      |
      22------23------24------
      | a64|__| a64|__|Symb|
      |   8|  |  17|  |uns_|
      ------  ------  ------
      |
      25------26------
      | a64|__|Symb|
      |  17|  |uns_|
      ------  ------
      *)
WITH acv DO
    BEGIN
    (* put another in into the tree and change first_node to 'OR' *)
    a01_put_same_node (acv, first_node, first_left);
    a_ap_tree^[first_left].n_lo_level := a_ap_tree^[first_node].n_lo_level;
    a01_call_put( acv, a64, cak_x_or_operator, new_first_node);
    a_ap_tree^[new_first_node].n_symb := s_or;
    a_ap_tree^[first_node] := a_ap_tree^[new_first_node];
    a_ap_tree^[first_node].n_lo_level := first_left;
    (* the node new_first_node is of no use any more *)
    (* first_left is on the first 'IN' *)
    a01_put_same_node (acv, first_left, a_ap_tree^[first_left].n_sa_level);
    second_in := a_ap_tree^[first_left].n_sa_level;
    first_left := a_ap_tree^[first_left].n_lo_level;
    a_scv.sc_symb := s_to_number;
    a01_function_put (acv, a_ap_tree^[second_in].n_lo_level);
    second_left := a_ap_tree^[second_in].n_lo_level;
    a01_put_same_node (acv, first_left, a_ap_tree^[second_left].n_lo_level);
    second_left := a_ap_tree^[second_left].n_lo_level;
    IF  a_ap_tree^[first_left].n_lo_level > 0
    THEN
        BEGIN
        ak65copy_expression (acv, a_ap_tree^[first_left].n_lo_level,
              a_ap_tree^[second_left].n_lo_level);
        first_left  := a_ap_tree^[first_left].n_sa_level;
        END
    ELSE
        BEGIN
        first_left  := a_ap_tree^[first_left].n_sa_level;
        WHILE (a_ap_tree^[first_left].n_proc <> a64) OR
              (a_ap_tree^[first_left].n_subproc <> cak_x_in_pred_list) DO
            BEGIN
            a01_put_same_node (acv, first_left, a_ap_tree^[second_left].n_sa_level);
            second_left := a_ap_tree^[second_left].n_sa_level;
            first_left  := a_ap_tree^[first_left].n_sa_level;
            END;
        (*ENDWHILE*) 
        END;
    (*ENDIF*) 
    IF  a_returncode = 0
    THEN
        BEGIN
        second_left := a_ap_tree^[second_in].n_lo_level;
        a01_put_same_node (acv, first_left, a_ap_tree^[second_left].n_sa_level);
        (* that was the cak_x_in_pred_list-node *)
        (* now we have to move only             *)
        first_list  := a_ap_tree^[first_left].n_lo_level;
        second_list := a_ap_tree^[second_left].n_sa_level;
        WHILE first_list <> 0 DO
            BEGIN
            IF  a_ap_tree^[first_list].n_datatype = dfixed
            THEN
                BEGIN
                curr_listelem := first_list;
                IF  first_list = a_ap_tree^[first_left].n_lo_level
                THEN
                    a_ap_tree^[first_left].n_lo_level := a_ap_tree^[curr_listelem].n_sa_level
                ELSE
                    a_ap_tree^[first_left].n_sa_level := a_ap_tree^[curr_listelem].n_sa_level;
                (*ENDIF*) 
                first_list := a_ap_tree^[curr_listelem].n_sa_level;
                IF  (a_ap_tree^[second_list].n_proc = a64) AND
                    (a_ap_tree^[second_list].n_subproc = cak_x_in_pred_list)
                THEN
                    a_ap_tree^[second_list].n_lo_level := curr_listelem
                ELSE
                    a_ap_tree^[second_list].n_sa_level := curr_listelem;
                (*ENDIF*) 
                second_list := curr_listelem;
                a_ap_tree^[curr_listelem].n_sa_level := 0;
                END
            ELSE
                BEGIN
                first_left := first_list;
                first_list := a_ap_tree^[first_list].n_sa_level;
                END
            (*ENDIF*) 
            END;
        (*ENDWHILE*) 
&       ifdef TRACE
        t01aptree (ak_sem, a_ap_tree^, a_scv_index, a_first_hint_node);
&       endif
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(* END PTS 1116838 E.Z. *)
(*------------------------------*) 
 
PROCEDURE
      ak65oracle_typecheck (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR list_info  : list_elem_info;
            first_node     : integer;
            VAR normpred   : boolean);
 
VAR
      only_numbers    : boolean;
      number_found    : boolean;
      subquery_list   : boolean;
      sel_n           : integer;
      act_node        : integer;
      left_node       : integer;
      right_node      : integer;
      list_elem       : integer;
      list_elem_node  : integer;
      list_node       : integer;
      list_cnt        : integer;
      left_fixed      : PACKED ARRAY [ 1..MAX_COL_PER_TAB_GG00 ] OF boolean;
 
BEGIN
WITH acv, dmli DO
    BEGIN
    act_node := a_ap_tree^[ first_node ].n_lo_level;
    WITH a_ap_tree^[ act_node ] DO
        IF  (n_proc = a56) AND (n_subproc = cak_x_value_list)
        THEN
            BEGIN
            FOR list_elem := 1 TO MAX_COL_PER_TAB_GG00 DO
                list_info.elem[ list_elem ].datatype := dunknown;
            (*ENDFOR*) 
            subquery_list := false;
            list_node := act_node;
            list_cnt := 0;
            WHILE list_node > 0 DO
                BEGIN
                list_cnt := succ(list_cnt);
                list_elem_node := a_ap_tree^[ list_node ].n_lo_level;
                list_elem := 0;
                WHILE list_elem_node > 0 DO
                    BEGIN
                    d_datatype := dunknown;
                    a65_look_for_datatypes (acv, dmli,
                          a_ap_tree^[ list_elem_node ].n_lo_level);
                    IF  d_datatype in [ dfixed, dfloat, dvfloat, dnumber ]
                    THEN
                        a_ap_tree^[ list_elem_node ].n_datatype := dfixed
                    ELSE
                        a_ap_tree^[ list_elem_node ].n_datatype := dcha;
                    (*ENDIF*) 
                    list_elem := succ(list_elem);
                    IF  list_info.elem[ list_elem ].datatype = dunknown
                    THEN
                        BEGIN
                        list_info.elem[ list_elem ].datatype :=
                              a_ap_tree^[ list_elem_node ].n_datatype;
                        IF  list_info.elem[ list_elem ].datatype = dfixed
                        THEN
                            BEGIN
                            list_info.elem[ list_elem ].datalen :=
                                  a_ap_tree^[ list_elem_node ].n_pos DIV 100;
                            list_info.elem[ list_elem ].datafrac :=
                                  a_ap_tree^[ list_elem_node ].n_pos MOD 100;
                            END
                        ELSE
                            list_info.elem[ list_elem ].datalen :=
                                  a_ap_tree^[ list_elem_node ].n_pos;
                        (*ENDIF*) 
                        END
                    ELSE
                        IF  (a_ap_tree^[ list_elem_node ].n_datatype
                            <>
                            list_info.elem[ list_elem ].datatype)
                        THEN
                            a07_b_put_error (acv, e_incompatible_datatypes,
                                  a_ap_tree^[ list_elem_node ].n_pos);
                        (*ENDIF*) 
                    (*ENDIF*) 
                    list_elem_node := a_ap_tree^[ list_elem_node ].n_sa_level;
                    END;
                (*ENDWHILE*) 
                IF  list_cnt = 1
                THEN
                    BEGIN
                    FOR list_elem := 1 TO MAX_COL_PER_TAB_GG00 DO
                        BEGIN
                        left_fixed[ list_elem ] :=
                              (list_info.elem[ list_elem ].datatype = dfixed);
                        list_info.elem[ list_elem ].datatype := dunknown;
                        END;
                    (*ENDFOR*) 
                    list_node := a_ap_tree^[ list_node ].n_sa_level;
                    IF  (a_ap_tree^[ list_node ].n_symb = s_all) OR
                        (a_ap_tree^[ list_node ].n_symb = s_any)
                    THEN
                        list_node := a_ap_tree^[ list_node ].n_sa_level;
                    (*ENDIF*) 
                    IF  (a_ap_tree^[ list_node ].n_proc = a63query_spec)
                        OR
                        ((a_ap_tree^[ list_node ].n_proc = a63) AND
                        (acv.a_ap_tree^[ list_node ].n_subproc = cak_x_start_union))
                    THEN
                        BEGIN
                        subquery_list := true;
                        list_node := 0;
                        END
                    ELSE
                        IF  (a_ap_tree^[ list_node ].n_proc = a64) AND
                            (a_ap_tree^[ list_node ].n_subproc = cak_x_in_pred_list)
                        THEN
                            list_node := a_ap_tree^[ list_node ].n_lo_level;
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END
                ELSE
                    list_node := a_ap_tree^[ list_node ].n_sa_level;
                (*ENDIF*) 
                END;
            (*ENDWHILE*) 
            IF  ((a_returncode = 0) AND
                (NOT subquery_list))
            THEN
                BEGIN
                list_node := act_node;
                list_cnt := 0;
                WHILE ((list_node > 0) AND
                      (a_returncode = 0)) DO
                    BEGIN
                    list_cnt := succ(list_cnt);
                    list_elem_node := a_ap_tree^[ list_node ].n_lo_level;
                    list_elem := 0;
                    WHILE list_elem_node > 0 DO
                        BEGIN
                        list_elem := succ(list_elem);
                        IF  ((list_cnt = 1)               AND
                            (NOT left_fixed[ list_elem ]) AND
                            (list_info.elem[ list_elem ].datatype = dfixed))
                            OR
                            ((list_cnt > 1)               AND
                            (    left_fixed[ list_elem ]) AND
                            (list_info.elem[ list_elem ].datatype = dcha))
                        THEN
                            ak65s_num_into_tree (acv,
                                  a_ap_tree^[ list_elem_node ].n_lo_level,
                                  a_ap_tree^[ list_elem_node ].n_lo_level, 0);
                        (*ENDIF*) 
                        list_elem_node := a_ap_tree^[ list_elem_node ].n_sa_level;
                        END;
                    (*ENDWHILE*) 
                    IF  list_cnt = 1
                    THEN
                        BEGIN
                        list_node := a_ap_tree^[ list_node ].n_sa_level;
                        IF  (a_ap_tree^[ list_node ].n_symb = s_all) OR
                            (a_ap_tree^[ list_node ].n_symb = s_any)
                        THEN
                            list_node := a_ap_tree^[ list_node ].n_sa_level;
                        (*ENDIF*) 
                        IF  (a_ap_tree^[ list_node ].n_proc = a64) AND
                            (a_ap_tree^[ list_node ].n_subproc = cak_x_in_pred_list)
                        THEN
                            list_node := a_ap_tree^[ list_node ].n_lo_level;
                        (*ENDIF*) 
                        END
                    ELSE
                        list_node := a_ap_tree^[ list_node ].n_sa_level;
                    (*ENDIF*) 
                    END;
                (*ENDWHILE*) 
                END
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            d_datatype := dunknown;
            a65_look_for_datatypes (acv, dmli, act_node);
            IF  NOT (d_datatype in [ dfixed, dfloat, dvfloat, dnumber ])
            THEN
                BEGIN
                d_datatype := dunknown;
                sel_n := a_ap_tree^[ first_node ].n_lo_level;
                IF  a_ap_tree^[ sel_n ].n_symb = s_authid
                THEN
                    sel_n := a_ap_tree^[ sel_n ].n_sa_level;
                (*ENDIF*) 
                IF  a_ap_tree^[ sel_n ].n_symb = s_tablename
                THEN
                    sel_n := a_ap_tree^[ sel_n ].n_sa_level;
                (*ENDIF*) 
                sel_n := a_ap_tree^[ sel_n ].n_sa_level;
                IF  a_ap_tree^[ first_node ].n_symb in
                    [ s_equal, s_greater, s_greater_or_eq,
                    s_less, s_less_or_eq, s_unequal ]
                THEN
                    BEGIN
                    IF  (a_ap_tree^[ sel_n ].n_symb = s_all)
                        OR
                        (a_ap_tree^[ sel_n ].n_symb = s_any)
                    THEN
                        sel_n := a_ap_tree^[ sel_n ].n_sa_level;
                    (*ENDIF*) 
                    IF  NOT(
                        (a_ap_tree^[ sel_n ].n_proc = a63query_spec)
                        OR
                        ((a_ap_tree^[ sel_n ].n_proc = a63) AND
                        ( a_ap_tree^[ sel_n ].n_subproc = cak_x_start_union))
                        OR
                        ((a_ap_tree^[ sel_n ].n_proc = a56) AND
                        ( a_ap_tree^[ sel_n ].n_subproc = cak_x_value_list))
                        )
                    THEN
                        BEGIN
                        a65_look_for_datatypes (acv, dmli, sel_n);
                        IF  d_datatype in [ dfixed, dfloat, dvfloat, dnumber ]
                        THEN
                            ak65s_num_into_tree (acv,
                                  a_ap_tree^[ first_node ].n_lo_level,
                                  act_node, sel_n);
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                ELSE
                    IF  a_ap_tree^[ first_node ].n_symb in [ s_between, s_notbetween ]
                    THEN
                        BEGIN
                        a65_look_for_datatypes (acv, dmli, sel_n);
                        left_node := sel_n;
                        IF  d_datatype in [ dfixed, dfloat, dvfloat, dnumber ]
                        THEN
                            BEGIN
                            ak65s_num_into_tree (acv,
                                  a_ap_tree^[ first_node ].n_lo_level,
                                  act_node, sel_n);
                            d_datatype := dunknown;
                            IF  a_ap_tree^[ sel_n ].n_symb = s_authid
                            THEN
                                sel_n := a_ap_tree^[ sel_n ].n_sa_level;
                            (*ENDIF*) 
                            IF  a_ap_tree^[ sel_n ].n_symb = s_tablename
                            THEN
                                sel_n := a_ap_tree^[ sel_n ].n_sa_level;
                            (*ENDIF*) 
                            right_node := a_ap_tree^[ sel_n ].n_sa_level;
                            a65_look_for_datatypes (acv, dmli, right_node);
                            IF  NOT (d_datatype in [ dfixed, dfloat, dvfloat, dnumber ])
                            THEN
                                a07_b_put_error (acv, e_incompatible_datatypes,
                                      a_ap_tree^[ right_node ].n_pos)
                                      (* ORACLE changes every x BETWEEN y AND z *)
                                      (* to x >= y AND x <= z, i.e.             *)
                                      (* charcol BETWEEN number and char        *)
                                      (* ==> NUM(charcol) >= number AND         *)
                                      (*         charcol  <= char               *)
                                      (* we don't do this, we present an error  *)
                                      (**)
                                      (* BEGIN   *)
                                      (* ak65s_num_into_tree (acv,   *)
                                      (*       a_ap_tree^[ sel_n ].n_sa_level,   *)
                                      (*       right_node, 0);   *)
                                      (* END   *)
                                      (**)
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            IF  a_ap_tree^[ sel_n ].n_symb = s_authid
                            THEN
                                sel_n := a_ap_tree^[ sel_n ].n_sa_level;
                            (*ENDIF*) 
                            IF  a_ap_tree^[ sel_n ].n_symb = s_tablename
                            THEN
                                sel_n := a_ap_tree^[ sel_n ].n_sa_level;
                            (*ENDIF*) 
                            d_datatype := dunknown;
                            right_node := a_ap_tree^[ sel_n ].n_sa_level;
                            a65_look_for_datatypes (acv, dmli, right_node);
                            IF  d_datatype in [ dfixed, dfloat, dvfloat, dnumber ]
                            THEN
                                a07_b_put_error (acv, e_incompatible_datatypes,
                                      a_ap_tree^[ right_node ].n_pos)
                                      (* see comment above *)
                                      (**)
                                      (*BEGIN   *)
                                      (*ak65s_num_into_tree (acv,   *)
                                      (*      a_ap_tree^[ first_node ].n_lo_level,   *)
                                      (*      act_node, left_node);   *)
                                      (*act_node := a_ap_tree^[ first_node ].n_lo_level;   *)
                                      (*ak65s_num_into_tree (acv,   *)
                                      (*      a_ap_tree^[ act_node ].n_sa_level,   *)
                                      (*      left_node, right_node);   *)
                                      (**)
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    ELSE
                        IF  a_ap_tree^[ first_node ].n_symb in [ s_in, s_notin ]
                        THEN
                            BEGIN
                            IF  (a_ap_tree^[ sel_n ].n_symb = s_all)
                                OR
                                (a_ap_tree^[ sel_n ].n_symb = s_any)
                            THEN
                                sel_n := a_ap_tree^[ sel_n ].n_sa_level;
                            (*ENDIF*) 
                            IF  NOT(
                                (a_ap_tree^[ sel_n ].n_proc = a63query_spec)
                                OR
                                ((a_ap_tree^[ sel_n ].n_proc = a63) AND
                                (acv.a_ap_tree^[ sel_n ].n_subproc = cak_x_start_union))
                                )
                            THEN
                                BEGIN
                                number_found := false;
                                only_numbers := true;
                                left_node := sel_n;
                                sel_n := a_ap_tree^[ sel_n ].n_lo_level;
                                WHILE sel_n <> 0 DO
                                    BEGIN
                                    d_datatype := dunknown;
                                    a65_look_for_datatypes (acv, dmli,
                                          a_ap_tree^[ sel_n ].n_lo_level);
                                    IF  d_datatype in [ dfixed, dfloat, dvfloat, dnumber ]
                                    THEN
                                        a_ap_tree^[ sel_n ].n_datatype := dfixed
                                    ELSE
                                        a_ap_tree^[ sel_n ].n_datatype := dcha;
                                    (*ENDIF*) 
                                    number_found := number_found OR
                                          (a_ap_tree^[ sel_n ].n_datatype = dfixed);
                                    only_numbers := only_numbers AND
                                          (a_ap_tree^[ sel_n ].n_datatype = dfixed);
                                    sel_n := a_ap_tree^[ sel_n ].n_sa_level;
                                    END;
                                (*ENDWHILE*) 
                                IF  number_found
                                THEN
                                    (* PTS 1116838 E.Z. *)
                                    IF  NOT only_numbers
                                    THEN
                                        BEGIN
                                        normpred := false;
                                        ak65split_in_clause (acv, first_node)
                                        END
                                    ELSE
                                        BEGIN
                                        ak65s_num_into_tree (acv,
                                              a_ap_tree^[ first_node ].n_lo_level,
                                              act_node, left_node);
                                        act_node := a_ap_tree^[ first_node ].n_lo_level;
                                        sel_n := a_ap_tree^[ act_node ].n_sa_level;
                                        sel_n := a_ap_tree^[ sel_n ].n_lo_level;
                                        WHILE sel_n <> 0 DO
                                            BEGIN
                                            IF  a_ap_tree^[ sel_n ].n_datatype <> dfixed
                                            THEN
                                                BEGIN
                                                ak65s_num_into_tree (acv,
                                                      a_ap_tree^[ sel_n ].n_lo_level,
                                                      a_ap_tree^[ sel_n ].n_lo_level, 0);
                                                a_ap_tree^[ sel_n ].n_datatype := dfixed;
                                                END;
                                            (*ENDIF*) 
                                            sel_n := a_ap_tree^[ sel_n ].n_sa_level;
                                            END
                                        (*ENDWHILE*) 
                                        END
                                    (*ENDIF*) 
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
    (*ENDWITH*) 
    d_datatype := dunknown;
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65predicate (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR first_node : integer; (* node of the operator *)
            mtabs_allowed  : boolean;
            VAR list_info  : list_elem_info);
 
VAR
      _normpred        : boolean;
      _snot_pred       : boolean;
      _snot_subq       : boolean;
      _types_ok        : boolean;
      _const_expr      : boolean;
      _act_node        : integer;
      _pred_node       : integer;
      _sel_n           : integer; (* start node of right side. *)
      _col_node        : integer; (* used to change left   *)
      _left_side       : integer; (* and right side of     *)
      _right_side      : integer; (* a comparison operator *)
      _operator        : tgg00_StackOpType;
      _convert_t       : tak_convert_type;
      _colin           : tak00_scolinf;
      _dtype_n         : integer;
      _list_node       : integer;
      _list_cnt        : integer;
      _this_size       : integer;
      _left_size       : integer;
      _startstack      : integer;
      _oldjoincnt      : integer;
      _field_found     : tsp00_Int2;
      _xi              : integer;
      _used_tab_cnt    : integer;
      _used_tables     : tak_joinset;
 
BEGIN
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    dmli.d_const_value_expr := (acv.a_is_ddl = no_ddl);
    dmli.d_param_st_index   := 0;
    dmli.d_param_st_begin   := 0;
    dmli.d_is_parameter_only:= false;
    IF  ( dmli.d_join )
    THEN
        BEGIN
        _oldjoincnt := dmli.d_joins.jrc_cnt;
        ak65init_one_join(dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ]);
        END;
    (*ENDIF*) 
    dmli.d_datatype  := dunknown;
    _pred_node   := first_node;
    _act_node    := first_node;
    _snot_subq   := ak65subq_se (acv, first_node);
    _snot_pred   := false;
    IF  ( NOT _snot_subq )
    THEN
        IF  acv.a_ap_tree^[ first_node ].n_symb = s_not
        THEN
            BEGIN
            _snot_pred  := true;
            first_node := acv.a_ap_tree^[ first_node ].n_sa_level
            END;
        (*===========================================================*)
        (* If left side of a comparison operator is a value or a     *)
        (* parameter name and the right side is a column             *)
        (* specification then change left and right side.           .*)
        (* So the optimizer can use key or index conditions.         *)
        (*===========================================================*)
        (*ENDIF*) 
    (*ENDIF*) 
    ;
&   ifdef trace
    t01int4 (ak_sem, 'first_node  ', first_node);
&   endif
    IF  ( acv.a_ap_tree^[ first_node ].n_symb in
        [ s_equal, s_greater, s_greater_or_eq,
        s_less, s_less_or_eq, s_unequal ] )
    THEN
        BEGIN
        _const_expr := true;
        _left_side  := acv.a_ap_tree^[ first_node ].n_lo_level;
        ak65is_const_expr( acv.a_ap_tree, _left_side,
              c_ignore_sa_level, _const_expr );
&       ifdef trace
        t01bool(ak_sem, 'left const? ', _const_expr );
&       endif
        _right_side := acv.a_ap_tree^[ _left_side ].n_sa_level;
        IF  ( _const_expr ) AND
            ( acv.a_ap_tree^[ _right_side ].n_proc = no_proc )
        THEN
            BEGIN
            ak65is_const_expr( acv.a_ap_tree, _right_side,
                  NOT c_ignore_sa_level, _const_expr );
            IF  ( NOT _const_expr )
            THEN
                (* predicate: <const> op <variable> *)
                BEGIN
&               ifdef trace
                t01sname(ak_sem, 'turn predica');
&               endif
                _col_node := _right_side;
                IF  acv.a_ap_tree^[ _col_node ].n_symb = s_authid
                THEN (* columnspecification with authname *)
                    _col_node := acv.a_ap_tree^[ _col_node ].n_sa_level;
                (*ENDIF*) 
                IF  acv.a_ap_tree^[ _col_node ].n_symb = s_tablename
                THEN (* columnspecification with tablename *)
                    _col_node := acv.a_ap_tree^[ _col_node ].n_sa_level;
                (*ENDIF*) 
                ;
                (* change left and right side of comparison operator *)
                acv.a_ap_tree^[ _col_node ].n_sa_level   := _left_side;
                acv.a_ap_tree^[ first_node ].n_lo_level := _right_side;
                acv.a_ap_tree^[ _left_side ].n_sa_level  := 0;
                (* change the comparison operator *)
                CASE acv.a_ap_tree^[ first_node ].n_symb OF
                    s_greater :
                        acv.a_ap_tree^[ first_node ].n_symb := s_less;
                    s_greater_or_eq :
                        acv.a_ap_tree^[ first_node ].n_symb := s_less_or_eq;
                    s_less :
                        acv.a_ap_tree^[ first_node ].n_symb := s_greater;
                    s_less_or_eq :
                        acv.a_ap_tree^[ first_node ].n_symb := s_greater_or_eq;
                    OTHERWISE
                        BEGIN
                        END;
                    END;
                (*ENDCASE*) 
&               ifdef TRACE
                t01aptree (ak_sem, acv.a_ap_tree^, acv.a_scv_index,
                      acv.a_first_hint_node);
&               endif
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    _normpred    := false;
    WITH acv.a_ap_tree^[ first_node ] DO
        BEGIN
        IF  n_symb = s_or
        THEN
            BEGIN
            IF  mtabs_allowed
            THEN
                dmli.d_first_tab := 0;
            (*ENDIF*) 
            ak65se_condition (acv, dmli, first_node,
                  NOT c_mtabs_allowed, list_info);
            END
        ELSE
            IF  n_symb = s_and
            THEN
                IF  _snot_pred OR _snot_subq
                THEN
                    BEGIN
                    IF  mtabs_allowed
                    THEN
                        dmli.d_first_tab := 0;
                    (*ENDIF*) 
                    ak65boolean_term (acv, dmli, first_node,
                          NOT c_mtabs_allowed, list_info)
                    END
                ELSE
                    ak65boolean_term (acv, dmli, first_node,
                          mtabs_allowed, list_info)
                (*ENDIF*) 
            ELSE (* n_symb <> s_or and n_symb <> s_and *)
                BEGIN
                _normpred := true;
                _act_node := acv.a_ap_tree^[ first_node ].n_lo_level
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  _normpred
        THEN (* n_symb <> s_or and n_symb <> s_and *)
            BEGIN
            IF  (acv.a_ap_tree^[ _act_node ].n_proc = a64) AND
                (acv.a_ap_tree^[ _act_node ].n_subproc  = cak_x_escape)
            THEN
                _act_node := acv.a_ap_tree^[ _act_node ].n_lo_level;
            (*ENDIF*) 
            dmli.d_allowed := may_more_tabs;
            IF  dmli.d_join
            THEN
                BEGIN
                dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                      jo_recs[ 1 ].jop_startstack :=
                      acv.a_mblock.mb_qual^.mfirst_free;
                dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                      jo_partno := 1
                END;
            (*ENDIF*) 
            _colin.sci_len := 0;
&           ifdef TRACE
            t01int4 (ak_sem, 'act_nodepred', _act_node);
&           endif
            IF  acv.a_ap_tree^[ first_node ].n_symb = s_exists
            THEN
                BEGIN
                (* ANSI allows 'HAVING EXISTS' *)
                ak65sub_op_set (acv, c_all, c_any, op_eq, _act_node);
                (* op_none => eop is used for not/and => Problems *)
                IF  NOT dmli.d_use_sub
                THEN
                    a01_dt_put_datatype_node (acv,
                          acv.a_ap_tree^[ _act_node ].n_sa_level,
                          dmli.d_datatype, 0, 0, 0);
                (*ENDIF*) 
                END
            ELSE (* ap_tree[ first_node ].n_symb <> s_exists *)
                BEGIN
                IF  (acv.a_sqlmode = sqlm_oracle) AND
                    (acv.a_ap_tree^[ first_node ].n_symb in
                    [ s_equal, s_greater, s_greater_or_eq,
                    s_less, s_less_or_eq, s_unequal,
                    s_between, s_notbetween,
                    s_in, s_notin ])
                THEN
                    BEGIN
                    (* PTS 1116838 E.Z. *)
                    ak65oracle_typecheck (acv, dmli, list_info,
                          first_node, _normpred);
                    IF  _normpred
                    THEN
                        BEGIN
                        _act_node := acv.a_ap_tree^[ first_node ].n_lo_level;
                        IF  (acv.a_ap_tree^[ _act_node ].n_proc = a64) AND
                            (acv.a_ap_tree^[ _act_node ].n_pos  = cak_x_escape)
                        THEN
                            _act_node := acv.a_ap_tree^[ _act_node ].n_lo_level;
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  NOT _normpred
                THEN
                    BEGIN
                    (* change of predicate done for oracle-mode *)
                    WITH acv.a_ap_tree^[ first_node ] DO
                        IF  n_symb = s_or
                        THEN
                            BEGIN
                            IF  mtabs_allowed
                            THEN
                                dmli.d_first_tab := 0;
                            (*ENDIF*) 
                            ak65se_condition (acv, dmli, first_node,
                                  NOT c_mtabs_allowed, list_info);
                            END
                        ELSE
                            IF  n_symb = s_and
                            THEN
                                IF  _snot_pred OR _snot_subq
                                THEN
                                    BEGIN
                                    IF  mtabs_allowed
                                    THEN
                                        dmli.d_first_tab := 0;
                                    (*ENDIF*) 
                                    ak65boolean_term (acv, dmli, first_node,
                                          NOT c_mtabs_allowed, list_info)
                                    END
                                ELSE
                                    ak65boolean_term (acv, dmli, first_node,
                                          mtabs_allowed, list_info)
                                (*ENDIF*) 
                            (*ENDIF*) 
                        (*ENDIF*) 
                    (*ENDWITH*) 
                    END
                ELSE
                    BEGIN
                    WITH acv.a_ap_tree^[ _act_node ] DO
                        IF  (n_proc = a56) AND (n_subproc = cak_x_value_list)
                        THEN (* Here comes a list of values. *)
                            WITH acv.a_ap_tree^ [n_lo_level] DO
                                BEGIN
                                _list_node := n_sa_level;
                                _act_node  := n_lo_level
                                END
                            (*ENDWITH*) 
                        ELSE (* Here comes a single value. *)
                            _list_node := 0;
                        (*ENDIF*) 
                    (*ENDWITH*) 
                    (* Let's have a look at the (b)right side of life. *)
                    _sel_n := acv.a_ap_tree^[ first_node ].n_lo_level;
                    IF  acv.a_ap_tree^[ _sel_n ].n_symb = s_authid
                    THEN
                        _sel_n := acv.a_ap_tree^[ _sel_n ].n_sa_level;
                    (*ENDIF*) 
                    IF  acv.a_ap_tree^[ _sel_n ].n_symb = s_tablename
                    THEN
                        _sel_n := acv.a_ap_tree^[ _sel_n ].n_sa_level;
                    (*ENDIF*) 
                    _sel_n := acv.a_ap_tree^[ _sel_n ].n_sa_level;
                    IF  acv.a_ap_tree^[ _sel_n ].n_symb = s_tablename
                    THEN
                        _sel_n := acv.a_ap_tree^[ _sel_n ].n_sa_level;
                    (*ENDIF*) 
                    IF  (acv.a_ap_tree^[ _sel_n ].n_symb = s_all) OR
                        (acv.a_ap_tree^[ _sel_n ].n_symb = s_any)
                    THEN
                        _sel_n := acv.a_ap_tree^[ _sel_n ].n_sa_level;
                    (*ENDIF*) 
                    IF  (acv.a_ap_tree^[ _sel_n ].n_proc = a63query_spec)
                        OR
                        ((acv.a_ap_tree^[ _sel_n ].n_proc = a63) AND
                        ( acv.a_ap_tree^[ _sel_n ].n_subproc = cak_x_start_union))
                    THEN (* If the right side is a subquery, there is a *)
                        (*  list of column datatypes at the same level. *)
                        _dtype_n := acv.a_ap_tree^[ _sel_n ].n_sa_level
                    ELSE
                        _dtype_n := -1;
                    (*ENDIF*) 
&                   ifdef TRACE
                    t01int4 (ak_sem, 'first_node  ', first_node);
                    t01int4 (ak_sem, 'sel_n       ', _sel_n);
                    t01int4 (ak_sem, 'n_proc      ',
                          ord (acv.a_ap_tree^[_sel_n].n_proc));
                    t01int4 (ak_sem, 'dtype_n     ', _dtype_n);
&                   endif
                    _left_size := 0;
                    _list_cnt  := 1;
                    WHILE _list_cnt <> 0 DO
                        BEGIN (* there are further values to evaluate. *)
                        IF  acv.a_ap_tree^[ _act_node ].n_symb in
                            [ s_columnname, s_tablename, s_authid ]
                        THEN
                            _field_found := acv.a_mblock.mb_qual^.mfirst_free
                        ELSE
                            _field_found := 0;
                        (*ENDIF*) 
                        dmli.d_colptr           := NIL;
                        dmli.d_colindex         := 0;
                        dmli.d_expand           := 0;
                        dmli.d_change_date_time := false;
                        ak65not_first_val_expr (acv, dmli, _colin, _act_node);
                        IF  acv.a_returncode = cak_e_parameter
                        THEN
                            BEGIN
                            acv.a_returncode         := 0;
                            dmli.d_is_parameter_only := true;
                            a65_look_for_datatypes (acv, dmli, _act_node);
                            IF  dmli.d_datatype = dunknown
                            THEN
                                a07_b_put_error (acv, e_without_datatypes,
                                      acv.a_ap_tree^[ _act_node ].n_pos)
                            ELSE
                                IF  acv.a_returncode = 0
                                THEN
                                    BEGIN
                                    _colin.sci_len := 0;
                                    dmli.d_colptr      := dmli.d_colbuf;
                                    ak65not_first_val_expr (acv, dmli,
                                          _colin, _act_node);
                                    END;
                                (* in Case of :a = column4 *)
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        IF  ( acv.a_returncode = 0 )
                        THEN
                            BEGIN
                            IF  _field_found > 0
                            THEN
                                dmli.d_colptr   := dmli.d_colbuf;
                            (*ENDIF*) 
                            IF  dmli.d_join
                            THEN
                                WITH dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ].
                                     jo_recs[ 1 ] DO
                                    IF  ((jop_tableno > 0) AND
                                        NOT dmli.d_joins.jrc_joinarr
                                        [ dmli.d_joins.jrc_cnt ].jo_no_join)
                                    THEN
                                        BEGIN
                                        jop_cntstack := acv.a_mblock.mb_qual^.mfirst_free-jop_startstack;
                                        jop_outpos   := 0;
                                        IF  ((jop_cntstack > 1) OR
                                            NOT (acv.a_mblock.mb_st^
                                            [jop_startstack].eop in
                                            [ op_none, op_unique, op_unique_desc,
                                            op_order_asc, op_order_desc, op_ascii ]))
                                        THEN
                                            BEGIN
                                            jop_propset := [  ];
                                            WITH _colin DO
                                                BEGIN
                                                jop_datatyp  := sci_typ;
                                                IF  sci_iolen >= mxsp_key -
                                                    sizeof (tsp00_Int4)
                                                THEN
                                                    BEGIN
                                                    jop_inoutlen := 0;
                                                    END
                                                ELSE
                                                    BEGIN
                                                    jop_inoutlen := sci_iolen;
                                                    END;
                                                (*ENDIF*) 
                                                END;
                                            (*ENDWITH*) 
                                            IF  jop_datatyp in [ dfixed,
                                                dfloat, dvfloat ]
                                            THEN
                                                BEGIN
                                                jop_datatyp  := dfloat;
                                                jop_inoutlen := NUMBER_MXGG04;
                                                END
                                            (*ENDIF*) 
                                            END
                                        (*ENDIF*) 
                                        END
                                    ELSE
                                        IF  ( jop_tableno <> 0 )
                                        THEN
                                            dmli.d_joins.
                                                  jrc_joinarr[ dmli.d_joins.
                                                  jrc_cnt ].jo_no_join := true
                                        (*ENDIF*) 
                                    (*ENDIF*) 
                                (*ENDWITH*) 
                            (*ENDIF*) 
                            END
                        ELSE
                            IF  ((acv.a_returncode =
                                a07_return_code (e_command_for_string_not_allow,
                                acv.a_sqlmode))                              AND
                                (_field_found > 0)                        AND
                                (*(acv.a_init_ex_kind = only_parsing) AND*)
                                ( ((acv.a_ap_tree^[ first_node ].n_symb in
                                [s_is_null, s_is_not_null])              AND
                                (acv.a_sqlmode <> sqlm_ansi))
                                OR
                                ((acv.a_ap_tree^[ first_node ].n_symb in
                                [ s_equal, s_greater,
                                s_greater_or_eq,
                                s_less, s_less_or_eq, s_unequal ])       AND
                                (acv.a_ap_tree^[ _sel_n ].n_symb = s_default) AND
                                (acv.a_sqlmode = sqlm_internal))))
                            THEN
                                BEGIN
                                acv.a_returncode := 0;
                                acv.a_errorpos := 0;
                                dmli.d_colptr    := dmli.d_colbuf
                                END;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        IF  (_list_node <> 0) OR (_list_cnt > 1)
                        THEN      (* We are constructing a list for     *)
                            BEGIN (* the comparison with a sub select.  *)
                            IF  (dmli.d_datatype in [ ddate, dtime, dtimestamp ])
                                AND (_dtype_n > 0)
                            THEN      (* We must change the format of every *)
                                BEGIN (* date/time expression on the left   *)
                                (*       before expanding or concating it.  *)
                                _startstack := acv.a_mblock.mb_qual^.mfirst_free;
                                a65ch_format (acv, dmli, _startstack,
                                      _colin, dcha, dmli.d_datatype);
                                END;
                            (* PTS 1000985/1001162 E.Z. *)
                            (*ENDIF*) 
                            IF  (_dtype_n > 0)
                            THEN      (* Except for corelated subqueries    *)
                                BEGIN (* in selects we must expand the val. *)
                                WITH acv.a_ap_tree^[ _dtype_n ] DO
                                    BEGIN
                                    _types_ok := a65_datatypes_ok (acv, dmli,
                                          n_datatype, n_length, dmli.d_datatype,
                                          c_is_subquery, _sel_n,
                                          acv.a_ap_tree^[ _act_node ].n_pos,
                                          c_convert, _convert_t);
                                    IF  _convert_t <> conv_none
                                    THEN
                                        BEGIN
                                        CASE _convert_t OF
                                            conv_unicode_to_ascii :
                                                dmli.d_datatype := dcha;
                                            conv_ascii_to_unicode :
                                                dmli.d_datatype := dunicode;
                                            OTHERWISE
                                                BEGIN
                                                END
                                            END;
                                        (*ENDCASE*) 
                                        IF  dmli.d_datatype = dunicode
                                        THEN
                                            _colin.sci_iolen := (2*_colin.sci_len)+1
                                        ELSE
                                            _colin.sci_iolen := _colin.sci_len+1
                                        (*ENDIF*) 
                                        END;
                                    (*ENDIF*) 
                                    _this_size := n_length;
                                    _dtype_n   := n_sa_level
                                    END;
                                (*ENDWITH*) 
                                (* We expand the operand to the width   *)
                                (* of the corresponding selected value. *)
                                a641string_set_operator (acv, op_b_expand,
                                      _this_size, 1, chr(1), chr(0))
                                END
                            ELSE
                                _this_size := _colin.sci_iolen;
                            (*ENDIF*) 
&                           ifdef trace
                            t01int4 (ak_sem, 'this_size   ', _this_size);
                            t01int4 (ak_sem, 'sci_iolen   ', _colin.sci_iolen);
                            t01int4 (ak_sem, 'sci_len     ', _colin.sci_len);
&                           endif
                            _left_size := _left_size + _this_size;
                            IF  (_list_cnt > 1) AND (_dtype_n >= 0)
                            THEN (* We concat every but the first operand *)
                                (*  to the end of the preceeding one.     *)
                                a641string_set_operator (acv, op_b_concat,
                                      _left_size, _this_size, chr(1), chr(0))
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        WITH list_info.elem[_list_cnt] DO
                            BEGIN (* Now save the evaluated datatype. *)
                            datatype  := dmli.d_datatype;
                            datalen   := _colin.sci_len;
                            datafrac  := _colin.sci_frac + cak_frac_offset;
                            is_field  := (_field_found > 0);
                            inout_len := _colin.sci_iolen;
                            pos       := acv.a_ap_tree^[ _act_node ].n_pos
                            END;
                        (*ENDWITH*) 
                        IF  _list_node <> 0
                        THEN (* There is another value in the list. *)
                            WITH acv.a_ap_tree^[ _list_node ] DO
                                BEGIN
                                _list_cnt   := succ (_list_cnt);
                                dmli.d_datatype := dunknown;
                                _act_node   := n_lo_level;
                                _list_node  := n_sa_level
                                END
                            (*ENDWITH*) 
                        ELSE      (* Let's finish this value list. *)
                            BEGIN
                            list_info.count := _list_cnt;
                            _list_cnt        := 0 (* flag for loop exit. *)
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDWHILE*) 
                    IF  acv.a_returncode = 0
                    THEN
                        BEGIN
                        IF  (acv.a_ap_tree^[ first_node ].n_symb in
                            [ s_equal, s_greater, s_greater_or_eq,
                            s_less, s_less_or_eq, s_unequal,
                            s_is_null, s_is_not_null, s_is_true, s_is_false ])
                        THEN
                            ak65compare_predicate (acv, dmli,
                                  _colin, first_node, _snot_pred,
                                  _field_found, list_info)
                        ELSE
                            BEGIN
                            (* h.b. PTS 1104314
                                  m_rowno_allowed := acv.a_rowno_allowed;
                                  acv.a_rowno_allowed := false;
                                  *)
                            ak65diff_predicates (acv, dmli, _colin,
                                  first_node, _snot_pred,
                                  _field_found, list_info);
                            (* acv.a_rowno_allowed := m_rowno_allowed *)
                            END;
                        (*ENDIF*) 
                        WITH dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ],
                             acv.a_ap_tree^[ first_node ] DO
                            IF  (n_pos = cak_x_left_outer_join) AND
                                (jo_recs [ 1 ].jop_tableno <  n_length) AND
                                ((jo_recs [ 2 ].jop_tableno < n_length) OR
                                (jo_recs [ 1 ].jop_tableno = cak68_join_value))
                            THEN
                                a07_b_put_error (acv , e_outer_join_not_allowed, 1);
                            (*ENDIF*) 
                        (*ENDWITH*) 
                        IF  dmli.d_joins.
                            jrc_joinarr[ dmli.d_joins.jrc_cnt ].jo_no_join
                        THEN
                            dmli.d_arith_where := true
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
    IF  _snot_pred OR _snot_subq
    THEN
        BEGIN
        a65_set_operator (acv, op_not);
        _used_tables  := [ ];
        _used_tab_cnt := 0;
        IF  dmli.d_join AND (dmli.d_joins.jrc_cnt > _oldjoincnt + 1)
        THEN
            BEGIN
            _xi := _oldjoincnt;
            WHILE (_xi < dmli.d_joins.jrc_cnt) DO
                WITH dmli.d_joins.jrc_joinarr[ _xi ] DO
                    BEGIN
                    IF  (NOT (jo_recs[ 1 ].jop_tableno in _used_tables))
                    THEN
                        BEGIN
                        _used_tab_cnt := succ (_used_tab_cnt);
                        _used_tables  := _used_tables +
                              [jo_recs[ 1 ].jop_tableno];
                        END;
                    (*ENDIF*) 
                    IF  (jo_recs[ 2 ].jop_tableno <>
                        cak68_join_value) AND
                        (NOT (jo_recs[ 2 ].jop_tableno in _used_tables))
                    THEN
                        BEGIN
                        _used_tab_cnt := succ (_used_tab_cnt);
                        _used_tables  := _used_tables +
                              [jo_recs[ 2 ].jop_tableno ];
                        END;
                    (*ENDIF*) 
                    IF  _used_tab_cnt > 1
                    THEN
                        BEGIN
                        dmli.d_arith_where := true;
                        _xi := dmli.d_joins.jrc_cnt;
                        END;
                    (*ENDIF*) 
                    _xi := succ (_xi);
                    END;
                (*ENDWITH*) 
            (*ENDWHILE*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  dmli.d_join
    THEN
        BEGIN
        ak65analyze_joinarr (acv, dmli, first_node, _act_node);
        IF  _snot_pred OR _snot_subq
        THEN
            BEGIN
&           ifdef trace
            t01name(ak_sem, 'reject new joins  ');
&           endif
            dmli.d_joins.jrc_cnt := _oldjoincnt;
            ak65init_one_join(dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ]);
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65s_num_into_tree (
            VAR acv    : tak_all_command_glob;
            VAR new_n  : tsp00_Int2;
            left_node  : integer;
            right_node : integer);
 
VAR
      put_node : tsp00_Int2;
 
BEGIN
WITH acv, a_scv DO
    BEGIN
    sc_symb := s_num;
    sc_sypos := a_ap_tree^[ left_node ].n_pos;
    a01_function_put (acv, put_node);
    WITH a_ap_tree^[ put_node ] DO
        BEGIN
        n_sa_level := right_node;
        n_lo_level := left_node
        END;
    (*ENDWITH*) 
    new_n := put_node;
    put_node := left_node;
    WHILE a_ap_tree^[ put_node ].n_sa_level <> right_node DO
        put_node := a_ap_tree^[ put_node ].n_sa_level;
    (*ENDWHILE*) 
    a_ap_tree^[ put_node ].n_sa_level := 0;
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65se_condition (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR first_node : integer;
            mtabs_allowed  : boolean;
            VAR list_info : list_elem_info);
 
VAR
      snot_se_con : boolean;
      act_node    : integer;
      oldjoincnt  : integer;
      stentryno   : integer;
 
BEGIN
WITH acv, a_mblock, mb_qual^, dmli DO
    IF  a_returncode = 0
    THEN
        BEGIN
&       ifdef TRACE
        IF  d_join
        THEN
            a683_output (ak_sem, dmli);
&       endif
        (*ENDIF*) 
        IF  d_join
        THEN
            oldjoincnt := d_joins.jrc_cnt;
        (*ENDIF*) 
        d_joins.jrc_joinarr[ d_joins.jrc_cnt ].jo_col_upd_stat := 0;
        snot_se_con := ak65subq_se (acv, first_node);
        WITH a_ap_tree^[ first_node ] DO
            IF  n_symb <> s_or
            THEN
                IF  snot_se_con
                THEN
                    BEGIN
                    IF  mtabs_allowed
                    THEN
                        d_first_tab := 0;
                    (*ENDIF*) 
                    ak65boolean_term (acv, dmli, first_node,
                          NOT c_mtabs_allowed, list_info);
                    IF  d_first_tab < 0
                    THEN
                        d_arith_where := true;
                    (*ENDIF*) 
                    IF  d_join
                    THEN
                        BEGIN
                        IF  (d_joins.jrc_cnt > oldjoincnt) AND
                            (NOT ak65only_jvalue_found (dmli, oldjoincnt))
                        THEN
                            BEGIN
                            d_arith_where := true;
                            d_joins.jrc_cnt     := oldjoincnt;
                            d_joins.jrc_joinarr[ d_joins.jrc_cnt ].jo_col_upd_stat := 0;
                            WITH d_joins, jrc_joinarr[ jrc_cnt ] DO
                                BEGIN
                                ak65init_one_join(jrc_joinarr[ jrc_cnt ]);
                                END
                            (*ENDWITH*) 
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    ak65boolean_term (acv, dmli, first_node, mtabs_allowed,
                          list_info)
                (*ENDIF*) 
            ELSE
                BEGIN
                act_node := n_lo_level;
                ak65boolean_term (acv, dmli, act_node,
                      NOT c_mtabs_allowed, list_info);
                stentryno := mfirst_free;
                IF  stentryno >= 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);
                    act_node    := a_ap_tree^[ act_node ].n_sa_level;
                    ak65boolean_term (acv, dmli, act_node,
                          NOT c_mtabs_allowed, list_info);
                    a65_set_operator (acv, op_or);
                    a61_set_jump (a_mblock, stentryno,
                          st_jump_true)
                    END;
                (*ENDIF*) 
                IF  d_join
                THEN
                    BEGIN
                    IF  d_first_tab < 0
                    THEN
                        d_arith_where := true;
                    (*ENDIF*) 
                    IF  (d_joins.jrc_cnt > oldjoincnt) AND
                        (NOT ak65only_jvalue_found (dmli, oldjoincnt))
                    THEN
                        BEGIN
                        IF  d_outer_join AND
                            ak65outer_cond_found (dmli, oldjoincnt)
                        THEN
                            a07_b_put_error (acv, e_outer_join_not_allowed, 1)
                        ELSE
                            BEGIN
                            d_arith_where    := true;
                            d_joins.jrc_cnt     := oldjoincnt;
                            WITH d_joins, jrc_joinarr[ jrc_cnt ] DO
                                BEGIN
                                ak65init_one_join(jrc_joinarr[ jrc_cnt ]);
                                END;
                            (*ENDWITH*) 
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END; (* PTS 1113326 end *)
            (*ENDIF*) 
        (*ENDWITH*) 
        IF  snot_se_con
        THEN
            a65_set_operator (acv, op_not)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65set_like_operator (
            VAR acv         : tak_all_command_glob;
            operator        : tgg00_StackOpType;
            like_expression : boolean;
            ord_typ         : integer;
            escape          : boolean);
 
BEGIN
IF  acv.a_returncode = 0
THEN
    WITH acv, a_mblock, mb_qual^ DO
        BEGIN
        IF  mfirst_free > mb_st_max
        THEN
            a07_b_put_error (acv, e_too_many_mb_stackentries, -mb_st_max)
        ELSE
            BEGIN
            mqual_cnt := succ(mqual_cnt);
            WITH mb_st^ [mfirst_free] DO
                BEGIN
                etype := st_op;
                eop := operator;
                epos := ord(acv.a_sqlmode);
                ecol_tab[ 2 ] := chr(0);
                IF  like_expression
                THEN
                    BEGIN
                    elen_var := 1;
                    ecol_tab[ 1 ] := chr(ord_typ);
                    IF  escape
                    THEN
                        ecol_tab[ 2 ] := chr(1)
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    elen_var := 0;
                    ecol_tab[ 1 ] := chr(0)
                    END
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
            mfirst_free := succ(mfirst_free)
            END
        (*ENDIF*) 
        END
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65sub_op_set (
            VAR acv    : tak_all_command_glob;
            all        : boolean;
            any        : boolean;
            operator   : tgg00_StackOpType;
            first_node : integer);
 
VAR
      subquery_count : integer;
      itree          : tgg00_FileId;
 
BEGIN
IF  acv.a_returncode = 0
THEN
    WITH acv, a_mblock, mb_qual^ DO
        BEGIN
        IF  mfirst_free > mb_st_max
        THEN
            a07_b_put_error (acv, e_too_many_mb_stackentries, -mb_st_max)
        ELSE
            BEGIN
            subquery_count := acv.a_ap_tree^[ first_node ].n_length;
            msubquery := true;
            WITH mb_st^ [mfirst_free] DO
                BEGIN
                mqual_cnt := succ(mqual_cnt);
                etype := st_subquery;
                eop := operator;
                WITH a_mblock, mb_data^ DO
                    BEGIN
                    a660construct_subtree (acv, itree, subquery_count);
&                   ifdef trace
                    t01int4 (ak_sem, 'first_node  ', first_node);
&                   endif
                    IF  mb_data_len + FILE_ID_MXGG00 <= mb_data_size
                    THEN
                        BEGIN
                        g10mv ('VAK65 ',   3,    
                              sizeof(itree), mb_data_size, @itree, 1,
                              @mbp_buf, mb_data_len+1, sizeof(itree),
                              a_returncode);
                        epos        := mb_data_len+1;
                        mb_data_len := mb_data_len+FILE_ID_MXGG00;
                        END
                    ELSE
                        a07_b_put_error (acv , e_too_many_mb_data, 1)
                    (*ENDIF*) 
                    END;
                (*ENDWITH*) 
                elen_var := - cgg04_cdistinct_bytes - 4;
                IF  all
                THEN
                    ecol_tab[ 1 ] := chr(1)
                ELSE
                    ecol_tab[ 1 ] := chr(0);
                (*ENDIF*) 
                IF  any
                THEN
                    ecol_tab[ 2 ] := chr(1)
                ELSE
                    ecol_tab[ 2 ] := chr(0);
                (*ENDIF*) 
                END
            (*ENDWITH*) 
            END;
        (*ENDIF*) 
        mfirst_free := succ(mfirst_free)
        END
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
(* PTS 1116169 E.Z. *)
(*------------------------------*) 
 
PROCEDURE
      a65subq_get_val (
            VAR acv    : tak_all_command_glob;
            first_node : integer;
            iolen      : integer);
 
VAR
      subquery_count : integer;
      needed_len     : integer;
      itree          : tgg00_FileId;
 
BEGIN
IF  acv.a_returncode = 0
THEN
    WITH acv, a_mblock, mb_qual^ DO
        BEGIN
        IF  mfirst_free > mb_st_max
        THEN
            a07_b_put_error (acv, e_too_many_mb_stackentries, -mb_st_max)
        ELSE
            BEGIN
            subquery_count := acv.a_ap_tree^[ first_node ].n_length;
            msubquery := true;
            WITH mb_st^ [mfirst_free] DO
                BEGIN
                mqual_cnt := succ(mqual_cnt);
                etype := st_subquery;
                eop := op_get_sub_value;
                WITH a_mblock, mb_data^ DO
                    BEGIN
                    a660construct_subtree (acv, itree, subquery_count);
&                   ifdef trace
                    t01int4 (ak_sem, 'first_node  ', first_node);
&                   endif
                    IF  iolen < FILE_ID_MXGG00
                    THEN
                        needed_len := FILE_ID_MXGG00
                    ELSE
                        needed_len := iolen;
                    (*ENDIF*) 
                    IF  mb_data_len + needed_len <= mb_data_size
                    THEN
                        BEGIN
                        g10mv ('VAK65 ',   4,    
                              sizeof(itree), mb_data_size, @itree, 1,
                              @mbp_buf, mb_data_len+1, sizeof(itree),
                              a_returncode);
                        epos        := mb_data_len+1;
                        mb_data_len := mb_data_len+needed_len;
                        END
                    ELSE
                        a07_b_put_error (acv , e_too_many_mb_data, 1)
                    (*ENDIF*) 
                    END;
                (*ENDWITH*) 
                elen_var := - cgg04_cdistinct_bytes - 4;
                ecol_pos := iolen;
                END
            (*ENDWITH*) 
            END;
        (*ENDIF*) 
        mfirst_free := succ(mfirst_free)
        END
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65try_like_optimization (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR first_node : integer;
            operator       : tgg00_StackOpType;
            col_len        : integer;
            keep_part_pos  : integer);
 
VAR
      rest_blanks          : boolean;
      star_any_class_found : boolean;
      ix                   : tsp00_Int2;
      i                    : tsp00_Int4;
      j                    : tsp00_Int4;
      k                    : tsp00_Int4;
      curr_data_len        : tsp00_Int4;
      star_offset          : tsp00_Int4;
      star_found_len       : tsp00_Int4;
      value_len            : tsp00_Int4;
      colin                : tak00_scolinf;
 
BEGIN
WITH acv.a_mblock, mb_data^ DO
    BEGIN
    IF  ((acv.a_ex_kind = only_parsing) AND
        (acv.a_ap_tree^[ first_node ].n_symb = s_parameter_name))
    THEN
        BEGIN
        (* ============================================ *)
        (* like value is a parameter that will only be  *)
        (* furnished at execution time. For an optional *)
        (* optimization at that time the following      *)
        (* stack pattern is provided:                   *)
        (* n    st_dummy, op_none, epos = keep_partpos  *)
        (* n+1  st_dummy, op_none, epos = keep_partpos  *)
        (* n+2  st_value, op_none, epos = keep_partpos  *)
        (* n+3  st_op   , op_like, epos = keep_partpos  *)
        (* ============================================ *)
        mb_st^[ mb_qual^.mfirst_free-1 ].etype := st_dummy;
        colin.sci_len := 0;
        dmli.d_like_part := 2;
        a640not_first_factor (acv, dmli, colin, first_node);
        mb_st^[ mb_qual^.mfirst_free-1 ].etype := st_dummy;
        colin.sci_len := 0;
        dmli.d_like_part := 3;
        a640not_first_factor (acv, dmli, colin, first_node); (* st_value *)
        ak65set_like_operator (acv, operator,
              NOT c_like_expression, 0, NOT c_escape);
        dmli.d_like := false;
        END
    ELSE
        IF  NOT (acv.a_ap_tree^[ first_node ].n_symb
            in [ s_authid, s_tablename,s_columnname ])
        THEN
            WITH mb_qual^ DO
                BEGIN
                k := mb_st^[ mfirst_free-1 ].elen_var;
                IF  (k > 1)
                THEN
                    BEGIN
                    curr_data_len := mb_data_len;
                    i := curr_data_len-k+2; (* first position after undef-byte *)
                    star_any_class_found := false;
                    star_found_len       := 0;
                    IF  mbp_buf[mb_st^ [mfirst_free-1].epos]
                        = csp_unicode_def_byte
                    THEN
                        BEGIN
                        i := succ(i);
                        WHILE (i <= curr_data_len) AND NOT star_any_class_found DO
                            IF  ((mbp_buf[i] = csp_star1) OR
                                ( mbp_buf[i] = csp_any1)
                                (* PTS 1123349 E.Z. *)
                                (*
                                      OR
                                      ( mbp_buf[i] = csp_cclass)
                                      *)
                                )
                                AND (mbp_buf[ i-1 ] = csp_unicode_mark)
                            THEN
                                BEGIN
                                star_any_class_found := true;
                                star_found_len       :=
                                      i - (curr_data_len - k);
                                ix                   := 2;
                                END
                            ELSE
                                i := i+2;
                            (*ENDIF*) 
                        (*ENDWHILE*) 
                        END
                    ELSE
                        WHILE (i <= curr_data_len) AND NOT star_any_class_found DO
                            IF  (mbp_buf[i] = csp_star1) OR
                                (mbp_buf[i] = csp_any1)
                                (* PTS 1123349 E.Z. *)
                                (*
                                      OR
                                      (mbp_buf[i] = csp_cclass )
                                      *)
                            THEN
                                BEGIN
                                star_any_class_found := true;
                                star_found_len       :=
                                      i - (curr_data_len - k);
                                ix                   := 1;
                                END
                            ELSE
                                i := succ (i);
                            (*ENDIF*) 
                        (*ENDWHILE*) 
                    (*ENDIF*) 
&                   ifdef TRACE
                    t01int4 (ak_sem, 'col_len     ', col_len);
                    t01int4 (ak_sem, 'star_fou_len', star_found_len);
                    IF  star_any_class_found
                    THEN
                        t01int4 (ak_sem, '*/? found at', i)
                    ELSE
                        t01int4 (ak_sem, '*/? notfound', i);
                    (*ENDIF*) 
                    t01moveobj (ak_sem, mbp_buf, curr_data_len - k + 1,
                          curr_data_len);
&                   endif
                    IF  (star_found_len > col_len)
                    THEN
                        IF  star_any_class_found
                            AND (mbp_buf[i] = csp_star1)
                            AND (k = star_found_len)
                            AND (col_len + ix = k)
                        THEN
                            BEGIN
                            mb_st^[ mfirst_free-1 ].elen_var :=
                                  mb_st^[ mfirst_free-1 ].elen_var - ix;
                            star_any_class_found := false;
                            END
                        ELSE
                            value_len := k
                        (*ENDIF*) 
                    ELSE
                        value_len := col_len;
                    (*ENDIF*) 
                    IF  NOT star_any_class_found
                    THEN
                        BEGIN
                        (* ============== *)
                        (* optimization:  *)
                        (* like -> equal  *)
                        (* ============== *)
                        IF  operator = op_not_like
                        THEN
                            a65_set_operator (acv, op_ne)
                        ELSE
                            a65_set_operator (acv, op_eq);
                        (*ENDIF*) 
                        dmli.d_like := false
                        END
                    ELSE
                        BEGIN
                        j := i+1;
                        rest_blanks := true;
                        IF  mbp_buf[mb_st^ [mfirst_free-1].epos]
                            = csp_unicode_def_byte
                        THEN
                            WHILE (j <= curr_data_len) AND rest_blanks DO
                                IF  (mbp_buf[j] <> csp_unicode_mark) OR
                                    (mbp_buf[j+1] <> csp_ascii_blank)
                                THEN
                                    rest_blanks := false
                                ELSE
                                    j := j + 2
                                (*ENDIF*) 
                            (*ENDWHILE*) 
                        ELSE
                            WHILE (j <= curr_data_len) AND rest_blanks DO
                                IF  mbp_buf[j] <> mbp_buf[curr_data_len-k+1]
                                THEN
                                    rest_blanks := false
                                ELSE
                                    j := succ (j);
                                (*ENDIF*) 
                            (*ENDWHILE*) 
                        (*ENDIF*) 
                        IF  (mbp_buf[i] = csp_star1) AND rest_blanks AND
                            (mb_data_len +
                            value_len - k + value_len <= mb_data_size)
                        THEN
                            BEGIN
                            (* in case the column is longer than the value, *)
                            (* for the between cases we have to fill up to  *)
                            (* col_len, otherwise x'FF' will not be found   *)
                            (* *)
                            (* ===================================== *)
                            (* optimization:   like -> between       *)
                            (* resulting stack-entry for string 'x*':*)
                            (*                                       *)
                            (*  st_value, op_none, epos -> 'x0000..' *)
                            (*  st_value, op_betw, epos -> 'xFFFF..' *)
                            (* ===================================== *)
                            star_offset := i -
                                  mb_st^ [mfirst_free-1].epos;
                            mb_data_len := mb_data_len + value_len - k;
                            mb_st^ [mfirst_free-1].elen_var
                                  := value_len;
                            IF  mbp_buf[mb_st^ [mfirst_free-1].epos]
                                = csp_unicode_def_byte
                            THEN
                                BEGIN
                                (* PTS 1107307 E.Z. *)
                                (* when star_offset was calculated,   *)
                                (* i was on the right byte of the '*' *)
                                star_offset := pred(star_offset);
                                SAPDB_PascalUnicodeFill ('VAK65 ',   5,    
                                      mb_data_size, @mbp_buf,
                                      mb_st^ [mfirst_free-1].epos + star_offset,
                                      value_len - star_offset + 1,
                                      csp_unicode_blank,
                                      acv.a_returncode)
                                END
                            ELSE
                                SAPDB_PascalFill ('VAK65 ',   6,    
                                      mb_data_size, @mbp_buf,
                                      mb_st^ [mfirst_free-1].epos + star_offset,
                                      value_len - star_offset,
                                      mbp_buf[mb_st^ [mfirst_free-1].epos],
                                      acv.a_returncode);
                            (*ENDIF*) 
                            acv.a_input_data_pos := keep_part_pos;
                            colin.sci_len := 0;
                            a640not_first_factor (acv, dmli, colin, first_node);
                            mb_data_len := mb_data_len + value_len - k;
                            mb_st^ [mfirst_free-1].elen_var
                                  := value_len;
                            SAPDB_PascalFill ('VAK65 ',   7,    
                                  mb_data_size, @mbp_buf,
                                  mb_st^ [mfirst_free-1].epos + star_offset,
                                  value_len - star_offset, chr (255),
                                  acv.a_returncode);
                            IF  operator = op_not_like
                            THEN
                                a65_set_operator (acv, op_not_between)
                            ELSE
                                a65_set_operator (acv, op_between);
                            (*ENDIF*) 
                            dmli.d_like := false;
                            END
                        ELSE
                            IF  ((mbp_buf[mb_st^ [mfirst_free-1].epos]
                                = csp_unicode_def_byte) AND
                                (mbp_buf[i  ] = csp_unicode_mark) AND
                                (mbp_buf[i+1] = csp_cclass)       AND
                                (mbp_buf[i+4] = csp_unicode_mark) AND
                                (mbp_buf[i+5] = csp_crange)       AND
                                (mbp_buf[i+8] = csp_unicode_mark) AND
                                (mbp_buf[i+9] = csp_cclass))
                                OR
                                ((mbp_buf[mb_st^ [mfirst_free-1].epos]
                                <> csp_unicode_def_byte) AND
                                ( mbp_buf[i]   = csp_cclass ) AND
                                ( mbp_buf[i+2] = csp_crange ) AND
                                ( mbp_buf[i+4] = csp_cclass ))
                            THEN
                                IF  mbp_buf[mb_st^ [mfirst_free-1].epos]
                                    = csp_unicode_def_byte
                                THEN
                                    BEGIN
                                    j := i + 11;
                                    rest_blanks := true;
                                    WHILE (j <= curr_data_len) AND rest_blanks DO
                                        IF  (mbp_buf[j-1] <> csp_unicode_mark) OR
                                            (mbp_buf[j] <> csp_ascii_blank)
                                        THEN
                                            rest_blanks := false
                                        ELSE
                                            j := j + 2;
                                        (*ENDIF*) 
                                    (*ENDWHILE*) 
                                    (* ================================= *)
                                    (* optimization:like_> between       *)
                                    (* resulting stack-entry             *)
                                    (* for string :'x(a-b)' :            *)
                                    (* st_value,op_none,epos ->'xa   ..' *)
                                    (* st_value,op_betw,epos ->'xb   ..' *)
                                    (* ================================= *)
                                    IF  rest_blanks
                                    THEN
                                        BEGIN
                                        mbp_buf[i  ] := mbp_buf[i+2];
                                        mbp_buf[i+1] := mbp_buf[i+3];
                                        SAPDB_PascalUnicodeFill ('VAK65 ',   8,    
                                              mb_data_size, @mbp_buf,
                                              i+2, curr_data_len-i-1,
                                              csp_unicode_blank,
                                              acv.a_returncode);
                                        j := curr_data_len - i;
                                        acv.a_input_data_pos := keep_part_pos;
                                        colin.sci_len := 0;
                                        a640not_first_factor (acv, dmli, colin, first_node);
                                        curr_data_len := mb_data_len;
                                        i := curr_data_len - j;
                                        mbp_buf[i]   := mbp_buf[i+6];
                                        mbp_buf[i+1] := mbp_buf[i+7];
                                        SAPDB_PascalUnicodeFill ('VAK65 ',   9,    
                                              mb_data_size, @mbp_buf,
                                              i+2, curr_data_len-i-1,
                                              csp_unicode_blank,
                                              acv.a_returncode);
                                        IF  operator = op_not_like
                                        THEN
                                            a65_set_operator (acv, op_not_between)
                                        ELSE
                                            a65_set_operator (acv, op_between);
                                        (*ENDIF*) 
                                        dmli.d_like := false
                                        END
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    BEGIN
                                    j := i + 5;
                                    rest_blanks := true;
                                    WHILE ( j <= curr_data_len ) AND rest_blanks DO
                                        IF  mbp_buf[j] <> mbp_buf[curr_data_len-k+1]
                                        THEN
                                            rest_blanks := false
                                        ELSE
                                            j := succ(j);
                                        (*ENDIF*) 
                                    (*ENDWHILE*) 
                                    (* ================================= *)
                                    (* optimization:like_> between       *)
                                    (* resulting stack-entry             *)
                                    (* for string :'x(a-b)' :            *)
                                    (* st_value,op_none,epos ->'xa   ..' *)
                                    (* st_value,op_betw,epos ->'xb   ..' *)
                                    (* ================================= *)
                                    IF  rest_blanks
                                    THEN
                                        BEGIN
                                        mbp_buf[i] := mbp_buf[i+1];
                                        FOR j := i+1 TO curr_data_len DO
                                            mbp_buf[j] := mbp_buf[curr_data_len-k+1];
                                        (*ENDFOR*) 
                                        j := curr_data_len - i;
                                        acv.a_input_data_pos := keep_part_pos;
                                        colin.sci_len := 0;
                                        a640not_first_factor (acv, dmli, colin, first_node);
                                        curr_data_len := mb_data_len;
                                        i := curr_data_len - j;
                                        mbp_buf[i] := mbp_buf[i+3];
                                        FOR j := i+1 TO curr_data_len DO
                                            mbp_buf[j] := mbp_buf[curr_data_len-k+1];
                                        (*ENDFOR*) 
                                        IF  operator = op_not_like
                                        THEN
                                            a65_set_operator (acv, op_not_between)
                                        ELSE
                                            a65_set_operator (acv, op_between);
                                        (*ENDIF*) 
                                        dmli.d_like := false
                                        END
                                    (*ENDIF*) 
                                    END
                                (*ENDIF*) 
                            ELSE
                                IF  (operator = op_like) AND
                                    (mb_data_len + 2 * value_len <= mb_data_size)
                                THEN
                                    BEGIN
                                    (* ================================= *)
                                    (* no stack-optimization for VKB71   *)
                                    (* possible; yet possibly useful as  *)
                                    (* an access strategy                *)
                                    (* ================================= *)
                                    star_offset := i -
                                          mb_st^ [mfirst_free-1].epos;
                                    mb_data_len := mb_data_len + value_len - k;
                                    mb_st^ [mfirst_free-1].elen_var :=
                                          value_len;
                                    mb_st^ [mfirst_free-1].etype := st_dummy;
                                    IF  mbp_buf[mb_st^ [mfirst_free-1].epos]
                                        = csp_unicode_def_byte
                                    THEN
                                        BEGIN
                                        (* PTS 1107307 E.Z. *)
                                        (* when star_offset was calculated,   *)
                                        (* i was on the right byte of the '*' *)
                                        star_offset := pred(star_offset);
                                        SAPDB_PascalUnicodeFill ('VAK65 ',  10,    
                                              mb_data_size, @mbp_buf,
                                              mb_st^ [mfirst_free-1].epos + star_offset,
                                              value_len - star_offset,
                                              csp_unicode_blank,
                                              acv.a_returncode)
                                        END
                                    ELSE
                                        SAPDB_PascalFill ('VAK65 ',  11,    
                                              mb_data_size, @mbp_buf,
                                              mb_st^ [mfirst_free-1].epos +
                                              star_offset,
                                              value_len - star_offset,
                                              mbp_buf
                                              [mb_st^ [mfirst_free-1].epos],
                                              acv.a_returncode);
                                    (*ENDIF*) 
                                    acv.a_input_data_pos := keep_part_pos;
                                    colin.sci_len := 0;
                                    a640not_first_factor (acv, dmli, colin, first_node);
                                    IF  (mb_data_len +
                                        value_len - k <= mb_data_size)
                                    THEN
                                        BEGIN
                                        mb_st^ [mfirst_free-1].elen_var
                                              := value_len;
                                        mb_data_len := mb_data_len + value_len - k;
                                        END;
                                    (*ENDIF*) 
                                    SAPDB_PascalFill ('VAK65 ',  12,    
                                          mb_data_size, @mbp_buf,
                                          mb_st^ [mfirst_free-1].epos +
                                          star_offset,
                                          value_len - star_offset,
                                          chr (255),
                                          acv.a_returncode);
                                    mb_st^ [mfirst_free-1].etype := st_dummy;
                                    acv.a_input_data_pos := keep_part_pos;
                                    colin.sci_len := 0;
                                    a640not_first_factor (acv, dmli, colin, first_node);
                                    ak65set_like_operator (acv, op_like,
                                          NOT c_like_expression, 0, NOT c_escape);
                                    dmli.d_like := false;
                                    END;
                                (*ENDIF*) 
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a65_convert (
            VAR acv   : tak_all_command_glob;
            operator  : tak_convert_type;
            maxlength : integer);
 
BEGIN
CASE operator OF
    conv_ascii_to_unicode:
        a641string_set_operator (acv, op_b_uni_trans, 0, 0,
              chr(csp_ascii), chr(csp_unicode));
    conv_unicode_to_ascii:
        a641string_set_operator (acv, op_b_uni_trans, 0, 0,
              chr(csp_unicode), chr(csp_ascii));
    (* the next variants only with Oracle and union *)
    conv_ascii_to_num :
        a65_set_operator (acv, op_num);
    conv_unicode_to_num :
        BEGIN
        a641string_set_operator (acv, op_b_uni_trans, 0, 0,
              chr(csp_unicode), chr(csp_ascii));
        a65_set_operator (acv, op_num);
        END;
    conv_num_to_ascii,
    conv_num_to_unicode :
        BEGIN
        (* compare vak641 ak641to_char *)
        a641string_set_operator (acv, op_b_chr, csp_float_frac,
              2 * csp_fixed, chr(2), chr(maxlength));
        IF  operator = conv_num_to_unicode
        THEN
            a641string_set_operator (acv, op_b_uni_trans, 0, 0,
                  chr(csp_ascii), chr(csp_unicode));
        (*ENDIF*) 
        END;
    OTHERWISE
        BEGIN
        END
    END;
(*ENDCASE*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      a65_datatypes_ok (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR dm_type    : tsp00_DataType;
            VAR dm_iolen   : tsp00_Int2;
            ctype          : tsp00_DataType;
            is_subquery    : boolean;
            first_node     : integer;
            error_pos      : tsp00_Int4;
            convert        : boolean;
            VAR convert_t  : tak_convert_type) : boolean;
 
VAR
      is_ok         : boolean;
      (* PTS 1000985/1001162 E.Z. *)
      may_become_ok : boolean;
      icolin        : tak00_scolinf;
      expr_st_cnt   : tsp00_Int2;
 
BEGIN
WITH acv DO
    BEGIN
    is_ok         := true;
    (* PTS 1000985/1001162 E.Z. *)
    may_become_ok := false;
    convert_t := conv_none;
&   ifdef TRACE
    t01int4 (ak_sem, 'dm_type     ', ord(dm_type));
    t01int4 (ak_sem, 'ctype       ', ord(ctype));
&   endif
    IF  (dm_type <> dnonumber) AND (ctype <> dnonumber) AND
        (dm_type <> dunknown)  AND (ctype <> dunknown)
    THEN
        BEGIN
        CASE dm_type OF
            dboolean :
                IF  (ctype <> dboolean)
                THEN
                    is_ok := false;
                (*ENDIF*) 
            dfixed,
            dfloat,
            dvfloat,
            dnumber :
                IF  (ctype <> dfixed)  AND
                    (ctype <> dfloat)  AND
                    (ctype <> dvfloat) AND
                    (ctype <> dnumber)
                THEN
                    is_ok := false;
                (*ENDIF*) 
            dchb :
                is_ok := ctype = dchb;
            ddate,
            dtime,
            dtimestamp :
                IF  ctype in [ dcha, dunicode,
                    ddate, dtime, dtimestamp ]
                THEN
                    CASE ctype OF
                        dcha :
                            BEGIN
                            END;
                        dunicode :
                            BEGIN
                            IF  is_subquery
                            THEN
                                BEGIN
                                is_ok := false;
                                IF  NOT (
                                    (a_ap_tree^[ first_node ].n_proc = a63) AND
                                    ( acv.a_ap_tree^[ first_node ].n_subproc = cak_x_start_union))
                                THEN
                                    BEGIN
                                    dm_type := dunicode;
                                    dm_iolen := succ(pred(dm_iolen) * 2);
                                    may_become_ok := true;
                                    END
                                (*ENDIF*) 
                                END
                            ELSE
                                convert_t := conv_unicode_to_ascii;
                            (*ENDIF*) 
                            END;
                        OTHERWISE
                            IF  dm_type <> ctype
                            THEN
                                is_ok := false
                            (*ENDIF*) 
                        END
                    (*ENDCASE*) 
                ELSE
                    is_ok := false;
                (*ENDIF*) 
            dcha :
                IF  ctype in [ dcha, dunicode,
                    ddate, dtime, dtimestamp ]
                THEN
                    CASE ctype OF
                        ddate, dtime, dtimestamp :
                            BEGIN
                            END;
                        dunicode :
                            IF  is_subquery
                            THEN
                                BEGIN
                                is_ok := false;
                                IF  NOT (
                                    (a_ap_tree^[ first_node ].n_proc = a63) AND
                                    ( acv.a_ap_tree^[ first_node ].n_subproc = cak_x_start_union))
                                THEN
                                    BEGIN
                                    dm_type := dunicode;
                                    dm_iolen := succ(pred(dm_iolen) * 2);
                                    may_become_ok := true;
                                    END
                                (*ENDIF*) 
                                END
                            ELSE
                                convert_t := conv_unicode_to_ascii;
                            (*ENDIF*) 
                        OTHERWISE
                            BEGIN
                            END
                        END
                    (*ENDCASE*) 
                ELSE
                    is_ok := false;
                (*ENDIF*) 
            dunicode :
                IF  ctype <> dunicode
                THEN
                    CASE ctype OF
                        dcha, ddate, dtime, dtimestamp :
                            convert_t := conv_ascii_to_unicode;
                        OTHERWISE
                            BEGIN
                            is_ok := false
                            END
                        END;
                    (*ENDCASE*) 
                (*ENDIF*) 
            OTHERWISE
                BEGIN
                END
            END;
        (*ENDCASE*) 
&       ifdef TRACE
        t01int4 (ak_sem, 'is_ok       ', ord(is_ok));
        t01int4 (ak_sem, 'may_becomeok', ord(may_become_ok));
        t01int4 (ak_sem, 'convert     ', ord(convert));
        t01int4 (ak_sem, 'sqlmode     ', ord(a_sqlmode));
        t01int4 (ak_sem, 'is_subquery ', ord(is_subquery));
        t01int4 (ak_sem, 'first_node  ', first_node);
&       endif
        IF  ((NOT is_ok)              AND
            NOT (may_become_ok)       AND
            (convert OR is_subquery)  AND
            (a_sqlmode = sqlm_oracle) AND
            NOT (
            ((a_ap_tree^[ first_node ].n_proc = a63) AND
            ( acv.a_ap_tree^[ first_node ].n_subproc = cak_x_start_union))))
        THEN
            BEGIN
            is_ok := true;
            CASE dm_type OF
                dcha, dunicode :
                    IF  (ctype <> dfixed)  AND
                        (ctype <> dfloat)  AND
                        (ctype <> dvfloat) AND
                        (ctype <> dnumber)
                    THEN
                        is_ok := false
                    ELSE
                        BEGIN
                        IF  is_subquery
                        THEN
                            BEGIN
                            is_ok := false;
                            dm_type := ctype;
                            dm_iolen := succ(mxsp_number);
                            may_become_ok := true;
                            END
                        ELSE
                            IF  NOT convert
                            THEN
                                is_ok := false
                            ELSE
                                BEGIN
                                icolin.sci_typ  := dfloat;
                                icolin.sci_len  := 2 * csp_fixed;
                                icolin.sci_frac := csp_fixed;
                                a641stack_for_op_b_chr (acv, dmli, icolin,
                                      0, dm_type);
                                (* PTS 1001011 E.Z. *)
                                END
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                (* PTS 1105457 E.Z. *)
                dchb :
                    is_ok := ctype = dchb;
                dfixed,
                dfloat,
                dvfloat,
                dnumber :
                    IF  is_subquery
                    THEN
                        CASE ctype OF
                            dcha, ddate, dtime, dtimestamp :
                                convert_t := conv_ascii_to_num;
                            dunicode :
                                convert_t := conv_unicode_to_num;
                            OTHERWISE
                                is_ok := false
                            END
                        (*ENDCASE*) 
                    ELSE
                        IF  NOT convert
                            (* PTS 1105457 E.Z. *)
                            OR (ctype = dchb)
                        THEN
                            is_ok := false
                        ELSE
                            BEGIN
                            IF  ctype = dunicode
                            THEN
                                a65_convert (acv, conv_unicode_to_ascii, 0);
                            (*ENDIF*) 
                            a65_set_operator (acv, op_num);
                            END;
                        (*ENDIF*) 
                    (*ENDIF*) 
                OTHERWISE
                    is_ok := false
                END;
            (*ENDCASE*) 
            IF  is_ok
            THEN
                WITH dmli, a_mblock, mb_qual^ DO
                    IF  d_const_value_expr AND NOT d_group
                    THEN
                        BEGIN
                        expr_st_cnt := mfirst_free - d_param_st_begin;
                        IF  (d_param_st_index > 0) AND
                            (expr_st_cnt <= 255)
                        THEN
                            a651code_for_const_param_expr (acv,
                                  dmli, d_param_st_begin, expr_st_cnt);
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                (*ENDWITH*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  NOT is_ok
        THEN
            IF  (is_subquery AND
                may_become_ok)
            THEN
                IF  convert AND
                    (dmli.d_corr <> no_correlation)
                THEN
                    BEGIN
                    is_ok := true;
                    END
                ELSE
                    IF  (dmli.d_corr = no_correlation) AND
                        (a_max_intern_select = 0)
                    THEN
                        BEGIN
&                       ifdef TRACE
                        t01int4 (ak_sem, 'subq_problem', 1);
&                       endif
                        (* PTS 1106602 E.Z. *)
                        IF  a_is_ddl <> no_ddl
                        THEN
                            a_returncode := cak_e_subq_type_diff
                        ELSE
                            is_ok := true;
                        (*ENDIF*) 
                        a_sql_cmd_state :=
                              a_sql_cmd_state + [ csa_subq_datatype_problem ];
                        a_retpart_locked := true
                        END
                    ELSE
                        a07_b_put_error (acv, e_incompatible_datatypes, error_pos)
                    (*ENDIF*) 
                (*ENDIF*) 
            ELSE
                a07_b_put_error (acv, e_incompatible_datatypes, error_pos)
            (*ENDIF*) 
        ELSE
            IF  (convert AND (convert_t <> conv_none))
            THEN
                BEGIN
                a65_convert (acv, convert_t, 0);
                WITH dmli, a_mblock, mb_qual^ DO
                    IF  d_const_value_expr AND NOT d_group
                    THEN
                        BEGIN
                        expr_st_cnt := mfirst_free - d_param_st_begin;
                        IF  (d_param_st_index > 0) AND
                            (expr_st_cnt <= 255)
                        THEN
                            a651code_for_const_param_expr (acv,
                                  dmli, d_param_st_begin, expr_st_cnt);
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                (*ENDWITH*) 
                END
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (* END OF PTS 1000985/1001162 E.Z. *)
    (*ENDIF*) 
    END;
(*ENDWITH*) 
a65_datatypes_ok := is_ok
END;
 
(*------------------------------*) 
 
PROCEDURE
      a65_look_for_datatypes (
            VAR acv    : tak_all_command_glob;
            VAR dmli   : tak_dml_info;
            first_node : integer);
 
VAR
      date_arith    : boolean;
      curr_n        : integer;
      h_datatyp     : tsp00_DataType;
      act_param     : integer;  (* number of actual parameter *)
      in_param_list : boolean;  (* act_param is in the list   *)
&     ifdef TRACE
      i : integer;
&     endif
 
BEGIN
WITH acv, a_ap_tree^[ first_node ], dmli DO
    IF  a_returncode = 0
    THEN
        BEGIN
&       ifdef TRACE
        t01int4 (ak_sem, 'first_node  ', first_node);
&       endif
        h_datatyp := dunknown;
        IF  n_symb = s_parameter_name
        THEN
            WITH a_parameter_spec DO
                BEGIN
                act_param := n_length;
                in_param_list := (act_param <= param_counter) AND
                      (param_spec_ptr <> NIL);
                IF  (NOT in_param_list)
                    OR
                    (param_spec_ptr^[ act_param ].para_length = 0)
                THEN
                    h_datatyp := dunknown
                ELSE
                    WITH param_spec_ptr^[ act_param ] DO
                        CASE para_type OF
                            dfixed, dsmallint, dinteger,
                            dfloat, dvfloat :
                                h_datatyp := dnumber;
                            dcha, dchb, drowid,
                            dstra, dstrb,
                            ddate, dtime, dtimestamp,
                            dlonga, dlongb,
                            dboolean,
                            dunicode, dstruni, dlonguni,
                            dvarchara, dvarcharb :
                                h_datatyp := para_type;
                            OTHERWISE :
                                h_datatyp := dunknown;
                            END;
                        (*ENDCASE*) 
                    (*ENDWITH*) 
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        ELSE
            IF  n_proc = a67
            THEN
                BEGIN
                CASE n_datatype OF
                    dfixed, dsmallint, dinteger,
                    dfloat, dvfloat :
                        BEGIN
                        d_datatype := dnumber;
                        h_datatyp  := dnumber
                        END;
                    OTHERWISE
                        BEGIN
                        d_datatype := n_datatype;
                        h_datatyp  := n_datatype;
                        END
                    END
                (*ENDCASE*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  h_datatyp = dunknown
        THEN
            CASE n_symb OF
                (* PTS 1122828 E.Z. *)
                s_upper, s_lower, s_initcap, s_chr, s_chr_ora, s_hex,
                (* PTS 1112767 E.Z. *)
                s_replace, s_concat, s_trim, s_ltrim, s_rtrim, s_translate :
                    IF  g01unicode
                    THEN
                        h_datatyp := dunicode
                    ELSE
                        h_datatyp := dcha;
                    (*ENDIF*) 
                s_ascii :
                    IF  (a_sqlmode = sqlm_internal)
                    THEN
                        h_datatyp := dcha
                    ELSE
                        (*   a_sqlmode = sqlm_oracle   *)
                        h_datatyp := dnumber;
                    (*ENDIF*) 
                OTHERWISE
                    BEGIN
                    END
                END;
            (*ENDCASE*) 
        (*ENDIF*) 
        CASE n_symb OF
            s_fixed_point_literal, s_floating_point_literal,
            s_unsigned_integer, s_nextval, s_currval,
            (* PTS 1109925 E.Z. *)
            s_utcdiff, s_timezone (* PTS 1122262 E.Z. *) :
                d_datatype := dnumber;
            s_adddate, s_subdate, s_makedate, s_date :
                d_datatype := ddate;
            s_addtime, s_subtime, s_timediff, s_maketime,
            s_time :
                d_datatype := dtime;
            (* PTS 1116175 E.Z. *)
            s_utcdate,
            s_timestamp, s_add_months, s_last_day, s_next_day, s_to_date :
                d_datatype := dtimestamp;
            s_uid :
                d_datatype := dfixed;
            (* PTS 1111797 E.Z. *)
            s_user, s_usergroup, s_sysdba :
                d_datatype := dcha;
            s_dayofweek, s_dayofmonth,
            s_weekofyear, s_dayofyear,
            s_datediff, s_months_between,
            s_num, s_to_number, s_index, s_integer, s_abs,
            s_noround, s_mod, s_div, s_length, s_vsize,
            s_float, s_fixed, s_ceil, s_floor, s_sign,
            s_mod_func, s_power, s_sqrt, s_exp, s_ln, s_log,
            s_log10, s_acos, s_asin, s_atan, s_atan2, s_cot,
            s_sin, s_sinh, s_cos, s_cosh, s_tan, s_tanh,
            s_degrees, s_radians, s_pi :
                d_datatype := dnumber;
            s_year, s_month, s_day :
                IF  n_proc = a641 (*no_proc*)
                THEN
                    d_datatype := dnumber
                ELSE (* duration *)
                    d_datatype := ddate;
                (*ENDIF*) 
            s_hour, s_minute, s_second:
                IF  n_proc = a641 (*no_proc*)
                THEN
                    d_datatype := dnumber
                ELSE (* duration *)
                    d_datatype := dtime;
                (*ENDIF*) 
            s_microsecond:
                IF  n_proc = a641 (*no_proc*)
                THEN
                    d_datatype := dnumber
                ELSE (* duration *)
                    d_datatype := dtimestamp;
                (*ENDIF*) 
            s_days :
                d_datatype := dnumber;
            s_avg, s_sum, s_stddev, s_variance,
            s_dis_avg, s_dis_sum, s_dis_stddev, s_dis_variance :
                d_datatype := dnumber;
            s_digits, s_chr_ora, s_to_24_char,
            s_string_literal, s_hextoraw,
            s_left, s_right, s_monthname, s_dayname,
            (* PTS 1112767 E.Z. *)
            s_lpad, s_rpad, s_rfill, s_lfill, s_substr,
            (* PTS 1111577 E.Z. *)
            s_get_owner, s_get_name :
                IF  (g01unicode)           AND
                    (g01code.char_default = csp_unicode)
                THEN
                    d_datatype := dunicode
                ELSE
                    d_datatype := dcha;
                (*ENDIF*) 
            s_mbcs, s_transaction :
                d_datatype := dchb;
            s_user_func:
                ak65_dt_look_for_user_def (acv, dmli, first_node);
            s_authid, s_tablename, s_columnname :
                BEGIN
                d_is_parameter_only := false;
                d_user              := a01_il_b_identifier;
                curr_n              := first_node;
                d_n_pos             := a_ap_tree^[ curr_n ].n_pos;
                a06get_username (acv, curr_n, d_user);
                WITH a_ap_tree^[ curr_n ] DO
                    IF  n_symb = s_tablename
                    THEN
                        BEGIN
                        a05identifier_get (acv, curr_n,
                              sizeof (d_table), d_table);
                        (* PTS 1107543 E.Z. *)
                        IF  a_is_ddl = ddl_create_trigger
                        THEN
                            BEGIN
                            IF  (d_table <> a01_i_old) AND
                                (d_table <> a01_i_new)
                            THEN
                                a07_b_put_error (acv,
                                      e_unknown_columnname, n_pos);
                            (*ENDIF*) 
                            d_table := a01_il_b_identifier
                            END;
                        (*ENDIF*) 
                        curr_n := n_sa_level;
                        END
                    ELSE
                        d_table := a01_il_b_identifier;
                    (*ENDIF*) 
                (*ENDWITH*) 
                WITH a_ap_tree^[ curr_n ] DO
                    IF  n_symb = s_columnname
                    THEN
                        BEGIN
                        a05identifier_get (acv, curr_n,
                              sizeof (d_column), d_column);
                        d_vppos  := n_pos;
                        a61_search_table (acv, dmli);
                        IF  a_returncode = 0
                        THEN
                            WITH d_colbuf^ DO
                                IF  (cdatatyp = dfixed) OR
                                    (cdatatyp = dfloat) OR
                                    (cdatatyp = dvfloat)
                                THEN
                                    d_datatype := dnumber
                                ELSE
                                    d_datatype := cdatatyp;
                                (*ENDIF*) 
                            (*ENDWITH*) 
                        (*ENDIF*) 
                        END
                    ELSE
                        d_column := a01_il_b_identifier
                    (*ENDIF*) 
                (*ENDWITH*) 
                END;
            OTHERWISE
                BEGIN
                date_arith := false;
                IF  (n_proc = a64) AND (n_subproc = cak_x_add_operator)
                THEN
                    date_arith := ak65is_datetime_arith (acv, dmli,
                          first_node, c_look_for_dtype);
                (*ENDIF*) 
                IF  NOT date_arith
                THEN
                    IF  (n_symb <> s_all) AND
                        (n_symb <> s_any) AND
                        (n_proc <> a63query_spec)
                    THEN
                        BEGIN (* don't try this for subqueries *)
                        IF  n_lo_level <> 0
                        THEN
                            a65_look_for_datatypes (acv, dmli, n_lo_level);
                        (*ENDIF*) 
                        IF  ((d_datatype = dunknown) AND
                            (n_sa_level <> 0))
                        THEN
                            a65_look_for_datatypes (acv, dmli, n_sa_level);
&                       ifdef TRACE
                        (*ENDIF*) 
                        t01int4 (ak_sem, 'a_insert_sel', ord(a_insert_select));
                        t01int4 (ak_sem, 'd_subcount  ', dmli.d_subcount);
                        t01int4 (ak_sem, 'd_outcolno  ', dmli.d_outcolno);
                        FOR i := 1 TO 10 DO
                            t01int4 (ak_sem, 'ch_datatype ',
                                  ord(dmli.d_change.cr_columns[ i ].ch_length));
                        (*ENDFOR*) 
&                       endif
                        IF  ((d_datatype = dunknown) AND
                            NOT d_wherepart AND NOT d_having AND
                            (a_ap_tree^[ a_ap_tree^[ 0 ].n_lo_level ].n_proc = a56) AND
                            (a_ap_tree^[ a_ap_tree^[ 0 ].n_lo_level ].n_subproc  =
                            cak_x_insert_select) AND
                            a_insert_select AND
                            (dmli.d_subcount = 0))
                        THEN
                            IF  d_outcolno > d_change.cr_colcount
                            THEN
                                a07_b_put_error (acv, e_too_many_values, 1)
                            ELSE
                                a56_datatype (d_change.cr_columns[ d_outcolno ].ch_length,
                                      d_datatype);
                            (*ENDIF*) 
                        (*ENDIF*) 
                        IF  d_datatype = dunknown
                        THEN
                            d_datatype := h_datatyp;
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        curr_n := a_ap_tree^[ first_node ].n_sa_level;
                        WITH a_ap_tree^[ curr_n ] DO
                            IF  n_proc = a63query_spec
                            THEN
                                curr_n := a_ap_tree^[ curr_n ].n_sa_level;
                            (*ENDIF*) 
                        (*ENDWITH*) 
                        IF  curr_n > 0
                        THEN
                            d_datatype := a_ap_tree^[ curr_n ].n_datatype
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                (*ENDIF*) 
                END
            END
        (*ENDCASE*) 
        END;
&   ifdef TRACE
    (*ENDIF*) 
(*ENDWITH*) 
t01int4 (ak_sem, 'look_datatyp', ord(dmli.d_datatype));
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65_dt_look_for_user_def (
            VAR acv  : tak_all_command_glob;
            VAR dmli : tak_dml_info;
            act_node : integer);
 
VAR
      curr_n         : integer;
      value_cnt      : integer;
      dummy_iolen    : tsp00_Int2;
      proc_colin     : tak00_scolinf;
      param_colin    : tak00_scolinf;
      keep_datatype  : tsp00_DataType;
      res_datatype   : tsp00_DataType;
      param_datatype : tsp00_DataType;
      convert_t      : tak_convert_type;
      func_name      : tsp00_KnlIdentifier;
      proc_buf       : tak_sysbufferaddress;
 
BEGIN
WITH acv, dmli DO
    BEGIN
    a05identifier_get (acv, act_node, sizeof (func_name), func_name);
    IF  NOT a12dbfunc_exist (acv, a01_il_b_identifier, func_name, d_release, proc_buf)
    THEN
        a07_b_put_error (acv, e_unknown_functionname,
              a_ap_tree^[ act_node ].n_pos)
    ELSE
        BEGIN (* There is (at least) one function with the given name. *)
        keep_datatype := d_datatype;
        value_cnt   := 0;
        curr_n      := a_ap_tree^[ act_node ].n_lo_level;
        a12describe_param  (acv, proc_buf,
              proc_buf^.smethod.me_param_cnt, proc_colin);
        IF  proc_colin.sci_typ in [ dfixed, dfloat ]
        THEN
            res_datatype := dnumber
        ELSE
            res_datatype := proc_colin.sci_typ;
        (*ENDIF*) 
        (* PTS 1000985/1001162 E.Z. *)
        dummy_iolen := 0;
        IF  a65_datatypes_ok (acv, dmli, keep_datatype,
            dummy_iolen, res_datatype,
            NOT c_is_subquery, 1, 1, NOT c_convert, convert_t)
        THEN (* The result type is matching. *)
            WHILE (curr_n <> 0) AND (a_returncode = 0) DO
                BEGIN (* for every parameter. *)
                value_cnt           := succ (value_cnt);
                param_colin.sci_len := 0;
                a12describe_param (acv, proc_buf, value_cnt, param_colin);
                IF  param_colin.sci_typ in [ dfixed, dfloat ]
                THEN
                    param_datatype := dnumber
                ELSE
                    param_datatype := param_colin.sci_typ;
                (*ENDIF*) 
                a65_look_for_datatypes (acv, dmli, curr_n);
                (* PTS 1000985/1001162 E.Z. *)
                IF  a65_datatypes_ok (acv, dmli, d_datatype, dummy_iolen,
                    param_datatype,
                    NOT c_is_subquery, 1, 1, NOT c_convert, convert_t)
                THEN
                    curr_n := a_ap_tree^[ curr_n ].n_sa_level
                (*ENDIF*) 
                END;
            (*ENDWHILE*) 
        (*ENDIF*) 
        IF  a_returncode = 0
        THEN
            d_datatype := res_datatype
        ELSE
            IF  keep_datatype <> dunknown
            THEN      (* We haven't to cry about incompatibility, since we *)
                BEGIN (* are only checking for a given result type.        *)
                a_returncode := 0;
                a_errorpos := 0;
                END
            ELSE
                a07_b_put_error (acv, e_incompatible_datatypes,
                      a_ap_tree^[ curr_n ].n_pos)
            (*ENDIF*) 
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a65_search_condition (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR first_node : integer);
 
VAR
      m_rowno_allowed : boolean;
      truth_node      : integer;
      list_info       : list_elem_info;
      (* 'list_info' should better be defined local to ak65predicate, *)
      (* but since that procedure is highly recursive and list_info   *)
      (* takes about 1k memory in each instance on the run time stack *)
      (* we define it here and pass it as reference parameter.        *)
 
BEGIN
WITH acv, dmli DO
    BEGIN
&   ifdef TRACE
    t01aptree (ak_sem, a_ap_tree^, a_scv_index, a_first_hint_node);
&   endif
    (* PTS 1117523 E.Z. *)
    d_pars_kind      := fp_val_all_without_l;
    (* PTS 1115725 E.Z. *)
    m_rowno_allowed := a_rowno_allowed;
    IF  NOT d_in_case_function
    THEN
        BEGIN
        a_rowno_allowed := true;
        IF  ((a_ap_tree^[ a_ap_tree^[ 0 ].n_lo_level ].n_proc in [a16,a56,a57,a58,a63]) OR
            ((a_ap_tree^[ a_ap_tree^[ 0 ].n_lo_level ].n_proc = a43) AND
            (a_ap_tree^[ a_ap_tree^[ 0 ].n_lo_level ].n_subproc = cak_x_explain)))
        THEN
            d_wherepart := NOT d_having
        ELSE
            d_wherepart := true;
        (*ENDIF*) 
        d_joins.jrc_cnt     := 0;
        d_joins.jrc_col_upd := false;
        IF  d_maxcounttabs > 1
        THEN
            BEGIN
            d_join := true;
            WITH d_joins, jrc_joinarr[ jrc_cnt ] DO
                BEGIN
                SAPDB_PascalForcedFill (sizeof(jrc_joinarr),
                      @jrc_joinarr, 1, sizeof(jrc_joinarr), chr(0));
                jo_partno              := 1;
                END;
            (*ENDWITH*) 
            END
        ELSE
            d_join := false;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    d_joins.jrc_joinarr[ d_joins.jrc_cnt ].jo_col_upd_stat := 0;
    d_first_tab := 0;
    d_arith_where := false;
    d_allowed := may_more_tabs;
    WITH a_mblock.mb_qual^ DO
        IF  mqual_pos = 0
        THEN
            mqual_pos := mfirst_free;
        (*ENDIF*) 
    (*ENDWITH*) 
    IF  a_ap_tree^[ first_node ].n_subproc = cak_x_truth_value
    THEN
        BEGIN
        truth_node := first_node;
        first_node := a_ap_tree^[ truth_node ].n_lo_level;
        END
    ELSE
        truth_node := 0;
    (*ENDIF*) 
    ak65se_condition (acv, dmli, first_node, c_mtabs_allowed, list_info);
    IF  truth_node > 0
    THEN
        WITH a_mblock, mb_qual^ DO
            BEGIN
            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_truth;
                    eop   := op_none;
                    CASE a_ap_tree^[ truth_node ].n_symb OF
                        s_is_true :
                            epos := cgg04_is_true;
                        s_is_not_true :
                            epos := cgg04_is_not_true;
                        s_is_false :
                            epos := cgg04_is_false;
                        s_is_not_false :
                            epos := cgg04_is_not_false;
                        s_is_null :
                            epos := cgg04_is_undef;
                        s_is_not_null :
                            epos := cgg04_is_not_undef;
                        END;
                    (*ENDCASE*) 
                    elen_var := 0;
                    ecol_tab[ 1 ] := chr(0);
                    ecol_tab[ 2 ] := chr(0)
                    END;
                (*ENDWITH*) 
                mfirst_free := succ(mfirst_free);
                mqual_cnt := succ(mqual_cnt);
                END
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
    (*ENDIF*) 
    a_rowno_allowed := m_rowno_allowed;
    IF  (d_maxcounttabs > 1) AND
        (a_mblock.mb_data_len < a_mblock.mb_data_size)
    THEN
        WITH a_mblock DO
            BEGIN
            (* join usually needs NULL-value for *)
            (* its is-not-null qualifications    *)
            mb_data_len                     := succ (mb_data_len );
            mb_data^.mbp_buf[ mb_data_len ] := csp_undef_byte;
            END;
        (*ENDWITH*) 
&   ifdef TRACE
    (*ENDIF*) 
    t01messblock (ak_sem, 'end search_c', a_mblock);
&   endif
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a65_set_operator (
            VAR acv  : tak_all_command_glob;
            operator : tgg00_StackOpType);
 
BEGIN
IF  acv.a_returncode = 0
THEN
    WITH acv, a_mblock, mb_qual^ DO
        BEGIN
        WITH mb_st^ [mfirst_free-1] DO
            IF  ((eop   = op_none)    AND
                ( operator <> op_and) AND
                ( operator <> op_or)  AND
                ( etype <> st_truth)  AND
                ( etype <> st_dummy)  AND
                (* View-Condition *)
                ((NOT acv.a_special_expr) OR (etype = st_value)))
            THEN
                eop := operator
            ELSE
                IF  mfirst_free > mb_st_max
                THEN
                    a07_b_put_error (acv, e_too_many_mb_stackentries, -mb_st_max)
                ELSE
                    BEGIN
                    IF  mupd_cnt = 0
                    THEN
                        mqual_cnt := succ(mqual_cnt)
                    ELSE
                        mupd_cnt := succ(mupd_cnt);
                    (*ENDIF*) 
                    WITH mb_st^ [mfirst_free] DO
                        BEGIN
                        etype         := st_op;
                        eop           := operator;
                        epos          := 0;
                        elen_var      := 0;
                        ecol_tab[ 1 ] := chr(0);
                        ecol_tab[ 2 ] := chr(0)
                        END;
                    (*ENDWITH*) 
                    mfirst_free := succ(mfirst_free)
                    END
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDWITH*) 
        END
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65set_mass_cmp (
            VAR acv  : tak_all_command_glob;
            operator : tgg00_StackOpType;
            all      : boolean;
            expr_cnt : integer;
            list_cnt : integer);
 
BEGIN
WITH acv.a_mblock, mb_qual^ DO
    IF  mfirst_free > mb_st_max
    THEN
        a07_b_put_error (acv, e_too_many_mb_stackentries, -mb_st_max)
    ELSE
        BEGIN
        IF  list_cnt < 1
        THEN
            list_cnt := 1;
        (*ENDIF*) 
        mqual_cnt := succ(mqual_cnt);
        WITH mb_st^ [mfirst_free] DO
            BEGIN
            etype    := st_mass_compare;
            eop      := operator;
            epos     := list_cnt;
            elen_var := expr_cnt DIV list_cnt;
            IF  all
            THEN
                ecol_tab[ 1 ] := chr(1)
            ELSE
                ecol_tab[ 1 ] := chr(0);
            (*ENDIF*) 
            ecol_tab[ 2 ] := chr(0);
            END;
        (*ENDWITH*) 
        mfirst_free := succ(mfirst_free)
        END
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65not_first_term (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR colin      : tak00_scolinf;
            VAR first_node : integer);
 
VAR
      st_begin : integer;
      st_index : integer;
 
BEGIN
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;
a65_term (acv, dmli, colin, first_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;
 
(*------------------------------*) 
 
PROCEDURE
      a65_term (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR colin      : tak00_scolinf;
            VAR first_node : integer);
 
VAR
      _act_node         : integer;
      _colin1           : tak00_scolinf;
      _const_value_expr : boolean;
      _st_begin         : integer;
      _st_end           : integer;
      _expr_st_cnt      : integer;
      _pos              : tsp00_Int4;
 
BEGIN
WITH acv.a_ap_tree^[ first_node ] DO
    BEGIN
    IF  acv.a_returncode = 0
    THEN
        BEGIN
        _act_node           := n_lo_level;
        IF  ((n_proc = a64) AND (n_subproc = cak_x_add_operator))
        THEN
            a65_val_expr (acv, dmli, colin, first_node)
        ELSE
            IF  NOT ((n_proc = a64) AND (n_subproc = cak_x_mult_operator))
            THEN
                a640factor (acv, dmli, colin, first_node)
            ELSE
                BEGIN
                _const_value_expr   := dmli.d_const_value_expr;
                dmli.d_const_value_expr := true;
                _st_begin           := acv.a_mblock.mb_qual^.mfirst_free;
                dmli.d_colptr      := NIL;
                a640factor (acv, dmli, colin, _act_node);
                _act_node := acv.a_ap_tree^[ _act_node ].n_sa_level;
                IF  NOT (dmli.d_datatype in [ dnumber, dfixed,
                    dfloat, dvfloat, dinteger, dsmallint ] )
                THEN
                    a07_b_put_error (acv, e_function_not_allowed,
                          acv.a_ap_tree^[ _act_node ].n_pos)
                ELSE
                    BEGIN
                    _colin1.sci_len := 0;
                    a640not_first_factor (acv, dmli, _colin1, _act_node)
                    END;
                (*ENDIF*) 
                IF  acv.a_returncode = 0
                THEN
                    BEGIN
                    CASE acv.a_ap_tree^[ first_node ].n_symb OF
                        s_mult :
                            BEGIN
                            ak65new_colinfo (acv, colin, _colin1, s_mult);
                            a65_set_operator (acv, op_mult);
                            END;
                        s_divide :
                            BEGIN
                            ak65new_colinfo (acv, colin, _colin1, s_divide);
                            a65_set_operator (acv, op_div);
                            END;
                        s_div :
                            a65_set_operator (acv, op_intdiv);
                        s_mod :
                            BEGIN
                            a65_set_operator (acv, op_mod);
                            colin := _colin1
                            END
                        END;
                    (*ENDCASE*) 
                    IF  dmli.d_const_value_expr AND NOT dmli.d_group AND
                        (acv.a_returncode = 0)
                    THEN
                        BEGIN
                        _expr_st_cnt := acv.a_mblock.mb_qual^.mfirst_free -
                              _st_begin;
                        WITH acv.a_mblock, mb_qual^ DO
                            IF  (dmli.d_param_st_index > 0) AND
                                (_expr_st_cnt <= 255) AND
                                (mb_data_len -
                                mb_st^[_st_begin].epos + 1 >= colin.sci_iolen)
                            THEN
                                a651code_for_const_param_expr (acv,
                                      dmli, _st_begin, _expr_st_cnt)
                            ELSE
                                IF  dmli.d_param_st_index = 0
                                THEN
                                    BEGIN
                                    IF  acv.a_ap_tree^[ _act_node ].n_symb in
                                        [ s_year, s_month, s_day, s_hour,
                                        s_minute, s_second, s_microsecond ]
                                    THEN
                                        _pos := 1
                                    ELSE
                                        _pos := acv.a_ap_tree^[ _act_node ].n_pos;
                                    (*ENDIF*) 
                                    _st_end :=
                                          acv.a_mblock.mb_qual^.mfirst_free - 1;
                                    a651value_calculate ( acv, _st_begin,
                                          _st_end, colin.sci_typ = dchb,
                                          dmli.d_like, colin.sci_iolen, _pos);
                                    END;
                                (*ENDIF*) 
                            (*ENDIF*) 
                        (*ENDWITH*) 
                        dmli.d_const_value_expr := _const_value_expr;
                        END;
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
&ifdef trace
t01int4 (ak_sem, 'factcoli len', colin.sci_len);
t01int4 (ak_sem, 'factcoli fra', colin.sci_frac);
t01int4 (ak_sem, 'factcoli iol', colin.sci_iolen);
&endif
END;
 
(*------------------------------*) 
 
FUNCTION
      ak65is_datetime_arith (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            op_node        : tsp00_Int2;
            look_for_dtype : boolean) : boolean;
 
VAR
      left_n     : tsp00_Int2; (* Left  operand of the plus.             *)
      last_left_n: tsp00_Int2; (* Last node of left operand of the plus. *)
      right_n    : tsp00_Int2; (* Right operand of the plus.             *)
      duration_n : tsp00_Int2; (* Node with the number to add or sub.    *)
      new_node   : tsp00_Int2; (* The new constructed node.              *)
      date_arith : boolean;  (* Have we found a datetime arithmetic?   *)
      op_dtype   : tsp00_DataType;
      (* The following variables are for storing the actual state.     *)
      save_datatype         : tsp00_DataType;
      save_change_date_time : boolean;
 
BEGIN
(* This function tests, if a valid oracle or db2 datetime operation   *)
(* is starting at op_node. Such operations can have one of the forms  *)
(* <date>+<number>, <number>+<date>, <date>-<number> or <date>-<date> *)
(* in oracle and the same in db2 with <number> replaced as <duration> *)
(* If look_for_dtype is true, ddatatype is set to the type of the     *)
(* operation-result, else to the expected type of the right operand.  *)
date_arith := false;
WITH acv, dmli DO
    IF  a_sqlmode IN [ sqlm_oracle, sqlm_db2 ]
    THEN
        BEGIN
        save_datatype         := d_datatype;
        save_change_date_time := d_change_date_time;
        duration_n := 0;
        left_n  := a_ap_tree^[ op_node ].n_lo_level;
        right_n := left_n;
        IF  a_ap_tree^[ right_n ].n_symb = s_authid
        THEN
            right_n := a_ap_tree^[ right_n ].n_sa_level;
        (*ENDIF*) 
        IF  a_ap_tree^[ right_n ].n_symb = s_tablename
        THEN
            right_n := a_ap_tree^[ right_n ].n_sa_level;
        (*ENDIF*) 
        last_left_n := right_n;
        right_n := a_ap_tree^[ right_n ].n_sa_level;
        a65_look_for_datatypes (acv, dmli, left_n);
        IF  d_datatype in [dnumber, dfixed, dfloat, dvfloat,
            dunknown, dduration]
        THEN
            BEGIN
            a65_look_for_datatypes (acv, dmli, right_n);
            IF  (d_datatype IN [ dtimestamp, dtime, ddate ]) AND
                (a_ap_tree^[ op_node ].n_symb = s_plus)
            THEN (* This was <number>+<date>, e.g. '1+SYSDATE'. *)
                BEGIN
                date_arith := true;
                op_dtype   := d_datatype;
                duration_n := left_n
                END
            (*ENDIF*) 
            END
        ELSE
            IF  d_datatype in [ dtimestamp, ddate, dtime ]
            THEN
                BEGIN
                op_dtype := d_datatype;
                WITH a_ap_tree^[ right_n ] DO
                    IF  (a_sqlmode = sqlm_oracle) AND
                        (n_proc = a64) AND (n_symb = s_day)
                    THEN
                        d_datatype := dduration
                    ELSE
                        a65_look_for_datatypes (acv, dmli, right_n);
                    (*ENDIF*) 
                (*ENDWITH*) 
                IF  d_datatype in [dnumber, dfixed, dfloat, dvfloat,
                    dunknown, dduration]
                THEN
                    BEGIN (* This was <date>+-<number>, e.g. SYSDATE-1. *)
                    date_arith := true;
                    duration_n := right_n
                    END
                ELSE
                    IF  (d_datatype in [ dtimestamp, ddate, dtime ])
                        AND (a_ap_tree^[ op_node ].n_symb = s_minus)
                    THEN (* It was <date>-<date>, e.g. SYSDATE-SYSDATE *)
                        BEGIN
                        date_arith := true;
                        op_dtype   := dnumber
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (duration_n <> 0) AND
            (a_sqlmode = sqlm_oracle) AND NOT look_for_dtype
        THEN (* The pattern matched, so we should add a duration node. *)
            IF  (a_ap_tree^[ duration_n ].n_proc <> a64)            OR
                (a_ap_tree^[ duration_n ].n_subproc  <> cak_x_duration) OR
                (a_ap_tree^[ duration_n ].n_symb <> s_day)
            THEN (* but we better don't do this twice! *)
                BEGIN
                a_scv.sc_symb := s_day;
                a01_call_put ( acv, a64, cak_x_duration, new_node);
                a_ap_tree^[ new_node ].n_symb := a_scv.sc_symb;
                a_ap_tree^[ new_node ].n_lo_level := duration_n;
                IF  duration_n = left_n
                THEN      (* We switch the right and the (new) left side, *)
                    BEGIN (* so that the timestamp is always on the left. *)
                    a_ap_tree^[ op_node     ].n_lo_level := right_n;
                    a_ap_tree^[ right_n     ].n_sa_level := new_node;
                    a_ap_tree^[ last_left_n ].n_sa_level := 0
                    END
                ELSE (* We put the new right operand beneath the left one. *)
                    a_ap_tree^[ last_left_n ].n_sa_level := new_node
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        d_change_date_time := save_change_date_time;
        IF  look_for_dtype AND date_arith
        THEN (* Set the result type of this datetime arithmetic. *)
            d_datatype := op_dtype
        ELSE (* Restore the original ddatatype. *)
            d_datatype := save_datatype
        (*ENDIF*) 
        END;
    (*ENDIF*) 
(*ENDWITH*) 
ak65is_datetime_arith := date_arith
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65set_op_datetime_arith (
            VAR acv     : tak_all_command_glob;
            VAR dmli    : tak_dml_info;
            VAR colin   : tak00_scolinf; (* Colinfo for left  operand. *)
            VAR colin1  : tak00_scolinf; (* Colinfo for right operand. *)
            act_node    : tsp00_Int4;
            is_plus     : boolean;
            dt_expected : expected_datetime_value);
 
VAR
      dig_len  : integer;
      dig_frac : integer;
 
BEGIN
WITH acv, dmli, a_mblock, mb_qual^, colin DO
    IF  mfirst_free >= mb_st_max
    THEN
        a07_b_put_error (acv,e_too_many_mb_stackentries, -mb_st_max)
    ELSE
        BEGIN
        IF  ((d_datatype = dunicode) AND
            (dt_expected in [ date_or_date_duration, time_or_time_duration ]))
        THEN
            BEGIN
            colin.sci_typ   := dcha;
            d_datatype      := dcha;
            colin.sci_iolen := colin.sci_len + 1;
            a641string_set_operator (acv, op_b_uni_trans,
                  colin.sci_iolen, 0, chr(csp_unicode),
                  chr(csp_ascii));
            END;
        (*ENDIF*) 
        CASE dt_expected OF
            date_or_date_duration :
                IF  NOT (d_datatype in [ ddate, dnumber, dduration,
                    dcha ])
                    OR
                    ((d_datatype = dduration) AND
                    NOT (colin1.sci_dttyp in [ year, month, day ]))
                THEN
                    a07_b_put_error (acv, e_function_not_allowed,
                          a_ap_tree^[ act_node ].n_pos)
                ELSE
                    IF  ((d_datatype = dnumber) AND
                        ((colin1.sci_len   > date_duration_len) OR
                        ( colin1.sci_frac <> 0)))
                    THEN
                        a07_b_put_error (acv, e_invalid_date,
                              a_ap_tree^[ act_node ].n_pos)
                    ELSE
                        BEGIN
                        IF  d_datatype = dcha
                        THEN
                            BEGIN
                            a641check_datetime (acv, dmli, ddate);
                            d_datatype := ddate
                            END;
                        (*ENDIF*) 
                        WITH mb_st^ [mfirst_free] DO
                            BEGIN
                            etype := st_datetime_arith;
                            eop   := op_minus;
                            IF  d_datatype = ddate
                            THEN
                                BEGIN
                                d_datatype    := dnumber;
                                sci_typ       := dfixed;
                                sci_len       := date_duration_len;
                                sci_iolen     := date_duration_iolen;
                                elen_var      := 0;
                                ecol_tab[ 1 ] := chr(0)
                                END
                            ELSE
                                BEGIN
                                sci_typ   := ddate;
                                sci_len   := mxsp_date;
                                sci_iolen := sci_len + 1;
                                IF  d_datatype = dnumber
                                THEN
                                    BEGIN
                                    elen_var      := 1;
                                    ecol_tab[ 1 ] := chr(0)
                                    END
                                ELSE
                                    BEGIN
                                    elen_var      := 2;
                                    ecol_tab[ 1 ] := chr(ord(colin1.sci_dttyp))
                                    END;
                                (*ENDIF*) 
                                d_datatype := ddate;
                                END;
                            (*ENDIF*) 
                            epos          := 0;
                            ecol_tab[ 2 ] := chr(0)
                            END
                        (*ENDWITH*) 
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
            date_duration :
                IF  NOT (d_datatype in [ dnumber, dduration ])
                    OR
                    ((d_datatype = dduration) AND
                    NOT (colin1.sci_dttyp in [ year, month, day ]))
                THEN
                    a07_b_put_error (acv, e_function_not_allowed,
                          a_ap_tree^[ act_node ].n_pos)
                ELSE
                    IF  ((d_datatype = dnumber) AND
                        ((colin1.sci_len   > date_duration_len) OR
                        ( colin1.sci_frac <> 0)))
                    THEN
                        a07_b_put_error (acv, e_invalid_date,
                              a_ap_tree^[ act_node ].n_pos)
                    ELSE
                        WITH mb_st^ [mfirst_free] DO
                            BEGIN
                            sci_typ   := ddate;
                            etype     := st_datetime_arith;
                            eop       := op_plus;
                            sci_len   := mxsp_date;
                            sci_iolen := sci_len + 1;
                            IF  d_datatype = dnumber
                            THEN
                                BEGIN
                                elen_var      := 1;
                                ecol_tab[ 1 ] := chr(0)
                                END
                            ELSE
                                BEGIN
                                elen_var      := 2;
                                ecol_tab[ 1 ] := chr(ord(colin1.sci_dttyp))
                                END;
                            (*ENDIF*) 
                            d_datatype    := ddate;
                            epos          := 0;
                            ecol_tab[ 2 ] := chr(0)
                            END;
                        (*ENDWITH*) 
                    (*ENDIF*) 
                (*ENDIF*) 
            time_or_time_duration :
                IF  NOT (d_datatype in [ dtime,
                    dnumber, dduration, dcha ])
                    OR
                    ((d_datatype = dduration) AND
                    NOT (colin1.sci_dttyp in [ hour, minute, second ]))
                THEN
                    a07_b_put_error (acv, e_function_not_allowed,
                          a_ap_tree^[ act_node ].n_pos)
                ELSE
                    IF  ((d_datatype = dnumber) AND
                        ((colin1.sci_len   > time_duration_len) OR
                        ( colin1.sci_frac <> 0)))
                    THEN
                        a07_b_put_error (acv, e_invalid_time,
                              a_ap_tree^[ act_node ].n_pos)
                    ELSE
                        BEGIN
                        IF  d_datatype = dcha
                        THEN
                            BEGIN
                            a641check_datetime (acv, dmli, dtime);
                            d_datatype := dtime
                            END;
                        (*ENDIF*) 
                        WITH mb_st^ [mfirst_free] DO
                            BEGIN
                            etype := st_datetime_arith;
                            eop   := op_minus;
                            IF  d_datatype = dtime
                            THEN
                                BEGIN
                                d_datatype    := dnumber;
                                sci_typ       := dfixed;
                                sci_len       := time_duration_len;
                                sci_iolen     := time_duration_iolen;
                                elen_var      := 0;
                                ecol_tab[ 1 ] := chr(0)
                                END
                            ELSE
                                BEGIN
                                sci_typ   := dtime;
                                sci_len   := mxsp_time;
                                sci_iolen := sci_len + 1;
                                IF  d_datatype = dnumber
                                THEN
                                    BEGIN
                                    elen_var      := 1;
                                    ecol_tab[ 1 ] := chr(0)
                                    END
                                ELSE
                                    BEGIN
                                    elen_var      := 2;
                                    ecol_tab[ 1 ] := chr(ord(colin1.sci_dttyp))
                                    END;
                                (*ENDIF*) 
                                d_datatype := dtime;
                                END;
                            (*ENDIF*) 
                            epos          := 1;
                            ecol_tab[ 2 ] := chr(0)
                            END
                        (*ENDWITH*) 
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
            time_duration :
                IF  NOT (d_datatype in [ dnumber, dduration ])
                    OR
                    ((d_datatype = dduration) AND
                    NOT (colin1.sci_dttyp in [ hour, minute, second ]))
                THEN
                    a07_b_put_error (acv, e_function_not_allowed,
                          a_ap_tree^[ act_node ].n_pos)
                ELSE
                    IF  ((d_datatype = dnumber) AND
                        ((colin1.sci_len   > time_duration_len) OR
                        ( colin1.sci_frac <> 0)))
                    THEN
                        a07_b_put_error (acv, e_invalid_time,
                              a_ap_tree^[ act_node ].n_pos)
                    ELSE
                        WITH mb_st^ [mfirst_free] DO
                            BEGIN
                            sci_typ   := dtime;
                            etype     := st_datetime_arith;
                            eop       := op_plus;
                            sci_len   := mxsp_time;
                            sci_iolen := succ (sci_len);
                            IF  d_datatype = dnumber
                            THEN
                                BEGIN
                                elen_var      := 1;
                                ecol_tab[ 1 ] := chr(0)
                                END
                            ELSE
                                BEGIN
                                elen_var      := 2;
                                ecol_tab[ 1 ] := chr(ord(colin1.sci_dttyp))
                                END;
                            (*ENDIF*) 
                            d_datatype    := dtime;
                            epos          := 1;
                            ecol_tab[ 2 ] := chr(0)
                            END;
                        (*ENDWITH*) 
                    (*ENDIF*) 
                (*ENDIF*) 
            timestamp_duration :
                BEGIN
                IF  NOT (d_datatype in [ dnumber, dduration, dtimestamp ])
                    OR
                    ((d_datatype = dduration) AND
                    NOT (colin1.sci_dttyp in [ year, month, day, hour,
                    minute, second, microsecond]))
                    OR
                    ((d_datatype = dtimestamp) AND
                    (((a_sqlmode <> sqlm_oracle) AND
                    (  a_sqlmode <> sqlm_db2)) OR is_plus))
                THEN
                    a07_b_put_error (acv, e_function_not_allowed,
                          a_ap_tree^[ act_node ].n_pos)
                ELSE
                    WITH mb_st^ [mfirst_free] DO
                        BEGIN
                        IF  d_datatype = dcha
                        THEN
                            BEGIN
                            a641check_datetime (acv, dmli, dtimestamp);
                            d_datatype := dtimestamp
                            END;
                        (*ENDIF*) 
                        etype := st_datetime_arith;
                        IF  is_plus
                        THEN
                            eop := op_plus
                        ELSE
                            eop := op_minus;
                        (*ENDIF*) 
                        epos          := 2;
                        ecol_tab[ 2 ] := chr(0);
                        IF  (d_datatype = dtimestamp)
                        THEN
                            BEGIN
                            d_datatype    := dnumber;
                            elen_var      := 0;
                            CASE a_sqlmode OF
                                sqlm_db2:
                                    BEGIN
                                    sci_typ       := dfixed;
                                    sci_iolen     := timestamp_duration_iolen;
                                    sci_len       := timestamp_duration_len;
                                    sci_frac      := 6;
                                    ecol_tab[ 1 ] := chr(1); (*seconds*)
                                    END
                                OTHERWISE
                                    BEGIN
                                    sci_typ       := dfloat;
                                    sci_iolen     := NUMBER_MXGG04;
                                    sci_len       := csp_fixed;
                                    sci_frac      := csp_float_frac;
                                    ecol_tab[ 1 ] := chr(4); (*days*)
                                    END
                                END
                            (*ENDCASE*) 
                            END
                        ELSE
                            BEGIN
                            IF  d_datatype = dnumber
                            THEN
                                BEGIN
                                a05get_digit (a_cmd_part^.sp1p_buf,
                                      a_ap_tree^[ act_node ].n_pos,
                                      a_ap_tree^[ act_node ].n_length,
                                      dig_len, dig_frac);
&                               ifdef trace
                                t01int4 (ak_sem, 'dig_len     ', dig_len);
                                t01int4 (ak_sem, 'dig_frac    ', dig_frac);
&                               endif
                                CASE a_sqlmode OF
                                    sqlm_db2:
                                        IF  (dig_len - dig_frac > 14) OR
                                            (dig_frac > 6)
                                        THEN
                                            a07_b_put_error (acv,
                                                  e_function_not_allowed,
                                                  a_ap_tree^[ act_node ].n_pos)
                                        (*ENDIF*) 
                                    OTHERWISE
                                        IF  dig_frac <> 0
                                        THEN
                                            a07_b_put_error (acv,
                                                  e_invalid_timestamp,
                                                  a_ap_tree^[ act_node ].n_pos)
                                        (*ENDIF*) 
                                    END
                                (*ENDCASE*) 
                                END;
                            (*ENDIF*) 
                            IF  a_returncode = 0
                            THEN
                                BEGIN
                                sci_typ   := dtimestamp;
                                sci_len   := mxsp_timestamp;
                                sci_iolen := sci_len + 1;
                                IF  d_datatype = dnumber
                                THEN
                                    BEGIN
                                    elen_var      := 1;
                                    ecol_tab[ 1 ] := chr(5) (*seconds*)
                                    END
                                ELSE
                                    BEGIN
                                    elen_var      := 2;
                                    ecol_tab[ 1 ] := chr(ord(colin1.sci_dttyp))
                                    END;
                                (*ENDIF*) 
                                d_datatype := dtimestamp
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    (*ENDWITH*) 
                (*ENDIF*) 
                END
            END;
        (*ENDCASE*) 
        mfirst_free := succ (mfirst_free);
        mqual_cnt   := succ (mqual_cnt)
        END
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65not_first_val_expr (
            VAR acv    : tak_all_command_glob;
            VAR dmli   : tak_dml_info;
            VAR colin  : tak00_scolinf;
            first_node : integer);
 
VAR
      _st_begin : integer;
      _st_index : integer;
 
BEGIN
_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;
a65_val_expr (acv, dmli, colin, first_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;
 
(*------------------------------*) 
 
PROCEDURE
      a65_val_expr (
            VAR acv    : tak_all_command_glob;
            VAR dmli   : tak_dml_info;
            VAR colin  : tak00_scolinf;
            first_node : integer);
 
VAR
      _datetime_arith   : boolean;
      _change_date_time : boolean;
      _keep_plus        : boolean;
      _dummy_ok         : boolean;
      _dt_expected      : expected_datetime_value;
      _act_node         : integer;
      _convert_t        : tak_convert_type;
      _keep_datatype    : tsp00_DataType;
      _colin1           : tak00_scolinf;
      _const_value_expr : boolean;
      _st_begin         : integer;
      _st_end           : integer;
      _pos              : tsp00_Int4;
      _expr_st_cnt      : tsp00_Int2;
      _save_single_expr : boolean;
 
BEGIN
WITH acv.a_ap_tree^[ first_node ] DO
    BEGIN
&   ifdef TRACE
    t01int4 (ak_sem, 'd_having    ',ord(dmli.d_having));
    t01int4 (ak_sem, 'd_subquery  ',ord(dmli.d_subquery));
    t01int4 (ak_sem, 'd_is_functio',ord(dmli.d_is_function_column));
&   endif
    (* PTS 1119064 E.Z. *)
    IF  g01userstackoverflow
    THEN
        a07_b_put_error (acv, e_program_stack_overflow, 1);
    (*ENDIF*) 
    IF  acv.a_returncode = 0
    THEN
        BEGIN
        _save_single_expr := dmli.d_single_expr;
        dmli.d_single_expr := false;
        IF  dmli.d_having AND NOT dmli.d_subquery AND NOT dmli.d_is_function_column AND
            (dmli.d_corr = no_correlation)
        THEN
            a61_is_group_field ( acv, dmli, dmli.d_column, 0, c_is_expression,
                  first_node, n_pos);
        (*ENDIF*) 
        IF  acv.a_returncode = 0
        THEN
            BEGIN
            _const_value_expr   := dmli.d_const_value_expr;
            dmli.d_const_value_expr := true;
            _st_begin           := acv.a_mblock.mb_qual^.mfirst_free;
            dmli.d_concat           := false;
            dmli.d_hex              := false;
            IF  NOT ((n_proc = a64) AND (n_subproc = cak_x_add_operator))
            THEN
                BEGIN
                _act_node := n_lo_level;
                a65_term (acv, dmli, colin, first_node)
                END
            ELSE      (* For add operations we must deal with the possibility *)
                BEGIN (* of adding a date or time with a duration.            *)
                _keep_plus          := (n_symb = s_plus);
                dmli.d_colptr           := NIL;
                _keep_datatype      := dmli.d_datatype;
                dmli.d_datatype         := dunknown;
                _change_date_time   := dmli.d_change_date_time;
                dmli.d_change_date_time := false;
                _act_node           := n_lo_level;
                (* Check, if a datetime_arith is present and must be modified. *)
                _datetime_arith     := ak65is_datetime_arith (acv, dmli,
                      first_node, NOT c_look_for_dtype);
                IF  _datetime_arith AND (acv.a_sqlmode = sqlm_oracle)
                THEN
                    BEGIN
                    _dt_expected := timestamp_duration;
                    _act_node    := n_lo_level; (* This could have changed. *)
                    END;
                (*ENDIF*) 
                a65_term (acv, dmli, colin, _act_node);
                IF  acv.a_returncode = cak_e_parameter
                THEN
                    BEGIN
                    acv.a_returncode := 0;
                    a65_look_for_datatypes (acv, dmli, _act_node);
                    IF  dmli.d_datatype = dunknown
                    THEN
                        dmli.d_datatype := dnumber;
                    (*ENDIF*) 
                    a65_term(acv, dmli, colin, _act_node)
                    END;
                (*ENDIF*) 
                IF  (acv.a_sqlmode = sqlm_oracle) AND _datetime_arith
                THEN (* For oracle mode we have already checked that. *)
                    dmli.d_datatype := dunknown
                ELSE
                    IF  dmli.d_datatype in [ dcha, dunicode,
                        ddate, dtime, dtimestamp ]
                    THEN
                        BEGIN
                        IF  dmli.d_datatype in [ dcha, dunicode ]
                        THEN
                            IF  acv.a_sqlmode <> sqlm_db2
                            THEN
                                a07_b_put_error (acv, e_function_not_allowed,
                                      acv.a_ap_tree^[ first_node ].n_pos)
                            ELSE
                                BEGIN
                                IF  dmli.d_datatype = dunicode
                                THEN
                                    BEGIN
                                    a641string_set_operator (acv, op_b_uni_trans,
                                          colin.sci_len+1, 0, chr(csp_unicode),
                                          chr(csp_ascii));
                                    colin.sci_iolen := colin.sci_len+1;
                                    colin.sci_typ   := dcha
                                    END;
                                (*ENDIF*) 
                                CASE acv.a_ap_tree^[ acv.a_ap_tree^[ _act_node ]
                                      .n_sa_level ].n_symb OF
                                    s_year, s_month, s_day:
                                        IF  n_proc = no_proc
                                        THEN
                                            dmli.d_datatype := dnumber
                                        ELSE (* duration *)
                                            IF  colin.sci_len > mxsp_extdate
                                            THEN
                                                dmli.d_datatype := dtimestamp
                                            ELSE
                                                dmli.d_datatype := ddate;
                                            (*ENDIF*) 
                                        (*ENDIF*) 
                                    s_hour, s_minute, s_second:
                                        IF  n_proc = no_proc
                                        THEN
                                            dmli.d_datatype := dnumber
                                        ELSE (* duration *)
                                            IF  colin.sci_len > mxsp_exttime
                                            THEN
                                                dmli.d_datatype := dtimestamp
                                            ELSE
                                                dmli.d_datatype := dtime;
                                            (*ENDIF*) 
                                        (*ENDIF*) 
                                    OTHERWISE
                                        a65_look_for_datatypes (acv, dmli,
                                              acv.a_ap_tree^[ _act_node ].n_sa_level);
                                    END;
                                (*ENDCASE*) 
                                IF  dmli.d_datatype in [ ddate, dtime, dtimestamp ]
                                THEN
                                    a641check_datetime (acv, dmli, dmli.d_datatype)
                                ELSE
                                    a07_b_put_error (acv, e_function_not_allowed,
                                          acv.a_ap_tree^[ first_node ].n_pos)
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        IF  acv.a_returncode = 0
                        THEN
                            IF  acv.a_sqlmode = sqlm_db2
                            THEN
                                BEGIN
                                _datetime_arith := true;
                                CASE dmli.d_datatype OF
                                    ddate :
                                        IF  _keep_plus
                                        THEN
                                            _dt_expected := date_duration
                                        ELSE
                                            _dt_expected := date_or_date_duration;
                                        (*ENDIF*) 
                                    dtime :
                                        IF  _keep_plus
                                        THEN
                                            _dt_expected := time_duration
                                        ELSE
                                            _dt_expected := time_or_time_duration;
                                        (*ENDIF*) 
                                    dtimestamp :
                                        _dt_expected := timestamp_duration;
                                    END;
                                (*ENDCASE*) 
                                dmli.d_datatype := dunknown
                                END
                            ELSE
                                a07_b_put_error (acv, e_function_not_allowed,
                                      acv.a_ap_tree^[ first_node ].n_pos)
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END
                    ELSE
                        IF  NOT (dmli.d_datatype in [dnumber, dfixed, dfloat, dvfloat])
                        THEN
                            a07_b_put_error (acv, e_function_not_allowed,
                                  acv.a_ap_tree^[ first_node ].n_pos);
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
                IF  acv.a_returncode = 0
                THEN
                    BEGIN
                    _act_node   := acv.a_ap_tree^[ _act_node ].n_sa_level;
                    _colin1.sci_len := 0;
                    ak65not_first_term (acv, dmli, _colin1, _act_node)
                    END;
&               ifdef TRACE
                (*ENDIF*) 
                t01int4 (ak_sem, 'pmtcoli  len', colin.sci_len);
                t01int4 (ak_sem, 'pmtcoli  fra', colin.sci_frac);
                t01int4 (ak_sem, 'pmtcoli  iol', colin.sci_iolen);
                t01int4 (ak_sem, 'pmtcoli1 len', _colin1.sci_len);
                t01int4 (ak_sem, 'pmtcoli1 fra', _colin1.sci_frac);
                t01int4 (ak_sem, 'pmtcoli1 iol', _colin1.sci_iolen);
&               endif
                IF  acv.a_returncode = cak_e_parameter
                THEN
                    IF  NOT _keep_plus
                    THEN
                        (* PTS 1109261 E.Z. *)
                        BEGIN
                        acv.a_returncode := 0;
                        a07_b_put_error (acv, e_without_datatypes,
                              acv.a_ap_tree^[ _act_node ].n_pos)
                        END
                    ELSE
                        BEGIN
                        acv.a_returncode := 0;
                        a65_look_for_datatypes (acv, dmli, _act_node);
                        IF  dmli.d_datatype = dunknown
                        THEN
                            dmli.d_datatype := dnumber;
                        (*ENDIF*) 
                        ak65not_first_term(acv, dmli, _colin1, _act_node)
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
                IF  acv.a_returncode = 0
                THEN
                    BEGIN
                    IF  _datetime_arith
                    THEN
                        ak65set_op_datetime_arith (acv, dmli, colin, _colin1,
                              _act_node, _keep_plus, _dt_expected)
                    ELSE
                        IF  _keep_plus
                        THEN
                            BEGIN
                            ak65new_colinfo (acv, colin, _colin1, s_plus);
                            a65_set_operator (acv, op_plus)
                            END
                        ELSE
                            BEGIN
                            ak65new_colinfo (acv, colin, _colin1, s_minus);
                            a65_set_operator (acv, op_minus)
                            END;
                        (*ENDIF*) 
                    (*ENDIF*) 
&                   ifdef TRACE
                    t01int4 (ak_sem, 'pmtcoli  len', colin.sci_len);
                    t01int4 (ak_sem, 'pmtcoli  fra', colin.sci_frac);
                    t01int4 (ak_sem, 'pmtcoli  iol', colin.sci_iolen);
                    t01int4 (ak_sem, 'keep_type   ', ord(_keep_datatype));
                    t01int4 (ak_sem, 'd_datatype  ', ord(dmli.d_datatype));
                    t01int4 (ak_sem, 'colin_type  ', ord(colin.sci_typ));
                    t01int4 (ak_sem, 'd_change    ', ord(dmli.d_change_date_time));
&                   endif
                    END;
                (*ENDIF*) 
                IF  _keep_datatype <> dunknown
                THEN
                    (* PTS 1000985/1001162 E.Z. *)
                    _dummy_ok := a65_datatypes_ok (acv, dmli,
                          _keep_datatype, colin.sci_iolen,
                          dmli.d_datatype, NOT c_is_subquery,
                          first_node, acv.a_ap_tree^[ first_node ].n_pos,
                          c_convert, _convert_t);
                (*ENDIF*) 
                dmli.d_change_date_time := _change_date_time
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  dmli.d_const_value_expr AND NOT dmli.d_group AND
            (acv.a_returncode = 0)
        THEN
            BEGIN
            _expr_st_cnt := acv.a_mblock.mb_qual^.mfirst_free - _st_begin;
            WITH acv.a_mblock, mb_qual^ DO
                IF  (dmli.d_param_st_index > 0) AND
                    (_expr_st_cnt <= 255) AND
                    (((n_proc = a64) AND (n_subproc = cak_x_add_operator)) OR
                    (_st_begin <> dmli.d_param_st_begin)) AND
                    (mb_data_len - mb_st^[_st_begin].epos + 1 >= colin.sci_iolen)
                THEN
                    a651code_for_const_param_expr (acv,
                          dmli, _st_begin, _expr_st_cnt)
                ELSE
                    IF  dmli.d_param_st_index = 0
                    THEN
                        BEGIN
                        IF  acv.a_ap_tree^[ _act_node ].n_symb in [ s_year, s_month,
                            s_day, s_hour, s_minute, s_second, s_microsecond ]
                        THEN
                            _pos := 1
                        ELSE
                            _pos := acv.a_ap_tree^[ _act_node ].n_pos;
                        (*ENDIF*) 
                        _st_end := acv.a_mblock.mb_qual^.mfirst_free - 1;
                        a651value_calculate ( acv, _st_begin, _st_end,
                              colin.sci_typ = dchb, dmli.d_like, colin.sci_iolen, _pos);
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDWITH*) 
            dmli.d_const_value_expr := _const_value_expr;
            END;
        (*ENDIF*) 
        dmli.d_single_expr := _save_single_expr;
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      ak65only_jvalue_found (
            VAR dmli   : tak_dml_info;
            oldjoincnt : integer) : boolean;
 
VAR
      only_jvalue_found : boolean;
      j                 : integer;
      jval_cnt          : integer;
 
BEGIN
j            := oldjoincnt;
jval_cnt     := 0;
WHILE (j < dmli.d_joins.jrc_cnt) DO
    BEGIN
    IF  (dmli.d_joins.jrc_joinarr[ j ].jo_recs[ 2 ].jop_tableno =
        cak68_join_value)
    THEN
        jval_cnt := succ (jval_cnt);
    (*ENDIF*) 
    j := succ (j);
    END;
(*ENDWHILE*) 
only_jvalue_found := (jval_cnt > 0) AND
      (dmli.d_joins.jrc_cnt - oldjoincnt - jval_cnt = 0);
&ifdef TRACE
t01int4 (ak_sem, 'jrc_cnt     ', dmli.d_joins.jrc_cnt);
t01int4 (ak_sem, 'oldjoincnt  ', oldjoincnt);
t01int4 (ak_sem, 'jvalue_found', ord (only_jvalue_found));
&endif
IF  only_jvalue_found
THEN
    BEGIN
    (* reset last entry *)
    dmli.d_joins.jrc_cnt := oldjoincnt;
    ak65init_one_join(dmli.d_joins.jrc_joinarr[ dmli.d_joins.jrc_cnt ]);
    END;
(*ENDIF*) 
ak65only_jvalue_found := only_jvalue_found;
END;
 
(*------------------------------*) 
 
FUNCTION
      ak65outer_cond_found (
            VAR dmli   : tak_dml_info;
            oldjoincnt : integer) : boolean;
 
VAR
      outer_cond_found  : boolean;
      j                 : integer;
 
BEGIN (* PTS 1113326 *)
WITH dmli, d_joins DO
    BEGIN
    outer_cond_found := false;
    j                := oldjoincnt;
    WHILE (j < jrc_cnt) AND NOT outer_cond_found DO
        BEGIN
        outer_cond_found := ((jrc_joinarr[ j ].jo_recs[ 1 ].jop_outer_join)
              OR (jrc_joinarr[ j ].jo_recs[ 2 ].jop_outer_join));
        j := succ (j);
        END;
    (*ENDWHILE*) 
    ak65outer_cond_found := outer_cond_found;
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      ak65subq_se (
            VAR acv        : tak_all_command_glob;
            VAR first_node : integer) : boolean;
 
VAR
      _snot : boolean;
      _ix   : tsp00_Int4;
 
BEGIN
&ifdef trace
t01int4 (ak_sem, 'fi_node in  ', first_node);
&endif
_snot := false;
WITH acv, a_ap_tree^[ first_node ] DO
    (* *** case of 'not (a = b and/or c = d)'        *)
    (*     ===> no change of compare-operator !  *** *)
    IF  n_symb = s_not
    THEN
        BEGIN
        (* *** check if subquery exists *** *)
        _ix   := n_sa_level;
        IF  (a_ap_tree^[ _ix ].n_sa_level > 0)
        THEN
            _ix := a_ap_tree^[ _ix ].n_sa_level
        ELSE
            _ix := a_ap_tree^[ _ix ].n_lo_level;
        (*ENDIF*) 
        WHILE (_ix > 0) AND (NOT _snot) DO
            BEGIN
            _snot := (a_ap_tree^[ _ix ].n_proc = a63query_spec);
            IF  (a_ap_tree^[ _ix ].n_sa_level > 0)
            THEN
                _ix := a_ap_tree^[ _ix ].n_sa_level
            ELSE
                _ix := a_ap_tree^[ _ix ].n_lo_level;
            (*ENDIF*) 
            END;
        (*ENDWHILE*) 
        IF  (a_ap_tree^[ n_sa_level ].n_symb = s_and) OR
            (a_ap_tree^[ n_sa_level ].n_symb = s_or)  OR
            _snot
        THEN
            BEGIN
            _snot       := true;
            first_node := n_sa_level
            END;
        (*ENDIF*) 
        END;
&   ifdef trace
    (*ENDIF*) 
(*ENDWITH*) 
t01int4 (ak_sem, 'fi_node out ', first_node);
t01int4 (ak_sem, 'snot        ', ord(_snot));
&endif
ak65subq_se := _snot;
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65init_one_join(
            VAR ojoin   : tak_one_join );
 
BEGIN
ojoin.jo_no_join      := false;
ojoin.jo_partno       := 1;
ojoin.jo_col_upd_stat := 0;
ojoin.jo_op           := op_none;
ojoin.jo_recs[1].jop_tableno    := 0;
ojoin.jo_recs[1].jop_fieldno    := 0;
ojoin.jo_recs[1].jop_startstack := 0;
ojoin.jo_recs[1].jop_cntstack   := 0;
ojoin.jo_recs[1].jop_filler0    := 0;
ojoin.jo_recs[1].jop_inoutlen   := 0;
ojoin.jo_recs[1].jop_outpos     := 0;
ojoin.jo_recs[1].jop_outer_join := false;
ojoin.jo_recs[1].jop_datatyp    := dunknown;
ojoin.jo_recs[1].jop_propset    := [];
;
ojoin.jo_recs[2].jop_tableno    := 0;
ojoin.jo_recs[2].jop_fieldno    := 0;
ojoin.jo_recs[2].jop_startstack := 0;
ojoin.jo_recs[2].jop_cntstack   := 0;
ojoin.jo_recs[2].jop_filler0    := 0;
ojoin.jo_recs[2].jop_inoutlen   := 0;
ojoin.jo_recs[2].jop_outpos     := 0;
ojoin.jo_recs[2].jop_outer_join := false;
ojoin.jo_recs[2].jop_datatyp    := dunknown;
ojoin.jo_recs[2].jop_propset    := [];
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65is_const_expr(
            ap_tree         : tak_ap_max_tree_ptr;
            node            : tsp00_Int4;
            ignore_sa_level : boolean; (* true = first node of left side *)
            VAR is_const    : boolean );
 
BEGIN
&ifdef trace
t01int4 (ak_sem, 'node        ', node );
&endif
IF  (( is_const ) AND ( node <> 0 ))
THEN
    BEGIN
    is_const :=
          (( ap_tree^[ node ].n_proc = a67 ) AND
          ( ap_tree^[ node ].n_subproc = 0 ))
          (* value of correlated subquery *)
          OR
          ((ap_tree^[ node ].n_proc = a63query_spec) OR
          ((ap_tree^[ node ].n_proc = a63) AND
          (ap_tree^[ node ].n_subproc in
          [cak_x_start_union,cak_x_arith_with_subquery])))
          (* subquery *)
          OR
          NOT (( ap_tree^[ node ].n_symb in
          [ s_authid, s_tablename, s_columnname, s_reference_name,
          s_count, s_all_count, s_avg, s_stddev,
          s_variance, s_min, s_max, s_sum,
          s_dis_count, s_dis_avg, s_dis_stddev,
          s_dis_variance, s_dis_sum, s_rowno ]) OR
          ( NOT ( ap_tree^[ node ].n_proc in [ no_proc, a64, a641 ])));
    IF  ( is_const )
    THEN
        BEGIN
        IF  ( NOT ignore_sa_level ) AND
            ( ap_tree^[ node ].n_sa_level <> 0 )
        THEN
            ak65is_const_expr( ap_tree, ap_tree^[ node ].n_sa_level,
                  NOT c_ignore_sa_level, is_const );
        (*ENDIF*) 
        IF  is_const AND (ap_tree^[ node ].n_lo_level <> 0) AND
            NOT ((ap_tree^[ node ].n_proc = a63query_spec) OR
            ((ap_tree^[ node ].n_proc = a63) AND
            (ap_tree^[ node ].n_subproc in
            [cak_x_start_union,cak_x_arith_with_subquery])))
        THEN
            ak65is_const_expr( ap_tree, ap_tree^[ node ].n_lo_level,
                  NOT c_ignore_sa_level, is_const );
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
