attribute attribute_find ( relation rel, char *name) { /* attribute_find * Locates the given attribute, and returns an attribute structure */ attribute catt,ratt; tuple ctuple; word anum; /* Get the first attribute */ /* catt=attribute_findfirst(rel,&attribute_file); */ catt=relation_attribute_readfirst(rel,&ctuple,&anum); /* Whilst the attribute is valid, and the attribute does * not match the search criteria */ while ( (catt!=NULL) && (name!=NULL) && (strcmp(attribute_name(catt),name)!=0) ) { /* Locate the next field */ catt=relation_attribute_readnext(rel,&ctuple,catt,&anum); } /* Check to see if we actually found anything */ if ( (catt!=NULL) && (name!=NULL) && (strcmp(attribute_name(catt),name)==0) ) { /* We're about to destroy the tuple, which will destroy the attribute * we just found. Make a copy quick! */ /* Create a ptr to an attribute structure */ ratt=(attribute_struct *) malloc(sizeof(attribute_struct)); /* Check that the ptr was allocated. */ check_assign(ratt,"attributes.attribute_find(cpy)"); strcpy(attribute_name(ratt),attribute_name(catt)); attribute_type(ratt)=attribute_type(catt); attribute_size(ratt)=attribute_size(catt); attribute_no(ratt)=attribute_no(catt); close_tuple(&ctuple,TUPLE_DISPOSE); /* Return the ptr */ return(ratt); } else { /* Close the tuple */ close_tuple(&ctuple,TUPLE_DISPOSE); /* Return nothing */ return(NULL); } }
void test_sort_1(CuTest *tc) { /* General variable declaration. */ db_query_mm_t mm; char segment[2000]; init_query_mm(&mm, segment, 2000); scan_t scan; sort_t sort; db_tuple_t t; db_eet_t oneExpr[1]; db_uint8 oneOrder[1]; db_eetnode_attr_t attrNode; attrNode.base.type = DB_EETNODE_ATTR; db_int intResult; puts("**********************************************************************"); puts("Test 1: Sort test_rel3 using first attribute in ascending order."); fflush(stdout); oneExpr[0].size = (1*sizeof(db_eetnode_attr_t) + 0*sizeof(db_eetnode_dbint_t)); oneExpr[0].nodes = malloc((size_t)oneExpr[0].size); oneExpr[0].stack_size = oneExpr[0].size; oneOrder[0] = (db_uint8)DB_TUPLE_ORDER_ASC; attrNode.pos = 0; attrNode.tuple_pos = 0; (*((db_eetnode_attr_t*)(oneExpr[0].nodes))) = attrNode; init_scan(&scan, "test_rel3", &mm); init_sort(&sort, (db_op_base_t*)(&scan), oneExpr, 1, oneOrder, &mm); init_tuple(&t, sort.base.header->tuple_size, sort.base.header->num_attr, &mm); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 1 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); //printf("Result of next call: %d\n", intResult); CuAssertTrue(tc, 1 == intResult); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 73 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 0 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 0 == intResult); close((db_op_base_t*)&sort, &mm); close((db_op_base_t*)&scan, &mm); free(oneExpr[0].nodes); close_tuple(&t, &mm); puts("**********************************************************************"); }
/* Close the selection operator. */ db_int close_osijoin(osijoin_t *jp, db_query_mm_t *mmp) { close_tuple(&(jp->ut), mmp); /* Free all header properties that were allocated */ DB_QMM_BFREE(mmp, jp->base.header->size_name); DB_QMM_BFREE(mmp, jp->base.header->names); DB_QMM_BFREE(mmp, jp->base.header->types); DB_QMM_BFREE(mmp, jp->base.header->offsets); DB_QMM_BFREE(mmp, jp->base.header->sizes); DB_QMM_BFREE(mmp, jp->uexpr->nodes); DB_QMM_BFREE(mmp, jp->uexpr); /* Free the header itself. */ DB_QMM_BFREE(mmp, jp->base.header); /* For the time being, do nothing! */ return 1; }
void test_sort_11(CuTest *tc) { /* General variable declaration. */ db_query_mm_t mm; char segment[2000]; init_query_mm(&mm, segment, 2000); scan_t scan; sort_t sort; db_tuple_t t; db_eet_t twoExpr[2]; db_uint8 twoOrder[2]; db_eetnode_attr_t attrNode; attrNode.base.type = DB_EETNODE_ATTR; db_eetnode_t opNode; db_eetnode_t *arr_p; db_int intResult; puts("**********************************************************************"); puts("Test 11: Sort fruit_stock_1 using two complex expressions."); fflush(stdout); twoExpr[0].size = (1*sizeof(db_eetnode_attr_t) + 0*sizeof(db_eetnode_dbstring_t)+ 1*sizeof(db_eetnode_t)); twoExpr[0].nodes = malloc((size_t)twoExpr[0].size); twoExpr[0].stack_size = twoExpr[0].size; twoExpr[1].size = (2*sizeof(db_eetnode_attr_t) + 0*sizeof(db_eetnode_dbint_t)+ 1*sizeof(db_eetnode_t)); twoExpr[1].nodes = malloc((size_t)twoExpr[1].size); twoExpr[1].stack_size = twoExpr[1].size; twoOrder[0] = DB_TUPLE_ORDER_ASC; twoOrder[1] = DB_TUPLE_ORDER_ASC; arr_p = twoExpr[0].nodes; attrNode.pos = 1; attrNode.tuple_pos = 0; (*((db_eetnode_attr_t*)(arr_p))) = attrNode; arr_p = ((db_eetnode_t*)(((db_eetnode_attr_t*)(arr_p))+1)); opNode.type = DB_EETNODE_FUNC_LENGTH_DBSTRING; *arr_p = opNode; arr_p++; arr_p = twoExpr[1].nodes; attrNode.pos = 2; attrNode.tuple_pos = 0; (*((db_eetnode_attr_t*)(arr_p))) = attrNode; arr_p = ((db_eetnode_t*)(((db_eetnode_attr_t*)(arr_p))+1)); attrNode.pos = 3; attrNode.tuple_pos = 0; (*((db_eetnode_attr_t*)(arr_p))) = attrNode; arr_p = ((db_eetnode_t*)(((db_eetnode_attr_t*)(arr_p))+1)); opNode.type = DB_EETNODE_OP_MOD; *arr_p = opNode; arr_p++; init_scan(&scan, "fruit_stock_2", &mm); init_sort(&sort, (db_op_base_t*)(&scan), twoExpr, 2, twoOrder, &mm); init_tuple(&t, sort.base.header->tuple_size, sort.base.header->num_attr, &mm); // TODO: I really should change getintbypos and such to return to an address. intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); CuAssertTrue(tc, (1 << 0) + (1 << 1) + (1 << 2) == t.isnull[0]); //intResult = getintbypos(&t, 0, sort.base.header); //printf("Int value at position %d the tuple: %d\n", 0, intResult); //CuAssertTrue(tc, 3 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); CuAssertTrue(tc, (1 << 1) + (1 << 2) == t.isnull[0]); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 8 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); CuAssertTrue(tc, (1 << 1) == t.isnull[0]); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 3 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); CuAssertTrue(tc, (1 << 0) + (1 << 1) == t.isnull[0]); //intResult = getintbypos(&t, 0, sort.base.header); //printf("Int value at position %d the tuple: %d\n", 0, intResult); //CuAssertTrue(tc, 3 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); CuAssertTrue(tc, (1 << 2) == t.isnull[0]); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 5 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); CuAssertTrue(tc, (1 << 0) + (1 << 2) == t.isnull[0]); //intResult = getintbypos(&t, 0, sort.base.header); //printf("Int value at position %d the tuple: %d\n", 0, intResult); //CuAssertTrue(tc, 3 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); CuAssertTrue(tc, (1 << 0) == t.isnull[0]); //intResult = getintbypos(&t, 0, sort.base.header); //printf("Int value at position %d the tuple: %d\n", 0, intResult); //CuAssertTrue(tc, 3 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); CuAssertTrue(tc, 0 == t.isnull[0]); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 2 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 0 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 0 == intResult); close((db_op_base_t*)&sort, &mm); close((db_op_base_t*)&scan, &mm); close_tuple(&t, &mm); free(twoExpr[0].nodes); free(twoExpr[1].nodes); puts("**********************************************************************"); }
void test_sort_9(CuTest *tc) { /* General variable declaration. */ db_query_mm_t mm; char segment[2000]; init_query_mm(&mm, segment, 2000); scan_t scan; sort_t sort; db_tuple_t t; db_eet_t oneExpr[1]; db_uint8 oneOrder[1]; db_eetnode_attr_t attrNode; attrNode.base.type = DB_EETNODE_ATTR; db_eetnode_t opNode; db_eetnode_t *arr_p; db_int intResult; puts("**********************************************************************"); puts("Test 9: Sort fruit_stock_1 using (3rd > 4th), in descending order."); fflush(stdout); oneExpr[0].size = (2*sizeof(db_eetnode_attr_t) + 0*sizeof(db_eetnode_dbint_t)+ 2*sizeof(db_eetnode_t)); oneExpr[0].nodes = malloc((size_t)oneExpr[0].size); oneExpr[0].stack_size = oneExpr[0].size; oneOrder[0] = DB_TUPLE_ORDER_DESC; arr_p = oneExpr[0].nodes; attrNode.pos = 2; attrNode.tuple_pos = 0; (*((db_eetnode_attr_t*)(arr_p))) = attrNode; arr_p = ((db_eetnode_t*)(((db_eetnode_attr_t*)(arr_p))+1)); attrNode.pos = 3; attrNode.tuple_pos = 0; (*((db_eetnode_attr_t*)(arr_p))) = attrNode; init_scan(&scan, "fruit_stock_1", &mm); init_sort(&sort, (db_op_base_t*)(&scan), oneExpr, 1, oneOrder, &mm); init_tuple(&t, sort.base.header->tuple_size, sort.base.header->num_attr, &mm); opNode.type = DB_EETNODE_OP_GT; *arr_p = opNode; arr_p++; opNode.type = DB_EETNODE_OP_NOT; *arr_p = opNode; arr_p++; intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 1 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 2 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 3 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 4 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 5 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 0 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 0 == intResult); close((db_op_base_t*)&sort, &mm); close((db_op_base_t*)&scan, &mm); close_tuple(&t, &mm); free(oneExpr[0].nodes); puts("**********************************************************************"); }
void test_sort_7(CuTest *tc) { /* General variable declaration. */ db_query_mm_t mm; char segment[2000]; init_query_mm(&mm, segment, 2000); scan_t scan; sort_t sort; db_tuple_t t; db_eet_t twoExpr[2]; db_uint8 twoOrder[2]; db_eetnode_attr_t attrNode; attrNode.base.type = DB_EETNODE_ATTR; db_int intResult; puts("**********************************************************************"); puts("Test 7: Sort fruit_stock_1 using 4th and 3rd attributes, in asc/desc order (respectively)."); fflush(stdout); twoExpr[0].size = (1*sizeof(db_eetnode_attr_t) + 0*sizeof(db_eetnode_dbint_t)); twoExpr[0].nodes = malloc((size_t)twoExpr[0].size); twoExpr[0].stack_size = twoExpr[0].size; twoExpr[1].size = (1*sizeof(db_eetnode_attr_t) + 0*sizeof(db_eetnode_dbint_t)); twoExpr[1].nodes = malloc((size_t)twoExpr[1].size); twoExpr[1].stack_size = twoExpr[1].size; twoOrder[0] = DB_TUPLE_ORDER_ASC; twoOrder[1] = DB_TUPLE_ORDER_DESC; attrNode.pos = 3; attrNode.tuple_pos = 0; (*((db_eetnode_attr_t*)(twoExpr[0].nodes))) = attrNode; attrNode.pos = 2; attrNode.tuple_pos = 0; (*((db_eetnode_attr_t*)(twoExpr[1].nodes))) = attrNode; init_scan(&scan, "fruit_stock_1", &mm); init_sort(&sort, (db_op_base_t*)(&scan), twoExpr, 2, twoOrder, &mm); init_tuple(&t, sort.base.header->tuple_size, sort.base.header->num_attr, &mm); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 3 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 1 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 2 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 5 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 1 == intResult); intResult = getintbypos(&t, 0, sort.base.header); printf("Int value at position %d the tuple: %d\n", 0, intResult); CuAssertTrue(tc, 4 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 0 == intResult); intResult = next((db_op_base_t*)&sort, &t, &mm); CuAssertTrue(tc, 0 == intResult); close((db_op_base_t*)&sort, &mm); close((db_op_base_t*)&scan, &mm); close_tuple(&t, &mm); free(twoExpr[0].nodes); free(twoExpr[1].nodes); puts("**********************************************************************"); }
/* This for now assumes that we are only doing a=b join conditions, where a b are from different relations. */ db_int setup_osijoin(osijoin_t *jp, db_query_mm_t *mmp) { if (NULL == jp->tree || NULL == jp->tree->nodes) return 0; db_int8 rindexed = -1, lindexed = -1; db_eetnode_t *cursor = jp->tree->nodes; db_eetnode_attr_t *lattrp, *rattrp; db_uint8 count = 0, lcount = 0, rcount = 0; // FIXME: See below. /* For now, we'll assume that things need to be indexed on a single attribute. */ /* We also need to make the assumption that this condition only contains stuff for this join specifically. */ while (POINTERBYTEDIST(cursor, jp->tree->nodes) < jp->tree->size) { if (DB_EETNODE_ATTR == cursor->type) { if (1==((db_eetnode_attr_t*)cursor)->tuple_pos) { rattrp = (db_eetnode_attr_t*)cursor; rcount++; rindexed = findindexon((scan_t*)(jp->rchild), rattrp); } else if (0==((db_eetnode_attr_t*)cursor)->tuple_pos) { lattrp = (db_eetnode_attr_t*)cursor; lcount++; lindexed = findindexon((scan_t*)(jp->lchild), lattrp); } else { return 0; } } else if (DB_EETNODE_OP_EQ == cursor->type) { /* Do nothing, these are allowed. */ } else return 0; advanceeetnodepointer(&cursor, 1); count++; } if (3 != count || lcount > 1 || rcount > 1) return 0; db_op_base_t *indexed, *unindexed; jp->bitinfo = 1; if (rindexed < 0) { if (lindexed >= 0) { jp->indexon = (db_uint8)lindexed; indexed = jp->lchild; unindexed = jp->rchild; jp->bitinfo = 0; jp->uexpr = DB_QMM_BALLOC(mmp, sizeof(db_eet_t)); jp->uexpr->size = sizeof(db_eetnode_attr_t); jp->uexpr->nodes = DB_QMM_BALLOC(mmp, sizeof(db_eetnode_attr_t)); *((db_eetnode_attr_t*)(jp->uexpr->nodes)) = *rattrp; ((db_eetnode_attr_t*)(jp->uexpr->nodes))->tuple_pos = 0; /* If our new tuple will not fit in old one, create a new one. */ if ( ((((jp->rchild->header->num_attr) / 8) + ((jp->rchild->header->num_attr) % 8)) > (((jp->lchild->header->num_attr) / 8) + ((jp->lchild->header->num_attr) % 8))) || ((jp->rchild->header->tuple_size) > (jp->lchild->header->tuple_size)) ) { close_tuple(&(jp->ut), mmp); init_tuple(&(jp->ut), jp->rchild->header->num_attr, jp->rchild->header->tuple_size, mmp); next(jp->rchild, &(jp->ut), mmp); } } else return 0; } else { jp->indexon = (db_uint8)rindexed; indexed = jp->rchild; unindexed = jp->lchild; jp->uexpr = DB_QMM_BALLOC(mmp, sizeof(db_eet_t)); jp->uexpr->size = sizeof(db_eetnode_attr_t); jp->uexpr->nodes = DB_QMM_BALLOC(mmp, sizeof(db_eetnode_attr_t)); *((db_eetnode_attr_t*)(jp->uexpr->nodes)) = *lattrp; } rewind_dbop(unindexed, mmp); DB_OSIJOIN_UPDATE_UMORE(jp->bitinfo, next(unindexed, &(jp->ut), mmp)); db_uint8 lvalid = scan_find((scan_t*)indexed, jp->indexon, jp->uexpr, &(jp->ut), unindexed->header, mmp); DB_OSIJOIN_UPDATE_IVALID(jp->bitinfo, lvalid); jp->base.type = DB_OSIJOIN; return 1; }
db_int next_osijoin(osijoin_t *jp, db_tuple_t *next_tp, db_query_mm_t *mmp) { /* Create necessary result variable. */ db_int result = 0; db_tuple_t indexedtuple; /* Build arrays to be passed to eet evaluation engine. Left = 0, Right = 1. */ relation_header_t *hpa[2]; db_tuple_t *tpa[2]; hpa[0] = jp->lchild->header; hpa[1] = jp->rchild->header; // TODO: Reduce memory footprint. db_op_base_t *indexed, *unindexed; db_tuple_t *it; it = &indexedtuple; if (DB_OSIJOIN_RINDEXED(jp->bitinfo)) { unindexed = jp->lchild; indexed = jp->rchild; tpa[0] = &(jp->ut); tpa[1] = it; } else { unindexed = jp->rchild; indexed = jp->lchild; tpa[0] = it; tpa[1] = &(jp->ut); } init_tuple(it, indexed->header->tuple_size, indexed->header->num_attr, mmp); db_uint8 lvalid; while (DB_OSIJOIN_UMORE(jp->bitinfo)) { if (DB_OSIJOIN_IVALID(jp->bitinfo) && 1==next(indexed, it, mmp) && 1==evaluate_eet(jp->tree, &result, tpa, hpa, 0, mmp) && 1==result) { } else { DB_OSIJOIN_UPDATE_UMORE(jp->bitinfo, next(unindexed, &(jp->ut), mmp)); lvalid = scan_find((scan_t*)indexed, jp->indexon, jp->uexpr, &(jp->ut), unindexed->header, mmp); DB_OSIJOIN_UPDATE_IVALID(jp->bitinfo, lvalid); continue; } /*** Do the join by combining the tuples * together. ***/ /* Write out left tuples bytes into new tuple. * */ /* Write out left tuples isnull into new tuple. * */ db_int l_isnullsize = (db_int)(hpa[0]->num_attr) % 8 > 0 ? ((db_int)(hpa[0]->num_attr) / 8) + 1 : ((db_int)(hpa[0]->num_attr) / 8); copytuplebytes(next_tp, tpa[0], 0, 0, hpa[0]->tuple_size); copytupleisnull(next_tp, tpa[0], 0, 0, l_isnullsize); /* Write out right tuples bytes directly after * left tuples bytes. */ copytuplebytes(next_tp, tpa[1], hpa[0]->tuple_size, 0, hpa[1]->tuple_size); /* Write out right tuples isnull into new tuple. * */ db_int i; db_int j = (db_int)(hpa[0]->num_attr); for (i = 0; i < (db_int)(hpa[1]->num_attr); ++i) { /* If this bit is 0 ... */ if (0 == (tpa[1]->isnull[i/8] & (1 << (i % 8)))) { next_tp->isnull[j/8] &= ~(1 << (j % 8)); } else { next_tp->isnull[j/8] |= (1 << (j % 8)); } j++; } close_tuple(it, mmp); return 1; } close_tuple(it, mmp); return 0; }
// FIXME: For now, this assumes equality for each of the expressions. db_index_offset_t db_index_getoffset(scan_t *sp, db_uint8 indexon, db_eet_t *searchfor, db_tuple_t *comparator_tp, relation_header_t *comparator_hp, db_query_mm_t *mmp) { if (sp->idx_meta_data.num_idx <= indexon) return -1; db_index_t index; if (1!=init_index(&index, sp->idx_meta_data.names[indexon])) { return -1; } if (DB_INDEX_TYPE_INLINE == index.type) { long first = sp->tuple_start; size_t total_size = sp->base.header->tuple_size + (sp->base.header->num_attr / 8); total_size += (sp->base.header->num_attr) % 8 > 0 ? 1 : 0; long last; if (sizeof(long)!=db_fileread(index.indexref, (unsigned char*)&(last), sizeof(long))) { return -1; } if (last > 0) last = first + (total_size * (last - 1)); else last = first; long imin = 0; long imax = (last - first) / total_size; long imid; db_uint8 order[sp->idx_meta_data.num_expr[indexon]]; int result; for (result = 0; result < sp->idx_meta_data.num_expr[indexon]; ++result) order[result] = DB_TUPLE_ORDER_ASC; db_tuple_t temp; init_tuple(&temp, sp->base.header->tuple_size, sp->base.header->num_attr, mmp); rewind_scan(sp, mmp); long i = -1; /* We binary search on expressions for first occurence. */ while (imin <= imax) { imid = imin + ((imax - imin) / 2); db_filerewind(sp->relation); db_fileseek(sp->relation, (imid*(total_size))+first); next_scan(sp, &temp, mmp); /* arr[imid], key */ if (NULL == comparator_hp) /* FIXME: quick hack to let indexed scans work. */ { result = getintbypos(&temp, ((db_int)searchfor), sp->base.header) - ((db_int)comparator_tp); } else result = cmp_tuple(&temp, comparator_tp, sp->base.header, comparator_hp, sp->idx_meta_data.exprs[indexon], searchfor, sp->idx_meta_data.num_expr[indexon], order, 1, mmp); if (result < 0) imin = imid + 1; else if (result > 0) imax = imid - 1; else if (imin != imid) imax = imid; else { i = imid; break; } } if (i <= -1) i = imin; i = (first + (i*total_size)); db_filerewind(sp->relation); db_fileseek(sp->relation, i); next_scan(sp, &temp, mmp); /* FIXME: quick hack to let indexed scans work. (first part of the condition) */ if (NULL != comparator_hp && 0!=cmp_tuple(&temp, comparator_tp, sp->base.header, comparator_hp, sp->idx_meta_data.exprs[indexon], searchfor, sp->idx_meta_data.num_expr[indexon], order, 1, mmp)) i = -1; close_tuple(&temp, mmp); close_index(&index); return i; } return -1; }