/*!***************************************************************************
 
  module      : vkb45
  author      : JuergenA
  responsible : UweH
  special area: KB_stringcol_read_search_length
  last changed: 1999-09-27
  copyright   : Copyright by SAP AG, 2001
  see also    :
  description :
 
 
 
    ========== 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
 
*****************************************************************************/
 
.tt 1 $SAP$LiveCache$VKB45$
.tt 3 $UweH$KB_stringcol_read_search_length$1999-09-27$
 
Module  : KB_stringcol_read_search_length
 
Define  :
 
        PROCEDURE
              k45clength_column (VAR m : tgg00_MessBlock);
 
        PROCEDURE
              k45cnread_column (VAR m : tgg00_MessBlock);
 
        PROCEDURE
              k45cread_column (VAR m : tgg00_MessBlock);
 
        PROCEDURE
              k45csearch_column (VAR m : tgg00_MessBlock);
 
        PROCEDURE
              k45test_short_col_upgraded (VAR m : tgg00_MessBlock;
                    VAR upgraded : boolean);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
&       ifdef TRACE
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01basis_error (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname;
                    b_err : tgg00_BasisError);
 
        PROCEDURE
              t01int4 (layer : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01p2int4 (layer : tgg00_Debug;
                    nam_1     : tsp00_Sname;
                    int_1     : tsp00_Int4;
                    nam_2     : tsp00_Sname;
                    int_2     : tsp00_Int4);
 
        PROCEDURE
              t01sname (layer : tgg00_Debug;
                    nam       : tsp00_Sname);
&       endif
 
      ------------------------------ 
 
        FROM
              KB_stringcol_copy_trunc_expand : VKB43;
 
        PROCEDURE
              k43cnew_lock_column (VAR m : tgg00_MessBlock;
                    copy_target : boolean);
 
      ------------------------------ 
 
        FROM
              KB_stringcol_open_close : VKB44;
 
        PROCEDURE
              k44get_short_col_rec (VAR m : tgg00_MessBlock;
                    VAR shc_buf    : tgg00_Rec;
                    VAR prim_tabid : tgg00_Surrogate;
                    VAR shc_id     : tgg00_Surrogate);
 
      ------------------------------ 
 
        FROM
              KB_transaction : VKB53;
 
        PROCEDURE
              k53child_trans_build (MessType : tgg00_MessType;
                    TransCnt       : tsp00_Int4;
                    VAR ChildTrans : tgg00_TransChild);
 
        PROCEDURE
              k53lock (VAR t         : tgg00_TransContext;
                    VAR lock_tabid   : tgg00_Surrogate;
                    VAR k            : tgg00_Lkey;
                    wanted_mode      : tgg00_LockReqMode;
                    wanted_state     : tgg00_LockReqState;
                    nowait           : boolean;
                    collision_test   : boolean;
                    VAR granted_mode : tgg00_LockReqMode);
 
        PROCEDURE
              k53wait (VAR t  : tgg00_TransContext;
                    MessType  : tgg00_MessType;
                    MessType2 : tgg00_MessType2);
 
      ------------------------------ 
 
        FROM
              KB_sender_receiver : VKB90;
 
        PROCEDURE
              k90send (VAR mblock    : tgg00_MessBlock;
                    VAR remote_trans : tgg00_TransChild);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1 : VBD01;
 
        PROCEDURE
              b01filestate (VAR t : tgg00_TransContext;
                    VAR file_id   : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_5 : VBD05;
 
        PROCEDURE
              b05find_substring (VAR t : tgg00_TransContext;
                    VAR file_id        : tgg00_FileId;
                    start_pos          : tsp00_Int4;
                    stop_pos           : tsp00_Int4;
                    VAR patt           : tgg00_Lkey;
                    with_patt          : boolean;
                    VAR from_str_pos   : tsp00_Int4;
                    VAR to_str_pos     : tsp00_Int4);
 
        PROCEDURE
              b05length_bytestr (VAR t : tgg00_TransContext;
                    VAR file_id        : tgg00_FileId;
                    VAR filelength     : tsp00_Int4;
                    VAR page_count     : tsp00_Int4;
                    VAR str_vers       : tsp00_Int4);
 
        PROCEDURE
              b05read_bytestr (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId;
                    pos         : tsp00_Int4;
                    VAR length  : tsp00_Int4;
                    buf_size    : tsp00_Int4;
                    buf_addr    : tsp00_MoveObjPtr;
                    bufpos      : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        FUNCTION
              g01BlobPrefetchLowerLimit : tsp00_Int4;
 
        PROCEDURE
              g01mblock_init (
                    VAR source_trans : tgg00_TransContext;
                    mess_type  : tgg_message_type;
                    mess2_type : tgg_message2_type;
                    VAR mblock : tgg_mess_block);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG10;
 
        PROCEDURE
              g10mv (mod_id    : tsp_c6;            mod_num    : tsp_int4;
                    source_upb : tsp_int4;          destin_upb : tsp_int4;
                    VAR source : tsp_moveobj;       source_pos : tsp_int4;
                    VAR destin : tsp00_Key;         destin_pos : tsp_int4;
                    length     : tsp_int4;
                    VAR err    : tgg_basis_error);
 
        PROCEDURE
              g10mv1 (mod_id   : tsp_c6;            mod_num    : tsp_int4;
                    source_upb : tsp_int4;          destin_upb : tsp_int4;
                    VAR source : tsp00_Buf;         source_pos : tsp_int4;
                    VAR destin : tsp_moveobj;       destin_pos : tsp_int4;
                    length     : tsp_int4;
                    VAR err    : tgg_basis_error);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-30 : VSP30;
 
        PROCEDURE
              s30cmp (VAR b      : tsp00_Buf;
                    fieldpos1    : tsp_int4;
                    fieldlength1 : tsp_int4;
                    VAR pattern  : tsp00_Key;
                    fieldpos2    : tsp_int4;
                    fieldlength2 : tsp_int4;
                    VAR l_result : tsp_lcomp_result);
 
      ------------------------------ 
 
        FROM
              Patterns : VSP49;
 
        FUNCTION
              s49onecmatch (VAR pat : tsp00_Key;
                    pos             : tsp_int4;
                    comp_ch         : char;
                    VAR pat_incr    : tsp_int4) : boolean;
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              g10mv;
 
              tsp_moveobj tsp00_Key
 
        PROCEDURE
              g10mv1;
 
              tsp_moveobj tsp00_Buf
 
        PROCEDURE
              s30cmp;
 
              tsp_moveobj tsp00_Buf
              tsp_moveobj tsp00_Key
 
        PROCEDURE
              s49onecmatch;
 
              tsp_moveobj tsp00_Key
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  :
.sp
.cp 3
Created : 1986-01-28
.sp
.cp 3
.sp
.cp 3
Release :      Date : 1999-09-27
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
.sp 2
K45cread_column
.sp;.in +3
Reads a maximum of 8104 bytes (currently) from a string
column or file. A special technique is used to send back
the result by using the message buffer:
.in +3;.sp
Normally, result buffers from the BD layer are sent
back as part2 of the message buffer. This has a capacity
of 4096 Bytes.  Two BD read accesses and a special handling of the
message buffer are required to read a string part of the above length.
The first part of the total result is sent back, as usual, as part2
and the second part is returned as part1.
.in -3
.nf;.sp;.in +3
m.part1 :
.sp
mtree              : input  string descriptor
mst_addr^[ 1 ].eval4_var : input  start
mst_addr^[ 2 ].elen_var  : input  length wanted
mst_addr^[ 1 ].eval4_var : result length found
.fo;.in -3
.sp 2;.in -3
K45csearch_column
.sp;.in +3
Searches for either a substring or a pattern
in a string column or file in a designated range
and returns the start and
end position of this string part.
.nf;.sp;.in +3
m.part1 :
.sp
mtree              : input  string descriptor
mst_addr^[ 1 ].eval4_var : input  search range start
mst_addr^[ 1 ].eop       : input  pattern contains match characters y/n
                            op_like , op_none
mst_addr^[ 2 ].eval4_var : input  search range end
mst_addr^[ 1 ].eval4_var : result start
mst_addr^[ 2 ].eval4_var : result end
.fo;.in -3
.sp 2;.in -3
K45clength_column
.sp;.in +3
Returns the length of a string column or file.
.nf;.sp;.in +3
m.part1 :
.sp
mtree              : input  string descriptor
mst_addr^[ 1 ].eval4_var : result length
.fo;.in -3
.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
 
.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
 
.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
 
 
CONST
      c_collision_test = true; (* k53lock *)
      c_copy_target    = true;
      c_nowait         = true; (* k53lock *)
      (**)
      c_str_id_sign     = 128;
      c_pos_str_id_sign =   3;
 
 
(*------------------------------*) 
 
PROCEDURE
      kb45lock_tabid (VAR m : tgg00_MessBlock);
 
VAR
      dummy_granted     : tgg00_LockReqMode;
      dummy_key         : tgg00_Lkey;
      lock_tabid        : tgg00_Surrogate;
 
BEGIN
lock_tabid := m.mb_qual^.mtree.fileTabId_gg00;
lock_tabid[c_pos_str_id_sign] := chr(c_str_id_sign);
k53lock (m.mb_trns^, lock_tabid, dummy_key, lckTabShare_egg00, [ ],
      NOT c_nowait, NOT c_collision_test, dummy_granted);
IF  m.mb_trns^.trError_gg00 = e_wait_for_lock_release
THEN
    k53wait (m.mb_trns^, m.mb_type, m.mb_type2)
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k45cnread_column (VAR m : tgg00_MessBlock);
 
VAR
      upgraded   : boolean;
      dummy_vers : tsp00_Int4;
      page_count : tsp00_Int4;
      prim_tabid : tgg00_Surrogate;
      str_id     : tgg00_FileId;
      shc_buf    : tgg00_Rec;
 
BEGIN
WITH m, mb_qual^, ml_long_qual DO
    BEGIN
    mb_trns^.trError_gg00 := e_ok;
    str_id          := mtree;
    IF  lq_len > mb_data_size - lq_data_offset
    THEN
        IF  lq_trunc_req
        THEN
            lq_len := mb_data_size - lq_data_offset
        ELSE
            mb_trns^.trError_gg00 := e_st_invalid_length;
        (*ENDIF*) 
&   ifdef TRACE
    (*ENDIF*) 
    t01int4 (fs_kb, 'curr data sz', mb_data_size - lq_data_offset);
    t01int4 (fs_kb, 'read len    ', lq_len);
&   endif
    upgraded := false;
    IF  mb_trns^.trError_gg00 = e_ok
    THEN
        BEGIN
        prim_tabid := lq_lock_tabid;
        IF  NOT lq_long_in_file
        THEN
            BEGIN
            k44get_short_col_rec (m, shc_buf, prim_tabid, mtree.fileTabId_gg00);
            IF  mb_trns^.trError_gg00 = e_ok
            THEN
                BEGIN
                lq_long_size := shc_buf.len - cgg_rec_key_offset -
                      shc_buf.keylen;
                IF  (lq_long_size > (lq_pos + lq_len - 1)) AND
                    (lq_pos = 1)
                THEN
                    BEGIN
                    kb45lock_tabid (m);
                    lq_try_unlock := true;
                    (* sign for 'is locked' *)
                    IF  mb_trns^.trError_gg00 = e_ok
                    THEN
                        BEGIN
                        k44get_short_col_rec (m, shc_buf, prim_tabid, mtree.fileTabId_gg00);
                        IF  mb_trns^.trError_gg00 = e_ok
                        THEN
                            lq_long_size := shc_buf.len
                                  - cgg_rec_key_offset - shc_buf.keylen
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  mb_trns^.trError_gg00 = e_ok
                THEN
                    BEGIN
                    IF  (lq_pos > lq_long_size) OR
                        (lq_pos < 1           )
                    THEN
                        BEGIN
                        IF  lq_long_size = 0
                        THEN
                            BEGIN
                            mb_data_len     := lq_data_offset;
                            lq_len          := 0;
                            mb_trns^.trError_gg00 := e_key_not_found
                            END
                        ELSE
                            mb_trns^.trError_gg00 := e_file_limit
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        IF  lq_long_size < lq_pos + lq_len - 1
                        THEN
                            lq_len := lq_long_size - lq_pos + 1;
&                       ifdef TRACE
                        (*ENDIF*) 
                        t01int4 (fs_kb, 'read len    ', lq_len);
&                       endif
                        g10mv1 ('VKB45 ',   1,    
                              sizeof (shc_buf.buf), mb_data_size,
                              shc_buf.buf,
                              cgg_rec_key_offset + shc_buf.keylen + lq_pos,
                              mb_data^.mbp_buf, lq_data_offset + 1,
                              lq_len, mb_trns^.trError_gg00);
                        mb_data_len := lq_data_offset + lq_len;
                        IF  lq_data_offset > cgg_rec_key_offset
                        THEN
                            BEGIN
                            mb_data^.mbp_reclen := mb_data_len ;
                            mb_data^.mbp_keylen := LOCK_MXGG00 + KEY_MXSP00
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE
                IF  mb_trns^.trError_gg00 = e_key_not_found
                THEN
                    BEGIN
                    k45test_short_col_upgraded (m, upgraded);
                    IF  mb_trns^.trError_gg00 = e_file_read_only
                    THEN
                        mb_trns^.trError_gg00 := e_ok
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
&   ifdef TRACE
    (*ENDIF*) 
    t01int4 (fs_kb, 'upgraded    ', ord (upgraded));
&   endif
    IF  (upgraded OR lq_long_in_file)
        AND
        (lq_pos = 1)
        AND
        (mb_trns^.trError_gg00 = e_ok)
    THEN
        BEGIN
        kb45lock_tabid (m);
        lq_try_unlock := true
        END;
    (*ENDIF*) 
    IF  (mb_trns^.trError_gg00 = e_ok) AND (upgraded OR lq_long_in_file)
    THEN
        BEGIN
        b05length_bytestr (mb_trns^, mb_qual^.mtree, lq_long_size,
              page_count, dummy_vers);
        IF  mb_trns^.trError_gg00 = e_ok
        THEN
            BEGIN
            b05read_bytestr (mb_trns^, mtree, lq_pos, lq_len,
                  mb_data_size, @mb_data^.mbp_buf, lq_data_offset + 1);
            mb_data_len  := lq_data_offset + lq_len;
            IF  lq_data_offset > cgg_rec_key_offset
            THEN
                BEGIN
                mb_data^.mbp_reclen := mb_data_len ;
                mb_data^.mbp_keylen := LOCK_MXGG00 + KEY_MXSP00;
                END;
            (*ENDIF*) 
            IF  (mb_trns^.trError_gg00 = e_ok) AND lq_read_ahead
            THEN
                BEGIN
                (* Before the order segment is send back to the client   *)
                (* a prefetch is started to get the next requested pages *)
                (* as long as the communication takes place              *)
                IF  (
                    (lq_long_size > g01BlobPrefetchLowerLimit) AND
                    ((lq_long_size - (lq_pos + lq_len)) > sizeof(tsp00_Page))
                    )
                THEN
                    kb45_StartPrefetch (mb_trns^, mtree, (lq_pos + lq_len));
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  mb_trns^.trError_gg00 = e_ok
    THEN
        BEGIN
        IF  upgraded
        THEN
            lq_long_in_file := true;
        (*ENDIF*) 
        lq_pos      := lq_pos + lq_len;
        mcol_pos    := 0;
        mcol_cnt    := 0;
        mfirst_free := 1;
        mb_qual_len := MB_PART1_HEAD_MXGG00 + sizeof (ml_long_qual);
        mb_type     := m_return_result;
        mb_type2    := mm_nil;
        mb_struct   := mbs_long
        END
    ELSE
        BEGIN
        IF  mb_trns^.trError_gg00 = e_key_not_found
        THEN
            BEGIN
            mb_trns^.trError_gg00 := e_ok;
            lq_pos      := lq_pos + lq_len;
            mb_qual_len := MB_PART1_HEAD_MXGG00 + sizeof (ml_long_qual);
            mb_type     := m_return_result;
            mb_type2    := mm_nil;
            mb_struct   := mbs_long
            END
        ELSE
            BEGIN
            mb_qual_len := 0;
            mb_data_len := 0;
            mb_type     := m_return_error
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k45cread_column (VAR m : tgg00_MessBlock);
 
VAR
      upgraded   : boolean;
      dummy_vers : tsp00_Int4;
      page_count : tsp00_Int4;
      prim_tabid : tgg00_Surrogate;
      str_id     : tgg00_FileId;
      shc_buf    : tgg00_Rec;
 
BEGIN
WITH m, mb_qual^, ml_long_qual DO
    BEGIN
    mb_trns^.trError_gg00 := e_ok;
    IF  NOT (hsWithoutLock_egg00 in mtree.fileHandling_gg00)
    THEN
        k43cnew_lock_column (m, NOT c_copy_target);
    (*ENDIF*) 
    IF  mb_trns^.trError_gg00 = e_ok
    THEN
        BEGIN
        str_id := mtree;
        IF  lq_len > mb_data_size - lq_data_offset
        THEN
            IF  lq_trunc_req
            THEN
                lq_len := mb_data_size - lq_data_offset
            ELSE
                mb_trns^.trError_gg00 := e_st_invalid_length;
            (*ENDIF*) 
        (*ENDIF*) 
        END;
&   ifdef TRACE
    (*ENDIF*) 
    t01int4 (fs_kb, 'curr data sz', mb_data_size - lq_data_offset);
    t01int4 (fs_kb, 'read len    ', lq_len);
&   endif
    upgraded := false;
    IF  mb_trns^.trError_gg00 = e_ok
    THEN
        BEGIN
        prim_tabid := lq_lock_tabid;
        IF  NOT lq_long_in_file
        THEN
            BEGIN
            k44get_short_col_rec (m, shc_buf, prim_tabid, mtree.fileTabId_gg00);
            IF  mb_trns^.trError_gg00 = e_ok
            THEN
                BEGIN
                lq_long_size := shc_buf.len - cgg_rec_key_offset -
                      shc_buf.keylen;
                IF  (lq_pos > lq_long_size) OR
                    (lq_pos < 1           )
                THEN
                    BEGIN
                    IF  lq_long_size = 0
                    THEN
                        BEGIN
                        mb_data_len     := lq_data_offset;
                        lq_len          := 0;
                        mb_trns^.trError_gg00 := e_key_not_found
                        END
                    ELSE
                        mb_trns^.trError_gg00 := e_file_limit
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  lq_long_size < lq_pos + lq_len - 1
                    THEN
                        lq_len := lq_long_size - lq_pos + 1;
&                   ifdef TRACE
                    (*ENDIF*) 
                    t01int4 (fs_kb, 'read len    ', lq_len);
&                   endif
                    g10mv1 ('VKB45 ',   2,    
                          sizeof (shc_buf.buf), mb_data_size,
                          shc_buf.buf,
                          cgg_rec_key_offset + shc_buf.keylen + lq_pos,
                          mb_data^.mbp_buf, lq_data_offset + 1,
                          lq_len, mb_trns^.trError_gg00);
                    mb_data_len := lq_data_offset + lq_len;
                    IF  lq_data_offset > cgg_rec_key_offset
                    THEN
                        BEGIN
                        mb_data^.mbp_reclen := mb_data_len ;
                        mb_data^.mbp_keylen := LOCK_MXGG00 + KEY_MXSP00;
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            ELSE
                IF  mb_trns^.trError_gg00 = e_key_not_found
                THEN
                    BEGIN
                    k45test_short_col_upgraded (m, upgraded);
                    IF  mb_trns^.trError_gg00 = e_file_read_only
                    THEN
                        mb_trns^.trError_gg00 := e_ok;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
&   ifdef TRACE
    (*ENDIF*) 
    t01int4 (fs_kb, 'upgraded    ', ord (upgraded));
&   endif
    IF  (mb_trns^.trError_gg00 = e_ok) AND (upgraded OR lq_long_in_file)
    THEN
        BEGIN
        b05length_bytestr (mb_trns^, mb_qual^.mtree, lq_long_size,
              page_count, dummy_vers);
        IF  mb_trns^.trError_gg00 = e_ok
        THEN
            BEGIN
            b05read_bytestr (mb_trns^, mtree, lq_pos, lq_len,
                  mb_data_size, @mb_data^.mbp_buf, lq_data_offset + 1);
            mb_data_len  := lq_data_offset + lq_len;
            IF  lq_data_offset > cgg_rec_key_offset
            THEN
                BEGIN
                mb_data^.mbp_reclen := mb_data_len ;
                mb_data^.mbp_keylen := LOCK_MXGG00 + KEY_MXSP00;
                END;
            (*ENDIF*) 
            IF  (mb_trns^.trError_gg00 = e_ok) AND lq_read_ahead
            THEN
                BEGIN
                (* Before the order segment is send back to the client   *)
                (* a prefetch is started to get the next requested pages *)
                (* as long as the communication takes place              *)
                IF  (
                    (lq_long_size > g01BlobPrefetchLowerLimit) AND
                    ((lq_long_size - (lq_pos + lq_len)) > sizeof(tsp00_Page))
                    )
                THEN
                    kb45_StartPrefetch (mb_trns^, mtree, (lq_pos + lq_len));
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  mb_trns^.trError_gg00 = e_ok
    THEN
        BEGIN
        IF  upgraded
        THEN
            lq_long_in_file := true;
        (*ENDIF*) 
        lq_pos      := lq_pos + lq_len;
        mcol_pos    := 0;
        mcol_cnt    := 0;
        mfirst_free := 1;
        mb_qual_len := MB_PART1_HEAD_MXGG00 + sizeof (ml_long_qual);
        mb_type     := m_return_result;
        mb_type2    := mm_nil;
        mb_struct   := mbs_long
        END
    ELSE
        BEGIN
        IF  mb_trns^.trError_gg00 = e_key_not_found
        THEN
            BEGIN
            mb_trns^.trError_gg00 := e_ok;
            lq_pos      := lq_pos + lq_len;
            mb_qual_len := MB_PART1_HEAD_MXGG00 + sizeof (ml_long_qual);
            mb_type     := m_return_result;
            mb_type2    := mm_nil;
            mb_struct   := mbs_long
            END
        ELSE
            BEGIN
            mb_qual_len  := 0;
            mb_data_len  := 0;
            mb_type      := m_return_error
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k45clength_column (VAR m : tgg00_MessBlock);
 
VAR
      upgraded   : boolean;
      dummy_vers : tsp00_Int4;
      page_count : tsp00_Int4;
      prim_tabid : tgg00_Surrogate;
      shc_buf    : tgg00_Rec;
 
BEGIN
WITH m, mb_qual^, ml_long_qual DO
    BEGIN
    IF  NOT (hsWithoutLock_egg00 in mtree.fileHandling_gg00)
    THEN
        k43cnew_lock_column (m, NOT c_copy_target);
    (*ENDIF*) 
    IF  mb_trns^.trError_gg00 = e_ok
    THEN
        BEGIN
        upgraded   := false;
        prim_tabid := lq_lock_tabid;
        IF  NOT lq_long_in_file
        THEN
            BEGIN
            k44get_short_col_rec (m, shc_buf, prim_tabid, mtree.fileTabId_gg00);
            IF  mb_trns^.trError_gg00 = e_ok
            THEN
                lq_long_size := shc_buf.len - cgg_rec_key_offset -
                      shc_buf.keylen
            ELSE
                IF  mb_trns^.trError_gg00 = e_key_not_found
                THEN
                    BEGIN
                    k45test_short_col_upgraded (m, upgraded);
                    IF  mb_trns^.trError_gg00 = e_file_read_only
                    THEN
                        mb_trns^.trError_gg00 := e_ok;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
&       ifdef TRACE
        (*ENDIF*) 
        t01int4 (fs_kb, 'upgraded    ', ord (upgraded));
&       endif
        IF  (mb_trns^.trError_gg00 = e_ok) AND
            (upgraded  OR lq_long_in_file)
        THEN
            b05length_bytestr (mb_trns^, mtree, lq_long_size,
                  page_count, dummy_vers);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  mb_trns^.trError_gg00 = e_ok
    THEN
        BEGIN
        IF  upgraded
        THEN
            lq_long_in_file := true;
        (*ENDIF*) 
        mcol_pos    := 0;
        mcol_cnt    := 0;
        mfirst_free := 1;
        mb_qual_len := MB_PART1_HEAD_MXGG00 + sizeof (ml_long_qual);
        mb_data_len := 0;
        mb_type     := m_return_result;
        mb_type2    := mm_nil;
        mb_struct   := mbs_long
        END
    ELSE
        BEGIN
        mb_qual_len := 0;
        mb_type     := m_return_error;
        mb_type2    := mm_nil
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k45csearch_column (VAR m : tgg00_MessBlock);
 
VAR
      upgraded      : boolean;
      stop_pos      : tsp00_Int4;
      res_start_pos : tsp00_Int4;
      res_stop_pos  : tsp00_Int4;
      patt          : tgg00_Lkey;
      prim_tabid    : tgg00_Surrogate;
      shc_buf       : tgg00_Rec;
 
BEGIN
WITH m, mb_qual^, ml_long_qual DO
    BEGIN
    IF  NOT (hsWithoutLock_egg00 in mb_qual^.mtree.fileHandling_gg00)
    THEN
        k43cnew_lock_column (m, NOT c_copy_target);
    (*ENDIF*) 
    IF  mb_trns^.trError_gg00 = e_ok
    THEN
        BEGIN
        stop_pos := lq_pos + lq_len - 1;
        IF  stop_pos = -1
        THEN
            stop_pos := cgg_eo_bytestr;
        (*ENDIF*) 
        patt.len := mb_data_len  - mb_data^.mbp_keylen -
              cgg_rec_key_offset;
        g10mv ('VKB45 ',   3,    
              mb_data_size, sizeof (patt.k),
              mb_data^.mbp_buf,
              cgg_rec_key_offset + mb_data^.mbp_keylen + 1,
              patt.k, 1, patt.len, mb_trns^.trError_gg00);
        upgraded := false;
        prim_tabid := lq_lock_tabid;
        IF  NOT lq_long_in_file AND (mb_trns^.trError_gg00 = e_ok)
        THEN
            BEGIN
            k44get_short_col_rec (m, shc_buf, prim_tabid, mtree.fileTabId_gg00);
            IF  mb_trns^.trError_gg00 = e_ok
            THEN
                kb45find_substring (shc_buf, lq_pos, stop_pos, patt,
                      lq_is_pattern, res_start_pos, res_stop_pos)
            ELSE
                IF  mb_trns^.trError_gg00 = e_key_not_found
                THEN
                    BEGIN
                    k45test_short_col_upgraded (m, upgraded);
                    IF  mb_trns^.trError_gg00 = e_file_read_only
                    THEN
                        mb_trns^.trError_gg00 := e_ok;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
&       ifdef TRACE
        (*ENDIF*) 
        t01int4 (fs_kb, 'upgraded    ', ord (upgraded));
&       endif
        IF  (upgraded OR lq_long_in_file) AND (mb_trns^.trError_gg00 = e_ok)
        THEN
            b05find_substring (mb_trns^, mtree,
                  lq_pos, stop_pos,
                  patt, lq_is_pattern, res_start_pos, res_stop_pos);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  mb_trns^.trError_gg00 = e_ok
    THEN
        BEGIN
        IF  upgraded
        THEN
            lq_long_in_file := true;
        (*ENDIF*) 
        lq_pos      := res_start_pos;
        lq_len      := res_stop_pos - res_start_pos + 1;
        mcol_pos    := 0;
        mcol_cnt    := 0;
        mfirst_free := 1;
        mb_qual_len := MB_PART1_HEAD_MXGG00 + sizeof (ml_long_qual);
        mb_data_len := 0;
        mb_type     := m_return_result;
        mb_type2    := mm_nil;
        mb_struct   := mbs_long
        END
    ELSE
        BEGIN
        mb_type     := m_return_error;
        mb_type2    := mm_nil;
        mb_qual_len := 0;
        mb_data_len := 0
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k45test_short_col_upgraded (VAR m : tgg00_MessBlock;
            VAR upgraded : boolean);
 
BEGIN
m.mb_trns^.trError_gg00        := e_ok;
m.mb_qual^.mtree.fileType_gg00 := [ftsByteStr_egg00, ftsConcurrent_egg00];
m.mb_qual^.mtree.fileTfn_gg00  := tfnColumn_egg00;
b01filestate (m.mb_trns^, m.mb_qual^.mtree);
IF  (m.mb_trns^.trError_gg00 = e_ok) OR
    (m.mb_trns^.trError_gg00 = e_file_read_only)
THEN
    upgraded := true;
(*ENDIF*) 
;
(* ELSE
      IF  m.mb_trns^.trError_gg00 = e_file_not_found
      THEN
      m.mb_trns^.trError_gg00 := e_key_not_found *)
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb45find_substring (VAR shc_buf : tgg00_Rec;
            start_pos        : tsp00_Int4;
            stop_pos         : tsp00_Int4;
            VAR patt         : tgg00_Lkey;
            with_patt        : boolean;
            VAR firstpos     : tsp00_Int4;
            VAR lastpos      : tsp00_Int4);
 
VAR
      found   : boolean;
      result  : tsp00_LcompResult;
 
BEGIN
found    := false;
firstpos := start_pos;
lastpos  := 0;
IF  stop_pos = cgg_eo_bytestr
THEN
    stop_pos := shc_buf.len - cgg_rec_key_offset - shc_buf.keylen;
(*ENDIF*) 
IF  NOT with_patt
THEN
    BEGIN
    WHILE ((firstpos + patt.len) <= stop_pos) AND NOT found
          DO
        BEGIN
        s30cmp (shc_buf.buf, firstpos + cgg_rec_key_offset +
              shc_buf.keylen, patt.len,
              patt.k, 1, patt.len, result);
        found := result = l_equal;
        IF  found
        THEN
            lastpos := firstpos + patt.len - 1
        ELSE
            firstpos := succ (firstpos)
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  NOT found
    THEN
        firstpos := 0;
    (*ENDIF*) 
    END
ELSE
    BEGIN
    (* PTS 1111159 E.Z. *)
    IF  (patt.k [ 1 ] <> csp_star1) (* AND
          (patt.k [ 1 ] <> csp_any1)  AND
          (patt.k [ 1 ] <> csp_cclass) *)
    THEN
        BEGIN
        WHILE (firstpos <= stop_pos) AND NOT found
              DO
            BEGIN
            IF  (shc_buf.buf [ firstpos + cgg_rec_key_offset +
                shc_buf.keylen  ] = patt.k [ 1 ])
                (* PTS 1111159 E.Z. *)
                OR  (patt.k [ 1 ] = csp_any1)
                OR  (patt.k [ 1 ] = csp_cclass)
            THEN
                kb45string_match (shc_buf.buf, cgg_rec_key_offset +
                      shc_buf.keylen + firstpos - 1 ,
                      stop_pos, patt.k, 0,
                      patt.len, lastpos, found);
            (*ENDIF*) 
            IF  NOT found
            THEN
                firstpos := succ(firstpos);
            (*ENDIF*) 
            END
        (*ENDWHILE*) 
        END
    ELSE
        kb45string_match (shc_buf.buf, cgg_rec_key_offset +
              shc_buf.keylen + firstpos - 1, stop_pos, patt.k, 0,
              patt.len, lastpos, found);
    (*ENDIF*) 
    IF  NOT found
    THEN
        firstpos := 0
    ELSE
        lastpos := lastpos - cgg_rec_key_offset - shc_buf.keylen;
    (*ENDIF*) 
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb45string_match (VAR val : tsp00_Buf;
            val_offset  : integer;
            stoppos     : integer;
            VAR pat     : tsp00_Key;
            pat_offset  : integer;
            pat_len     : integer;
            VAR lastpos : integer;
            VAR found   : boolean);
 
VAR
      match           : boolean;
      ok              : boolean;
      shift           : boolean;
      star_occurred   : boolean;
      act_pat_ch      : char;
      val_pos         : integer;
      pat_pos         : integer;
      closure_val_pos : integer;
      closure_pat_pos : integer;
      pat_incr        : integer;
&     ifdef DEBUG_VKB45
      loop_count : integer;
&     endif
 
BEGIN
(* prerequisite: stoppos > 0 AND pat_len > 0 *)
&ifdef DEBUG_VKB45
t01sname  (kb_qual, '============');
t01sname  (kb_qual, 'kb45str_mat:');
t01p2int4 (kb_qual, 'pat_offset  ', pat_offset
      ,             'pat_len     ', pat_len);
t01p2int4 (kb_qual, 'val_offset  ', val_offset
      ,             'stoppos     ', stoppos);
loop_count := 0;
&endif
found         := false;
ok            := true;
shift         := false;
star_occurred := false;
pat_pos       := 1;
val_pos       := 1;
lastpos       := 0;
act_pat_ch    := pat [ pat_offset + 1 ];
IF  (pat_len = 1) AND ((act_pat_ch = csp_star1) OR (act_pat_ch =
    csp_any1))
THEN
    BEGIN
    found := true;
    IF  (act_pat_ch = csp_any1)
    THEN
        lastpos := val_offset + val_pos
    ELSE
        lastpos := val_offset + val_pos - 1;
    (*ENDIF*) 
    END
ELSE
    BEGIN
    REPEAT
&       ifdef DEBUG_VKB45
        loop_count := loop_count + 1;
        t01sname  (kb_qual, '============');
        t01p2int4 (kb_qual, 'loop        ', loop_count
              ,             'shift       ', ord (shift));
        t01p2int4 (kb_qual, 'pat_pos     ', pat_pos
              ,             'val_pos     ', val_pos);
&       endif
        IF  pat [ pat_offset + pat_pos ] = csp_star1
        THEN
            BEGIN
            pat_pos         := pat_pos + 1;
            shift           := true;
            star_occurred   := true;
            closure_pat_pos := pat_pos;
            closure_val_pos := 0;
            IF  pat_pos > pat_len
            THEN
                BEGIN
                found := true;
                lastpos := val_offset + val_pos - 1
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        ok := (val_offset + val_pos) < sizeof (val);
        IF  (pat_pos <= pat_len) AND ok
        THEN
            BEGIN
&           ifdef DEBUG_VKB45
            t01int4   (kb_qual, 'pat_pos     ', pat_pos);
            t01p2int4 (kb_qual, 'act_pat_ch  ',
                  ord (pat [ pat_offset + pat_pos ]),
                  'act_val_ch  ', ord (val [ val_offset + val_pos ]));
&           endif
            match := false;
            IF  (pat[ pat_offset + pat_pos ] = val[ val_offset+val_pos ])
                OR (pat[ pat_offset + pat_pos ] = csp_any1)
            THEN
                BEGIN
                pat_incr := 1;
                match    := true
                END
            ELSE
                IF  pat [ pat_offset + pat_pos ] = csp_cclass
                THEN
                    match := s49onecmatch (pat, pat_offset + pat_pos,
                          val [ val_offset + val_pos ], pat_incr);
&               ifdef DEBUG_VKB45
                (*ENDIF*) 
            (*ENDIF*) 
            t01int4 (kb_qual, 'match       ', ord(match));
&           endif
            IF  match
            THEN
                BEGIN
                pat_pos := pat_pos + pat_incr;
                val_pos := val_pos + 1;
                IF  shift
                THEN
                    BEGIN
                    closure_val_pos := val_pos;
                    shift := false
                    END;
                (*========
                      IF  (pat_pos > pat_len) AND (val_pos <= stoppos)
                      THEN
                      IF  NOT star_occurred
                      THEN
                      ok := false
                      ELSE
                      BEGIN
                      pat_pos := closure_pat_pos;
                      val_pos := closure_val_pos;
                      shift   := true
                      END
                      =========*)
                (*ENDIF*) 
                END
            ELSE
                IF  shift
                THEN
                    BEGIN
                    IF  pat [ pat_offset + pat_pos ] <> csp_star1
                    THEN
                        val_pos := val_pos + 1
                    (*ENDIF*) 
                    END
                ELSE
                    IF  NOT star_occurred
                    THEN
                        ok := false
                    ELSE
                        BEGIN
                        val_pos := closure_val_pos;
                        pat_pos := closure_pat_pos;
                        shift   := true
                        END
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
            END
        (*ENDIF*) 
    UNTIL
        (pat_pos > pat_len) OR (val_pos > stoppos ) OR NOT ok;
    (*ENDREPEAT*) 
&   ifdef DEBUG_VKB45
    t01sname  (kb_qual, 'end loop:   ');
    t01p2int4 (kb_qual, 'shift       ', ord (shift)
          ,             'ok          ', ord (ok));
    t01p2int4 (kb_qual, 'pat_pos     ', pat_pos
          ,             'val_pos     ', val_pos);
&   endif
    IF  (pat_pos > pat_len) AND ok
    THEN
        BEGIN
        found := true;
        lastpos := val_offset + val_pos - 1;
        END;
    (*ENDIF*) 
    IF  (pat_pos <= pat_len) AND (val_pos > stoppos) AND ok
    THEN
        BEGIN
        (* test trailing star1 *)
        found := true;
        lastpos := val_offset + val_pos - 1;
        REPEAT
            IF  pat [ pat_offset + pat_pos ] <> csp_star1
            THEN
                BEGIN
                lastpos := 0;
                found := false
                END
            ELSE
                pat_pos := pat_pos + 1
            (*ENDIF*) 
        UNTIL
            (pat_pos > pat_len) OR NOT found
        (*ENDREPEAT*) 
        END
    (*ENDIF*) 
    END;
(*ENDIF*) 
&ifdef DEBUG_VKB45
t01int4 (kb_qual, 'k45str_mat :', ord (found));
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb45_StartPrefetch (
            VAR trans       : tgg00_TransContext;
            VAR fileId      : tgg00_FileId;
            blobPosition    : tsp00_Int4);
 
VAR
      sendMBlock : tgg00_MessBlock;
      sendTrans  : tgg00_TransChild;
 
BEGIN
WITH trans DO
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        k53child_trans_build (m_column, trTaskId_gg00, sendTrans);
        g01mblock_init (trans, m_column, mm_participant, sendMBlock);
        WITH sendMBlock DO
            BEGIN
            mb_struct    := mbs_buf;
            mb_qual      := @fileId;
            mb_qual_size := sizeof (fileId);
            mb_qual_len  := sizeof (fileId);
            (* *)
            mb_data      := @blobPosition;
            mb_data_size := sizeof (blobPosition);
            mb_data_len  := sizeof (blobPosition)
            END;
        (*ENDWITH*) 
        (*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*)
        k90send (sendMBlock, sendTrans);
        (*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*)
        IF  trError_gg00 <> e_ok
        THEN
            BEGIN
&           ifdef TRACE
            t01basis_error (fs_kb, 'kb45prefetch', trError_gg00);
&           endif
            trError_gg00 := e_ok; (* ignore all errors *)
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
