home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1986 Alan Kent
- *
- * Permission is granted to freely distribute part or
- * all of this code as long as it is not for profit
- * and this message is retained in the code.
- *
- * No resposibility is taken for any damage or incorect
- * results this program generates.
- *
- */
-
-
- #include <stdio.h>
- #include "graph.h"
-
-
- extern char *new ();
- extern table_st *new_table ();
-
-
- table_st *
- join ( tab1 , tab2 , attr1 , attr2 )
- table_st *tab1 , *tab2;
- int attr1 , attr2;
- {
- double floor ();
-
- int i , j , j0 , newsize , ni;
- int free1 , free2;
- double *data1 , *data2;
- table_st *newtab , *pcol , *pcol1 , *pcol2;
-
-
- if ( attr1 == 0 ) {
-
- /* to make life easy, create a dummy array for $0 */
-
- data1 = (double *) new ( sizeof ( double ) * tab1->size );
- for ( i = 0; i < tab1->size; i++ )
- data1[i] = i + 1;
- free1 = 1;
- }
- else {
-
- /* look for column in table */
-
- for ( i = 1, pcol1 = tab1; pcol1 != NULL && i != attr1; pcol1 = pcol1->next, i++ );
- if ( pcol1 == NULL )
- abort ( "Illegal attribute selected for join" );
- data1 = pcol1->data;
- free1 = 0;
- }
-
- if ( attr2 == 0 ) {
-
- /* to make life easy, create a dummy array for $0 */
-
- data2 = (double *) new ( sizeof ( double ) * tab2->size );
- for ( i = 0; i < tab2->size; i++ )
- data2[i] = i + 1;
- free2 = 1;
- }
- else {
-
- /* look for column in table */
-
- for ( i = 1, pcol2 = tab2; pcol2 != NULL && i != attr2; pcol2 = pcol2->next, i++ );
- if ( pcol2 == NULL )
- abort ( "Illegal attribute selected for join" );
- data2 = pcol2->data;
- free2 = 0;
- }
-
- /* check that data has been sorted on join field, and if not, sort it */
-
- for ( i = 0; i < tab1->size - 1; i++ ) {
- if ( data1[i] > data1[i+1] ) {
- sort ( tab1 , attr1 );
- break;
- }
- }
- for ( i = 0; i < tab2->size - 1; i++ ) {
- if ( data2[i] > data2[i+1] ) {
- sort ( tab2 , attr2 );
- break;
- }
- }
-
- /* determine how big the final table will be */
-
- i = 0;
- j0 = 0;
- newsize = 0;
- for ( i = 0; i < tab1->size; i++ ) {
- while ( j0 < tab2->size && data1[i] > data2[j0] )
- j0++;
- for ( j = j0; j < tab2->size && data1[i] == data2[j]; j++ ) {
- newsize++;
- }
- }
-
- /* ok, build the new table */
-
- newtab = new_table ( num_cols ( tab1 ) + num_cols ( tab2 ) , newsize );
-
- /* now do the join */
-
- i = 0;
- j0 = 0;
- ni = 0;
- for ( i = 0; i < tab1->size; i++ ) {
- while ( j0 < tab2->size && data1[i] > data2[j0] ) {
- j0++;
- }
- for ( j = j0; j < tab2->size && data1[i] == data2[j]; j++ ) {
- pcol = newtab;
- for ( pcol1 = tab1; pcol1 != NULL; pcol1 = pcol1->next ) {
- pcol->data[ni] = pcol1->data[i];
- pcol = pcol->next;
- }
- for ( pcol2 = tab2; pcol2 != NULL; pcol2 = pcol2->next ) {
- pcol->data[ni] = pcol2->data[j];
- pcol = pcol->next;
- }
- ni++;
- }
- }
- if ( ni != newsize )
- abort ( "Internal error in JOIN - pass 2 returns different size than pass 1" );
-
- /* free up and return */
-
- free_table ( tab1 );
- free_table ( tab2 );
- if ( free1 )
- release ( data1 );
- if ( free2 )
- release ( data2 );
- return ( newtab );
- }
-
-