.nf
 
 
    ========== licence begin  GPL
    Copyright (C) 2000 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
*****************************************************
Copyright by SAP AG, 2000
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      : tsp_data_type;
                    d_type         : tsp_data_type);
 
        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 : tgg_stack_op_type);
 
        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    : tsp_data_type;
                    VAR dm_iolen   : tsp_int2;
                    ctype          : tsp_data_type;
                    is_subquery    : boolean;
                    first_node     : integer;
                    error_pos      : tsp_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             : tsp_knl_identifier;
              a01_i_old             : tsp_knl_identifier;
              a01_il_b_identifier   : tsp_knl_identifier;
 
        PROCEDURE
              a01_dt_put_datatype_node (
                    VAR acv    : tak_all_command_glob;
                    VAR curr_n : tsp_int2;
                    data_type  : tsp_data_type;
                    datalen    : tsp_int2;
                    datafrac   : tsp_int2;
                    inoutlen   : integer);
 
        PROCEDURE
              a01_call_put (
                    VAR acv  : tak_all_command_glob;
                    proc     : tak_procs;
                    subproc  : tsp_int2;
                    VAR curr_n : tsp_int2);
 
        PROCEDURE
              a01_function_put (
                    VAR acv    : tak_all_command_glob;
                    VAR curr_n : tsp_int2);
 
        PROCEDURE
              a01_put_same_node (
                    VAR acv    : tak_all_command_glob;
                    input_node : tsp_int2;
                    VAR curr_n : tsp_int2);
 
      ------------------------------ 
 
        FROM
              AK_semantic_scanner_tools : VAK05;
 
        PROCEDURE
              a05dfts_date_from_timestamp (
                    VAR sbuf   : tsp_moveobj;
                    VAR dbuf   : tsp_c28;
                    spos       : tsp_int4;
                    dpos       : tsp_int4;
                    dbufsize   : tsp_int4;
                    actlen     : integer;
                    format     : tgg_datetimeformat;
                    language   : tsp_c3;
                    ch_code    : boolean;
                    VAR b_err  : tgg_basis_error);
 
        PROCEDURE
              a05tfts_time_from_timestamp (
                    VAR sbuf   : tsp_moveobj;
                    VAR dbuf   : tsp_c28;
                    spos       : tsp_int4;
                    dpos       : tsp_int4;
                    dbufsize   : tsp_int4;
                    actlen     : integer;
                    format     : tgg_datetimeformat;
                    language   : tsp_c3;
                    ch_code    : boolean;
                    VAR b_err  : tgg_basis_error);
 
        PROCEDURE
              a05tsfdt_timestamp_from_dattim (
                    VAR sbuf   : tsp_moveobj;
                    VAR dbuf   : tsp_c28;
                    spos       : tsp_int4;
                    dpos       : tsp_int4;
                    dbufsize   : tsp_int4;
                    actlen     : integer;
                    format     : tgg_datetimeformat;
                    stype      : tsp_data_type;
                    ch_code    : boolean;
                    VAR b_err  : tgg_basis_error);
 
        PROCEDURE
              a05identifier_get (
                    VAR acv     : tak_all_command_glob;
                    tree_index  : integer;
                    obj_len     : integer;
                    VAR moveobj : tsp_knl_identifier);
 
        PROCEDURE
              a05timestamp_get (
                    VAR acv   : tak_all_command_glob;
                    VAR src   : tsp_moveobj;
                    src_pos   : tsp_int4;
                    VAR dest  : tsp_c28;
                    dest_pos  : tsp_int4;
                    check_len : tsp_int4;
                    ch_code   : boolean;
                    VAR b_err : tgg_basis_error);
 
        PROCEDURE
              a05get_digit (
                    VAR num_buf  : tsp_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   : tsp_knl_identifier);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK07;
 
        PROCEDURE
              a07_b_put_error (
                    VAR acv : tak_all_command_glob;
                    b_err   : tgg_basis_error;
                    err_code : tsp_int4);
 
        FUNCTION
              a07_return_code (
                    b_err   : tgg_basis_error;
                    sqlmode : tsp_sqlmode) : tsp_int2;
 
      ------------------------------ 
 
        FROM
              AK_Domain : VAK12;
 
        FUNCTION
              a12dbfunc_exist (
                    VAR acv         : tak_all_command_glob;
                    VAR dbfunc_name : tsp_knl_identifier;
                    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 : tsp_data_type);
 
      ------------------------------ 
 
        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 : tgg_mess_block;
                    stentrynr : integer;
                    operator  : tgg_stack_entry_type);
 
        PROCEDURE
              a61_format_change (
                    VAR acv     : tak_all_command_glob;
                    VAR dmli    : tak_dml_info;
                    stackpos    : integer;
                    cdatatyp    : tsp_data_type;
                    VAR datalen : tsp_int2);
 
        PROCEDURE
              a61_is_group_field (
                    VAR acv       : tak_all_command_glob;
                    VAR dmli      : tak_dml_info;
                    VAR fieldname : tsp_knl_identifier;
                    refname_ptr   : tsp_knl_identifier_ptr;
                    use_refname   : boolean;
                    extcolno      : tsp_int2;
                    is_expression : boolean;
                    expression_n  : tsp_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  : tsp_data_type);
 
        PROCEDURE
              a641s_literal_value (
                    VAR acv           : tak_all_command_glob;
                    act_node           : integer;
                    keep_datatype      : tsp_data_type;
                    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     : tgg_stack_op_build_in;
                    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          : tsp_int2;
                    keep_datatype      : tsp_data_type);
 
        PROCEDURE
              a641translate_string_literal (
                    VAR letter        : char;
                    VAR keep_datatype : tsp_data_type);
 
        PROCEDURE
              a641u_literal_value (
                    VAR acv            : tak_all_command_glob;
                    act_node           : integer;
                    VAR c2             : tsp_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    : tgg_stack_op_type);
 
        PROCEDURE
              a651in_const_expression (
                    VAR acv     : tak_all_command_glob;
                    VAR dmli    : tak_dml_info;
                    st_begin    : tsp_int2;
                    st_end      : tsp_int2);
 
        PROCEDURE
              a651code_for_const_param_expr
                    (VAR acv : tak_all_command_glob;
                    VAR dmli    : tak_dml_info;
                    st_begin    : tsp_int2;
                    expr_st_cnt : tsp_int2);
 
        PROCEDURE
              a651value_calculate (
                    VAR acv  : tak_all_command_glob;
                    st_begin : integer;
                    st_end   : integer;
                    byte_str : boolean;
                    like     : boolean;
                    iolen    : tsp_int2;
                    err_pos  : tsp_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);
&       endif
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01code           : tgg_code_globals;
              g01unicode        : boolean;
 
        FUNCTION
              g01userstackoverflow : boolean;
 
        FUNCTION
              g01mb_data_size : tsp_int4;
 
      ------------------------------ 
 
        FROM
              Check-Date-Time : VGG03;
 
        PROCEDURE
              g03fdcheck_date (
                    VAR sbuf : tsp_moveobj;
                    VAR dbuf : tsp_c28;
                    spos     : tsp_int4;
                    dpos     : tsp_int4;
                    actlen   : integer;
                    format   : tgg_datetimeformat;
                    ch_code  : boolean;
                    VAR e    : tgg_basis_error);
 
        PROCEDURE
              g03ftcheck_time (
                    VAR sbuf : tsp_moveobj;
                    VAR dbuf : tsp_c28;
                    spos     : tsp_int4;
                    dpos     : tsp_int4;
                    actlen   : integer;
                    format   : tgg_datetimeformat;
                    ch_code  : boolean;
                    VAR e    : tgg_basis_error);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG10;
 
        PROCEDURE
              g10mv1  (
                    mod_id         : tsp_c6;
                    mod_intern_num : tsp_int4;
                    size1          : tsp_int4;
                    size2          : tsp_int4;
                    VAR val1       : tgg00_FileId;
                    p1             : tsp_int4;
                    VAR val2       : tsp_moveobj;
                    p2             : tsp_int4;
                    cnt            : tsp_int4;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10mv2  (
                    mod_id         : tsp_c6;
                    mod_intern_num : tsp_int4;
                    size1          : tsp_int4;
                    size2          : tsp_int4;
                    VAR val1       : tsp_c28;
                    p1             : tsp_int4;
                    VAR val2       : tsp_moveobj;
                    p2             : tsp_int4;
                    cnt            : tsp_int4;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10mvr  (
                    mod_id         : tsp_c6;
                    mod_intern_num : tsp_int4;
                    size1          : tsp_int4;
                    size2          : tsp_int4;
                    VAR val1       : tgg_stack_list;
                    p1             : tsp_int4;
                    VAR val2       : tgg_stack_list;
                    p2             : tsp_int4;
                    cnt            : tsp_int4;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10fil  (
                    mod_id         : tsp_c6;
                    mod_intern_num : tsp_int4;
                    size           : tsp_int4;
                    VAR m          : tsp_moveobj;
                    pos            : tsp_int4;
                    len            : tsp_int4;
                    fillchar       : char;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10filuni  (
                    mod_id         : tsp_c6;
                    mod_intern_num : tsp_int4;
                    size           : tsp_int4;
                    VAR m          : tsp_moveobj;
                    pos            : tsp_int4;
                    len            : tsp_int4;
                    filluchar      : tsp_c2;
                    VAR e          : tgg_basis_error);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-10 : VSP10;
 
        PROCEDURE
              s10fil (
                    size     : tsp_int4;
                    VAR m    : tak_joinarr;
                    pos      : tsp_int4;
                    len      : tsp_int4;
                    fillchar : char);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        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   : tsp_int2);
&       endif
 
.CM *-END-* use -----------------------------------------
***********************************************************
 
Synonym :
 
        PROCEDURE
              a56_datatype;
 
              tsp_data_type char
 
        PROCEDURE
              a05dfts_date_from_timestamp ;
 
              tsp_moveobj tsp_c28
 
        PROCEDURE
              a05tfts_time_from_timestamp ;
 
              tsp_moveobj tsp_c28
 
        PROCEDURE
              a05tsfdt_timestamp_from_dattim ;
 
              tsp_moveobj tsp_c28
 
        PROCEDURE
              g03fdcheck_date ;
 
              tsp_moveobj tsp_c28
 
        PROCEDURE
              g03ftcheck_time ;
 
              tsp_moveobj tsp_c28
 
        PROCEDURE
              a05timestamp_get;
 
              tsp_moveobj tsp_c28
 
        PROCEDURE
              a05identifier_get;
 
              tsp_moveobj tsp_knl_identifier
 
        PROCEDURE
              g10mv1;
 
              tsp_moveobj tgg00_FileId
 
        PROCEDURE
              g10mv2;
 
              tsp_moveobj tsp_c28
 
        PROCEDURE
              g10mvr;
 
              tsp_moveobj tgg_stack_list
 
        PROCEDURE
              s10fil;
 
              tsp_moveobj tak_joinarr
&             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_return_segm^.sp1r_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_return_segm^.sp1r_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), dche (4), 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'. In the case of ASCII - EBCDIC
incompatibility, a corresponding conversion is entered in the stack.
 
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', 'dche'
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, dche )
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_use_refname       = true (* a61_is_group_field *);
      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  : tsp_data_type;
            datalen   : tsp_int2;
            datafrac  : tsp_int1;
            filler    : boolean;
            inout_len : tsp_int2;
            pos       : tsp_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;
 
BEGIN
WITH acv, dmli, d_joins, jrc_joinarr[ jrc_cnt ] DO
    IF  NOT jo_no_join
    THEN
        BEGIN
        IF  (jo_recs[ 1 ].jop_tableno > 0)
        THEN
            BEGIN
            IF  jrc_cnt = MAX_JOINS_GG00
            THEN
                BEGIN
                (* end of jrc_joinarr reached, test if *)
                (* a real join predicate has to be *)
                (* inserted                        *)
                IF  jo_recs[ 2 ].jop_tableno <> 0
                THEN
                    BEGIN
                    (* join predicate, try to remove a *)
                    (* value predicate                 *)
                    ix := 0;
                    WHILE ix < MAX_JOINS_GG00 DO
                        IF  jrc_joinarr[ix].jo_recs[2].jop_tableno =
                            cak68_join_value
                        THEN
                            BEGIN
                            jrc_joinarr[ix] := jrc_joinarr[MAX_JOINS_GG00];
                            ix          := c_found
                            END
                        ELSE
                            ix := ix + 1;
                        (*ENDIF*) 
                    (*ENDWHILE*) 
                    IF  ix <> c_found
                    THEN
                        a07_b_put_error (acv, e_too_many_joins,
                              a_ap_tree^[ act_node ].n_pos)
                    ELSE
                        BEGIN
                        jrc_joinarr[MAX_JOINS_GG00].jo_recs[1].jop_tableno    := 0;
                        jrc_joinarr[MAX_JOINS_GG00].jo_recs[2].jop_tableno    := 0;
                        jrc_joinarr[MAX_JOINS_GG00].jo_recs[1].jop_outer_join := false;
                        jrc_joinarr[MAX_JOINS_GG00].jo_recs[2].jop_outer_join := false;
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
&               ifdef TRACE
                t01int4 (ak_sem, 'first_node^^', first_node);
                t01int4 (ak_sem, 'act_nodepred', act_node);
                t01int4 (ak_sem, 'jrc_cnt     ', d_joins.jrc_cnt);
                d_joins.jrc_cnt := succ (d_joins.jrc_cnt);
                IF  d_join
                THEN
                    a683_output (ak_sem, dmli);
                (*ENDIF*) 
                d_joins.jrc_cnt := pred (d_joins.jrc_cnt);
&               endif
                curr_n := a_ap_tree^[ act_node ].n_sa_level;
                IF  (curr_n > 0)
                THEN
                    IF  (a_ap_tree^[ curr_n ].n_symb = s_tablename)
                    THEN
                        curr_n := a_ap_tree^[ curr_n ].n_sa_level;
                    (*ENDIF*) 
                (*ENDIF*) 
                IF  (curr_n > 0)
                THEN
                    IF  (a_ap_tree^[ curr_n ].n_symb = s_columnname)
                    THEN
                        curr_n := a_ap_tree^[ curr_n ].n_sa_level;
                    (* h.b. PTS 1000329 *)
                    (*ENDIF*) 
                (*ENDIF*) 
                IF  (curr_n > 0)                           AND
                    (jo_recs[ 1 ].jop_tableno <> 0)             AND
                    (jo_recs[ 2 ].jop_tableno =  0)             AND
                    (a_ap_tree^[ act_node ].n_symb IN
                    [ s_authid, s_tablename, s_columnname ])    AND
                    (( a_outer_join AND (jo_op <> op_none)) (* PTS 1113327 *)
                    OR
                    ((a_ap_tree^[ first_node ].n_symb = s_equal)
                    AND (jo_op = op_eq)))
                THEN
                    BEGIN
                    WITH a_ap_tree^[ curr_n ], jo_recs [ 2 ],
                         a_mblock, mb_qual^,
                         mb_st^[jo_recs [1].jop_startstack + 1] DO
                        IF  (n_sa_level = 0) AND
                            (n_lo_level = 0)
                        THEN
                            BEGIN
                            IF  (n_symb IN
                                [ s_parameter_name,
                                s_string_literal,
                                s_byte_string, (* PTS 1117492 *)
                                s_unsigned_integer,
                                s_fixed_point_literal,
                                s_floating_point_literal,
                                s_null]) (* PTS 1113327 *)
                                AND (etype = st_value)
                                AND (jo_recs[ 1 ].jop_inoutlen <> 0)
                            THEN
                                IF   jo_recs[ 2 ].jop_outer_join
                                THEN
                                    a07_b_put_error (acv,
                                          e_outer_join_not_allowed, n_pos)
                                ELSE
                                    BEGIN
                                    jop_tableno    := cak68_join_value;
                                    jop_fieldno    := 0;
                                    jop_startstack := succ (jo_recs[ 1 ].jop_startstack);
                                    jop_cntstack   := 1;
                                    jop_datatyp    := jo_recs[ 1 ].jop_datatyp;
                                    jop_inoutlen   := jo_recs[ 1 ].jop_inoutlen;
                                    jop_datalen    := jo_recs[ 1 ].jop_datalen;
                                    jop_propset    := [  ];
                                    jop_outer_join := false;
                                    jop_outpos     := 0;
                                    jop_multiplier := csp_maxint4;
&                                   ifdef TRACE
                                    t01int4 (ak_sem, 'value_found ',
                                          ord (a_ap_tree^[ curr_n ].n_symb));
&                                   endif
                                    END;
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                    (*ENDWITH*) 
                    END
                ELSE
                    (* *** PTS 2801 961112 multiple Indexfelder       *)
                    (*     werden von a70_strategy nicht erkannt  *** *)
                    IF  (jo_recs[ 2 ].jop_startstack > 0) AND
                        (jo_recs[ 2 ].jop_startstack <=
                        a_mblock.mb_qual^.mfirst_free) AND
                        (jo_recs[ 2 ].jop_tableno <> 0)
                    THEN
                        WITH a_mblock, mb_qual^,
                             mb_st^[jo_recs[ 2 ].jop_startstack ] DO
                            IF  (jtmulti in jo_recs[ 2 ].jop_propset) AND
                                (ord (ecol_tab[ 2 ]) < 100)      AND
                                (etype in [ st_fixkey, st_varkey,
                                st_fixcol, st_varcol ])
                            THEN
                                ecol_tab[ 2 ] :=
                                      chr( ord (ecol_tab[ 2 ]) + 100);
&                           ifdef TRACE
                            (*ENDIF*) 
                        (*ENDWITH*) 
                    (*ENDIF*) 
                (*ENDIF*) 
                t01int4 (ak_sem, '@@@@@@@@@@@@',
                      jo_recs[ 2 ].jop_startstack);
                t01messblock (ak_join, 'ak65analyze ', a_mblock);
&               endif
                IF  (jo_recs[ 2 ].jop_tableno = 0)
                THEN
                    BEGIN
                    d_joins.jrc_cnt := pred (d_joins.jrc_cnt);
&                   ifdef TRACE
                    t01int4 (ak_sem, 'jcnt!!!!!!!!', d_joins.jrc_cnt);
&                   endif
                    END
                ELSE
                    IF  ((jo_recs[ 1 ].jop_inoutlen = 0) OR
                        ( jo_recs[ 2 ].jop_inoutlen = 0))
                    THEN
                        a07_b_put_error (acv, e_join_fields_too_long,
                              a_ap_tree^[ act_node ].n_pos);
&                   ifdef TRACE
                    (*ENDIF*) 
                (*ENDIF*) 
                t01int4 (ak_sem, 'jrc_jcnt    ', d_joins.jrc_cnt);
                d_joins.jrc_cnt := succ (d_joins.jrc_cnt);
                IF  d_join
                THEN
                    a683_output (ak_sem, dmli);
                (*ENDIF*) 
                d_joins.jrc_cnt := pred (d_joins.jrc_cnt);
&               endif
                jrc_cnt := succ(jrc_cnt);
                d_joins.jrc_joinarr[ jrc_cnt ].jo_col_upd_stat := 0;
                WITH d_joins, jrc_joinarr[ jrc_cnt ] DO
                    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
                (*ENDWITH*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
(*ENDWITH*) 
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       : tgg_stack_op_type;
            field_found    : tsp_int2;
            VAR e          : tgg_basis_error);
 
VAR
      nochange        : boolean;
      no_check        : boolean;
      startstack      : integer;
      i               : integer;
      sel_n           : integer;
      dummy_iolen     : tsp_int2;
      st_begin        : tsp_int2;
      st_begin1       : tsp_int2;
      both_const_expr : boolean;
      check_type      : tsp_data_type;
      helpbuf         : tak00_colinfo_ptr;
      keep_dtype      : ARRAY [ 1.. 3 ] OF tsp_data_type;
      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
WITH acv, a_mblock, mb_qual^, dmli DO
    BEGIN
    sel_n := sel_start_n;
    both_const_expr := false;
    node [ 1 ]      := first_node;
    no_check        := false;
    startstack      := mfirst_free;
    val_const[ 1 ]  := 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 d_colbuf^.ccolpropset
        THEN
            WITH mb_st^ [field_found] DO
                ecol_tab[ 2 ] := chr( ord (ecol_tab[ 2 ]) + 100);
            (*ENDWITH*) 
        (*ENDIF*) 
    (*ENDIF*) 
    helpbuf      := d_colptr;
    i            := 1;
    cchange[ i ] := d_datatype in [ ddate,dtime,dtimestamp ];
    IF  cchange[ i ]
    THEN
        check_type := d_datatype
    ELSE
        IF  NOT val_const[ i ]
        THEN
            no_check := true;
        (*ENDIF*) 
    (*ENDIF*) 
    startstck[ i ]  := startstack;
    keep_dtype[ i ] := d_datatype;
    ccolin[ i ]     := colin;
&   ifdef trace
    t01int4 (ak_sem, 'node       1', node[ i ]);
    t01int4 (ak_sem, 'd_datatype 1', ord (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  (((a_ap_tree^[ sel_n ].n_symb in
        [ s_plus, s_minus, s_mult, s_divide,
        s_div, s_mod ]) AND (a_ap_tree^[sel_n ].n_proc = a64))
        OR
        (a_ap_tree^[ sel_n ].n_proc = a641)) OR
        (check_type <> dunknown)
    THEN
        d_colptr := NIL;
    (*ENDIF*) 
    colin.sci_len      := 0;
    IF  (g01unicode AND
        (d_datatype in [ ddate, dtime, dtimestamp ]) AND
        (a_ap_tree^[ sel_n ].n_symb = s_string_literal))
    THEN
        d_datatype := dcha
    ELSE
        d_datatype := dunknown;
    (*ENDIF*) 
    d_change_date_time := false;
    st_begin           := mfirst_free;
    d_single_expr      := true;
    a65_val_expr (acv, dmli, colin, sel_n);
    IF  d_const_value_expr
    THEN
        IF  mfirst_free - st_begin > 1
        THEN
            IF  a_mblock.mb_st^[ st_begin ].ecol_tab[ 2 ] = chr(0)
            THEN
                d_const_value_expr := false;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    both_const_expr    := d_const_value_expr AND (a_is_ddl = no_ddl);
    IF  a_return_segm^.sp1r_returncode = cak_e_parameter
    THEN
        BEGIN
        val_const[ i ]        := true;
        d_datatype            := keep_dtype[ i-1 ];
        a_return_segm^.sp1r_returncode := 0;
        d_colptr              := helpbuf;
        a65_val_expr (acv, dmli, colin, sel_n);
        END
    ELSE
        val_const[ i ] := 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 1120681 E.Z. *)
    IF  acv.a_return_segm^.sp1r_returncode = cak_e_parameter
    THEN
        BEGIN
        acv.a_return_segm^.sp1r_returncode := 0;
        a07_b_put_error (acv, e_without_datatypes,
              acv.a_ap_tree^[ sel_n ].n_pos);
        END;
    (*ENDIF*) 
    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;
    nochange := false;
    d_single_expr := false;
    (* PTS 1000985/1001162 E.Z. *)
    dummy_iolen := 0;
    IF  a65_datatypes_ok (acv, dmli, keep_dtype[ i-1 ], dummy_iolen,
        d_datatype, NOT c_is_subquery, node[ i ],
        a_ap_tree^[ node[ i ]].n_pos, c_convert, convert_t)
    THEN
        BEGIN
        d_single_expr := true;
        cchange[ i ] := (d_datatype in [ ddate,dtime,dtimestamp ]);
        IF  cchange[ i ] AND (check_type = dunknown)
        THEN
            check_type := d_datatype
        ELSE
            IF  NOT cchange[ i ] AND NOT val_const[ i ]
            THEN
                no_check := true;
            (*ENDIF*) 
        (*ENDIF*) 
        startstck[ i ]  := mfirst_free;
        keep_dtype[ i ] := d_datatype;
        ccolin[ i ]     := colin;
&       ifdef trace
        t01int4 (ak_sem, 'node       2', node[ i ]);
        t01int4 (ak_sem, 'd_datatype 2', ord (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  (((a_ap_tree^[ sel_n ].n_symb in
            [ s_plus, s_minus, s_mult, s_divide,
            s_div, s_mod ]) AND (a_ap_tree^[sel_n ].n_proc = a64))
            OR
            (a_ap_tree^[ sel_n ].n_proc = a641)) OR
            (check_type <> dunknown)
        THEN
            d_colptr := NIL;
        (*ENDIF*) 
        colin.sci_len      := 0;
        IF  (g01unicode AND
            (keep_dtype[ 1 ] in [ ddate, dtime, dtimestamp ]) AND
            (a_ap_tree^[ sel_n ].n_symb = s_string_literal))
        THEN
            d_datatype := dcha
        ELSE
            d_datatype := dunknown;
        (*ENDIF*) 
        d_change_date_time := false;
        d_param_st_index   := 0;
        d_param_st_begin   := 0;
        st_begin1          := mfirst_free;
        a65_val_expr (acv, dmli, colin, sel_n);
        IF  d_const_value_expr
        THEN
            IF  mfirst_free - st_begin1 > 1
            THEN
                IF  a_mblock.mb_st^[ st_begin1 ].ecol_tab[ 2 ] = chr(0)
                THEN
                    d_const_value_expr := false;
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
        both_const_expr := both_const_expr AND d_const_value_expr;
        IF  a_return_segm^.sp1r_returncode = cak_e_parameter
        THEN
            BEGIN
            val_const[ i ]        := true;
            d_datatype            := keep_dtype[ i-2 ];
            a_return_segm^.sp1r_returncode := 0;
            d_colptr              := helpbuf;
            a65_val_expr (acv, dmli, colin, sel_n);
            END
        ELSE
            val_const[ i ] :=
                  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 1120681 E.Z. *)
        IF  acv.a_return_segm^.sp1r_returncode = cak_e_parameter
        THEN
            BEGIN
            acv.a_return_segm^.sp1r_returncode := 0;
            a07_b_put_error (acv, e_without_datatypes,
                  acv.a_ap_tree^[ sel_n ].n_pos);
            END;
        (*ENDIF*) 
        d_single_expr := false;
        (* PTS 1000985/1001162 E.Z. *)
        IF  a65_datatypes_ok (acv, dmli, keep_dtype[ i-2 ], dummy_iolen,
            d_datatype, NOT c_is_subquery, node[ i ],
            a_ap_tree^[ node[ i ]].n_pos, c_convert, convert_t)
        THEN
            IF  a65_datatypes_ok (acv, dmli, keep_dtype[ i-1 ], dummy_iolen,
                d_datatype, NOT c_is_subquery, node[ i ],
                a_ap_tree^[ node[ i ]].n_pos, NOT c_convert, convert_t)
            THEN
                BEGIN
                keep_dtype[ i ] := d_datatype;
                cchange[ i ] := (d_datatype in [ ddate,dtime,dtimestamp ]);
                IF  cchange[ i ] AND
                    (check_type = dunknown)
                THEN
                    check_type := 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 (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
        d_single_expr := true;
    (*ENDIF*) 
    IF  nochange AND (a_return_segm^.sp1r_returncode = 0)
    THEN
        BEGIN
        i := 0;
        e := e_ok;
        REPEAT
            BEGIN
            i := succ(i);
            IF  i = 3
            THEN
                startstck[ i ] := 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 (d_param_st_index <> 0) AND
        (mfirst_free - st_begin > 2)
    THEN
        a651const_between_expression( acv, dmli, st_begin, operator)
    ELSE
        a65_set_operator (acv, operator);
    (*ENDIF*) 
    END;
(*ENDWITH*) 
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
WITH acv, a_mblock, mb_qual^ DO
    BEGIN
    IF  g01userstackoverflow
    THEN
        a07_b_put_error (acv, e_program_stack_overflow, 1);
    (*ENDIF*) 
    IF  a_return_segm^.sp1r_returncode = 0
    THEN
        BEGIN
        act_node := first_node;
        snot_bool := ak65subq_se (acv, first_node);
        WITH 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 := 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;
                                ak65predicate (acv, dmli, act_node,
                                      NOT c_mtabs_allowed, list_info);
                                a65_set_operator (acv, op_and);
                                a61_set_jump (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
                                    jo_no_join          := false;
                                    jo_partno           := 1;
                                    jo_recs[ 1 ].jop_tableno := 0;
                                    jo_recs[ 2 ].jop_tableno := 0;
                                    END
                                (*ENDWITH*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDWITH*) 
                    ELSE
                        BEGIN
                        ak65predicate (acv, dmli, act_node, 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;
                            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*) 
                            ak65predicate (acv, dmli, act_node,
                                  mtabs_allowed, list_info);
                            a65_set_operator (acv, op_and);
                            a61_set_jump (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;
(*ENDWITH*) 
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   : tsp_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     : tsp_int2;
      convert_t       : tak_convert_type;
      operator        : tgg_stack_op_type;
      check_type      : tsp_data_type;
      ix              : integer;
      keep_dtype      : ARRAY[ 1..2 ] OF tsp_data_type;
      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               : tgg_basis_error;
      val_const       : boolean;
      level_node      : tsp_int2;
      list_node       : tsp_int2;
      list_cnt        : integer;
      dm_datatype     : tsp_data_type;
      st_begin        : tsp_int2;
      expr_st_cnt     : tsp_int2;
 
BEGIN
WITH acv, a_mblock, a_ap_tree^[ first_node ], dmli 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 := a_special_expr;
    IF  d_join AND ((a_outer_join OR d_outer_join) OR d_view)
    THEN
        WITH d_joins, jrc_joinarr[ jrc_cnt ] DO
            BEGIN
            CASE 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 *)
                    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 (a_outer_join));
            t01int4 (ak_sem, 'dm_outer_joi', ord (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 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 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 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*) 
            a_outer_join  := a_outer_join OR
                  jo_recs[ 1 ].jop_outer_join OR
                  jo_recs[ 2 ].jop_outer_join;
            IF  NOT d_outer_join
            THEN
                d_outer_join := a_outer_join;
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
    (*ENDIF*) 
    val_const     := false;
    check_type    := dunknown;
    ix            := 1;
    sel_n         := a_ap_tree^[ first_node ].n_lo_level;
    node[ ix ]    := sel_n;
    cchange[ ix ] := (d_datatype in [ ddate,dtime,dtimestamp ]);
    IF  cchange[ ix ]
    THEN
        check_type := d_datatype;
    (*ENDIF*) 
    startstck[ ix ]  := mb_qual^.mfirst_free;
    keep_dtype[ ix ] := d_datatype;
    helpbuf          := d_colptr;
    ccolin[ ix ]     := colin;
    IF  (d_datatype <> dboolean) AND (n_symb in [s_is_false, s_is_true])
    THEN
        a07_b_put_error (acv, e_incompatible_datatypes,
              a_ap_tree^[ sel_n ].n_pos);
    (*ENDIF*) 
    IF  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  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;
&   ifdef trace
    t01int4 (ak_sem, 'node       4', node[ ix ]);
    t01int4 (ak_sem, 'd_datatype 4', ord (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           := mb_qual^.mfirst_free;
    d_const_value_expr := ( a_is_ddl = no_ddl);
    IF  (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_symb = s_all)
        OR
        (a_ap_tree^[ sel_n ].n_symb = s_any)
        OR
        ((a_ap_tree^[ sel_n ].n_proc = a56) AND
        ( a_ap_tree^[ sel_n ].n_subproc = cak_x_value_list))
    THEN
        BEGIN
        IF  d_join
        THEN
            WITH d_joins, jrc_joinarr[ jrc_cnt ] DO
                IF  jo_no_join
                THEN
                    d_arith_where := true;
                (*ENDIF*) 
            (*ENDWITH*) 
        (*ENDIF*) 
        IF  a_ap_tree^[ sel_n ].n_symb = s_all
        THEN
            BEGIN
            all   := true;
            any   := false;
            sel_n := a_ap_tree^[ sel_n ].n_sa_level;
            END
        ELSE
            IF  a_ap_tree^[ sel_n ].n_symb = s_any
            THEN
                BEGIN
                all := false;
                any := true;
                sel_n := 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  ((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 )))
        THEN (* the right side of the compare operation is a subquery. *)
            BEGIN
&           ifdef TRACE
            t01int4 (ak_sem, 'd_use_sub 65', ord(d_use_sub));
            t01int4 (ak_sem, 'd_datatype  ', ord(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 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, 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  a_ap_tree^[ list_node ].n_sa_level > 0
                    THEN
                        BEGIN
                        level_node  := 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,
                              a_ap_tree^[ level_node ].n_datatype,
                              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*) 
                        a_ap_tree^[ list_node  ].n_sa_level := level_node;
                        END;
                    (*ENDIF*) 
&                   ifdef trace
                    WITH 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 := a_ap_tree^[ sel_n ].n_sa_level;
                list_cnt  := 0;
                WHILE (list_node <> 0) AND (a_return_segm^.sp1r_returncode = 0) DO
                    WITH 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 := a_ap_tree^[ list_node ].n_sa_level
                        END
                    (*ENDWITH*) 
                (*ENDWHILE*) 
                END;
            (*ENDIF*) 
            IF  (a_return_segm^.sp1r_returncode = 0) AND types_ok
            THEN
                BEGIN
                IF  ((field_found > 0) AND
                    (operator =  op_eq))
                THEN
                    IF  ctmulti in d_colbuf^.ccolpropset
                    THEN
                        WITH mb_qual^, 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 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  := 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. *)
                    d_datatype := list_info.elem[ list_cnt ].datatype;
                    d_colptr   := NIL (* Here we don't know anything. *)
                    END
                ELSE
                    d_colptr := helpbuf;
                (*ENDIF*) 
                a65_val_expr (acv, dmli, colin,
                      a_ap_tree^[ expr_n ].n_lo_level);
                cnt_expr := succ (cnt_expr);
                expr_n   := 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 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*) 
        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 d_colbuf^.ccolpropset
            THEN
                WITH mb_st^[ field_found ] DO
                    ecol_tab[ 2 ] := chr (ord (ecol_tab[ 2 ]) + 100);
                (*ENDWITH*) 
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (((a_ap_tree^[ sel_n ].n_symb in
            [ s_plus, s_minus, s_mult, s_divide,
            s_div, s_mod ]) AND (a_ap_tree^[sel_n ].n_proc = a64))
            OR
            (a_ap_tree^[ sel_n ].n_proc = a641))
            OR
            ((check_type <> dunknown) AND
            ((a_ap_tree^[ sel_n ].n_proc <> no_proc) OR
            ( a_ap_tree^[ sel_n ].n_symb <> s_default)))
        THEN
            d_colptr := NIL;
        (*ENDIF*) 
        colin.sci_len := 0;
        IF  d_datatype <> dunicode
        THEN
            (* otherwise unicode = timestamp will not do format_change *)
            d_change_date_time := false;
        (*ENDIF*) 
        IF  (g01unicode AND
            (d_datatype in [ ddate, dtime, dtimestamp ]) AND
            (a_ap_tree^[ sel_n ].n_symb = s_string_literal))
        THEN
            d_datatype := dcha
        ELSE
            d_datatype := dunknown;
        (*ENDIF*) 
        IF  d_join (* PTS 1113327 *)
        THEN
            WITH d_joins, jrc_joinarr[ jrc_cnt ], jo_recs[ 2 ], mb_qual^ DO
                BEGIN
                jo_op         := operator;
                jop_startstack := mfirst_free;
                IF  (((a_ap_tree^[ sel_n ].n_symb in
                    [ s_plus, s_minus, s_mult, s_divide,
                    s_div, s_mod ]) AND (a_ap_tree^[sel_n ].n_proc = a64))
                    OR
                    (a_ap_tree^[ sel_n ].n_proc = a641))
                THEN
                    d_colptr := NIL;
                (*ENDIF*) 
                jo_partno := 2;
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        a65_val_expr (acv, dmli, colin, sel_n);
        IF  a_return_segm^.sp1r_returncode = cak_e_parameter
        THEN
            BEGIN
            val_const := true;
            d_datatype := keep_dtype[ ix-1 ];
            a_return_segm^.sp1r_returncode := 0;
            d_colptr := helpbuf;
            a65_val_expr (acv, dmli, colin, sel_n);
            END
        ELSE
            IF  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 1120681 E.Z. *)
            (*ENDIF*) 
        (*ENDIF*) 
        IF  acv.a_return_segm^.sp1r_returncode = cak_e_parameter
        THEN
            BEGIN
            acv.a_return_segm^.sp1r_returncode := 0;
            a07_b_put_error (acv, e_without_datatypes,
                  acv.a_ap_tree^[ sel_n ].n_pos);
            END;
        (*ENDIF*) 
        cchange[ ix ] := (d_datatype in [ ddate,dtime,dtimestamp ]);
        IF  cchange[ ix ]
        THEN
            IF  check_type = dunknown
            THEN
                check_type := d_datatype
            ELSE
                IF  check_type <> 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 ] := d_datatype;
        ccolin[ ix ] := colin;
        startstck[ ix ] := mb_qual^.mfirst_free;
&       ifdef trace
        t01int4 (ak_sem, 'node       5', node[ ix ]);
        t01int4 (ak_sem, 'd_datatype 5', ord (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  a_return_segm^.sp1r_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 ], a_ap_tree^[ node[ 2 ]].n_pos,
                NOT nochange, convert_t)
            THEN
                nochange := false;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (d_datatype = dudt) AND (a_return_segm^.sp1r_returncode = 0)
        THEN
            a07_b_put_error (acv, e_incompatible_datatypes,
                  acv.a_ap_tree^[ node[ ix ] ].n_pos);
        (*ENDIF*) 
        IF  nochange AND (a_return_segm^.sp1r_returncode = 0)
        THEN
            BEGIN
            ix := 0;
            e  := e_ok;
            REPEAT
                BEGIN
                ix    := succ(ix);
                IF  ix = 2
                THEN
                    startstck[ ix ] := 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 d_join) AND
                NOT(operator in [ op_null, op_not_null ])
            THEN
                WITH 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 (tsp_int4)
                        THEN
                            BEGIN
                            jop_datalen  := 0;
                            jop_inoutlen := 0;
                            END
                        ELSE
                            BEGIN
                            jop_datalen  := sci_len;
                            jop_inoutlen := sci_iolen;
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDWITH*) 
                    END;
                (*ENDWITH*) 
            (*ENDIF*) 
            END;
        (* PTS 1113318 E.Z. *)
        (*ENDIF*) 
        IF  d_join AND d_outer_join AND (operator in [ op_null, op_not_null ])
            (* PTS 1113327 *)
            AND NOT d_joins.jrc_joinarr[ d_joins.jrc_cnt ].jo_recs[ 1 ].jop_outer_join
        THEN
            d_arith_where := true;
        (*ENDIF*) 
        IF  d_join AND NOT(operator in [ op_null, op_not_null ])
        THEN
            WITH d_joins, jrc_joinarr[ jrc_cnt ], jo_recs[ 2 ], mb_qual^ DO
                BEGIN
                IF  jo_no_join
                THEN
                    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 (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
                                    (a_mblock.mb_st^ [jop_startstack].eop in
                                    [ op_ascii, op_ebcdic ]))
                                THEN
                                    jop_propset := [  ];
                                (*ENDIF*) 
                                WITH ccolin[ 2 ] DO
                                    BEGIN
                                    CASE convert_t OF
                                        conv_ascii_to_ebcdic,
                                        conv_unicode_to_ebcdic:
                                            sci_typ := dche;
                                        conv_ebcdic_to_ascii,
                                        conv_unicode_to_ascii:
                                            sci_typ := dcha;
                                        conv_ascii_to_unicode,
                                        conv_ebcdic_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 (tsp_int4)
                                    THEN
                                        BEGIN
                                        jop_datalen  := 0;
                                        jop_inoutlen := 0;
                                        a07_b_put_error (acv, e_join_fields_too_long, 1);
                                        END
                                    ELSE
                                        BEGIN
                                        jop_datalen  := sci_len;
                                        jop_inoutlen := sci_iolen;
                                        END;
                                    (*ENDIF*) 
                                    END;
                                (*ENDWITH*) 
                                IF  jop_datatyp in [ dfixed,
                                    dfloat, dvfloat ]
                                THEN
                                    BEGIN
                                    jop_datatyp  := dfloat;
                                    jop_datalen  := csp_fixed;
                                    jop_inoutlen := mxgg_number;
                                    END
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                            END
                        ELSE
                            a07_b_put_error (acv, e_join_fields_too_long, 1);
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        IF  (a_return_segm^.sp1r_returncode = 0)
        THEN
            BEGIN
            expr_st_cnt := 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',d_param_st_index);
            t01int4 (ak_sem,'d_const_valu',ord(d_const_value_expr));
            t01int4 (ak_sem,'true        ',ord(true));
            t01int4 (ak_sem,'mb_data_len ',a_mblock.mb_data_len );
            t01int4 (ak_sem,'epos        ',
                  a_mblock.mb_st^ [st_begin].epos);
&           endif
            IF  d_const_value_expr AND
                (mb_st^ [st_begin].etype = st_value) AND
                (mb_st^[ st_begin ].ecol_tab [2] <> chr(0))
            THEN
                mb_st^ [st_begin].eop := operator
            ELSE
                a65_set_operator (acv, operator);
            (*ENDIF*) 
            IF  ((NOT a_rowno_allowed) AND (a_return_segm^.sp1r_returncode = 0))
            THEN
                BEGIN
                WITH mb_st^[ 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
                            d_rowno := epos
                        ELSE
                            d_rowno := -epos;
                        (*ENDIF*) 
                        END;
                    (* Destroy Rowno- and Value-Stackentries *)
                    (*ENDIF*) 
                    mb_st^[ mb_qual^.mfirst_free-1 ].etype := st_bool;
                    mb_st^[ mb_qual^.mfirst_free-1 ].eop   := op_none;
                    mb_st^[ mb_qual^.mfirst_free-1 ].epos  := 1;
                    mb_st^[ mb_qual^.mfirst_free-2 ].etype := st_dummy;
                    mb_st^[ mb_qual^.mfirst_free-2 ].eop   := op_none;
                    (* PTS 1104018 E.Z. *)
                    mb_data_len := mb_data_len - colin.sci_iolen +
                          RESNUM_MXSP00;
                    END;
                (*ENDWITH*) 
                a_rowno_allowed := true
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  (operator = op_ne)
        THEN
            ak65ne_handle (acv, dmli, colin, sel_n);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    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      : tsp_int4);
 
BEGIN (* h.b. PTS 1106859 *)
WITH acv, a_mblock, mb_qual^ DO
    BEGIN
    IF  (mfirst_free + 4 <= mb_st_max)
        AND
        (mb_st^[mfirst_free - 1].etype = st_value)
        AND
        (mb_st^[mfirst_free - 1].eop   = op_ne)
        AND
        (mb_st^[mfirst_free - 2].etype IN
        [ st_fixkey, st_varkey, st_fixcol, st_varcol ])
        AND
        (mb_st^[mfirst_free - 2].eop IN
        [ op_order_asc, op_order_desc, op_none ])
        AND
        ((mb_st^[mfirst_free - 2].ecol_tab[ 1 ] > chr(0))   OR
        (mb_st^[mfirst_free - 2].ecol_tab[ 2 ] > chr(100)) OR
        (mb_st^[mfirst_free - 2].etype in [st_fixkey, st_varkey]))
    THEN
        BEGIN
        mb_st^[mfirst_free - 1].eop := op_lt;
        mfirst_free                 := succ(mfirst_free);
        mb_st^[mfirst_free]         := mb_st^[mfirst_free - 3];
        mfirst_free                 := succ(mfirst_free);
        colin.sci_len               := 0;
        a640not_first_factor (acv, dmli, colin, sel_node);
        mb_st^[mfirst_free - 1].eop := op_gt;
        mqual_cnt                   := mqual_cnt + 2;
        a65_set_operator (acv, op_or);
        a61_set_jump (acv.a_mblock, mfirst_free - 4, st_jump_true);
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a65ch_format (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR startstack : integer;
            VAR colin      : tak00_scolinf;
            left_type      : tsp_data_type;
            d_type         : tsp_data_type);
 
VAR
      entry_cnt : integer;
 
BEGIN
IF  acv.a_return_segm^.sp1r_returncode = 0
THEN
    WITH acv, a_mblock, mb_qual^, dmli DO
        BEGIN
        IF  (a_dt_format = dtf_oracle_date) AND (d_type = dtimestamp)
        THEN
            entry_cnt := 3
        ELSE
            entry_cnt := 1;
        (*ENDIF*) 
        IF  mfirst_free+entry_cnt-1 > mb_st_max
        THEN
            a07_b_put_error (acv, e_too_many_mb_stackentries, -mb_st_max)
        ELSE
            BEGIN
            a_date_time_used := true;
            IF  (a_dt_format <> dtf_normal)
            THEN
                BEGIN
                IF  (startstack < mfirst_free)
                THEN
                    g10mvr ('VAK65 ',   1,    
                          mb_st_size, mb_st_size,
                          mb_st^, (startstack-1)*mxgg_stack_entry+1,
                          mb_st^, (startstack+entry_cnt-1)*mxgg_stack_entry+1,
                          (mfirst_free - startstack) * mxgg_stack_entry,
                          a_return_segm^.sp1r_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);
            IF  (g01code.ctype <> csp_ascii) AND (left_type <> dcha)
            THEN
                BEGIN
                IF  (startstack < mfirst_free)
                THEN
                    g10mvr ('VAK65 ',   2,    
                          mb_st_size, mb_st_size,
                          mb_st^, (startstack-1)*mxgg_stack_entry+1,
                          mb_st^, startstack*mxgg_stack_entry+1,
                          (mfirst_free - startstack) * mxgg_stack_entry,
                          a_return_segm^.sp1r_returncode);
                (*ENDIF*) 
                WITH mb_st^ [startstack-1] DO
                    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^ [startstack] DO
                            BEGIN
                            etype := st_op;
                            eop := op_ebcdic;
                            epos := 1;
                            elen_var := 0;
                            ecol_tab[ 1 ] := chr(0);
                            ecol_tab[ 2 ] := chr(0)
                            END;
                        (*ENDWITH*) 
                        mfirst_free := succ(mfirst_free);
                        startstack := succ(startstack);
                        END;
                    (*ENDIF*) 
                (*ENDWITH*) 
                colin.sci_typ := dche;
                d_datatype := dche;
                END
            ELSE
                BEGIN
                colin.sci_typ := dcha;
                d_datatype := dcha;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65check_change (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            c_type         : tsp_data_type;
            change         : boolean;
            VAR act_node   : integer;
            VAR startstack : integer;
            VAR colin      : tak00_scolinf;
            d_type         : tsp_data_type;
            left_type      : tsp_data_type;
            VAR e          : tgg_basis_error);
 
VAR
      alen          : integer;
      curr_data_pos : tsp_int4;
      re_buf        : tsp_c28;
 
BEGIN
WITH acv, a_mblock, dmli DO
    BEGIN
    IF  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 := a_ap_tree^[ act_node ].n_length;
&       ifdef TRACE
        t01messblock (ak_sem, 'ak65check_c1', 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 (a_ap_tree^[ act_node ].n_datatype));
&       endif
        IF  (a_is_ddl = ddl_create_view) AND
            (c_type in [ ddate, dtime, dtimestamp ])
        THEN
            BEGIN
            a16inc_vdesc_cnt (acv, dmli, a_ptr10);
            IF  a_return_segm^.sp1r_returncode = 0
            THEN
                WITH a_ptr10^.sviewdesc, vdescription[ vdesc_cnt ] DO
                    BEGIN
                    vfromtabno    := alen;
                    vfromextcolno := 0;
                    vn_pos        := 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  a_ap_tree^[ act_node ].n_datatype = dtimestamp
                THEN
                    a05dfts_date_from_timestamp (mb_data^.mbp_buf, re_buf,
                          mb_st^ [startstack-1].epos+ 1, sizeof(re_buf),
                          1, alen, a_dt_format, a_ak_language,
                          c_ch_code, e)
                ELSE
                    g03fdcheck_date (mb_data^.mbp_buf, re_buf,
                          mb_st^ [startstack-1].epos+ 1,
                          1, alen, a_dt_format, c_ch_code, e);
                (*ENDIF*) 
                alen := mxsp_date + 1;
                END;
            dtime :
                BEGIN
                IF  a_ap_tree^[ act_node ].n_datatype = dtimestamp
                THEN
                    a05tfts_time_from_timestamp (mb_data^.mbp_buf, re_buf,
                          mb_st^ [startstack-1].epos+ 1, sizeof(re_buf),
                          1, alen, a_dt_format, a_ak_language,
                          c_ch_code, e)
                ELSE
                    g03ftcheck_time (mb_data^.mbp_buf, re_buf,
                          mb_st^ [startstack-1].epos+ 1,
                          1, alen, a_dt_format, c_ch_code, e);
                (*ENDIF*) 
                alen := mxsp_time + 1;
                END;
            dtimestamp :
                BEGIN
                IF  a_ap_tree^[ act_node ].n_datatype in [ddate, dtime]
                THEN
                    a05tsfdt_timestamp_from_dattim (mb_data^.mbp_buf, re_buf,
                          mb_st^ [startstack-1].epos+ 1,
                          1,sizeof(re_buf), alen, a_dt_format,
                          a_ap_tree^[ act_node ].n_datatype,
                          c_ch_code, e)
                ELSE
                    a05timestamp_get (acv, mb_data^.mbp_buf,
                          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, a_ap_tree^[ act_node ].n_pos)
        ELSE
            WITH mb_data^ DO
                IF  mb_data_len + alen <= mb_data_size
                THEN
                    BEGIN
                    mb_st^ [startstack-1].epos := mb_data_len + 1;
                    mb_st^ [startstack-1].elen_var := alen;
                    mb_data_len := succ(mb_data_len);
                    curr_data_pos := mb_data_len;
                    mbp_buf [curr_data_pos] := csp_ascii_blank;
                    g10mv2 ('VAK65 ',   3,    
                          sizeof(re_buf), mb_data_size, re_buf, 1,
                          mbp_buf, curr_data_pos+1, alen-1,
                          a_return_segm^.sp1r_returncode);
                    mb_data_len := 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', a_mblock);
&       endif
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
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    : tsp_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                : tsp_c2;
      keep_part_pos     : integer;
      sel_n             : integer;
      escape_n          : integer;
      i                 : integer;
      strat_size        : integer;
      dummy_iolen       : tsp_int2;
      helpbuf           : tak00_colinfo_ptr;
      check_type        : tsp_data_type;
      startstack        : integer;
      keep_dtype        : ARRAY[ 1..3 ] OF tsp_data_type;
      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          : tgg_stack_op_type;
      nochange          : boolean;
      e                 : tgg_basis_error;
      val_const         : ARRAY[ 1..3 ] OF boolean;
      no_check          : boolean;
      dont_care         : boolean;
 
BEGIN
WITH acv, a_mblock, dmli DO
    IF  a_return_segm^.sp1r_returncode = 0
    THEN
        BEGIN
        strat_size := sizeof( tgg07_StrategyInfo );
        IF  snot_pred
        THEN
            BEGIN
            CASE 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 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*) 
        d_const_value_expr := ( a_is_ddl = no_ddl);
        d_param_st_index   := 0;
        d_param_st_begin   := 0;
        no_check           := false;
        sel_n              := a_ap_tree^[ first_node ].n_lo_level;
        IF  ((a_ap_tree^[ sel_n ].n_proc = a64) AND
            (a_ap_tree^[ sel_n ].n_subproc  = cak_x_escape))
        THEN
            BEGIN
            d_escape := true;
            escape_n := a_ap_tree^[ sel_n ].n_sa_level;
            sel_n    := a_ap_tree^[ sel_n ].n_lo_level
            END;
        (*ENDIF*) 
        node[ 1 ]      := sel_n;
        val_const[ 1 ] := 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  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  (d_join AND NOT d_escape AND
            (operator in [ op_sounds, op_not_sounds,
            op_like, op_not_like ]) AND
            (a_ap_tree^[ sel_n ].n_symb in
            [ s_authid, s_tablename, s_columnname ]) AND
            NOT (a_outer_join OR d_outer_join))
        THEN
            WITH d_joins, jrc_joinarr[ jrc_cnt ] DO
                BEGIN
                jo_op := operator;
                WITH d_joins, jrc_joinarr[ jrc_cnt ], mb_qual^ DO
                    jo_recs[ 2 ].jop_startstack := mfirst_free;
                (*ENDWITH*) 
                jo_partno := 2;
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        startstack := mb_qual^.mfirst_free;
        WITH a_ap_tree^[ first_node ] DO
            CASE n_symb OF
                s_between, s_notbetween : (*between*)
                    ak65between_predicate (acv, dmli, colin, sel_n,
                          first_node, operator, field_found, e);
                s_in, s_notin : (*in*)
                    ak65in_predicate (acv, dmli, sel_n, operator,
                          field_found, list_info);
                s_like, s_notlike :
                    IF  ((d_datatype = dnumber) OR
                        (d_datatype = ddbyteebcdic))
                    THEN
                        a07_b_put_error (acv, e_incompatible_datatypes,
                              a_ap_tree^[ sel_n ].n_pos)
                    ELSE
                        BEGIN (*like*)
                        i            := 0;
                        check_type   := dunknown;
                        i            := succ(i);
                        cchange[ i ] := (d_datatype in [ ddate,dtime,dtimestamp ]);
                        IF  cchange[ i ]
                        THEN
                            check_type  := d_datatype;
                        (*ENDIF*) 
                        startstck[ i ]  := startstack;
                        keep_dtype[ i ] := d_datatype;
                        ccolin[ i ]     := colin;
&                       ifdef trace
                        t01int4 (ak_sem, 'node       6', node[ i ]);
                        t01int4 (ak_sem, 'd_datatype 6', ord (d_datatype));
                        t01int4 (ak_sem, 'startstack 6', startstck[ i ]);
                        t01int4 (ak_sem, 'colin.typ  6', ord(ccolin[ i ].sci_typ));
&                       endif
                        d_like          := true;
                        d_like_optimize := false;
                        keep_part_pos := a_input_data_pos;
                        (* keep_part_pos is pointer to     *)
                        (* data-part where parameter       *)
                        (* from user is expected at exe-   *)
                        (* cution time                     *)
                        IF  (((a_ap_tree^[ sel_n ].n_symb in
                            [ s_plus, s_minus, s_mult, s_divide,
                            s_div, s_mod ]) AND (a_ap_tree^[sel_n ].n_proc = a64))
                            OR
                            (a_ap_tree^[ sel_n ].n_symb in
                            [ s_authid, s_tablename, s_columnname ]) OR
                            (a_ap_tree^[ sel_n ].n_proc = a641))
                        THEN
                            d_like_expression := true;
                        (*ENDIF*) 
                        escape_char_found := false;
                        IF  d_escape
                        THEN
                            WITH a_ap_tree^[ escape_n ] DO
                                IF  ((n_symb   = s_string_literal) OR
                                    ( n_symb   = s_byte_string)   )
                                    AND NOT d_like_expression
                                THEN
                                    BEGIN
                                    wrong_datatype := false;
                                    IF  (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, 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*) 
                                    IF  a_return_segm^.sp1r_returncode = 0
                                    THEN
                                        IF  (d_datatype <> dunicode) AND
                                            (c2[2] <> csp_undef_byte)
                                        THEN
                                            a641translate_string_literal (c2[2], d_datatype);
                                        (*ENDIF*) 
                                    (*ENDIF*) 
                                    d_escape_char     := c2;
                                    escape_char_found := true;
                                    END
                                ELSE
                                    BEGIN
                                    d_like := false;
                                    IF  a_ap_tree^[ escape_n ].n_symb <>
                                        s_parameter_name
                                    THEN
                                        d_like_expression := true
                                    ELSE
                                        IF  a_ap_tree^[ sel_n ].n_symb <>
                                            s_parameter_name
                                        THEN
                                            d_like_expression := true;
                                        (*ENDIF*) 
                                    (*ENDIF*) 
                                    IF  a_ap_tree^[ escape_n ].n_symb =
                                        s_parameter_name
                                    THEN
                                        BEGIN
                                        d_expand := 1;
                                        IF  a_ap_tree^[ sel_n ].n_symb =
                                            s_parameter_name
                                        THEN
                                            d_like_expression := false;
                                        (*ENDIF*) 
                                        END;
                                    (*ENDIF*) 
                                    helpbuf            := d_colptr;
                                    d_colptr           := NIL;
                                    d_const_value_expr := d_like_expression;
&                                   ifdef trace
                                    t01int4 (ak_sem, 'a640factor  ', 1);
&                                   endif
                                    a640factor (acv, dmli, colin,
                                          escape_n);
                                    IF  NOT d_like_expression
                                    THEN
                                        WITH mb_qual^ DO
                                            BEGIN
                                            mqual_cnt   := mqual_cnt-1;
                                            mfirst_free := mfirst_free-1
                                            END;
                                        (*ENDWITH*) 
                                    (*ENDIF*) 
                                    d_colptr := helpbuf;
                                    IF  a_ap_tree^[ escape_n ].n_symb =
                                        s_parameter_name
                                    THEN
                                        d_expand := 0
                                    ELSE
                                        IF  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*) 
                                    d_like        := true;
                                    colin.sci_len := 0
                                    END;
                                (*ENDIF*) 
                            (*ENDWITH*) 
                        (*ENDIF*) 
                        IF  d_like_expression
                        THEN
                            BEGIN
                            (* ======================== *)
                            (* like cannot be used for  *)
                            (* optimization or strategy *)
                            (* ======================== *)
                            IF  (((a_ap_tree^[ sel_n ].n_symb in
                                [ s_plus, s_minus, s_mult, s_divide,
                                s_div, s_mod ]) AND (a_ap_tree^[sel_n ].n_proc = a64))
                                OR
                                (a_ap_tree^[ sel_n ].n_proc = a641)) OR
                                (check_type <> dunknown)
                            THEN
                                d_colptr := NIL;
                            (*ENDIF*) 
                            IF  (a_ap_tree^[ sel_n ].n_symb <>
                                s_parameter_name)
                            THEN
                                BEGIN
                                colin.sci_len      := 0;
                                d_change_date_time := false;
                                IF  (g01unicode AND
                                    (d_datatype in [ ddate, dtime, dtimestamp ]) AND
                                    (a_ap_tree^[ sel_n ].n_symb = s_string_literal))
                                THEN
                                    d_datatype := dcha
                                ELSE
                                    d_datatype := dunknown;
                                (*ENDIF*) 
                                END;
&                           ifdef trace
                            (*ENDIF*) 
                            t01int4 (ak_sem, 'a640factor  ', 2);
&                           endif
                            a640factor (acv, dmli, colin, sel_n);
                            IF  a_return_segm^.sp1r_returncode = cak_e_parameter
                            THEN
                                BEGIN
                                a_return_segm^.sp1r_returncode := 0;
                                d_datatype := keep_dtype[ 1 ];
                                a640factor (acv, dmli, colin, sel_n);
                                END;
                            (* PTS 1120681 E.Z. *)
                            (*ENDIF*) 
                            IF  acv.a_return_segm^.sp1r_returncode = cak_e_parameter
                            THEN
                                BEGIN
                                acv.a_return_segm^.sp1r_returncode := 0;
                                a07_b_put_error (acv, e_without_datatypes,
                                      acv.a_ap_tree^[ sel_n ].n_pos);
                                END;
                            (*ENDIF*) 
                            IF  (d_escape AND
                                ((a_ap_tree^[ sel_n ].n_symb = s_authid)
                                OR
                                (a_ap_tree^[ sel_n ].n_symb = s_tablename)
                                OR
                                (a_ap_tree^[ sel_n ].n_symb =
                                s_columnname)
                                OR
                                (a_ap_tree^[ sel_n ].n_symb =
                                s_string_literal)
                                OR
                                (a_ap_tree^[ sel_n ].n_symb =
                                s_byte_string)
                                OR
                                (a_ap_tree^[ sel_n ].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 mb_st^[ field_found ] DO
                                    IF  ctmulti in d_colbuf^.ccolpropset
                                    THEN
                                        BEGIN
                                        ecol_tab[ 2 ]   :=
                                              chr( ord (ecol_tab[ 2 ]) + 100);
                                        (* h.b. PTS 1105535 *)
                                        IF  ((a_no_of_likes *
                                            c_like_mult *
                                            d_colbuf^.cinoutlen)
                                            + strat_size
                                            + c_reserve_mbsize
                                            < g01mb_data_size)
                                        THEN
                                            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
                                            ((a_no_of_likes *
                                            c_like_mult *
                                            d_colbuf^.cinoutlen)
                                            + strat_size
                                            + c_reserve_mbsize
                                            < g01mb_data_size)
                                        THEN
                                            d_like_optimize := true;
                                        (*ENDIF*) 
                                        END;
                                    (*ENDIF*) 
                                (*ENDWITH*) 
                            (*ENDIF*) 
                            IF  ((a_ap_tree^[ sel_n ].n_symb =
                                s_parameter_name) AND escape_char_found)
                            THEN
                                ak65fix_escape (acv, dmli);
&                           ifdef trace
                            (*ENDIF*) 
                            t01int4 (ak_sem, 'a640factor  ', 3);
&                           endif
                            IF  (((a_ap_tree^[ sel_n ].n_symb in
                                [ s_plus, s_minus, s_mult, s_divide,
                                s_div, s_mod ]) AND (a_ap_tree^[sel_n ].n_proc = a64))
                                OR
                                (a_ap_tree^[ sel_n ].n_proc = a641))
                                OR
                                (check_type <> dunknown)
                            THEN
                                d_colptr := NIL;
                            (*ENDIF*) 
                            IF  (a_ap_tree^[ sel_n ].n_symb <>
                                s_parameter_name)
                            THEN
                                BEGIN
                                colin.sci_len      := 0;
                                d_change_date_time := false;
                                IF  (g01unicode AND
                                    (d_datatype in [ ddate, dtime, dtimestamp ]) AND
                                    (a_ap_tree^[ sel_n ].n_symb = s_string_literal))
                                THEN
                                    d_datatype := dcha
                                ELSE
                                    d_datatype := dunknown;
                                (*ENDIF*) 
                                END
                            ELSE
                                IF  cchange[ i ]
                                THEN
                                    IF  (g01code.ctype <> csp_ascii)
                                    THEN
                                        d_datatype := dche
                                    ELSE
                                        d_datatype := dcha;
                                    (*ENDIF*) 
                                (*ENDIF*) 
                            (*ENDIF*) 
                            d_like_part := 1;
                            a640factor (acv, dmli, colin, sel_n);
                            IF  ( a_return_segm^.sp1r_returncode = 0 ) AND d_like_optimize
                            THEN
                                ak65try_like_optimization (acv, dmli,
                                      sel_n, 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 ]    := sel_n;
                        cchange[ i ] := (d_datatype in [ ddate,dtime,dtimestamp ]);
                        IF  cchange[ i ]
                        THEN
                            IF  check_type = dunknown
                            THEN
                                check_type := d_datatype
                            ELSE
                                IF  check_type <> 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 ] := d_datatype;
                        ccolin[ i ]     := colin;
                        startstck[ i ]  := mb_qual^.mfirst_free;
&                       ifdef trace
                        t01int4 (ak_sem, 'node       7', node[ i ]);
                        t01int4 (ak_sem, 'd_datatype 7', ord (d_datatype));
                        t01int4 (ak_sem, 'startstack 7', startstck[ i ]);
                        t01int4 (ak_sem, 'colin.typ  7', ord(ccolin[ i ].sci_typ));
&                       endif
                        nochange := false;
                        IF  a_return_segm^.sp1r_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 ],
                                a_ap_tree^[ node[ 2 ]].n_pos,
                                c_convert, convert_t)
                            THEN
                                nochange := cchange[ 1 ] OR cchange[ 2 ];
                            (*ENDIF*) 
                        (*ENDIF*) 
                        IF  nochange AND (a_return_segm^.sp1r_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 ] := 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  d_like
                        THEN
                            BEGIN
                            (* ================================ *)
                            (* no previous optimization         *)
                            (* -> attach standard like-operator *)
                            (* ================================ *)
                            d_like    := false;
                            ak65set_like_operator (acv, operator,
                                  d_like_expression,
                                  ord(colin.sci_typ), d_escape);
                            d_like_expression := false;
                            END;
                        (*ENDIF*) 
                        d_escape := false;
                        END;
                    (*ENDIF*) 
                s_sounds, s_notsounds :
                    IF  ((d_datatype = dnumber)     OR
                        (d_datatype = ddate)        OR
                        (d_datatype = dtime)        OR
                        (d_datatype = ddbyteebcdic) OR
                        (d_datatype = dunicode))
                    THEN
                        a07_b_put_error (acv, e_incompatible_datatypes,
                              a_ap_tree^[ sel_n ].n_pos)
                    ELSE
                        BEGIN (*sounds*)
                        IF  (((a_ap_tree^[ sel_n ].n_symb in
                            [ s_plus, s_minus, s_mult, s_divide,
                            s_div, s_mod ]) AND (a_ap_tree^[sel_n ].n_proc = a64))
                            OR
                            (a_ap_tree^[ sel_n ].n_proc = a641))
                        THEN
                            d_colptr := NIL;
                        (*ENDIF*) 
                        a640factor (acv, dmli, colin, sel_n);
                        a65_set_operator (acv, operator)
                        END
                    (*ENDIF*) 
                END;
            (*ENDCASE*) 
        (*ENDWITH*) 
        IF  d_join
        THEN
            WITH d_joins, jrc_joinarr[ jrc_cnt ], jo_recs[ 2 ], a_mblock, mb_qual^ DO
                IF  jo_partno = 2
                THEN
                    IF  jo_no_join
                    THEN
                        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
                                FOR i := 0 TO jrc_cnt-1 DO
                                    WITH jrc_joinarr[ i ] DO
                                        IF  (jo_op = op_like)       OR
                                            (jo_op = op_not_like)   OR
                                            (jo_op = op_sounds)     OR
                                            (jo_op = op_not_sounds)
                                        THEN
                                            BEGIN
                                            jrc_joinarr[ jrc_cnt ].jo_no_join := true;
                                            d_arith_where := true
                                            END;
                                        (*ENDIF*) 
                                    (*ENDWITH*) 
                                (*ENDFOR*) 
                                IF  NOT d_arith_where
                                THEN
                                    BEGIN
                                    IF  mb_st^ [mfirst_free-1].etype =
                                        st_op (* op_(not_)like *)
                                    THEN
                                        jop_cntstack :=
                                              mfirst_free-jop_startstack-1
                                    ELSE
                                        jop_cntstack :=
                                              mfirst_free-jop_startstack;
                                    (*ENDIF*) 
                                    jop_outpos   := 0;
                                    IF  ((jop_cntstack > 1) OR
                                        NOT (mb_st^ [jop_startstack].eop in
                                        [ op_none, op_unique, op_unique_desc,
                                        op_order_asc, op_order_desc,
                                        op_ascii, op_ebcdic ]))
                                    THEN
                                        BEGIN
                                        jop_propset := [  ];
                                        WITH colin DO
                                            BEGIN
                                            jop_datatyp  := sci_typ;
                                            IF  sci_iolen >= mxsp_key -
                                                sizeof (tsp_int4)
                                            THEN
                                                a07_b_put_error (acv, e_join_fields_too_long, 1)
                                            ELSE
                                                BEGIN
                                                jop_datalen  := sci_len;
                                                jop_inoutlen := sci_iolen;
                                                END
                                            (*ENDIF*) 
                                            ;
                                            END;
                                        (*ENDWITH*) 
                                        IF  jop_datatyp in [ dfixed,
                                            dfloat, dvfloat ]
                                        THEN
                                            BEGIN
                                            jop_datatyp  := dfloat;
                                            jop_datalen  := csp_fixed;
                                            jop_inoutlen := mxgg_number;
                                            END
                                        (*ENDIF*) 
                                        END;
                                    (*ENDIF*) 
                                    END
                                (*ENDIF*) 
                                END
                            ELSE
                                a07_b_put_error (acv, e_join_fields_too_long, 1);
                            (*ENDIF*) 
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDWITH*) 
        (*ENDIF*) 
        END
    (*ENDIF*) 
(*ENDWITH*) 
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_return_segm^.sp1r_returncode = 0
    THEN
        parsinfo_ptr := @dmli.d_sparr.pparsp^.sparsinfo
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  acv.a_return_segm^.sp1r_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   : tgg_stack_op_type;
            field_found    : tsp_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  : tsp_int2;
      list_node   : integer;
      in_check    : boolean;
      in_strat    : boolean;
      first_entry : tsp_int2;
      first_free  : tsp_int2;
      list_cnt    : integer;
      dm_datatype : tsp_data_type;
 
BEGIN
WITH acv, a_mblock, dmli DO
    BEGIN
    d_const_value_expr := false;
    d_param_st_index   := 0;
    d_param_st_begin   := 0;
    d_single_expr      := true;
    first_entry        := a_mblock.mb_qual^.mfirst_free;
    cnt_fac            := 0;
    in_check           := true;
    be_q_cnt           := a_mblock.mb_qual^.mqual_cnt;
    IF  (a_ap_tree^[ first_node ].n_proc = a63query_spec)
        OR
        ((a_ap_tree^[ first_node ].n_proc = a63) AND
        ( 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 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  a_ap_tree^[ list_node ].n_sa_level > 0
                THEN
                    BEGIN
                    level_node  := 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,
                          a_ap_tree^[ level_node ].n_datatype,
                          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*) 
                    a_ap_tree^[ list_node  ].n_sa_level := level_node;
                    END;
                (*ENDIF*) 
&               ifdef trace
                WITH 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 := a_ap_tree^[ first_node ].n_sa_level;
            list_cnt  := 0;
            WHILE (list_node <> 0) AND (a_return_segm^.sp1r_returncode = 0) DO
                WITH 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  := 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 := a_ap_tree^[ list_node ].n_sa_level
                    END;
                (*ENDWITH*) 
            (*ENDWHILE*) 
            IF  (a_return_segm^.sp1r_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 (a_ap_tree^[ list_node ].n_proc <> no_proc) AND
                      (a_ap_tree^[ list_node ].n_lo_level <> 0) DO
                    list_node := 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,
                          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,
                              a_ap_tree^[ list_node ].n_pos)
                    (*ENDIF*) 
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  (a_return_segm^.sp1r_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 d_colbuf^.ccolpropset
                    THEN
                        WITH mb_qual^, 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    := a_ap_tree^[ first_node ].n_lo_level;
        colin.sci_len := 0;
        help_buf      := d_colptr;
        IF  field_found > 0
        THEN
            IF  ctmulti in d_colbuf^.ccolpropset
            THEN
                WITH mb_st^[ field_found ] DO
                    ecol_tab[ 2 ] := chr (ord (ecol_tab[ 2 ]) + 100);
                (*ENDWITH*) 
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (a_sqlmode = sqlm_adabas) OR (a_sqlmode = sqlm_oracle)
        THEN
            BEGIN
            in_strat := true;
            WITH 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 := 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. *)
                    d_datatype := list_info.elem[list_cnt].datatype;
                    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 (d_datatype));
&               endif
                a65_val_expr (acv, dmli, colin,
                      a_ap_tree^[ first_node ].n_lo_level);
                IF  a_return_segm^.sp1r_returncode <> 0
                THEN
                    first_node := 0 (* signal to exit loop. *)
                ELSE
                    BEGIN
                    WITH  a_mblock DO
                        BEGIN
                        IF  mb_st^ [ mb_qual^.mfirst_free-1 ].etype <> st_value
                        THEN
                            in_check := false;
                        (*ENDIF*) 
                        in_strat := in_strat AND
                              (mb_st^ [first_free].etype = st_value) AND
                              ((mb_st^[ first_free ].ecol_tab [2] <> chr(0)) OR
                              (first_free = mb_qual^.mfirst_free - 1));
                        END;
                    (*ENDWITH*) 
                    cnt_fac    := succ(cnt_fac);
                    first_node := 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 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;
                        d_colptr           := help_buf;
                        d_const_value_expr := false;
                        d_param_st_index   := 0;
                        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 a_ap_tree^[ first_node ].n_sa_level <> 0 DO
                BEGIN
                first_node := a_ap_tree^[ first_node ].n_sa_level;
                colin.sci_len := 0;
                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 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;
                        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 (a_return_segm^.sp1r_returncode = 0)
        THEN
            a651in_const_expression (acv, dmli, first_entry,
                  a_mblock.mb_qual^.mfirst_free - 1);
        (*ENDIF*) 
        d_single_expr := false;
        END;
    (*ENDIF*) 
    END
(*ENDWITH*) 
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 := mxgg_number;
    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   : tsp_int2;
            VAR dest : tsp_int2);
 
BEGIN
WITH acv DO
    BEGIN
    a01_put_same_node (acv, source, dest);
    IF  a_return_segm^.sp1r_returncode = 0
    THEN
        IF  a_ap_tree^[source].n_lo_level > 0
        THEN
            ak65copy_expression (acv, a_ap_tree^[source].n_lo_level,
                  a_ap_tree^[dest].n_lo_level);
        (*ENDIF*) 
    (*ENDIF*) 
    IF  a_return_segm^.sp1r_returncode = 0
    THEN
        IF  a_ap_tree^[source].n_sa_level > 0
        THEN
            ak65copy_expression (acv, a_ap_tree^[source].n_sa_level,
                  a_ap_tree^[dest].n_sa_level);
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65split_in_clause (VAR acv : tak_all_command_glob;
            first_node : integer);
 
VAR
      second_in     : tsp_int2;
      first_left    : tsp_int2;
      second_left   : tsp_int2;
      new_first_node: tsp_int2;
      first_list    : tsp_int2;
      second_list   : tsp_int2;
      curr_listelem : tsp_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_return_segm^.sp1r_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
                        ( 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_return_segm^.sp1r_returncode = 0) AND
                (NOT subquery_list))
            THEN
                BEGIN
                list_node := act_node;
                list_cnt := 0;
                WHILE ((list_node > 0) AND
                      (a_return_segm^.sp1r_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
                                ( 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;
      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        : tgg_stack_op_type;
      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     : tsp_int2;
      xi              : integer;
      used_tab_cnt    : integer;
      used_tables     : tak_joinset;
 
BEGIN
WITH acv, dmli DO
    IF  a_return_segm^.sp1r_returncode = 0
    THEN
        BEGIN
        d_const_value_expr  := (a_is_ddl = no_ddl);
        d_param_st_index   := 0;
        d_param_st_begin   := 0;
        d_is_parameter_only := false;
        IF  d_join
        THEN
            BEGIN
            WITH d_joins, jrc_joinarr[ jrc_cnt ] DO
                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;
            (*ENDWITH*) 
            oldjoincnt := d_joins.jrc_cnt;
            END;
        (*ENDIF*) 
        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
            WITH a_ap_tree^[ first_node ] DO
                IF  n_symb = s_not
                THEN
                    BEGIN
                    snot_pred  := true;
                    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*) 
            (*ENDWITH*) 
        (*ENDIF*) 
        left_side  :=  a_ap_tree^[ first_node ].n_lo_level;
        right_side := a_ap_tree^[ left_side ].n_sa_level;
        IF  (((a_ap_tree^[ left_side ].n_lo_level = 0) OR
            (a_ap_tree^[ left_side ].n_symb in
            [ s_plus, s_minus, s_mult, s_divide, s_div, s_mod ] ) OR
            (a_ap_tree^[ left_side ].n_proc = a641)) AND
            (a_ap_tree^[ left_side ].n_symb <> s_authid)    AND
            (a_ap_tree^[ left_side ].n_symb <> s_tablename) AND
            (a_ap_tree^[ left_side ].n_symb <> s_columnname))
            AND NOT d_outer_join AND NOT a_outer_join
        THEN (* only one value on the left side of
              comparison operator and no column specification *)
            BEGIN
            col_node := right_side;
            IF  a_ap_tree^[ col_node ].n_symb = s_authid
            THEN (* columnspecification with authname *)
                col_node := a_ap_tree^[ col_node ].n_sa_level;
            (*ENDIF*) 
            IF  a_ap_tree^[ col_node ].n_symb = s_tablename
            THEN (* columnspecification with tablename *)
                col_node := a_ap_tree^[ col_node ].n_sa_level;
            (*ENDIF*) 
            IF  a_ap_tree^[ col_node ].n_symb = s_columnname
            THEN (* columnspec on right side of comparison operator *)
                WITH a_ap_tree^[ first_node ] DO
                    IF  (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 ])
                    THEN
                        BEGIN
                        (* change left and right side of comparison operator *)
                        a_ap_tree^[ col_node ].n_sa_level   := left_side;
                        a_ap_tree^[ first_node ].n_lo_level := right_side;
                        a_ap_tree^[ left_side ].n_sa_level  := 0;
                        (* change the comparison operator *)
                        CASE n_symb OF
                            s_greater :
                                n_symb := s_less;
                            s_greater_or_eq :
                                n_symb := s_less_or_eq;
                            s_less :
                                n_symb := s_greater;
                            s_less_or_eq :
                                n_symb := s_greater_or_eq;
                            OTHERWISE
                                BEGIN
                                END;
                            END;
                        (*ENDCASE*) 
                        END;
                    (*ENDIF*) 
                (*ENDWITH*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        normpred    := false;
        WITH a_ap_tree^[ first_node ] DO
            BEGIN
            IF  n_symb = s_or
            THEN
                BEGIN
                IF  mtabs_allowed
                THEN
                    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
                            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 := 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  (a_ap_tree^[ act_node ].n_proc = a64) AND
                    (a_ap_tree^[ act_node ].n_subproc  = cak_x_escape)
                THEN
                    act_node := a_ap_tree^[ act_node ].n_lo_level;
                (*ENDIF*) 
                d_allowed := may_more_tabs;
                IF  d_join
                THEN
                    WITH d_joins, jrc_joinarr[ jrc_cnt ], a_mblock.mb_qual^ DO
                        BEGIN
                        jo_recs[ 1 ].jop_startstack := mfirst_free;
                        jo_partno              := 1
                        END;
                    (*ENDWITH*) 
                (*ENDIF*) 
                colin.sci_len := 0;
&               ifdef TRACE
                t01int4 (ak_sem, 'act_nodepred', act_node);
&               endif
                IF  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 d_use_sub
                    THEN
                        a01_dt_put_datatype_node (acv,
                              a_ap_tree^[ act_node ].n_sa_level,
                              d_datatype, 0, 0, 0);
                    (*ENDIF*) 
                    END
                ELSE (* ap_tree[ first_node ].n_symb <> s_exists *)
                    BEGIN
                    IF  (a_sqlmode = sqlm_oracle) AND
                        (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 := a_ap_tree^[ first_node ].n_lo_level;
                            IF  (a_ap_tree^[ act_node ].n_proc = a64) AND
                                (a_ap_tree^[ act_node ].n_pos  = cak_x_escape)
                            THEN
                                act_node := 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 a_ap_tree^[ first_node ] DO
                            IF  n_symb = s_or
                            THEN
                                BEGIN
                                IF  mtabs_allowed
                                THEN
                                    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
                                            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 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 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 := 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^[ sel_n ].n_symb = s_tablename
                        THEN
                            sel_n := a_ap_tree^[ sel_n ].n_sa_level;
                        (*ENDIF*) 
                        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  (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))
                        THEN (* If the right side is a subquery, there is a *)
                            (*  list of column datatypes at the same level. *)
                            dtype_n := 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 (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  a_ap_tree^[ act_node ].n_symb in
                                [ s_columnname, s_tablename, s_authid ]
                            THEN
                                field_found := a_mblock.mb_qual^.mfirst_free
                            ELSE
                                field_found := 0;
                            (*ENDIF*) 
                            d_colptr           := NIL;
                            d_colindex         := 0;
                            d_expand           := 0;
                            d_change_date_time := false;
                            ak65not_first_val_expr (acv, dmli,
                                  colin, act_node);
                            IF  a_return_segm^.sp1r_returncode = cak_e_parameter
                            THEN
                                BEGIN
                                a_return_segm^.sp1r_returncode         := 0;
                                d_is_parameter_only := true;
                                a65_look_for_datatypes (acv, dmli, act_node);
                                IF  d_datatype = dunknown
                                THEN
                                    a07_b_put_error (acv, e_without_datatypes,
                                          a_ap_tree^[ act_node ].n_pos)
                                ELSE
                                    IF  a_return_segm^.sp1r_returncode = 0
                                    THEN
                                        BEGIN
                                        colin.sci_len := 0;
                                        d_colptr      := d_colbuf;
                                        ak65not_first_val_expr (acv, dmli,
                                              colin, act_node);
                                        END;
                                    (* in Case of :a = column4 *)
                                    (*ENDIF*) 
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                            IF  a_return_segm^.sp1r_returncode = 0
                            THEN
                                BEGIN
                                IF  field_found > 0
                                THEN
                                    d_colptr   := d_colbuf;
                                (*ENDIF*) 
                                IF  d_join
                                THEN
                                    WITH d_joins, jrc_joinarr[ jrc_cnt ],
                                         jo_recs[ 1 ], a_mblock.mb_qual^ DO
                                        IF  ((jop_tableno > 0) AND
                                            NOT jo_no_join)
                                        THEN
                                            BEGIN
                                            jop_cntstack := mfirst_free-jop_startstack;
                                            jop_outpos   := 0;
                                            IF  ((jop_cntstack > 1) OR
                                                NOT (a_mblock.mb_st^ [jop_startstack].eop in
                                                [ op_none, op_unique, op_unique_desc,
                                                op_order_asc, op_order_desc,
                                                op_ascii, op_ebcdic ]))
                                            THEN
                                                BEGIN
                                                jop_propset := [  ];
                                                WITH colin DO
                                                    BEGIN
                                                    jop_datatyp  := sci_typ;
                                                    IF  sci_iolen >= mxsp_key -
                                                     sizeof (tsp_int4)
                                                    THEN
                                                     BEGIN
                                                     jop_datalen  := 0;
                                                     jop_inoutlen := 0;
                                                     END
                                                    ELSE
                                                     BEGIN
                                                     jop_datalen  := sci_len;
                                                     jop_inoutlen := sci_iolen;
                                                     END;
                                                    (*ENDIF*) 
                                                    END;
                                                (*ENDWITH*) 
                                                IF  jop_datatyp in [ dfixed,
                                                    dfloat, dvfloat ]
                                                THEN
                                                    BEGIN
                                                    jop_datatyp  := dfloat;
                                                    jop_datalen  := csp_fixed;
                                                    jop_inoutlen := mxgg_number;
                                                    END
                                                (*ENDIF*) 
                                                END
                                            (*ENDIF*) 
                                            END
                                        ELSE
                                            IF  jop_tableno <> 0
                                            THEN
                                                jo_no_join := true
                                            (*ENDIF*) 
                                        (*ENDIF*) 
                                    (*ENDWITH*) 
                                (*ENDIF*) 
                                END
                            ELSE
                                IF  ((a_return_segm^.sp1r_returncode = a07_return_code
                                    (e_command_for_string_not_allow,
                                    a_sqlmode))                              AND
                                    (field_found > 0)                        AND
                                    (*(a_init_ex_kind = only_parsing) AND*)
                                    ( ((a_ap_tree^[ first_node ].n_symb in
                                    [s_is_null, s_is_not_null])              AND
                                    (a_sqlmode <> sqlm_ansi))
                                    OR
                                    ((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
                                    (a_ap_tree^[ sel_n ].n_symb = s_default) AND
                                    (a_sqlmode = sqlm_adabas))))
                                THEN
                                    BEGIN
                                    a_return_segm^.sp1r_returncode := 0;
                                    a_return_segm^.sp1r_errorpos := 0;
                                    d_colptr    := 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  (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 := a_mblock.mb_qual^.mfirst_free;
                                    a65ch_format (acv, dmli, startstack,
                                          colin, dcha, 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 a_ap_tree^[ dtype_n ] DO
                                        BEGIN
                                        types_ok := a65_datatypes_ok (acv, dmli,
                                              n_datatype, n_length, d_datatype,
                                              c_is_subquery, sel_n,
                                              a_ap_tree^[ act_node ].n_pos,
                                              c_convert, convert_t);
                                        IF  convert_t <> conv_none
                                        THEN
                                            BEGIN
                                            CASE convert_t OF
                                                conv_ascii_to_ebcdic,
                                                conv_unicode_to_ebcdic :
                                                    d_datatype := dche;
                                                conv_ebcdic_to_ascii,
                                                conv_unicode_to_ascii :
                                                    d_datatype := dcha;
                                                conv_ascii_to_unicode,
                                                conv_ebcdic_to_unicode :
                                                    d_datatype := dunicode;
                                                OTHERWISE
                                                    BEGIN
                                                    END
                                                END;
                                            (*ENDCASE*) 
                                            IF  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  := d_datatype;
                                datalen   := colin.sci_len;
                                datafrac  := colin.sci_frac + cak_frac_offset;
                                is_field  := (field_found > 0);
                                inout_len := colin.sci_iolen;
                                pos       := a_ap_tree^[ act_node ].n_pos
                                END;
                            (*ENDWITH*) 
                            IF  list_node <> 0
                            THEN (* There is another value in the list. *)
                                WITH a_ap_tree^[ list_node ] DO
                                    BEGIN
                                    list_cnt   := succ (list_cnt);
                                    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  a_return_segm^.sp1r_returncode = 0
                        THEN
                            WITH a_ap_tree^[ first_node ] DO
                                BEGIN
                                IF  (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 := a_rowno_allowed;
                                          a_rowno_allowed := false;
                                          *)
                                    ak65diff_predicates (acv, dmli, colin,
                                          first_node, snot_pred,
                                          field_found, list_info);
                                    (* 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*) 
                                WITH d_joins, jrc_joinarr[ jrc_cnt ] DO
                                    IF  jo_no_join
                                    THEN
                                        d_arith_where := true
                                    (*ENDIF*) 
                                (*ENDWITH*) 
                                END
                            (*ENDWITH*) 
                        (*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  d_join
            THEN
                IF  (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*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  d_join
        THEN
            BEGIN
            ak65analyze_joinarr (acv, dmli,
                  first_node, act_node);
            IF  snot_pred OR snot_subq
            THEN
                BEGIN
                d_joins.jrc_cnt := oldjoincnt;
                WITH d_joins, jrc_joinarr[ jrc_cnt ] DO
                    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;
                (*ENDWITH*) 
                END;
            (*ENDIF*) 
            END;
&       ifdef TRACE
        (*ENDIF*) 
        IF  d_join
        THEN
            a683_output (ak_sem, dmli);
&       endif
        (*ENDIF*) 
        END;
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak65s_num_into_tree (
            VAR acv    : tak_all_command_glob;
            VAR new_n  : tsp_int2;
            left_node  : integer;
            right_node : integer);
 
VAR
      put_node : tsp_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_return_segm^.sp1r_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
                                jo_no_join          := false;
                                jo_recs[ 1 ].jop_tableno := 0;
                                jo_recs[ 2 ].jop_tableno := 0;
                                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
                                jo_col_upd_stat          := 0;
                                jo_no_join          := false;
                                jo_recs[ 1 ].jop_tableno := 0;
                                jo_recs[ 2 ].jop_tableno := 0;
                                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        : tgg_stack_op_type;
            like_expression : boolean;
            ord_typ         : integer;
            escape          : boolean);
 
BEGIN
IF  acv.a_return_segm^.sp1r_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   : tgg_stack_op_type;
            first_node : integer);
 
VAR
      subquery_count : integer;
      itree          : tgg00_FileId;
 
BEGIN
IF  acv.a_return_segm^.sp1r_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 + mxgg_treeid <= mb_data_size
                    THEN
                        BEGIN
                        g10mv1 ('VAK65 ',   4,    
                              sizeof(itree), mb_data_size, itree, 1,
                              mbp_buf, mb_data_len+1, sizeof(itree),
                              a_return_segm^.sp1r_returncode);
                        epos        := mb_data_len+1;
                        mb_data_len := mb_data_len+mxgg_treeid;
                        END
                    ELSE
                        a07_b_put_error (acv , e_too_many_mb_data, 1)
                    (*ENDIF*) 
                    END;
                (*ENDWITH*) 
                elen_var := - cgg_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_return_segm^.sp1r_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 < mxgg_treeid
                    THEN
                        needed_len := mxgg_treeid
                    ELSE
                        needed_len := iolen;
                    (*ENDIF*) 
                    IF  mb_data_len + needed_len <= mb_data_size
                    THEN
                        BEGIN
                        g10mv1 ('VAK65 ',   5,    
                              sizeof(itree), mb_data_size, itree, 1,
                              mbp_buf, mb_data_len+1, sizeof(itree),
                              a_return_segm^.sp1r_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 := - cgg_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       : tgg_stack_op_type;
            col_len        : integer;
            keep_part_pos  : integer);
 
VAR
      rest_blanks          : boolean;
      star_any_class_found : boolean;
      ix                   : tsp_int2;
      i                    : tsp_int4;
      j                    : tsp_int4;
      k                    : tsp_int4;
      curr_data_len        : tsp_int4;
      star_offset          : tsp_int4;
      star_found_len       : tsp_int4;
      value_len            : tsp_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)  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) 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);
                                g10filuni ('VAK65 ',   6,    
                                      mb_data_size, mbp_buf,
                                      mb_st^ [mfirst_free-1].epos + star_offset,
                                      value_len - star_offset + 1,
                                      csp_unicode_blank,
                                      acv.a_return_segm^.sp1r_returncode)
                                END
                            ELSE
                                g10fil ('VAK65 ',   7,    
                                      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_return_segm^.sp1r_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;
                            g10fil ('VAK65 ',   8,    
                                  mb_data_size, mbp_buf,
                                  mb_st^ [mfirst_free-1].epos + star_offset,
                                  value_len - star_offset, chr (255),
                                  acv.a_return_segm^.sp1r_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];
                                        g10filuni ('VAK65 ',   9,    
                                              mb_data_size, mbp_buf,
                                              i+2, curr_data_len-i-1,
                                              csp_unicode_blank,
                                              acv.a_return_segm^.sp1r_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];
                                        g10filuni ('VAK65 ',  10,    
                                              mb_data_size, mbp_buf,
                                              i+2, curr_data_len-i-1,
                                              csp_unicode_blank,
                                              acv.a_return_segm^.sp1r_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);
                                        g10filuni ('VAK65 ',  11,    
                                              mb_data_size, mbp_buf,
                                              mb_st^ [mfirst_free-1].epos + star_offset,
                                              value_len - star_offset,
                                              csp_unicode_blank,
                                              acv.a_return_segm^.sp1r_returncode)
                                        END
                                    ELSE
                                        g10fil ('VAK65 ',  12,    
                                              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_return_segm^.sp1r_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*) 
                                    g10fil ('VAK65 ',  13,    
                                          mb_data_size, mbp_buf,
                                          mb_st^ [mfirst_free-1].epos +
                                          star_offset,
                                          value_len - star_offset,
                                          chr (255),
                                          acv.a_return_segm^.sp1r_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_ebcdic:
        a65_set_operator (acv, op_ebcdic);
    conv_ebcdic_to_ascii:
        a65_set_operator (acv, op_ascii);
    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));
    conv_ebcdic_to_unicode:
        BEGIN
        a65_set_operator (acv, op_ascii);
        a641string_set_operator (acv, op_b_uni_trans, 0, 0,
              chr(csp_ascii), chr(csp_unicode));
        END;
    conv_unicode_to_ebcdic:
        BEGIN
        a641string_set_operator (acv, op_b_uni_trans, 0, 0,
              chr(csp_unicode), chr(csp_ascii));
        a65_set_operator (acv, op_ebcdic);
        END;
    (* the next variants only with Oracle and union *)
    conv_ascii_to_num :
        a65_set_operator (acv, op_num);
    conv_ebcdic_to_num :
        BEGIN
        a65_set_operator (acv, op_ascii);
        a65_set_operator (acv, op_num);
        END;
    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_ebcdic,
    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_ebcdic
        THEN
            a65_set_operator (acv, op_ebcdic)
        ELSE
            IF  operator = conv_num_to_unicode
            THEN
                a641string_set_operator (acv, op_b_uni_trans, 0, 0,
                      chr(csp_ascii), chr(csp_unicode));
            (*ENDIF*) 
        (*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    : tsp_data_type;
            VAR dm_iolen   : tsp_int2;
            ctype          : tsp_data_type;
            is_subquery    : boolean;
            first_node     : integer;
            error_pos      : tsp_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   : tsp_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 [ dche, dcha, dunicode,
                    ddate, dtime, dtimestamp ]
                THEN
                    CASE ctype OF
                        dche :
                            IF  g01code.ctype = csp_ascii
                            THEN
                                convert_t := conv_ebcdic_to_ascii;
                            (*ENDIF*) 
                        dcha :
                            IF  g01code.ctype <> csp_ascii
                            THEN
                                convert_t := conv_ascii_to_ebcdic;
                            (*ENDIF*) 
                        dunicode :
                            BEGIN
                            IF  is_subquery
                            THEN
                                BEGIN
                                is_ok := false;
                                IF  NOT (
                                    (a_ap_tree^[ first_node ].n_proc = a63) AND
                                    (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*) 
            dche :
                IF  ctype in [ dche, dcha, dunicode,
                    ddate, dtime, dtimestamp ]
                THEN
                    CASE ctype OF
                        ddate, dtime, dtimestamp :
                            IF  g01code.ctype = csp_ascii
                            THEN
                                convert_t := conv_ascii_to_ebcdic;
                            (*ENDIF*) 
                        dcha :
                            convert_t := conv_ascii_to_ebcdic;
                        dunicode :
                            IF  is_subquery
                            THEN
                                BEGIN
                                is_ok := false;
                                IF  NOT (
                                    (a_ap_tree^[ first_node ].n_proc = a63) AND
                                    (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_ebcdic;
                            (*ENDIF*) 
                        OTHERWISE
                            BEGIN
                            END
                        END
                    (*ENDCASE*) 
                ELSE
                    is_ok := false;
                (*ENDIF*) 
            dcha :
                IF  ctype in [ dche, dcha, dunicode,
                    ddate, dtime, dtimestamp ]
                THEN
                    CASE ctype OF
                        ddate, dtime, dtimestamp :
                            IF  g01code.ctype = csp_ebcdic
                            THEN
                                convert_t := conv_ebcdic_to_ascii;
                            (*ENDIF*) 
                        dche :
                            convert_t := conv_ebcdic_to_ascii;
                        dunicode :
                            IF  is_subquery
                            THEN
                                BEGIN
                                is_ok := false;
                                IF  NOT (
                                    (a_ap_tree^[ first_node ].n_proc = a63) AND
                                    (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*) 
            ddbyteebcdic :
                is_ok := ctype = ddbyteebcdic;
            dunicode :
                IF  ctype <> dunicode
                THEN
                    CASE ctype OF
                        dcha, ddate, dtime, dtimestamp :
                            convert_t := conv_ascii_to_unicode;
                        dche :
                            convert_t := conv_ebcdic_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
            ( a_ap_tree^[ first_node ].n_subproc = cak_x_start_union ))))
        THEN
            BEGIN
            is_ok := true;
            CASE dm_type OF
                dcha, dche, 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;
                            dche :
                                convert_t := conv_ebcdic_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 in [ dcha, ddate, dtime, dtimestamp ]
                            THEN
                                BEGIN
                                IF  g01code.ctype = csp_ebcdic
                                THEN
                                    a65_set_operator( acv, op_ebcdic )
                                (*ENDIF*) 
                                END
                            ELSE
                                IF  ctype = dche
                                THEN
                                    BEGIN
                                    IF  g01code.ctype = csp_ascii
                                    THEN
                                        a65_set_operator ( acv, op_ascii );
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    IF  ctype = dunicode
                                    THEN
                                        a65_convert (acv, conv_unicode_to_ascii, 0);
                                    (*ENDIF*) 
                                (*ENDIF*) 
                            (*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) OR
                        (a_intern_select_cnt = 0))
                    THEN
                        BEGIN
&                       ifdef TRACE
                        t01int4 (ak_sem, 'subq_problem', 1);
&                       endif
                        (* PTS 1106602 E.Z. *)
                        IF  a_is_ddl <> no_ddl
                        THEN
                            a_return_segm^.sp1r_returncode := cak_e_subq_type_diff
                        ELSE
                            is_ok := true;
                        (*ENDIF*) 
                        a_subq_datatype_problem := 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     : tsp_data_type;
      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_return_segm^.sp1r_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, dche, dchb, drowid,
                            dstra, dstre, dstrb, dstrdb,
                            ddate, dtime, dtimestamp,
                            ddbyteebcdic,
                            dlonga, dlonge, dlongb, dlongdb,
                            dboolean,
                            dunicode, dstruni, dlonguni,
                            dvarchara, dvarchare, 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
                s_upper, s_lower, s_initcap, s_chr, s_ebcdic, 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
                        IF  g01code.ctype = csp_ascii
                        THEN
                            h_datatyp := dcha
                        ELSE
                            h_datatyp := dche;
                        (*ENDIF*) 
                    (*ENDIF*) 
                s_ascii :
                    IF  (a_sqlmode = sqlm_adabas)
                    THEN
                        IF  g01code.ctype = csp_ascii
                        THEN
                            h_datatyp := dcha
                        ELSE
                            h_datatyp := dche
                        (*ENDIF*) 
                    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 :
                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
                    IF  g01code.ctype = csp_ascii
                    THEN
                        d_datatype := dcha
                    ELSE
                        d_datatype := dche;
                    (*ENDIF*) 
                (*ENDIF*) 
            s_mbcs, s_transaction :
                d_datatype := dchb;
            s_user_func:
                ak65_dt_look_for_user_def (acv, dmli, first_node);
            s_kanji_string :
                d_datatype := ddbyteebcdic;
            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_return_segm^.sp1r_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    : tsp_int2;
      proc_colin     : tak00_scolinf;
      param_colin    : tak00_scolinf;
      keep_datatype  : tsp_data_type;
      res_datatype   : tsp_data_type;
      param_datatype : tsp_data_type;
      convert_t      : tak_convert_type;
      func_name      : tsp_knl_identifier;
      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, func_name, 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_return_segm^.sp1r_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_return_segm^.sp1r_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_return_segm^.sp1r_returncode := 0;
                a_return_segm^.sp1r_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
                s10fil (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 := cgg_is_true;
                        s_is_not_true :
                            epos := cgg_is_not_true;
                        s_is_false :
                            epos := cgg_is_false;
                        s_is_not_false :
                            epos := cgg_is_not_false;
                        s_is_null :
                            epos := cgg_is_undef;
                        s_is_not_null :
                            epos := cgg_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 : tgg_stack_op_type);
 
BEGIN
IF  acv.a_return_segm^.sp1r_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 : tgg_stack_op_type;
            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
      a65not_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              : tsp_int4;
 
BEGIN
WITH acv, a_ap_tree^[ first_node ], dmli DO
    IF  a_return_segm^.sp1r_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   := d_const_value_expr;
                d_const_value_expr := true;
                st_begin           := a_mblock.mb_qual^.mfirst_free;
                dmli.d_colptr      := NIL;
                a640factor (acv, dmli, colin, act_node);
                act_node := 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,
                          a_ap_tree^[ act_node ].n_pos)
                ELSE
                    BEGIN
                    colin1.sci_len := 0;
                    a640not_first_factor (acv, dmli, colin1, act_node)
                    END;
                (*ENDIF*) 
                IF  a_return_segm^.sp1r_returncode = 0
                THEN
                    BEGIN
                    CASE 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  d_const_value_expr AND NOT d_group AND
                        (a_return_segm^.sp1r_returncode = 0)
                    THEN
                        BEGIN
                        expr_st_cnt := a_mblock.mb_qual^.mfirst_free -
                              st_begin;
                        WITH a_mblock, mb_qual^ DO
                            IF  (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  d_param_st_index = 0
                                THEN
                                    BEGIN
                                    IF  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 := a_ap_tree^[ act_node ].n_pos;
                                    (*ENDIF*) 
                                    st_end :=
                                          a_mblock.mb_qual^.mfirst_free - 1;
                                    a651value_calculate ( acv, st_begin,
                                          st_end, colin.sci_typ = dchb,
                                          d_like, colin.sci_iolen, pos);
                                    END;
                                (*ENDIF*) 
                            (*ENDIF*) 
                        (*ENDWITH*) 
                        d_const_value_expr := const_value_expr;
                        END;
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
        (*ENDIF*) 
        END;
&   ifdef trace
    (*ENDIF*) 
(*ENDWITH*) 
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        : tsp_int2;
            look_for_dtype : boolean) : boolean;
 
VAR
      left_n     : tsp_int2; (* Left  operand of the plus.             *)
      last_left_n: tsp_int2; (* Last node of left operand of the plus. *)
      right_n    : tsp_int2; (* Right operand of the plus.             *)
      duration_n : tsp_int2; (* Node with the number to add or sub.    *)
      new_node   : tsp_int2; (* The new constructed node.              *)
      date_arith : boolean;  (* Have we found a datetime arithmetic?   *)
      op_dtype   : tsp_data_type;
      (* The following variables are for storing the actual state.     *)
      save_datatype         : tsp_data_type;
      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    : tsp_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, dche ])
                    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 in [ dcha, dche ]
                        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, dche ])
                    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 in [ dcha, dche ]
                        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 in [ dcha, dche ]
                        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     := mxgg_number;
                                    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_return_segm^.sp1r_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    : tsp_data_type;
      colin1           : tak00_scolinf;
      const_value_expr : boolean;
      st_begin         : integer;
      st_end           : integer;
      pos              : tsp_int4;
      expr_st_cnt      : tsp_int2;
      save_single_expr : boolean;
 
BEGIN
WITH acv, a_ap_tree^[ first_node ], dmli DO
    BEGIN
&   ifdef TRACE
    t01int4 (ak_sem, 'd_having    ',ord(d_having));
    t01int4 (ak_sem, 'd_subquery  ',ord(d_subquery));
    t01int4 (ak_sem, 'd_is_functio',ord(d_is_function_column));
&   endif
    (* PTS 1119066 E.Z. *)
    IF  g01userstackoverflow
    THEN
        a07_b_put_error (acv, e_program_stack_overflow, 1);
    (*ENDIF*) 
    IF  a_return_segm^.sp1r_returncode = 0
    THEN
        BEGIN
        save_single_expr := d_single_expr;
        d_single_expr := false;
        IF  d_having AND NOT d_subquery AND NOT d_is_function_column AND
            (d_corr = no_correlation)
        THEN
            a61_is_group_field ( acv, dmli, d_column,
                  @d_column, NOT c_use_refname, 0, c_is_expression,
                  first_node, n_pos);
        (*ENDIF*) 
        IF  a_return_segm^.sp1r_returncode = 0
        THEN
            BEGIN
            const_value_expr   := d_const_value_expr;
            d_const_value_expr := true;
            st_begin           := a_mblock.mb_qual^.mfirst_free;
            d_concat           := false;
            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);
                d_colptr           := NIL;
                keep_datatype      := d_datatype;
                d_datatype         := dunknown;
                change_date_time   := d_change_date_time;
                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 (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  a_return_segm^.sp1r_returncode = cak_e_parameter
                THEN
                    BEGIN
                    a_return_segm^.sp1r_returncode := 0;
                    a65_look_for_datatypes (acv, dmli, act_node);
                    IF  d_datatype = dunknown
                    THEN
                        d_datatype := dnumber;
                    (*ENDIF*) 
                    a65_term(acv, dmli, colin, act_node)
                    END;
                (*ENDIF*) 
                IF  (a_sqlmode = sqlm_oracle) AND datetime_arith
                THEN (* For oracle mode we have already checked that. *)
                    d_datatype := dunknown
                ELSE
                    IF  d_datatype in [ dcha, dche, dunicode,
                        ddate, dtime, dtimestamp ]
                    THEN
                        BEGIN
                        IF  d_datatype in [ dcha, dche, dunicode ]
                        THEN
                            IF  a_sqlmode <> sqlm_db2
                            THEN
                                a07_b_put_error (acv, e_function_not_allowed,
                                      a_ap_tree^[ first_node ].n_pos)
                            ELSE
                                BEGIN
                                IF  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 a_ap_tree^[ a_ap_tree^[ act_node ]
                                      .n_sa_level ].n_symb OF
                                    s_year, s_month, s_day:
                                        IF  n_proc = no_proc
                                        THEN
                                            d_datatype := dnumber
                                        ELSE (* duration *)
                                            IF  colin.sci_len > mxsp_extdate
                                            THEN
                                                d_datatype := dtimestamp
                                            ELSE
                                                d_datatype := ddate;
                                            (*ENDIF*) 
                                        (*ENDIF*) 
                                    s_hour, s_minute, s_second:
                                        IF  n_proc = no_proc
                                        THEN
                                            d_datatype := dnumber
                                        ELSE (* duration *)
                                            IF  colin.sci_len > mxsp_exttime
                                            THEN
                                                d_datatype := dtimestamp
                                            ELSE
                                                d_datatype := dtime;
                                            (*ENDIF*) 
                                        (*ENDIF*) 
                                    OTHERWISE
                                        a65_look_for_datatypes (acv, dmli,
                                              a_ap_tree^[ act_node ].n_sa_level);
                                    END;
                                (*ENDCASE*) 
                                IF  d_datatype in [ ddate, dtime, dtimestamp ]
                                THEN
                                    a641check_datetime (acv, dmli, d_datatype)
                                ELSE
                                    a07_b_put_error (acv, e_function_not_allowed,
                                          a_ap_tree^[ first_node ].n_pos)
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        IF  a_return_segm^.sp1r_returncode = 0
                        THEN
                            IF  a_sqlmode = sqlm_db2
                            THEN
                                BEGIN
                                datetime_arith := true;
                                CASE 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*) 
                                d_datatype := dunknown
                                END
                            ELSE
                                a07_b_put_error (acv, e_function_not_allowed,
                                      a_ap_tree^[ first_node ].n_pos)
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END
                    ELSE
                        IF  NOT (d_datatype in [dnumber, dfixed, dfloat, dvfloat])
                        THEN
                            a07_b_put_error (acv, e_function_not_allowed,
                                  a_ap_tree^[ first_node ].n_pos);
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
                IF  a_return_segm^.sp1r_returncode = 0
                THEN
                    BEGIN
                    act_node   := a_ap_tree^[ act_node ].n_sa_level;
                    colin1.sci_len := 0;
                    a65not_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  a_return_segm^.sp1r_returncode = cak_e_parameter
                THEN
                    IF  NOT keep_plus
                    THEN
                        (* PTS 1109261 E.Z. *)
                        BEGIN
                        a_return_segm^.sp1r_returncode := 0;
                        a07_b_put_error (acv, e_without_datatypes,
                              a_ap_tree^[ act_node ].n_pos)
                        END
                    ELSE
                        BEGIN
                        a_return_segm^.sp1r_returncode := 0;
                        a65_look_for_datatypes (acv, dmli, act_node);
                        IF  d_datatype = dunknown
                        THEN
                            d_datatype := dnumber;
                        (*ENDIF*) 
                        a65not_first_term(acv, dmli, colin1, act_node)
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
                IF  a_return_segm^.sp1r_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(d_datatype));
                    t01int4 (ak_sem, 'colin_type  ', ord(colin.sci_typ));
                    t01int4 (ak_sem, 'd_change    ', ord(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,
                          d_datatype, NOT c_is_subquery,
                          first_node, a_ap_tree^[ first_node ].n_pos,
                          c_convert, convert_t);
                (*ENDIF*) 
                d_change_date_time := change_date_time
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  d_const_value_expr AND NOT d_group AND
            (a_return_segm^.sp1r_returncode = 0)
        THEN
            BEGIN
            expr_st_cnt := a_mblock.mb_qual^.mfirst_free - st_begin;
            WITH a_mblock, mb_qual^ DO
                IF  (d_param_st_index > 0) AND
                    (expr_st_cnt <= 255) AND
                    (((n_proc = a64) AND (n_subproc = cak_x_add_operator)) OR
                    (st_begin <> 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  d_param_st_index = 0
                    THEN
                        BEGIN
                        IF  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 := a_ap_tree^[ act_node ].n_pos;
                        (*ENDIF*) 
                        st_end := a_mblock.mb_qual^.mfirst_free - 1;
                        a651value_calculate ( acv, st_begin, st_end,
                              colin.sci_typ = dchb, d_like, colin.sci_iolen, pos);
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDWITH*) 
            d_const_value_expr := const_value_expr;
            END;
        (*ENDIF*) 
        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
WITH dmli, d_joins DO
    BEGIN
    j            := oldjoincnt;
    jval_cnt     := 0;
    WHILE (j < jrc_cnt) DO
        BEGIN
        IF  (jrc_joinarr[ j ].jo_recs[ 2 ].jop_tableno = cak68_join_value)
        THEN
            BEGIN
            jval_cnt := succ (jval_cnt);
            END;
        (*ENDIF*) 
        j := succ (j);
        END;
    (*ENDWHILE*) 
    only_jvalue_found := (jval_cnt > 0) AND
          (jrc_cnt - oldjoincnt - jval_cnt = 0);
&   ifdef TRACE
    t01int4 (ak_sem, 'jrc_cnt     ', jrc_cnt);
    t01int4 (ak_sem, 'oldjoincnt  ', oldjoincnt);
    t01int4 (ak_sem, 'jvalue_found', ord (only_jvalue_found));
&   endif
    IF  only_jvalue_found
    THEN
        BEGIN
        jrc_cnt     := oldjoincnt;
        d_joins.jrc_joinarr[ d_joins.jrc_cnt ].jo_col_upd_stat := 0;
        WITH jrc_joinarr[ jrc_cnt ] DO
            BEGIN
            jo_no_join          := false;
            jo_recs[ 1 ].jop_tableno := 0;
            jo_recs[ 2 ].jop_tableno := 0;
            END
        (*ENDWITH*) 
        END;
    (*ENDIF*) 
    ak65only_jvalue_found := only_jvalue_found;
    END;
(*ENDWITH*) 
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   : tsp_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;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
