/** * @author Matija Šestak. * @brief Function that fetches all values in some column and put on the list * @param num zero-based column index * @param *tblName table name * @return column values list */ struct list_node *AK_get_column(int num, char *tblName) { AK_PRO; int num_attr = AK_num_attr(tblName); if (num >= num_attr || num < 0){ AK_EPI; return NULL; } struct list_node *row_root = (struct list_node *) AK_malloc(sizeof (struct list_node)); Ak_Init_L3(&row_root); table_addresses *addresses = (table_addresses*) AK_get_table_addresses(tblName); int i, j, k; char data[ MAX_VARCHAR_LENGTH ]; i = 0; while (addresses->address_from[i] != 0) { for (j = addresses->address_from[i]; j < addresses->address_to[i]; j++) { AK_mem_block *temp = (AK_mem_block*) AK_get_block(j); if (temp->block->last_tuple_dict_id == 0) break; for (k = num; k < DATA_BLOCK_SIZE; k += num_attr) { if (temp->block->tuple_dict[k].type != FREE_INT) { int type = temp->block->tuple_dict[k].type; int size = temp->block->tuple_dict[k].size; int address = temp->block->tuple_dict[k].address; memcpy(data, &(temp->block->data[address]), size); data[ size ] = '\0'; Ak_InsertAtEnd_L3(type, data, size, row_root); } } } i++; } AK_EPI; return row_root; }
/** * @author Matija Šestak. * @brief Function that determines the number of rows in the table * <ol> * <li>Read addresses of extents</li> * <li>If there is no extents in the table, return EXIT_WARNING</li> * <li>For each extent from table</li> * <li>For each block in the extent</li> * <li>Get a block</li> * <li>Exit if there is no records in block</li> * <li>Count tuples in block</li> * <li>Return the number of tuples divided by number of attributes</li> * </ol> * @param *tableName table name * @return number of rows in the table */ int AK_get_num_records(char *tblName) { int num_rec = 0; AK_PRO; table_addresses *addresses = (table_addresses*) AK_get_table_addresses(tblName); if (addresses->address_from[0] == 0){ AK_EPI; return EXIT_WARNING; } int i = 0, j, k; AK_mem_block *temp = (AK_mem_block*) AK_get_block(addresses->address_from[0]); while (addresses->address_from[ i ] != 0) { for (j = addresses->address_from[ i ]; j < addresses->address_to[ i ]; j++) { temp = (AK_mem_block*) AK_get_block(j); if (temp->block->last_tuple_dict_id == 0) break; for (k = 0; k < DATA_BLOCK_SIZE; k++) { if (temp->block->tuple_dict[ k ].size > 0) { num_rec++; } } } i++; } AK_free(addresses); int num_head = AK_num_attr(tblName); AK_EPI; return num_rec / num_head; }
/** * @author Matija Šestak. * @brief Function that fetches a value in some row and column * @param row zero-based row index * @param column zero-based column index * @param *tblName table name * @return value in the list */ struct list_node *AK_get_tuple(int row, int column, char *tblName) { AK_PRO; int num_rows = AK_get_num_records(tblName); int num_attr = AK_num_attr(tblName); if (row >= num_rows || column >= num_attr){ AK_EPI; return NULL; } table_addresses *addresses = (table_addresses*) AK_get_table_addresses(tblName); struct list_node *row_root = (struct list_node *) AK_malloc(sizeof (struct list_node)); Ak_Init_L3(&row_root); int i, j, k, counter; char data[ MAX_VARCHAR_LENGTH ]; i = 0; counter = -1; while (addresses->address_from[ i ] != 0) { for (j = addresses->address_from[ i ]; j < addresses->address_to[ i ]; j++) { AK_mem_block *temp = (AK_mem_block*) AK_get_block(j); if (temp->block->last_tuple_dict_id == 0) break; for (k = 0; k < DATA_BLOCK_SIZE; k += num_attr) { if (temp->block->tuple_dict[k].size > 0) counter++; if (counter == row) { struct list_node *next; int type = temp->block->tuple_dict[ k + column ].type; int size = temp->block->tuple_dict[ k + column ].size; int address = temp->block->tuple_dict[ k + column ].address; memcpy(data, &(temp->block->data[address]), size); data[ size ] = '\0'; Ak_InsertAtEnd_L3(type, data, size, row_root); AK_free(addresses); next = Ak_First_L2(row_root); //store next AK_free(row_root); //now we can free base AK_EPI; //returns next in row_root leaving base of the list allocated, so we made some corrections //return (struct list_node *) Ak_First_L2(row_root); return next; //returns next } } } i++; } AK_free(addresses); Ak_DeleteAll_L3(&row_root); AK_free(row_root); AK_EPI; return NULL; }
/** * @author Matija Šestak. * @brief Function that fetches attribute name for some zero-based index * @param *tblName table name * @param index zero-based index * @return attribute name */ char *AK_get_attr_name(char *tblName, int index) { AK_PRO; int num_attr = AK_num_attr(tblName); if (index >= num_attr){ AK_EPI; return NULL; } else { AK_header *header = AK_get_header(tblName); AK_EPI; return (header + index)->att_name; } AK_EPI; }
/** * @author Matija Šestak. * @brief Function that fetches the table header * <ol> * <li>Read addresses of extents</li> * <li>If there is no extents in the table, return 0</li> * <li>else read the first block</li> * <li>allocate array</li> * <li>copy table header to the array</li> * </ol> * @param *tblName table name * @result array of table header */ AK_header *AK_get_header(char *tblName) { AK_PRO; table_addresses *addresses = (table_addresses*) AK_get_table_addresses(tblName); if (addresses->address_from[0] == 0){ AK_EPI; return EXIT_WARNING + 2; } AK_mem_block *temp = (AK_mem_block*) AK_get_block(addresses->address_from[0]); int num_attr = AK_num_attr(tblName); AK_header *head = (AK_header*) AK_calloc(num_attr, sizeof (AK_header)); memcpy(head, temp->block->header, num_attr * sizeof (AK_header)); AK_free(addresses); AK_EPI; return head; }
char* AK_get_table_atribute_types(char* tblName){ int len_attr, num_attr, next_attr, attr_type; int next_address = 0; char attr_buffer[4]; AK_PRO; num_attr = AK_num_attr(tblName); if (num_attr == EXIT_WARNING) { AK_EPI; return NULL; } char *attr = (char *) AK_calloc(1, sizeof (char)); AK_header *table_header = (AK_header *) AK_get_header(tblName); for (next_attr = 0; next_attr < num_attr; next_attr++) { attr_type = (table_header + next_attr)->type; len_attr = sprintf(attr_buffer,"%d",attr_type); attr = (char *) AK_realloc(attr, len_attr + next_address + 1); memcpy(attr + next_address, attr_buffer, len_attr); next_address += len_attr; if (next_attr < num_attr - 1) { memcpy(attr + next_address, ATTR_DELIMITER, 1); next_address++; } else { memcpy(attr + next_address, "\0", 1); } } AK_free(table_header); if (next_address > 0) { AK_EPI; return attr; } else { AK_free(attr); AK_EPI; return NULL; } AK_EPI; }
/** * @author Markus Schatten, Matija Šestak. * @brief Function that fetches all values in some row and put on the list * @param num zero-based row index * @param * tblName table name * @return row values list */ struct list_node *AK_get_row(int num, char * tblName) { AK_PRO; table_addresses *addresses = (table_addresses*) AK_get_table_addresses(tblName); struct list_node *row_root = (struct list_node *)AK_calloc(1, sizeof (struct list_node)); Ak_Init_L3(&row_root); int num_attr = AK_num_attr(tblName); int i, j, k, l, counter; i = 0; char data[MAX_VARCHAR_LENGTH]; counter = -1; while (addresses->address_from[i] != 0) { for (j = addresses->address_from[i]; j < addresses->address_to[i]; j++) { AK_mem_block *temp = (AK_mem_block*) AK_get_block(j); if (temp->block->last_tuple_dict_id == 0) break; for (k = 0; k < DATA_BLOCK_SIZE; k += num_attr) { if (temp->block->tuple_dict[k].size > 0) counter++; if (counter == num) { for (l = 0; l < num_attr; l++) { int type = temp->block->tuple_dict[k + l].type; int size = temp->block->tuple_dict[k + l].size; int address = temp->block->tuple_dict[k + l].address; memcpy(data, &(temp->block->data[address]), size); data[size] = '\0'; Ak_InsertAtEnd_L3(type, data, size, row_root); } AK_free(addresses); AK_EPI; return row_root; } } } i++; } AK_free(addresses); Ak_DeleteAll_L3(&row_root); AK_free(row_root); AK_EPI; return NULL; }
/** * @author Dino Laktašić. * @brief Get attributes for a given table and store them to the char array * <ol> * <li>Get the number of attributes in a given table</li> * <li>If there is no attributes return NULL</li> * <li>Get the table header for a given table</li> * <li>Initialize struct list_node</li> * <li>For each attribute in table header, insert attribute in the array</li> * <li>Delimit each new attribute with ";" (ATTR_DELIMITER)</li> * <li>return pointer to char array</li> * </ol> * @param *tblName name of the table * @result pointer to char array */ char *AK_rel_eq_get_atrributes_char(char *tblName) { int len_attr, num_attr, next_attr; int next_address = 0; char *attr_name; AK_PRO; num_attr = AK_num_attr(tblName); if (num_attr == -1) { AK_EPI; return NULL; } char *attr = (char *) AK_calloc(1, sizeof (char)); AK_header *table_header = (AK_header *) AK_get_header(tblName); for (next_attr = 0; next_attr < num_attr; next_attr++) { attr_name = (table_header + next_attr)->att_name; len_attr = strlen(attr_name); attr = (char *) AK_realloc(attr, len_attr + next_address + 1); memcpy(attr + next_address, attr_name, len_attr); next_address += len_attr; if (next_attr < num_attr - 1) { memcpy(attr + next_address, ATTR_DELIMITER, 1); next_address++; } else { memcpy(attr + next_address, "\0", 1); } } AK_free(table_header); if (next_address > 0) { AK_EPI; return attr; } else { AK_free(attr); AK_EPI; return NULL; } }
/** * @author Matija Šestak. * @brief Function that fetches zero-based index for atrribute * @param *tblName table name * @param *attrName attribute name * @return zero-based index */ int AK_get_attr_index(char *tblName, char *attrName) { AK_PRO; if (tblName == NULL || attrName == NULL){ AK_EPI; return EXIT_WARNING; } int num_attr = AK_num_attr(tblName); AK_header *header = AK_get_header(tblName); int index = 0; while (index < num_attr) { if (strcmp(attrName, (header + index)->att_name) == 0) { AK_free(header); AK_EPI; return index; } index++; } AK_free(header); AK_EPI; return EXIT_WARNING; }
/** * @author Dino Laktašić and Mislav Čakarić (replaced old print table function by new one) * update by Luka Rajcevic * @brief Function that prints a table * @param *tblName table name * @return No return value * update by Anto Tomaš (corrected the Ak_DeleteAll_L3 function) */ void AK_print_table_to_file(char *tblName) { char* FILEPATH = "table_test.txt"; FILE *fp; AK_PRO; fp = fopen(FILEPATH, "a"); table_addresses *addresses = (table_addresses*) AK_get_table_addresses(tblName); if (addresses->address_from[0] == 0) { fprintf(fp, "Table %s does not exist!\n", tblName); } else { AK_header *head = AK_get_header(tblName); int i, j, k, l; int num_attr = AK_num_attr(tblName); int num_rows = AK_get_num_records(tblName); int len[num_attr]; //max length for each attribute in row int length = 0; //length of spacer //store lengths of header attributes for (i = 0; i < num_attr; i++) { len[i] = strlen((head + i)->att_name); } //for each header attribute iterate through all table rows and check if //there is longer element than previously longest and store it in array for (i = 0; i < num_attr; i++) { for (j = 0; j < num_rows; j++) { struct list_node *el = AK_get_tuple(j, i, tblName); switch (el->type) { case TYPE_INT: length = AK_chars_num_from_number(*((int *) (el)->data), 10); if (len[i] < length) { len[i] = length; } break; case TYPE_FLOAT: length = AK_chars_num_from_number(*((float *) (el)->data), 10); if (len[i] < length) { len[i] = length; } break; case TYPE_VARCHAR: default: if (len[i] < el->size) { len[i] = el->size; } break; } } } //num_attr is number of char | + space in printf //set offset to change the box size length = 0; for (i = 0; i < num_attr; length += len[i++]); length += num_attr * TBL_BOX_OFFSET + 2 * num_attr + 1; fprintf(fp, "Table: %s\n", tblName); if (num_attr <= 0 || num_rows <= 0) { fprintf(fp, "Table is empty.\n"); } else { //print table header fclose(fp); AK_print_row_spacer_to_file(len, length); fp = fopen(FILEPATH, "a"); fprintf(fp, "\n|"); for (i = 0; i < num_attr; i++) { //print attributes center aligned inside box k = (len[i] - (int) strlen((head + i)->att_name) + TBL_BOX_OFFSET + 1); if (k % 2 == 0) { k /= 2; fprintf(fp, "%-*s%-*s|", k, " ", k + (int) strlen((head + i)->att_name), (head + i)->att_name); } else { k /= 2; fprintf(fp, "%-*s%-*s|", k, " ", k + (int) strlen((head + i)->att_name) + 1, (head + i)->att_name); } //print attributes left aligned inside box //printf(" %-*s|", len[i] + MAX_TABLE_BOX_OFFSET, (head + i)->att_name); } fprintf(fp, "\n"); fclose(fp); AK_print_row_spacer_to_file(len, length); struct list_node *row_root = (struct list_node *) AK_malloc(sizeof (struct list_node)); Ak_Init_L3(&row_root); i = 0; int type, size, address; while (addresses->address_from[i] != 0) { for (j = addresses->address_from[i]; j < addresses->address_to[i]; j++) { AK_mem_block *temp = (AK_mem_block*) AK_get_block(j); if (temp->block->last_tuple_dict_id == 0) break; for (k = 0; k < DATA_BLOCK_SIZE; k += num_attr) { if (temp->block->tuple_dict[k].size > 0) { for (l = 0; l < num_attr; l++) { type = temp->block->tuple_dict[k + l].type; size = temp->block->tuple_dict[k + l].size; address = temp->block->tuple_dict[k + l].address; Ak_InsertAtEnd_L3(type, &(temp->block->data[address]), size, row_root); } AK_print_row_to_file(len, row_root); AK_print_row_spacer_to_file(len, length); Ak_DeleteAll_L3(&row_root); } } } i++; } fp = fopen(FILEPATH, "a"); fprintf(fp, "\n"); } } fclose(fp); AK_EPI; }
/** * @author Dino Laktašić and Mislav Čakarić (replaced old print table function by new one) * @brief Function for printing table * @param *tblName table name * @return No return value */ void AK_print_table(char *tblName) { AK_PRO; table_addresses *addresses = (table_addresses*) AK_get_table_addresses(tblName); // || (AK_table_exist(tblName) == 0) if ((addresses->address_from[0] == 0) || (AK_table_exist(tblName) == 0)) { printf("Table %s does not exist!\n", tblName); AK_free(addresses); } else { AK_header *head = AK_get_header(tblName); int i, j, k, l; int num_attr = AK_num_attr(tblName); int num_rows = AK_get_num_records(tblName); int len[num_attr]; //max length for each attribute in row int length = 0; //length of spacer clock_t t; //store lengths of header attributes for (i = 0; i < num_attr; i++) { len[i] = strlen((head + i)->att_name); } //for each header attribute iterate through all table rows and check if //there is longer element than previously longest and store it in array for (i = 0; i < num_attr; i++) { for (j = 0; j < num_rows; j++) { struct list_node *el = AK_get_tuple(j, i, tblName); switch (el->type) { case TYPE_INT: length = AK_chars_num_from_number(*((int *) (el)->data), 10); if (len[i] < length) { len[i] = length; } break; case TYPE_FLOAT: length = AK_chars_num_from_number(*((float *) (el)->data), 10); if (len[i] < length) { len[i] = length; } break; case TYPE_VARCHAR: default: if (len[i] < el->size) { len[i] = el->size; } break; } //we don't need this linked list anymore (starting from tupple first to the end //see comment above in function AK_get_tuple - Elvis Popovic Ak_DeleteAll_L3(&el); AK_free(el); } } //num_attr is number of char | + space in printf //set offset to change the box size length = 0; for (i = 0; i < num_attr; length += len[i++]); length += num_attr * TBL_BOX_OFFSET + 2 * num_attr + 1; //start measuring time t = clock(); printf("Table: %s\n", tblName); if (num_attr <= 0 || num_rows <= 0) { printf("Table is empty.\n"); } else { //print table header AK_print_row_spacer(len, length); printf("\n|"); for (i = 0; i < num_attr; i++) { //print attributes center aligned inside box k = (len[i] - (int) strlen((head + i)->att_name) + TBL_BOX_OFFSET + 1); if (k % 2 == 0) { k /= 2; printf("%-*s%-*s|", k, " ", k + (int) strlen((head + i)->att_name), (head + i)->att_name); } else { k /= 2; printf("%-*s%-*s|", k, " ", k + (int) strlen((head + i)->att_name) + 1, (head + i)->att_name); } //print attributes left aligned inside box //printf(" %-*s|", len[i] + MAX_TABLE_BOX_OFFSET, (head + i)->att_name); } AK_free(head); printf("\n"); AK_print_row_spacer(len, length); struct list_node *row_root = (struct list_node *) AK_malloc(sizeof (struct list_node)); Ak_Init_L3(&row_root); i = 0; int type, size, address; while (addresses->address_from[i] != 0) { for (j = addresses->address_from[i]; j < addresses->address_to[i]; j++) { AK_mem_block *temp = (AK_mem_block*) AK_get_block(j); if (temp->block->last_tuple_dict_id == 0) break; for (k = 0; k < DATA_BLOCK_SIZE; k += num_attr) { if (temp->block->tuple_dict[k].size > 0 /*&& k / num_attr < num_rows*/) { for (l = 0; l < num_attr; l++) { type = temp->block->tuple_dict[k + l].type; size = temp->block->tuple_dict[k + l].size; address = temp->block->tuple_dict[k + l].address; Ak_InsertAtEnd_L3(type, &temp->block->data[address], size, row_root); } AK_print_row(len, row_root); AK_print_row_spacer(len, length); Ak_DeleteAll_L3(&row_root); } } } i++; } printf("\n"); t = clock() - t; if ((((double) t) / CLOCKS_PER_SEC) < 0.1) { printf("%i rows found, duration: %f μs\n", num_rows, ((double) t) / CLOCKS_PER_SEC * 1000); } else { printf("%i rows found, duration: %f s\n", num_rows, ((double) t) / CLOCKS_PER_SEC); } AK_free(row_root); } AK_free(addresses); } AK_EPI; }
/** * @author Unknown * @brief Function for testing table abstraction * @return No return value @update by Ana-Marija Balen - added getRow function to the test */ TestResult AK_table_test() { AK_PRO; printf("table.c: Present!\n"); printf("\n********** TABLE ABSTRACTION TEST by Matija Šestak **********\n\n"); printf("Table \"student\":AK_print_table\n"); AK_print_table("student"); printf("\n"); printf("Table \"student\": AK_table_empty: "); if (AK_table_empty("student")) printf("true\n"); else printf("false\n"); printf("\n"); printf("Table \"student\": AK_num_attr: "); printf("%d\n", AK_num_attr("student")); printf("\n"); int get_num_records; printf("Table \"student\": AK_get_num_records: "); printf("%d\n", get_num_records = AK_get_num_records("student")); printf("\n"); printf("Table \"student\": AK_get_row: "); int i; AK_header *head = AK_get_header("student"); int num_attr = AK_num_attr("student"); int len[num_attr]; for (i = 0; i < num_attr; i++) { len[i] = strlen((head + i)->att_name); } AK_print_row(len, AK_get_row(0,"student")); printf("\n"); printf("Table \"student\": AK_get_attr_name for index 3: "); int get_attr_name; printf("%s\n", get_attr_name = AK_get_attr_name("student", 3)); printf("\n"); int get_attr_index; printf("Table \"student\": AK_get_attr_index of \"year\": "); printf("%d\n", get_attr_index = AK_get_attr_index("student", "year")); printf("\n"); int tuple_to_string; printf("Table \"student\": AK_get_tuple for row=0, column=1:"); printf("%s\n", tuple_to_string = AK_tuple_to_string(AK_get_tuple(0, 1, "student"))); if (get_num_records != EXIT_WARNING & get_attr_name != NULL & get_attr_index != EXIT_WARNING & tuple_to_string != NULL) { printf("\nTest succeeded!\n"); } else{ printf("\nTest failed!\n"); } AK_EPI; return TEST_result(0,0); }
/** * @author Dino Laktašić. * @brief Function for testing rel_eq_selection * @return No return value */ void AK_rel_eq_selection_test() { AK_PRO; printf("rel_eq_selection.c: Present!\n"); printf("\n********** REL_EQ_SELECTION TEST by Dino Laktašić **********\n"); //create header AK_header t_header[MAX_ATTRIBUTES]; AK_header *temp; temp = (AK_header*) AK_create_header("id", TYPE_INT, FREE_INT, FREE_CHAR, FREE_CHAR); memcpy(t_header, temp, sizeof (AK_header)); temp = (AK_header*) AK_create_header("firstname", TYPE_VARCHAR, FREE_INT, FREE_CHAR, FREE_CHAR); memcpy(t_header + 1, temp, sizeof (AK_header)); temp = (AK_header*) AK_create_header("job", TYPE_VARCHAR, FREE_INT, FREE_CHAR, FREE_CHAR); memcpy(t_header + 2, temp, sizeof (AK_header)); temp = (AK_header*) AK_create_header("year", TYPE_INT, FREE_INT, FREE_CHAR, FREE_CHAR); memcpy(t_header + 3, temp, sizeof (AK_header)); temp = (AK_header*) AK_create_header("tezina", TYPE_FLOAT, FREE_INT, FREE_CHAR, FREE_CHAR); memcpy(t_header + 4, temp, sizeof (AK_header)); memset(t_header + 5, '\0', MAX_ATTRIBUTES - 5); //create table char *tblName = "profesor"; int startAddress = AK_initialize_new_segment(tblName, SEGMENT_TYPE_TABLE, t_header); if (startAddress != EXIT_ERROR) printf("\nTABLE %s CREATED!\n", tblName); printf("rel_eq_selection_test: After segment initialization: %d\n", AK_num_attr(tblName)); //create header AK_header t_header2[MAX_ATTRIBUTES]; AK_header *temp2; temp2 = (AK_header*) AK_create_header("mbr", TYPE_INT, FREE_INT, FREE_CHAR, FREE_CHAR); memcpy(t_header2, temp2, sizeof (AK_header)); temp2 = (AK_header*) AK_create_header("firstname", TYPE_VARCHAR, FREE_INT, FREE_CHAR, FREE_CHAR); memcpy(t_header2 + 1, temp2, sizeof (AK_header)); temp2 = (AK_header*) AK_create_header("lastname", TYPE_VARCHAR, FREE_INT, FREE_CHAR, FREE_CHAR); memcpy(t_header2 + 2, temp2, sizeof (AK_header)); temp2 = (AK_header*) AK_create_header("year", TYPE_INT, FREE_INT, FREE_CHAR, FREE_CHAR); memcpy(t_header2 + 3, temp2, sizeof (AK_header)); temp2 = (AK_header*) AK_create_header("weight", TYPE_FLOAT, FREE_INT, FREE_CHAR, FREE_CHAR); memcpy(t_header2 + 4, temp2, sizeof (AK_header)); memset(t_header2 + 5, '\0', MAX_ATTRIBUTES - 5); //create table char *tblName2 = "student"; int startAddress2 = AK_initialize_new_segment(tblName2, SEGMENT_TYPE_TABLE, t_header2); if (startAddress2 != EXIT_ERROR) printf("\nTABLE %s CREATED!\n", tblName2); printf("rel_eq_selection_test: After segment initialization: %d\n", AK_num_attr(tblName2)); //----------------------------------------------------------------------------------------- //Init list and insert elements (Query parser output) struct list_node *expr = (struct list_node *) AK_malloc(sizeof (struct list_node)); Ak_Init_L3(&expr); //Commutativity of Selection and Projection Ak_InsertAtEnd_L3(TYPE_OPERATOR, "s", sizeof ("s"), expr); Ak_InsertAtEnd_L3(TYPE_CONDITION, "`L1` 100 >", sizeof ("`L1` 100 >"), expr); Ak_InsertAtEnd_L3(TYPE_OPERATOR, "p", sizeof ("p"), expr); Ak_InsertAtEnd_L3(TYPE_ATTRIBS, "L1;L2;L3;L4", sizeof ("L1;L2;L3;L4"), expr); //projection attribute Ak_InsertAtEnd_L3(TYPE_OPERATOR, "p", sizeof ("p"), expr); Ak_InsertAtEnd_L3(TYPE_ATTRIBS, "L1;L4;L3;L2;L5", sizeof ("L1;L4;L3;L2;L5"), expr); //Cascade of Selection and Commutativity of Selection Ak_InsertAtEnd_L3(TYPE_OPERATOR, "s", sizeof ("s"), expr); Ak_InsertAtEnd_L3(TYPE_CONDITION, "`L1` 100 >", sizeof ("`L1` 100 >"), expr); // //Commutativity of Selection and set operations (Union, Intersection, and Set difference) Ak_InsertAtEnd_L3(TYPE_OPERATOR, "s", sizeof ("s"), expr); Ak_InsertAtEnd_L3(TYPE_CONDITION, "`L2` 100 > `L3` 50 < OR", sizeof ("`L2` 100 > `L3` 50 < OR"), expr); Ak_InsertAtEnd_L3(TYPE_OPERAND, "R", sizeof ("R"), expr); Ak_InsertAtEnd_L3(TYPE_OPERAND, "S", sizeof ("S"), expr); Ak_InsertAtEnd_L3(TYPE_OPERATOR, "u", sizeof ("u"), expr); //u, i, e //Commutativity of Selection and Theta join (or Cartesian product) Ak_InsertAtEnd_L3(TYPE_OPERATOR, "s", sizeof ("s"), expr); Ak_InsertAtEnd_L3(TYPE_CONDITION, "`job` 'teacher' = `mbr` 50 < AND", sizeof ("`job` 'teacher' = `mbr` 50 < AND"), expr); Ak_InsertAtEnd_L3(TYPE_OPERAND, "student", sizeof ("student"), expr); Ak_InsertAtEnd_L3(TYPE_OPERAND, "profesor", sizeof ("profesor"), expr); Ak_InsertAtEnd_L3(TYPE_OPERATOR, "t", sizeof ("t"), expr); Ak_InsertAtEnd_L3(TYPE_CONDITION, "`mbr` 50 = `job` 'teacher' = AND", sizeof ("`mbr` 50 = `job` 'teacher' = AND"), expr); //theta join attribute //printf("\nRA expr. before rel_eq optimization:\n"); //AK_print_rel_eq_projection(expr); AK_print_rel_eq_selection(AK_rel_eq_selection(expr)); if (DEBUG_ALL) { printf("\n------------------> TEST_SELECTION_FUNCTIONS <------------------\n\n"); char *test_cond1, *test_cond2; char *test_table; char *cond_attr1, *cond_attr2; test_table = "profesor"; test_cond1 = "`mbr` 100 > `firstname` 50 < AND `id` 'A' > OR"; test_cond2 = "`id` 100 > `firstname` 50 < AND `job` 'teacher' = AND"; cond_attr1 = AK_rel_eq_cond_attributes(test_cond1); cond_attr2 = AK_rel_eq_cond_attributes(test_cond2); printf("IS_SET_SUBSET_OF_LARGER_SET_TEST: (%i)\n\n", AK_rel_eq_is_attr_subset(cond_attr1, cond_attr2)); printf("GET_ALL_TABLE_ATTRIBUTES_TEST : (%s)\n\n", AK_rel_eq_get_atrributes_char(test_table)); printf("GET_CONDITION_ATTRIBUTES_TEST : (%s)\n\n", AK_rel_eq_cond_attributes(test_cond1)); printf("COMMUTE_WITH_THETA_JOIN_TEST : (%s)\n\n", AK_rel_eq_commute_with_theta_join(test_cond1, test_table)); printf("CONDITION_SHARE_ATTRIBUTES_TEST : (%i)\n", AK_rel_eq_share_attributes(cond_attr1, cond_attr2)); /**/ } else { printf("...\n"); } Ak_DeleteAll_L3(&expr); //dealocate variables ;) AK_EPI; }
//int AK_selection(char *srcTable, char *dstTable, AK_list *expr) { int AK_selection(char *srcTable, char *dstTable, struct list_node *expr) { AK_PRO; AK_header *t_header = (AK_header *) AK_get_header(srcTable); int num_attr = AK_num_attr(srcTable); int startAddress = AK_initialize_new_segment(dstTable, SEGMENT_TYPE_TABLE, t_header); if (startAddress == EXIT_ERROR) { AK_EPI; return EXIT_ERROR; } Ak_dbg_messg(LOW, REL_OP, "\nTABLE %s CREATED from %s!\n", dstTable, srcTable); table_addresses *src_addr = (table_addresses*) AK_get_table_addresses(srcTable); /* AK_list_elem row_root = (AK_list_elem) AK_malloc(sizeof (AK_list)); Ak_Init_L3(&row_root); */ struct list_node * row_root = (struct list_node *) AK_malloc(sizeof(struct list_node)); Ak_Init_L3(&row_root); int i, j, k, l, type, size, address; char data[MAX_VARCHAR_LENGTH]; for (i = 0; src_addr->address_from[i] != 0; i++) { for (j = src_addr->address_from[i]; j < src_addr->address_to[i]; j++) { AK_mem_block *temp = (AK_mem_block *) AK_get_block(j); if (temp->block->last_tuple_dict_id == 0) break; for (k = 0; k < DATA_BLOCK_SIZE; k += num_attr) { if (temp->block->tuple_dict[k].type == FREE_INT) break; for (l = 0; l < num_attr; l++) { type = temp->block->tuple_dict[k + l].type; size = temp->block->tuple_dict[k + l].size; address = temp->block->tuple_dict[k + l].address; memcpy(data, &(temp->block->data[address]), size); data[size] = '\0'; Ak_Insert_New_Element(type, data, dstTable, t_header[l].att_name, row_root); } if (AK_check_if_row_satisfies_expression(row_root, expr)) Ak_insert_row(row_root); Ak_DeleteAll_L3(&row_root); } } } AK_free(src_addr); AK_free(t_header); AK_free(row_root); AK_print_table(dstTable); Ak_dbg_messg(LOW, REL_OP, "SELECTION_TEST_SUCCESS\n\n"); AK_EPI; return EXIT_SUCCESS; }