campo-sirio/cb5/r4log.c
alex a0f5e0898b This commit was generated by cvs2svn to compensate for changes in r975,
which included commits to RCS files with non-trunk default branches.

git-svn-id: svn://10.65.10.50/trunk@976 c028cbd2-c16b-5b4b-a496-9718f37d4682
1995-02-06 15:33:45 +00:00

501 lines
15 KiB
C
Executable File

/* r4log.c (c)Copyright Sequiter Software Inc., 1992-1994. All rights reserved. */
#include "d4all.h"
#ifdef __TURBOC__
#pragma hdrstop
#endif
int S4FUNCTION e4is_constant( E4INFO *info_ptr )
{
int pos ;
if ( info_ptr->function_i == E4DOUBLE || info_ptr->function_i == E4STRING ||
( info_ptr->function_i >= E4LOG_LOW && info_ptr->function_i <= E4LOG_HIGH ) )
return 1 ;
if ( info_ptr->function_i == E4STOD || info_ptr->function_i == E4CTOD ) /* might be a constant */
{
for ( pos = info_ptr->num_entries - 1 ; pos >= 0 ; pos -- )
if ( (info_ptr-pos)->field_ptr != 0 || (info_ptr-pos)->function_i >= E4CALC_FUNCTION )
return 0 ;
return 1 ;
}
return 0 ;
}
/* returns true if there is a tag that matches the desired condition type,
AND if there is no filter on that tag */
int S4FUNCTION e4is_tag( E4INFO_REPORT *report_ptr, EXPR4 *expr, E4INFO *info_ptr, DATA4 *data )
{
#ifndef S4INDEX_OFF
TAG4 *tag_on ;
int is_same, i ;
E4INFO *info_on, *tag_info ;
for( tag_on = 0;; )
{
tag_on = d4tag_next( data, tag_on ) ;
if ( tag_on == 0 )
break ;
#ifdef S4NDX
if ( t4unique( tag_on ) != r4unique_continue ) /* if unique, can't filter */
#else
if ( tag_on->filter == 0 && ( t4unique( tag_on ) != r4unique_continue ) ) /* if unique a filter, than cannot bitmap optimize */
#endif
{
tag_info = tag_on->expr->info + tag_on->expr->info_n -1 ;
if ( tag_info->num_entries == info_ptr->num_entries )
{
is_same = 1 ;
info_on = info_ptr ;
for( i = 0; i < info_ptr->num_entries && is_same; i++, info_on--, tag_info-- )
{
if ( memcmp( (void *)info_on, (void *)tag_info, sizeof(E4INFO)
- sizeof(info_on->i1) - sizeof(info_on->result_pos)
- sizeof(info_on->function_i) - sizeof(info_on->function))
!= 0 )
{
is_same = 0 ;
break ;
}
switch( info_on->function_i )
{
case E4DOUBLE:
case E4STRING:
case E4CTOD:
case E4DTOC:
case E4DTOC+1:
/* Compare Constant */
if( memcmp( tag_on->expr->constants + tag_info->i1, expr->constants + info_on->i1, tag_info->len ) != 0 )
is_same = 0 ;
break ;
default:
is_same = (info_on->i1 == tag_info->i1) ;
break ;
}
if( info_on->function_i != tag_info->function_i )
if( info_on->function_i > E4LAST_FIELD
|| tag_info->function_i > E4LAST_FIELD )
is_same = 0 ;
}
if( is_same )
{
report_ptr->tag = tag_on ;
return 1 ;
}
}
}
}
#endif
return 0 ;
}
int S4FUNCTION data_list4add( DATA4LIST *list, CODE4 *code_base, RELATE4 *new_pointer )
{
if ( code_base->error_code < 0 )
return -1 ;
if ( new_pointer == 0 )
return 0 ;
if ( data_list4is_in( list, new_pointer ) )
return 0 ;
if( list->pointers_tot <= list->pointers_used )
{
list->pointers_tot += 5 ;
if ( u4alloc_again( code_base, (char **)&list->pointers, &list->mem_allocated, list->pointers_tot * sizeof(RELATE4 *)) < 0 )
return -1 ;
}
list->pointers[list->pointers_used++] = new_pointer ;
return 0 ;
}
int S4FUNCTION data_list4expand_from_db_tree( DATA4LIST *list, CODE4 *code_base )
{
int i ;
RELATE4 *relate_parent ;
for( i = list->pointers_used-1; i >= 0; i-- )
{
relate_parent = list->pointers[i]->master ;
while( relate_parent != 0 )
{
if ( data_list4add( list, code_base, relate_parent ) < 0 )
return -1 ;
relate_parent = relate_parent->master ;
}
}
if ( code_base->error_code < 0 )
return -1 ;
return 0 ;
}
int S4FUNCTION data_list4is_in( DATA4LIST *list, RELATE4 *new_pointer )
{
int i ;
for( i = 0 ; i < list->pointers_tot ; i++ )
if ( list->pointers[i] == new_pointer )
return 1 ;
return 0 ;
}
int S4FUNCTION data_list4read_records( DATA4LIST *data_list )
{
RELATE4 *cur ;
int i, rc ;
if ( data_list == 0 )
return 0 ;
for( i = data_list->pointers_used-1 ; i >= 0 ; i-- )
{
cur = data_list->pointers[i] ;
rc = relate4read_in( cur ) ;
if ( rc == relate4filter_record || rc == r4terminate )
return rc ;
if ( rc < 0 )
return -1 ;
}
return 0 ;
}
void S4FUNCTION data_list4remove( DATA4LIST *this_list, DATA4LIST *remove_list )
{
int i ;
#ifdef S4DEBUG
if ( this_list == 0 || remove_list == 0 )
e4severe( e4parm, E4_DATA_LIST4REM ) ;
#endif
for( i = 0; i < this_list->pointers_used; i++ )
if( data_list4is_in( remove_list, this_list->pointers[i]) )
this_list->pointers[i--] = this_list->pointers[--this_list->pointers_used] ;
}
int S4FUNCTION log4add_to_list( L4LOGICAL *log, E4INFO *info_ptr, DATA4LIST *list )
{
int num_parms, i ;
if ( info_ptr->function_i <= E4LAST_FIELD )
if ( data_list4add( list, log->code_base, relate4lookup_relate( (RELATE4 *)&log->relation->relate, f4data(info_ptr->field_ptr)) ) < 0 )
return -1 ;
if ( info_ptr->num_entries == 1 )
return 0 ;
num_parms = info_ptr->num_parms ;
info_ptr-- ;
for ( i = 0; i < num_parms; i++ )
{
if ( log4add_to_list( log, info_ptr, list ) < 0 )
return -1 ;
info_ptr -= info_ptr->num_entries ;
}
if ( log->code_base->error_code < 0 )
return -1 ;
return 0 ;
}
static int log4build_database_lists( L4LOGICAL *log )
{
int last_pos, pos, i ;
E4INFO *info_last ;
log->info_report = (E4INFO_REPORT *)u4alloc_er( log->code_base, (long)sizeof(E4INFO_REPORT) * log->expr->info_n ) ;
if ( log->info_report == 0 )
return -1 ;
last_pos = log->expr->info_n - 1 ;
info_last = (E4INFO *)log->expr->info + last_pos ;
if ( info_last->function_i == E4AND )
{
pos = last_pos - 1 ;
for ( i = 0; i < info_last->num_parms; i++ )
{
if ( log->info_report[pos].data_list == 0 )
{
log->info_report[pos].data_list = (DATA4LIST *)mem4create_alloc( log->code_base,
&log->relation->data_list_memory, 5, sizeof(DATA4LIST), 5, 0 ) ;
if ( log->info_report[pos].data_list == 0 )
return -1 ;
}
if ( log4add_to_list( log, log->expr->info+pos, log->info_report[pos].data_list ) < 0 )
return -1 ;
pos -= log->expr->info[pos].num_entries ;
}
}
else
{
if ( log->info_report[last_pos].data_list == 0 )
{
log->info_report[last_pos].data_list = (DATA4LIST *)mem4create_alloc( log->code_base,
&log->relation->data_list_memory, 5, sizeof( DATA4LIST ), 5, 0 ) ;
if ( log->info_report[last_pos].data_list == 0 )
return -1 ;
}
log4add_to_list( log, info_last, log->info_report[last_pos].data_list ) ;
}
if ( log->code_base->error_code < 0 )
return -1 ;
return 0 ;
}
int S4FUNCTION log4bitmap_do( L4LOGICAL *log )
{
if ( log->code_base->error_code < 0 )
return -1 ;
log4build_database_lists( log ) ;
#ifndef S4INDEX_OFF
if ( bitmap4evaluate( log, log->expr->info_n - 1 ) < 0 )
return -1 ;
#endif
if ( log->code_base->error_code < 0 )
return -1 ;
return 0 ;
}
int S4FUNCTION log4determine_evaluation_order( L4LOGICAL *log )
{
/* Expand Lists due to Database Tree */
int i, pos, num_left, cur_smallest_pos, cur_smallest_num, cur_pos ;
int num_compare, last_pos = log->expr->info_n -1 ;
E4INFO *info_last, *info_ptr ;
E4INFO_REPORT *report_last, *report, *cur_report ;
info_last = (E4INFO *)log->expr->info + last_pos ;
report_last = log->info_report + last_pos ;
if ( info_last->function_i != E4AND )
return data_list4expand_from_db_tree( report_last->data_list, log->code_base ) ;
info_ptr = info_last-1 ;
report = report_last-1 ;
for ( i = 0; i < info_last->num_parms; i++ )
{
if ( data_list4expand_from_db_tree(report->data_list, log->code_base) < 0 )
return -1 ;
report -= info_ptr->num_entries ;
info_ptr -= info_ptr->num_entries ;
}
/* Change the evaluation orders by repeatedly determining the
list with the smallest number of entries and puting it at the end.
The idea is that we want the conditions which causes the fewest
additional database records to be read in, to be evaluated first.
*/
pos = last_pos - 1 ; /* Position currently being made into the fewest. */
for( num_left = info_last->num_parms; num_left > 1; num_left-- )
{
report = log->info_report + pos ;
info_ptr = (E4INFO *)log->expr->info + pos ;
/* Now determine which is the entry with the fewest data files. */
cur_smallest_pos = pos ;
cur_smallest_num = report->data_list->pointers_used ;
cur_pos = pos - info_ptr->num_entries ;
for( num_compare = num_left-1; num_compare > 0; num_compare-- )
{
cur_report = log->info_report + cur_pos ;
if ( cur_report->data_list->pointers_used < cur_smallest_num )
{
cur_smallest_num = cur_report->data_list->pointers_used ;
cur_smallest_pos = cur_pos ;
}
cur_pos -= log->expr->info[cur_pos].num_entries ;
}
if( pos != cur_smallest_pos )
if ( log4swap_entries( log, pos, cur_smallest_pos ) < 0 )
return -1 ;
/* The next step is to remove the data list for the first evaluated
condition from the data list of the rest of the conditions. */
cur_pos = pos - info_ptr->num_entries ;
for( i = num_left-1; i > 0; i-- )
{
cur_report = log->info_report + cur_pos ;
data_list4remove( cur_report->data_list, report->data_list ) ;
cur_pos -= log->expr->info[cur_pos].num_entries ;
}
pos -= info_ptr->num_entries ;
}
if ( log->code_base->error_code < 0 )
return -1 ;
return 0 ;
}
int S4FUNCTION log4swap_entries( L4LOGICAL *log, int a, int b )
{
int large_entries, small_entries ;
char *save_buf ;
E4INFO *a_ptr, *b_ptr, *small, *large, *middle ;
E4INFO_REPORT *small2, *large2, *middle2 ;
int small_pos, large_pos, middle_pos, middle_entries, move_positions ;
if ( log->code_base->error_code < 0 )
return -1 ;
a_ptr = log->expr->info + a ;
b_ptr = log->expr->info + b ;
if ( a_ptr->num_entries > b_ptr->num_entries )
{
small = b_ptr ;
large = a_ptr ;
small_pos = b ;
large_pos = a ;
}
else
{
small = a_ptr ;
large = b_ptr ;
small_pos = a ;
large_pos = b ;
}
/* make copies of large and small entries because the info may be later
lost as swaps take place... */
large_entries = large->num_entries ;
small_entries = small->num_entries ;
save_buf = (char *)u4alloc_free( log->code_base, sizeof(E4INFO) * large_entries ) ;
if ( save_buf == 0 )
return e4( log->code_base, e4memory, E4_INFO_EXP ) ;
move_positions = large_entries - small_entries ;
if ( small_pos < large_pos )
{
middle_pos = small_pos + 1 ;
middle_entries = large_pos - small_pos - large_entries ;
}
else
{
middle_pos = large_pos + 1 ;
middle_entries = small_pos - large_pos - small_entries ;
move_positions = -move_positions ;
}
middle = log->expr->info + middle_pos ;
memcpy( save_buf, (void *)(large - large_entries + 1), sizeof(E4INFO) * large_entries ) ;
if ( large_pos > small_pos ) /* want to move small to end of large pos... */
{
memcpy( (void *)(large - small_entries + 1 ), (void *)(small - small_entries + 1),
sizeof(E4INFO) *small_entries ) ;
memmove( (void *)(middle + move_positions), middle, sizeof(E4INFO) * middle_entries ) ;
memcpy( (void *)(small - small_entries + 1), save_buf, sizeof(E4INFO) * large_entries ) ;
}
else /* want to move small to start of large pos... */
{
memcpy( (void *)(large - large_entries + 1 ), (void *)(small - small_entries + 1),
sizeof(E4INFO) *small_entries ) ;
memmove( (void *)(middle + move_positions), middle, sizeof(E4INFO) * middle_entries ) ;
memcpy( (void *)(small - large_entries + 1), save_buf, sizeof(E4INFO) * large_entries ) ;
}
large2 = log->info_report + large_pos ;
small2 = log->info_report + small_pos ;
middle2 = log->info_report + middle_pos ;
memcpy( save_buf, (void *)(large2 - large_entries + 1), sizeof(E4INFO_REPORT) * large_entries ) ;
if ( large_pos > small_pos ) /* want to move small to end of large pos... */
{
memcpy( (void *)(large2 - small_entries + 1), (void *)(small2 - small_entries + 1),
sizeof(E4INFO_REPORT) *small_entries ) ;
memmove( middle2 + move_positions, middle2, sizeof(E4INFO_REPORT) * middle_entries ) ;
memcpy( (void *)(small2 - small_entries + 1), save_buf, sizeof(E4INFO_REPORT) * large_entries ) ;
}
else /* want to move small to start of large pos... */
{
memcpy( (void *)(large2 - large_entries + 1), (void *)(small2 - small_entries + 1),
sizeof(E4INFO_REPORT) *small_entries ) ;
memmove( middle2 + move_positions, middle2, sizeof(E4INFO_REPORT) * middle_entries ) ;
memcpy( (void *)(small2 - large_entries + 1), save_buf, sizeof(E4INFO_REPORT) * large_entries ) ;
}
u4free( save_buf ) ;
return 0 ;
}
/* Must read in records, as appropriate, to evaluate the different parts of */
/* the expression. */
int S4FUNCTION log4true( L4LOGICAL *log )
{
int cur_pos, rc, i, *result_ptr ;
E4INFO *info_ptr ;
E4INFO_REPORT *info_report_ptr ;
int n_parms = 1 ;
cur_pos = log->expr->info_n - 1 ;
if( log->expr->info[cur_pos].function_i == E4AND )
{
n_parms = log->expr->info[cur_pos].num_parms ;
cur_pos-- ;
}
/* Go through each of the & sub-expressions and evaluate them, first */
/* reading in the appropriate database records for the sub-expression. */
for( i = 0; i < n_parms; i++ )
{
info_ptr = log->expr->info + cur_pos ;
info_report_ptr = log->info_report + cur_pos ;
rc = data_list4read_records( info_report_ptr->data_list ) ;
if ( rc == relate4filter_record )
return 0 ;
if ( rc == r4terminate )
return rc ;
if ( rc < 0 )
return -1 ;
if ( log->expr->info[cur_pos].num_parms < 2 )
{
if ( expr4execute( log->expr, cur_pos, (void **)&result_ptr ) < 0 )
return -1 ;
if ( *result_ptr == 0 )
return 0 ;
}
else
{
#ifdef S4TEST
#ifdef S4DEBUG
/* in debug case, if tag, the result must always be true if we get here... */
if ( log->code_base->bitmap_disable == 0 && !log->relation->bitmaps_freed ) /* then do check */
{
if ( expr4execute( log->expr, cur_pos, (void **)&result_ptr ) < 0 )
return -1 ;
if ( ( (info_report_ptr-1)->tag || (info_report_ptr-2)->tag ) )
if ( *result_ptr == 0 )
e4severe( e4info, E4_LOG4TRUE ) ;
}
#endif
#endif
if ( ( (info_report_ptr-1)->tag == 0 && (info_report_ptr-2)->tag == 0 ) || log->relation->bitmaps_freed )
{
if ( expr4execute( log->expr, cur_pos, (void **)&result_ptr ) < 0 )
return -1 ;
if ( *result_ptr == 0 )
return 0 ;
}
}
cur_pos -= info_ptr->num_entries ;
}
if ( log->code_base->error_code < 0 )
return -1 ;
return 1 ;
}