Header And Logo

PostgreSQL
| The world's most advanced open source database.

nbtcompare.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * nbtcompare.c
00004  *    Comparison functions for btree access method.
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/access/nbtree/nbtcompare.c
00012  *
00013  * NOTES
00014  *
00015  *  These functions are stored in pg_amproc.  For each operator class
00016  *  defined on btrees, they compute
00017  *
00018  *              compare(a, b):
00019  *                      < 0 if a < b,
00020  *                      = 0 if a == b,
00021  *                      > 0 if a > b.
00022  *
00023  *  The result is always an int32 regardless of the input datatype.
00024  *
00025  *  Although any negative int32 (except INT_MIN) is acceptable for reporting
00026  *  "<", and any positive int32 is acceptable for reporting ">", routines
00027  *  that work on 32-bit or wider datatypes can't just return "a - b".
00028  *  That could overflow and give the wrong answer.  Also, one must not
00029  *  return INT_MIN to report "<", since some callers will negate the result.
00030  *
00031  *  NOTE: it is critical that the comparison function impose a total order
00032  *  on all non-NULL values of the data type, and that the datatype's
00033  *  boolean comparison operators (= < >= etc) yield results consistent
00034  *  with the comparison routine.  Otherwise bad behavior may ensue.
00035  *  (For example, the comparison operators must NOT punt when faced with
00036  *  NAN or other funny values; you must devise some collation sequence for
00037  *  all such values.)  If the datatype is not trivial, this is most
00038  *  reliably done by having the boolean operators invoke the same
00039  *  three-way comparison code that the btree function does.  Therefore,
00040  *  this file contains only btree support for "trivial" datatypes ---
00041  *  all others are in the /utils/adt/ files that implement their datatypes.
00042  *
00043  *  NOTE: these routines must not leak memory, since memory allocated
00044  *  during an index access won't be recovered till end of query.  This
00045  *  primarily affects comparison routines for toastable datatypes;
00046  *  they have to be careful to free any detoasted copy of an input datum.
00047  *-------------------------------------------------------------------------
00048  */
00049 #include "postgres.h"
00050 
00051 #include "utils/builtins.h"
00052 #include "utils/sortsupport.h"
00053 
00054 
00055 Datum
00056 btboolcmp(PG_FUNCTION_ARGS)
00057 {
00058     bool        a = PG_GETARG_BOOL(0);
00059     bool        b = PG_GETARG_BOOL(1);
00060 
00061     PG_RETURN_INT32((int32) a - (int32) b);
00062 }
00063 
00064 Datum
00065 btint2cmp(PG_FUNCTION_ARGS)
00066 {
00067     int16       a = PG_GETARG_INT16(0);
00068     int16       b = PG_GETARG_INT16(1);
00069 
00070     PG_RETURN_INT32((int32) a - (int32) b);
00071 }
00072 
00073 static int
00074 btint2fastcmp(Datum x, Datum y, SortSupport ssup)
00075 {
00076     int16       a = DatumGetInt16(x);
00077     int16       b = DatumGetInt16(y);
00078 
00079     return (int) a - (int) b;
00080 }
00081 
00082 Datum
00083 btint2sortsupport(PG_FUNCTION_ARGS)
00084 {
00085     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
00086 
00087     ssup->comparator = btint2fastcmp;
00088     PG_RETURN_VOID();
00089 }
00090 
00091 Datum
00092 btint4cmp(PG_FUNCTION_ARGS)
00093 {
00094     int32       a = PG_GETARG_INT32(0);
00095     int32       b = PG_GETARG_INT32(1);
00096 
00097     if (a > b)
00098         PG_RETURN_INT32(1);
00099     else if (a == b)
00100         PG_RETURN_INT32(0);
00101     else
00102         PG_RETURN_INT32(-1);
00103 }
00104 
00105 static int
00106 btint4fastcmp(Datum x, Datum y, SortSupport ssup)
00107 {
00108     int32       a = DatumGetInt32(x);
00109     int32       b = DatumGetInt32(y);
00110 
00111     if (a > b)
00112         return 1;
00113     else if (a == b)
00114         return 0;
00115     else
00116         return -1;
00117 }
00118 
00119 Datum
00120 btint4sortsupport(PG_FUNCTION_ARGS)
00121 {
00122     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
00123 
00124     ssup->comparator = btint4fastcmp;
00125     PG_RETURN_VOID();
00126 }
00127 
00128 Datum
00129 btint8cmp(PG_FUNCTION_ARGS)
00130 {
00131     int64       a = PG_GETARG_INT64(0);
00132     int64       b = PG_GETARG_INT64(1);
00133 
00134     if (a > b)
00135         PG_RETURN_INT32(1);
00136     else if (a == b)
00137         PG_RETURN_INT32(0);
00138     else
00139         PG_RETURN_INT32(-1);
00140 }
00141 
00142 static int
00143 btint8fastcmp(Datum x, Datum y, SortSupport ssup)
00144 {
00145     int64       a = DatumGetInt64(x);
00146     int64       b = DatumGetInt64(y);
00147 
00148     if (a > b)
00149         return 1;
00150     else if (a == b)
00151         return 0;
00152     else
00153         return -1;
00154 }
00155 
00156 Datum
00157 btint8sortsupport(PG_FUNCTION_ARGS)
00158 {
00159     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
00160 
00161     ssup->comparator = btint8fastcmp;
00162     PG_RETURN_VOID();
00163 }
00164 
00165 Datum
00166 btint48cmp(PG_FUNCTION_ARGS)
00167 {
00168     int32       a = PG_GETARG_INT32(0);
00169     int64       b = PG_GETARG_INT64(1);
00170 
00171     if (a > b)
00172         PG_RETURN_INT32(1);
00173     else if (a == b)
00174         PG_RETURN_INT32(0);
00175     else
00176         PG_RETURN_INT32(-1);
00177 }
00178 
00179 Datum
00180 btint84cmp(PG_FUNCTION_ARGS)
00181 {
00182     int64       a = PG_GETARG_INT64(0);
00183     int32       b = PG_GETARG_INT32(1);
00184 
00185     if (a > b)
00186         PG_RETURN_INT32(1);
00187     else if (a == b)
00188         PG_RETURN_INT32(0);
00189     else
00190         PG_RETURN_INT32(-1);
00191 }
00192 
00193 Datum
00194 btint24cmp(PG_FUNCTION_ARGS)
00195 {
00196     int16       a = PG_GETARG_INT16(0);
00197     int32       b = PG_GETARG_INT32(1);
00198 
00199     if (a > b)
00200         PG_RETURN_INT32(1);
00201     else if (a == b)
00202         PG_RETURN_INT32(0);
00203     else
00204         PG_RETURN_INT32(-1);
00205 }
00206 
00207 Datum
00208 btint42cmp(PG_FUNCTION_ARGS)
00209 {
00210     int32       a = PG_GETARG_INT32(0);
00211     int16       b = PG_GETARG_INT16(1);
00212 
00213     if (a > b)
00214         PG_RETURN_INT32(1);
00215     else if (a == b)
00216         PG_RETURN_INT32(0);
00217     else
00218         PG_RETURN_INT32(-1);
00219 }
00220 
00221 Datum
00222 btint28cmp(PG_FUNCTION_ARGS)
00223 {
00224     int16       a = PG_GETARG_INT16(0);
00225     int64       b = PG_GETARG_INT64(1);
00226 
00227     if (a > b)
00228         PG_RETURN_INT32(1);
00229     else if (a == b)
00230         PG_RETURN_INT32(0);
00231     else
00232         PG_RETURN_INT32(-1);
00233 }
00234 
00235 Datum
00236 btint82cmp(PG_FUNCTION_ARGS)
00237 {
00238     int64       a = PG_GETARG_INT64(0);
00239     int16       b = PG_GETARG_INT16(1);
00240 
00241     if (a > b)
00242         PG_RETURN_INT32(1);
00243     else if (a == b)
00244         PG_RETURN_INT32(0);
00245     else
00246         PG_RETURN_INT32(-1);
00247 }
00248 
00249 Datum
00250 btoidcmp(PG_FUNCTION_ARGS)
00251 {
00252     Oid         a = PG_GETARG_OID(0);
00253     Oid         b = PG_GETARG_OID(1);
00254 
00255     if (a > b)
00256         PG_RETURN_INT32(1);
00257     else if (a == b)
00258         PG_RETURN_INT32(0);
00259     else
00260         PG_RETURN_INT32(-1);
00261 }
00262 
00263 static int
00264 btoidfastcmp(Datum x, Datum y, SortSupport ssup)
00265 {
00266     Oid         a = DatumGetObjectId(x);
00267     Oid         b = DatumGetObjectId(y);
00268 
00269     if (a > b)
00270         return 1;
00271     else if (a == b)
00272         return 0;
00273     else
00274         return -1;
00275 }
00276 
00277 Datum
00278 btoidsortsupport(PG_FUNCTION_ARGS)
00279 {
00280     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
00281 
00282     ssup->comparator = btoidfastcmp;
00283     PG_RETURN_VOID();
00284 }
00285 
00286 Datum
00287 btoidvectorcmp(PG_FUNCTION_ARGS)
00288 {
00289     oidvector  *a = (oidvector *) PG_GETARG_POINTER(0);
00290     oidvector  *b = (oidvector *) PG_GETARG_POINTER(1);
00291     int         i;
00292 
00293     /* We arbitrarily choose to sort first by vector length */
00294     if (a->dim1 != b->dim1)
00295         PG_RETURN_INT32(a->dim1 - b->dim1);
00296 
00297     for (i = 0; i < a->dim1; i++)
00298     {
00299         if (a->values[i] != b->values[i])
00300         {
00301             if (a->values[i] > b->values[i])
00302                 PG_RETURN_INT32(1);
00303             else
00304                 PG_RETURN_INT32(-1);
00305         }
00306     }
00307     PG_RETURN_INT32(0);
00308 }
00309 
00310 Datum
00311 btcharcmp(PG_FUNCTION_ARGS)
00312 {
00313     char        a = PG_GETARG_CHAR(0);
00314     char        b = PG_GETARG_CHAR(1);
00315 
00316     /* Be careful to compare chars as unsigned */
00317     PG_RETURN_INT32((int32) ((uint8) a) - (int32) ((uint8) b));
00318 }
00319 
00320 Datum
00321 btnamecmp(PG_FUNCTION_ARGS)
00322 {
00323     Name        a = PG_GETARG_NAME(0);
00324     Name        b = PG_GETARG_NAME(1);
00325 
00326     PG_RETURN_INT32(strncmp(NameStr(*a), NameStr(*b), NAMEDATALEN));
00327 }
00328 
00329 static int
00330 btnamefastcmp(Datum x, Datum y, SortSupport ssup)
00331 {
00332     Name        a = DatumGetName(x);
00333     Name        b = DatumGetName(y);
00334 
00335     return strncmp(NameStr(*a), NameStr(*b), NAMEDATALEN);
00336 }
00337 
00338 Datum
00339 btnamesortsupport(PG_FUNCTION_ARGS)
00340 {
00341     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
00342 
00343     ssup->comparator = btnamefastcmp;
00344     PG_RETURN_VOID();
00345 }