00001 #include <stdio.h>
00002 #ifndef __USE_ISOC99
00003 #define __USE_ISOC99
00004 #include <stdlib.h>
00005 #undef __USE_ISOC99
00006 #else
00007 #include <stdlib.h>
00008 #endif
00009 #include <string.h>
00010 #include "db.h"
00011 #include "xassert.h"
00012 #include "xmem.h"
00013
00014
00015
00016
00017
00018 static DB_Binary_Result_t *__sort_res;
00019 static int *__sort_cols;
00020 static int __num_sort_cols;
00021 static void db_permute(DB_Binary_Result_t *res, int n, int *p);
00022
00023
00024
00025 int db_type_compare(DB_Type_t type, char *p1, char *p2)
00026 {
00027 switch(type)
00028 {
00029 case DB_CHAR:
00030 return *p1 - *p2;
00031 case DB_INT1:
00032 return *((db_int1_t *) p1) - *((db_int1_t *) p2);
00033 case DB_INT2:
00034 return *((db_int2_t *) p1) - *((db_int2_t *) p2);
00035 case DB_INT4:
00036 return *((db_int4_t *) p1) - *((db_int4_t *) p2);
00037 case DB_INT8:
00038 {
00039 db_int8_t v1, v2;
00040 v1 = *((db_int8_t *) p1);
00041 v2 = *((db_int8_t *) p2);
00042 if (v1<v2)
00043 return -1;
00044 else if (v1>v2)
00045 return 1;
00046 else
00047 return 0;
00048 }
00049 case DB_FLOAT:
00050 {
00051 db_float_t v1, v2;
00052 v1 = *((db_float_t *) p1);
00053 v2 = *((db_float_t *) p2);
00054 if (v1<v2)
00055 return -1;
00056 else if (v1>v2)
00057 return 1;
00058 else
00059 return 0;
00060 }
00061 case DB_DOUBLE:
00062 {
00063 db_double_t v1, v2;
00064 v1 = *((db_double_t *) p1);
00065 v2 = *((db_double_t *) p2);
00066 if (v1<v2)
00067 return -1;
00068 else if (v1>v2)
00069 return 1;
00070 else
00071 return 0;
00072 }
00073 case DB_STRING:
00074 case DB_VARCHAR:
00075 return strcmp(p1,p2);
00076 default:
00077 return 0;
00078 }
00079 return 0;
00080 }
00081
00082
00083
00084 int db_binary_record_compare(DB_Binary_Result_t *res, int num_cols, int *cols,
00085 int i1, int i2)
00086 {
00087 int i;
00088 int col, comp, size;
00089 DB_Type_t type;
00090
00091 if (i1==i2)
00092 return 0;
00093 for (i=0; i<num_cols; i++)
00094 {
00095 col = cols[i];
00096 type = res->column[col].type;
00097 size = res->column[col].size;
00098 comp = db_type_compare(type,
00099 res->column[col].data+i1*size,
00100 res->column[col].data+i2*size);
00101 if (comp)
00102 return comp;
00103 }
00104 return 0;
00105 }
00106
00107
00108 static int qsort_compare(const void *p1, const void *p2)
00109 {
00110 int i1, i2;
00111
00112 i1 = *((int *) p1);
00113 i2 = *((int *) p2);
00114 return db_binary_record_compare(__sort_res, __num_sort_cols, __sort_cols,
00115 i1, i2);
00116 }
00117
00118
00119 int db_sort_binary_result(DB_Binary_Result_t *res, int num_cols, int *cols)
00120 {
00121 int i, permute;
00122 int *p;
00123 int num_rows;
00124
00125
00126 if (!cols || !res || num_cols<0)
00127 return 1;
00128
00129
00130 for (i=0;i<num_cols;i++)
00131 {
00132 if (cols[i]<0 || cols[i]>res->num_cols)
00133 return 1;
00134 }
00135
00136
00137
00138 if (num_cols==0 || res->num_rows==0 )
00139 return 0;
00140
00141 __sort_cols = cols;
00142 __sort_res = res;
00143 __num_sort_cols = num_cols;
00144 num_rows = res->num_rows;
00145 p = malloc(num_rows*sizeof(int));
00146 XASSERT(p);
00147 for (i=0; i<num_rows; i++)
00148 p[i] = i;
00149
00150 qsort(p, num_rows, sizeof(int), qsort_compare);
00151
00152
00153 permute = 0;
00154 for (i=0; i<num_rows; i++)
00155 {
00156 if ( p[i] != i)
00157 {
00158 permute=1;
00159 break;
00160 }
00161 }
00162
00163 if (permute)
00164 db_permute(res, res->num_rows, p);
00165
00166 free(p);
00167 return 0;
00168 }
00169
00170
00171 static void db_permute(DB_Binary_Result_t *res, int n, int *p)
00172 {
00173 int i,j;
00174 char *buf;
00175
00176
00177 for (i=0;i<res->num_cols; i++)
00178 {
00179 buf = malloc(res->column[i].size*n);
00180 XASSERT(buf);
00181 for (j=0; j<n; j++)
00182 memcpy(buf + j*res->column[i].size,
00183 res->column[i].data + p[j]*res->column[i].size,
00184 res->column[i].size);
00185 free(res->column[i].data);
00186 res->column[i].data = buf;
00187 res->column[i].num_rows = n;
00188 }
00189 res->num_rows = n;
00190 }
00191
00192
00193
00194 int db_maxbygroup(DB_Binary_Result_t *res, int maxcol, int num_cols, int *cols)
00195 {
00196 int i, n, *p, max;
00197
00198
00199 if (!cols || !res || num_cols<0)
00200 return 1;
00201
00202 for (i=0; i<num_cols; i++)
00203 if (cols[i] == maxcol)
00204 return 1;
00205
00206
00207
00208 if (db_sort_binary_result(res, num_cols, cols))
00209 return 1;
00210
00211 if (res->num_rows==1)
00212 return 0;
00213
00214
00215 p = malloc(res->num_rows*sizeof(int));
00216 XASSERT(p);
00217 n = 0;
00218 max = 0;
00219 i = 1;
00220 while (i<res->num_rows)
00221 {
00222 while(i<res->num_rows &&
00223 !db_binary_record_compare(res, num_cols, cols, i, max))
00224 {
00225 if (db_binary_record_compare(res, 1, &maxcol, i, max) > 0)
00226 max = i;
00227 i++;
00228 }
00229 p[n++] = max;
00230 max = i++;
00231 if (i==res->num_rows)
00232 p[n++] = max;
00233 }
00234 db_permute(res, n, p);
00235 free(p);
00236 return 0;
00237 }