~ubuntu-branches/ubuntu/hardy/postgresql-8.4/hardy-backports

« back to all changes in this revision

Viewing changes to src/backend/utils/adt/numeric.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-04-27 08:35:30 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090427083530-jhwzvyit4pbf64h1
Tags: 8.4~beta1-1
* First public beta of 8.4.
* debian/*.install: Add new gettext translations.
* debian/control: Bump p-common dependency to >= 98 to ensure support for
  8.4.
* debian/rules: Build with --enable-cassert while in beta.

Show diffs side-by-side

added added

removed removed

Lines of Context:
242
242
static void free_var(NumericVar *var);
243
243
static void zero_var(NumericVar *var);
244
244
 
245
 
static void set_var_from_str(const char *str, NumericVar *dest);
 
245
static const char *set_var_from_str(const char *str, const char *cp,
 
246
                                                                        NumericVar *dest);
246
247
static void set_var_from_num(Numeric value, NumericVar *dest);
247
248
static void set_var_from_var(NumericVar *value, NumericVar *dest);
248
249
static char *get_str_from_var(NumericVar *var, int dscale);
321
322
        Oid                     typelem = PG_GETARG_OID(1);
322
323
#endif
323
324
        int32           typmod = PG_GETARG_INT32(2);
324
 
        NumericVar      value;
325
325
        Numeric         res;
 
326
        const char *cp;
 
327
 
 
328
        /* Skip leading spaces */
 
329
        cp = str;
 
330
        while (*cp)
 
331
        {
 
332
                if (!isspace((unsigned char) *cp))
 
333
                        break;
 
334
                cp++;
 
335
        }
326
336
 
327
337
        /*
328
338
         * Check for NaN
329
339
         */
330
 
        if (pg_strcasecmp(str, "NaN") == 0)
331
 
                PG_RETURN_NUMERIC(make_result(&const_nan));
332
 
 
333
 
        /*
334
 
         * Use set_var_from_str() to parse the input string and return it in the
335
 
         * packed DB storage format
336
 
         */
337
 
        init_var(&value);
338
 
        set_var_from_str(str, &value);
339
 
 
340
 
        apply_typmod(&value, typmod);
341
 
 
342
 
        res = make_result(&value);
343
 
        free_var(&value);
 
340
        if (pg_strncasecmp(cp, "NaN", 3) == 0)
 
341
        {
 
342
                res = make_result(&const_nan);
 
343
 
 
344
                /* Should be nothing left but spaces */
 
345
                cp += 3;
 
346
                while (*cp)
 
347
                {
 
348
                        if (!isspace((unsigned char) *cp))
 
349
                                ereport(ERROR,
 
350
                                                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 
351
                                         errmsg("invalid input syntax for type numeric: \"%s\"",
 
352
                                                        str)));
 
353
                        cp++;
 
354
                }
 
355
        }
 
356
        else
 
357
        {
 
358
                /*
 
359
                 * Use set_var_from_str() to parse a normal numeric value
 
360
                 */
 
361
                NumericVar      value;
 
362
 
 
363
                init_var(&value);
 
364
 
 
365
                cp = set_var_from_str(str, cp, &value);
 
366
 
 
367
                /*
 
368
                 * We duplicate a few lines of code here because we would like to
 
369
                 * throw any trailing-junk syntax error before any semantic error
 
370
                 * resulting from apply_typmod.  We can't easily fold the two
 
371
                 * cases together because we mustn't apply apply_typmod to a NaN.
 
372
                 */
 
373
                while (*cp)
 
374
                {
 
375
                        if (!isspace((unsigned char) *cp))
 
376
                                ereport(ERROR,
 
377
                                                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 
378
                                         errmsg("invalid input syntax for type numeric: \"%s\"",
 
379
                                                        str)));
 
380
                        cp++;
 
381
                }
 
382
 
 
383
                apply_typmod(&value, typmod);
 
384
 
 
385
                res = make_result(&value);
 
386
                free_var(&value);
 
387
        }
344
388
 
345
389
        PG_RETURN_NUMERIC(res);
346
390
}
2121
2165
 
2122
2166
        init_var(&result);
2123
2167
 
2124
 
        set_var_from_str(buf, &result);
 
2168
        /* Assume we need not worry about leading/trailing spaces */
 
2169
        (void) set_var_from_str(buf, buf, &result);
 
2170
 
2125
2171
        res = make_result(&result);
2126
2172
 
2127
2173
        free_var(&result);
2181
2227
 
2182
2228
        init_var(&result);
2183
2229
 
2184
 
        set_var_from_str(buf, &result);
 
2230
        /* Assume we need not worry about leading/trailing spaces */
 
2231
        (void) set_var_from_str(buf, buf, &result);
 
2232
 
2185
2233
        res = make_result(&result);
2186
2234
 
2187
2235
        free_var(&result);
2972
3020
 * set_var_from_str()
2973
3021
 *
2974
3022
 *      Parse a string and put the number into a variable
 
3023
 *
 
3024
 * This function does not handle leading or trailing spaces, and it doesn't
 
3025
 * accept "NaN" either.  It returns the end+1 position so that caller can
 
3026
 * check for trailing spaces/garbage if deemed necessary.
 
3027
 *
 
3028
 * cp is the place to actually start parsing; str is what to use in error
 
3029
 * reports.  (Typically cp would be the same except advanced over spaces.)
2975
3030
 */
2976
 
static void
2977
 
set_var_from_str(const char *str, NumericVar *dest)
 
3031
static const char *
 
3032
set_var_from_str(const char *str, const char *cp, NumericVar *dest)
2978
3033
{
2979
 
        const char *cp = str;
2980
3034
        bool            have_dp = FALSE;
2981
3035
        int                     i;
2982
3036
        unsigned char *decdigits;
2993
3047
         * We first parse the string to extract decimal digits and determine the
2994
3048
         * correct decimal weight.      Then convert to NBASE representation.
2995
3049
         */
2996
 
 
2997
 
        /* skip leading spaces */
2998
 
        while (*cp)
2999
 
        {
3000
 
                if (!isspace((unsigned char) *cp))
3001
 
                        break;
3002
 
                cp++;
3003
 
        }
3004
 
 
3005
3050
        switch (*cp)
3006
3051
        {
3007
3052
                case '+':
3086
3131
                        dscale = 0;
3087
3132
        }
3088
3133
 
3089
 
        /* Should be nothing left but spaces */
3090
 
        while (*cp)
3091
 
        {
3092
 
                if (!isspace((unsigned char) *cp))
3093
 
                        ereport(ERROR,
3094
 
                                        (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3095
 
                                         errmsg("invalid input syntax for type numeric: \"%s\"",
3096
 
                                                        str)));
3097
 
                cp++;
3098
 
        }
3099
 
 
3100
3134
        /*
3101
3135
         * Okay, convert pure-decimal representation to base NBASE.  First we need
3102
3136
         * to determine the converted weight and ndigits.  offset is the number of
3137
3171
 
3138
3172
        /* Strip any leading/trailing zeroes, and normalize weight if zero */
3139
3173
        strip_var(dest);
 
3174
 
 
3175
        /* Return end+1 position for caller */
 
3176
        return cp;
3140
3177
}
3141
3178
 
3142
3179