/* SDB - sort routines */ #include #include "sdbio.h" extern int dbv_token; extern char dbv_tstring[]; extern int dbv_tvalue; #ifdef CPM68K struct scan *db_ropen(); #endif /* get_skeys - get sort key list */ static struct skey *get_skeys(sptr) struct scan *sptr; { struct skey *skeys,*newskey,*lastskey; struct skey *db_nerror(); /* parse a list of attribute names */ skeys = lastskey = NULL; while (TRUE) { /* get attribute name */ if (db_ntoken() != ID) return (db_nerror(SYNTAX)); /* allocate a sort key structure */ if ((newskey = malloc(sizeof(struct skey))) == NULL) return (db_nerror(INSMEM)); /* initialize the sort key structure */ newskey->sk_next = NULL; /* lookup the attribute name */ if (!find_attr(sptr,newskey,dbv_tstring)) { free(newskey); return (NULL); } /* check for ascending or descending */ if (db_token() == ASCENDING || dbv_token == DESCENDING) { newskey->sk_type = dbv_token; db_ntoken(); } else newskey->sk_type = ASCENDING; /* link the sort key structure into the list */ if (lastskey == NULL) skeys = newskey; else lastskey->sk_next = newskey; lastskey = newskey; /* check for more attributes */ if (db_token() != ',') break; db_ntoken(); } /* return successfully */ return (skeys); } /* db_sort - sort tuples in a relation */ int db_sort(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9) char *fmt; { struct scan *sptr1,*sptr2,*sptr3; /*dns*/ struct skey *skeys; int result; /* check for a command line */ if (fmt != NULL) db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9); /* checks for relation name */ if (db_token() == ID) db_ntoken(); else strcpy(dbv_tstring,"sdbcur"); /* open the relation */ if ((sptr1 = db_ropen(dbv_tstring)) == NULL) return (FALSE); if ((sptr2 = db_ropen(dbv_tstring)) == NULL) { db_rclose(sptr1); return (FALSE); } if ((sptr3 = db_ropen(dbv_tstring)) == NULL) { /*dns*/ db_rclose(sptr1); /*dns*/ db_rclose(sptr2); /*dns*/ return (FALSE); /*dns*/ } /* checks for " by " */ if (db_ntoken() != BY) return (db_ferror(SYNTAX)); if ((skeys = get_skeys(sptr1)) == NULL) { db_rclose(sptr1); db_rclose(sptr2); db_rclose(sptr3); /*dns*/ return (FALSE); } /* do the sort */ result = sort(skeys,sptr1,sptr2,sptr3); /*dns*/ /* close the relation */ db_rclose(sptr1); db_rclose(sptr2); db_rclose(sptr3); /*dns*/ /* free the sort keys */ free_skeys(skeys); return (result); } /* free_skeys - free a list of sort keys */ static free_skeys(skeys) struct skey *skeys; { struct skey *thisskey; for (thisskey = skeys; skeys != NULL; thisskey = skeys) { skeys = skeys->sk_next; free(thisskey); } } /* find_attr - find an attribute */ static int find_attr(sptr,newskey,aname) struct scan *sptr; struct skey *newskey; char *aname; { struct attribute *aptr; int i,astart; /* loop through each attribute within the relation */ astart = 1; for (i = 0; i < NATTRS; i++) { /* get a pointer to the current attribute */ aptr = &sptr->sc_relation->rl_header.hd_attrs[i]; /* check for last attribute */ if (aptr->at_name[0] == 0) break; /* check for attribute name match */ if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) { newskey->sk_start = astart; newskey->sk_aptr = aptr; return (TRUE); } /* update the attribute start */ astart += aptr->at_size; } /* attribute name not found */ return (db_ferror(ATUNDF)); } /* sort - sort the relation */ static int sort(skeys,sptr1,sptr2,sptr3) struct skey *skeys; struct scan *sptr1,*sptr2,*sptr3; { /* unsigned int j,k,l,r; dns */ long int passes,swaps; /*dns*/ int i, j, m, n; /*dns*/ int rec1 = 0; /*dns*/ int rec2 = 0; /*dns*/ int rec3 = 0; /*dns*/ int dns = 0; /*dns*/ FILE *test; /*dns*/ passes = 0L; swaps = 0L; /*dns ---> */ test = fopen("sort.dat", "w"); n = sptr1->sc_relation->rl_tcnt; m = n; while( m>1 ) { passes++; if ((m/=3.14159) < 1) m = 1; for ( j=1; j<=n-m; j++ ) { if( rec1 != j+m ) { if(dns) fprintf(test,"Read1: %d\n", j+m); if (!db_rget(sptr1, rec1=j+m)) return (FALSE); } for ( i=j; i>=1; i-=m ) { if( rec2 != i ) { if(dns) fprintf(test,"Read2: %d\n", i); if (!db_rget(sptr2, rec2=i)) return (FALSE); } if (compare(skeys,sptr1,sptr2) > 0) break; if(rec3 != i+m) { if(dns) fprintf(test,"Read3: %d\n", i+m); if (!db_rget(sptr3, rec3=i+m)) return (FALSE); } if(dns) fprintf(test,"Write 3,2: %d from %d\n", i+m, i); assign( sptr3, sptr2 ); swaps++; } if(rec1 != i+m) { if(rec3 != i+m) { if(dns) fprintf(test,"Read 3: %d\n", i+m); if (!db_rget(sptr3, rec3=i+m)) return (FALSE); } if(dns) fprintf(test,"Write 3,1: %d from %d\n", i+m, j+m); assign( sptr3, sptr1 ); swaps++; } } } fclose(test); /* l = 2; r = sptr1->sc_relation->rl_tcnt; k = r; do { for (j = r; j >= l; j--) { if (!db_rget(sptr1,j-1)) return (FALSE); if (!db_rget(sptr2,j)) return (FALSE); if (compare(skeys,sptr1,sptr2) > 0) { swap(sptr1,sptr2); k = j; swaps++; } } l = k + 1; for (j = l; j <= r; j++) { if (!db_rget(sptr1,j-1)) return (FALSE); if (!db_rget(sptr2,j)) return (FALSE); if (compare(skeys,sptr1,sptr2) > 0) { swap(sptr1,sptr2); k = j; swaps++; } } r = k - 1; passes++; } while (l <= r); */ printf("[ Passes: %ld Swaps: %ld ]\n",passes,swaps); return (TRUE); } /* compare - compare two tuples */ static int compare(skeys,sptr1,sptr2) struct skey *skeys; struct scan *sptr1,*sptr2; { struct skey *cskey; int result; for (cskey = skeys; cskey != NULL; cskey = cskey->sk_next) if ((result = cattr(cskey,sptr1,sptr2)) != 0) break; return (result); } /* cattr - compare two attributes */ static int cattr(cskey,sptr1,sptr2) struct skey *cskey; struct scan *sptr1,*sptr2; { int astart,aend,i; astart = cskey->sk_start; aend = astart + cskey->sk_aptr->at_size; for (i = astart; i < aend; i++) if (sptr1->sc_tuple[i] != sptr2->sc_tuple[i]) break; if (i == aend) return (0); if (sptr1->sc_tuple[i] < sptr2->sc_tuple[i]) if (cskey->sk_type == ASCENDING) return (-1); else return (1); else if (cskey->sk_type == ASCENDING) return (1); else return (-1); } /* swap - swap two tuples */ /* dns static int swap(sptr1,sptr2) struct scan *sptr1,*sptr2; { unsigned int tnum1,tnum2; tnum1 = sptr1->sc_atnum; tnum2 = sptr2->sc_atnum; if (!db_rput(sptr1,tnum2)) return (FALSE); if (!db_rput(sptr2,tnum1)) return (FALSE); return (TRUE); } dns */ /* assign - assign one tupple to another */ static int assign(sptr1,sptr2) struct scan *sptr1,*sptr2; { unsigned int tnum1,tnum2; tnum1 = sptr1->sc_atnum; if (!db_rput(sptr2,tnum1)) return (FALSE); return (TRUE); }