PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
preproc-outofscope.c File Reference
#include <ecpglib.h>
#include <ecpgerrno.h>
#include <sqlca.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <pgtypes.h>
Include dependency graph for preproc-outofscope.c:

Go to the source code of this file.

Data Structures

struct  numeric
 
struct  decimal
 
struct  mytype
 
struct  mynulltype
 

Macros

#define ECPGdebug(X, Y)   ECPGdebug((X)+100,(Y))
 
#define PGTYPES_NUMERIC
 
#define NUMERIC_POS   0x0000
 
#define NUMERIC_NEG   0x4000
 
#define NUMERIC_NAN   0xC000
 
#define NUMERIC_NULL   0xF000
 
#define NUMERIC_MAX_PRECISION   1000
 
#define NUMERIC_MAX_DISPLAY_SCALE   NUMERIC_MAX_PRECISION
 
#define NUMERIC_MIN_DISPLAY_SCALE   0
 
#define NUMERIC_MIN_SIG_DIGITS   16
 
#define DECSIZE   30
 

Typedefs

typedef unsigned char NumericDigit
 
typedef struct mytype MYTYPE
 
typedef struct mynulltype MYNULLTYPE
 

Functions

numericPGTYPESnumeric_new (void)
 
decimalPGTYPESdecimal_new (void)
 
void PGTYPESnumeric_free (numeric *var)
 
void PGTYPESdecimal_free (decimal *var)
 
numericPGTYPESnumeric_from_asc (char *str, char **endptr)
 
char * PGTYPESnumeric_to_asc (numeric *num, int dscale)
 
int PGTYPESnumeric_add (numeric *var1, numeric *var2, numeric *result)
 
int PGTYPESnumeric_sub (numeric *var1, numeric *var2, numeric *result)
 
int PGTYPESnumeric_mul (numeric *var1, numeric *var2, numeric *result)
 
int PGTYPESnumeric_div (numeric *var1, numeric *var2, numeric *result)
 
int PGTYPESnumeric_cmp (numeric *var1, numeric *var2)
 
int PGTYPESnumeric_from_int (signed int int_val, numeric *var)
 
int PGTYPESnumeric_from_long (signed long int long_val, numeric *var)
 
int PGTYPESnumeric_copy (numeric *src, numeric *dst)
 
int PGTYPESnumeric_from_double (double d, numeric *dst)
 
int PGTYPESnumeric_to_double (numeric *nv, double *dp)
 
int PGTYPESnumeric_to_int (numeric *nv, int *ip)
 
int PGTYPESnumeric_to_long (numeric *nv, long *lp)
 
int PGTYPESnumeric_to_decimal (numeric *src, decimal *dst)
 
int PGTYPESnumeric_from_decimal (decimal *src, numeric *dst)
 
static void get_var1 (MYTYPE **myvar0, MYNULLTYPE **mynullvar0)
 
static void open_cur1 (void)
 
static void get_record1 (void)
 
static void close_cur1 (void)
 
int main (void)
 

Macro Definition Documentation

◆ DECSIZE

#define DECSIZE   30

Definition at line 42 of file preproc-outofscope.c.

◆ ECPGdebug

#define ECPGdebug (   X,
 
)    ECPGdebug((X)+100,(Y))

Definition at line 7 of file preproc-outofscope.c.

◆ NUMERIC_MAX_DISPLAY_SCALE

#define NUMERIC_MAX_DISPLAY_SCALE   NUMERIC_MAX_PRECISION

Definition at line 38 of file preproc-outofscope.c.

◆ NUMERIC_MAX_PRECISION

#define NUMERIC_MAX_PRECISION   1000

Definition at line 37 of file preproc-outofscope.c.

◆ NUMERIC_MIN_DISPLAY_SCALE

#define NUMERIC_MIN_DISPLAY_SCALE   0

Definition at line 39 of file preproc-outofscope.c.

◆ NUMERIC_MIN_SIG_DIGITS

#define NUMERIC_MIN_SIG_DIGITS   16

Definition at line 40 of file preproc-outofscope.c.

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

Definition at line 35 of file preproc-outofscope.c.

◆ NUMERIC_NEG

#define NUMERIC_NEG   0x4000

Definition at line 34 of file preproc-outofscope.c.

◆ NUMERIC_NULL

#define NUMERIC_NULL   0xF000

Definition at line 36 of file preproc-outofscope.c.

◆ NUMERIC_POS

#define NUMERIC_POS   0x0000

Definition at line 33 of file preproc-outofscope.c.

◆ PGTYPES_NUMERIC

#define PGTYPES_NUMERIC

Definition at line 29 of file preproc-outofscope.c.

Typedef Documentation

◆ MYNULLTYPE

typedef struct mynulltype MYNULLTYPE

Definition at line 125 of file preproc-outofscope.c.

◆ MYTYPE

typedef struct mytype MYTYPE

Definition at line 112 of file preproc-outofscope.c.

◆ NumericDigit

typedef unsigned char NumericDigit

Definition at line 44 of file preproc-outofscope.c.

Function Documentation

◆ close_cur1()

static void close_cur1 ( void  )
static

Definition at line 251 of file preproc-outofscope.c.

252{
253 { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close mycur", ECPGt_EOIT, ECPGt_EORT);
254#line 52 "outofscope.pgc"
255
256if (sqlca.sqlcode < 0) exit (1);}
257#line 52 "outofscope.pgc"
258
259}
@ ECPGst_normal
Definition: ecpgtype.h:97
@ ECPGt_EOIT
Definition: ecpgtype.h:62
@ ECPGt_EORT
Definition: ecpgtype.h:63
bool ECPGdo(const int lineno, const int compat, const int force_indicator, const char *connection_name, const bool questionmarks, const int st, const char *query,...)
Definition: execute.c:2275
exit(1)
#define sqlca
Definition: sqlca.h:59

References ECPGdo(), ECPGst_normal, ECPGt_EOIT, ECPGt_EORT, exit(), and sqlca.

Referenced by main().

◆ get_record1()

static void get_record1 ( void  )
static

Definition at line 230 of file preproc-outofscope.c.

231{
232 { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch mycur", ECPGt_EOIT,
233 ECPGt_int,&((*( MYTYPE *)(ECPGget_var( 0)) ).id),(long)1,(long)1,sizeof( struct mytype ),
234 ECPGt_int,&((*( MYNULLTYPE *)(ECPGget_var( 1)) ).id),(long)1,(long)1,sizeof( struct mynulltype ),
235 ECPGt_char,&((*( MYTYPE *)(ECPGget_var( 0)) ).t),(long)64,(long)1,sizeof( struct mytype ),
236 ECPGt_int,&((*( MYNULLTYPE *)(ECPGget_var( 1)) ).t),(long)1,(long)1,sizeof( struct mynulltype ),
237 ECPGt_double,&((*( MYTYPE *)(ECPGget_var( 0)) ).d1),(long)1,(long)1,sizeof( struct mytype ),
238 ECPGt_int,&((*( MYNULLTYPE *)(ECPGget_var( 1)) ).d1),(long)1,(long)1,sizeof( struct mynulltype ),
239 ECPGt_double,&((*( MYTYPE *)(ECPGget_var( 0)) ).d2),(long)1,(long)1,sizeof( struct mytype ),
240 ECPGt_int,&((*( MYNULLTYPE *)(ECPGget_var( 1)) ).d2),(long)1,(long)1,sizeof( struct mynulltype ),
241 ECPGt_char,&((*( MYTYPE *)(ECPGget_var( 0)) ).c),(long)30,(long)1,sizeof( struct mytype ),
242 ECPGt_int,&((*( MYNULLTYPE *)(ECPGget_var( 1)) ).c),(long)1,(long)1,sizeof( struct mynulltype ), ECPGt_EORT);
243#line 46 "outofscope.pgc"
244
245if (sqlca.sqlcode < 0) exit (1);}
246#line 46 "outofscope.pgc"
247
248}
@ ECPGt_int
Definition: ecpgtype.h:44
@ ECPGt_double
Definition: ecpgtype.h:47
@ ECPGt_char
Definition: ecpgtype.h:43
void * ECPGget_var(int number)
Definition: misc.c:593
char * c

References ECPGdo(), ECPGget_var(), ECPGst_normal, ECPGt_char, ECPGt_double, ECPGt_EOIT, ECPGt_EORT, ECPGt_int, exit(), and sqlca.

Referenced by main().

◆ get_var1()

static void get_var1 ( MYTYPE **  myvar0,
MYNULLTYPE **  mynullvar0 
)
static

Definition at line 173 of file preproc-outofscope.c.

174{
175 /* exec sql begin declare section */
176
177
178
179#line 22 "outofscope.pgc"
180 MYTYPE * myvar = malloc ( sizeof ( MYTYPE ) ) ;
181
182#line 23 "outofscope.pgc"
183 MYNULLTYPE * mynullvar = malloc ( sizeof ( MYNULLTYPE ) ) ;
184/* exec sql end declare section */
185#line 24 "outofscope.pgc"
186
187
188 /* Test DECLARE ... SELECT ... INTO with pointers */
189
190 ECPGset_var( 0, ( myvar ), __LINE__);\
191 ECPGset_var( 1, ( mynullvar ), __LINE__);\
192 /* declare mycur cursor for select * from a1 */
193#line 28 "outofscope.pgc"
194
195if (sqlca.sqlcode < 0) exit (1);
196#line 28 "outofscope.pgc"
197
198#line 28 "outofscope.pgc"
199
200
201 if (sqlca.sqlcode != 0)
202 exit(1);
203
204 *myvar0 = myvar;
205 *mynullvar0 = mynullvar;
206}
#define malloc(a)
Definition: header.h:50
void ECPGset_var(int number, void *pointer, int lineno)
Definition: misc.c:538

References ECPGset_var(), exit(), malloc, and sqlca.

Referenced by main().

◆ main()

int main ( void  )

Definition at line 262 of file preproc-outofscope.c.

263{
264 MYTYPE *myvar;
265 MYNULLTYPE *mynullvar;
266 int loopcount;
267 char msg[128];
268
269 ECPGdebug(1, stderr);
270
271 strcpy(msg, "connect");
272 { ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0);
273#line 66 "outofscope.pgc"
274
275if (sqlca.sqlcode < 0) exit (1);}
276#line 66 "outofscope.pgc"
277
278
279 strcpy(msg, "set");
280 { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set datestyle to iso", ECPGt_EOIT, ECPGt_EORT);
281#line 69 "outofscope.pgc"
282
283if (sqlca.sqlcode < 0) exit (1);}
284#line 69 "outofscope.pgc"
285
286
287 strcpy(msg, "create");
288 { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table a1 ( id serial primary key , t text , d1 numeric , d2 float8 , c character ( 10 ) )", ECPGt_EOIT, ECPGt_EORT);
289#line 72 "outofscope.pgc"
290
291if (sqlca.sqlcode < 0) exit (1);}
292#line 72 "outofscope.pgc"
293
294
295 strcpy(msg, "insert");
296 { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'a' , 1.0 , 2 , 'a' )", ECPGt_EOIT, ECPGt_EORT);
297#line 75 "outofscope.pgc"
298
299if (sqlca.sqlcode < 0) exit (1);}
300#line 75 "outofscope.pgc"
301
302 { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , null , null , null , null )", ECPGt_EOIT, ECPGt_EORT);
303#line 76 "outofscope.pgc"
304
305if (sqlca.sqlcode < 0) exit (1);}
306#line 76 "outofscope.pgc"
307
308 { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'b' , 2.0 , 3 , 'b' )", ECPGt_EOIT, ECPGt_EORT);
309#line 77 "outofscope.pgc"
310
311if (sqlca.sqlcode < 0) exit (1);}
312#line 77 "outofscope.pgc"
313
314
315 strcpy(msg, "commit");
316 { ECPGtrans(__LINE__, NULL, "commit");
317#line 80 "outofscope.pgc"
318
319if (sqlca.sqlcode < 0) exit (1);}
320#line 80 "outofscope.pgc"
321
322
323 /* Test out-of-scope DECLARE/OPEN/FETCH/CLOSE */
324
325 get_var1(&myvar, &mynullvar);
326 open_cur1();
327
328 for (loopcount = 0; loopcount < 100; loopcount++)
329 {
330 memset(myvar, 0, sizeof(MYTYPE));
331 get_record1();
332 if (sqlca.sqlcode == ECPG_NOT_FOUND)
333 break;
334 printf("id=%d%s t='%s'%s d1=%f%s d2=%f%s c = '%s'%s\n",
335 myvar->id, mynullvar->id ? " (NULL)" : "",
336 myvar->t, mynullvar->t ? " (NULL)" : "",
337 myvar->d1, mynullvar->d1 ? " (NULL)" : "",
338 myvar->d2, mynullvar->d2 ? " (NULL)" : "",
339 myvar->c, mynullvar->c ? " (NULL)" : "");
340 }
341
342 close_cur1();
343
344 free(myvar);
345 free(mynullvar);
346
347 strcpy(msg, "drop");
348 { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table a1", ECPGt_EOIT, ECPGt_EORT);
349#line 107 "outofscope.pgc"
350
351if (sqlca.sqlcode < 0) exit (1);}
352#line 107 "outofscope.pgc"
353
354
355 strcpy(msg, "commit");
356 { ECPGtrans(__LINE__, NULL, "commit");
357#line 110 "outofscope.pgc"
358
359if (sqlca.sqlcode < 0) exit (1);}
360#line 110 "outofscope.pgc"
361
362
363 strcpy(msg, "disconnect");
364 { ECPGdisconnect(__LINE__, "CURRENT");
365#line 113 "outofscope.pgc"
366
367if (sqlca.sqlcode < 0) exit (1);}
368#line 113 "outofscope.pgc"
369
370
371 return 0;
372}
bool ECPGdisconnect(int lineno, const char *connection_name)
Definition: connect.c:676
bool ECPGconnect(int lineno, int c, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit)
Definition: connect.c:255
#define ECPG_NOT_FOUND
Definition: ecpgerrno.h:10
#define free(a)
Definition: header.h:65
bool ECPGtrans(int lineno, const char *connection_name, const char *transaction)
Definition: misc.c:160
#define printf(...)
Definition: port.h:244
static void open_cur1(void)
static void close_cur1(void)
static void get_record1(void)
#define ECPGdebug(X, Y)
static void get_var1(MYTYPE **myvar0, MYNULLTYPE **mynullvar0)
char c[30]
char t[64]

References mytype::c, mynulltype::c, close_cur1(), mytype::d1, mynulltype::d1, mytype::d2, mynulltype::d2, ECPG_NOT_FOUND, ECPGconnect(), ECPGdebug, ECPGdisconnect(), ECPGdo(), ECPGst_normal, ECPGt_EOIT, ECPGt_EORT, ECPGtrans(), exit(), free, get_record1(), get_var1(), mytype::id, mynulltype::id, open_cur1(), printf, sqlca, mytype::t, and mynulltype::t.

◆ open_cur1()

static void open_cur1 ( void  )
static

Definition at line 209 of file preproc-outofscope.c.

210{
211 { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare mycur cursor for select * from a1", ECPGt_EOIT,
212 ECPGt_int,&((*( MYTYPE *)(ECPGget_var( 0)) ).id),(long)1,(long)1,sizeof( struct mytype ),
213 ECPGt_int,&((*( MYNULLTYPE *)(ECPGget_var( 1)) ).id),(long)1,(long)1,sizeof( struct mynulltype ),
214 ECPGt_char,&((*( MYTYPE *)(ECPGget_var( 0)) ).t),(long)64,(long)1,sizeof( struct mytype ),
215 ECPGt_int,&((*( MYNULLTYPE *)(ECPGget_var( 1)) ).t),(long)1,(long)1,sizeof( struct mynulltype ),
216 ECPGt_double,&((*( MYTYPE *)(ECPGget_var( 0)) ).d1),(long)1,(long)1,sizeof( struct mytype ),
217 ECPGt_int,&((*( MYNULLTYPE *)(ECPGget_var( 1)) ).d1),(long)1,(long)1,sizeof( struct mynulltype ),
218 ECPGt_double,&((*( MYTYPE *)(ECPGget_var( 0)) ).d2),(long)1,(long)1,sizeof( struct mytype ),
219 ECPGt_int,&((*( MYNULLTYPE *)(ECPGget_var( 1)) ).d2),(long)1,(long)1,sizeof( struct mynulltype ),
220 ECPGt_char,&((*( MYTYPE *)(ECPGget_var( 0)) ).c),(long)30,(long)1,sizeof( struct mytype ),
221 ECPGt_int,&((*( MYNULLTYPE *)(ECPGget_var( 1)) ).c),(long)1,(long)1,sizeof( struct mynulltype ), ECPGt_EORT);
222#line 40 "outofscope.pgc"
223
224if (sqlca.sqlcode < 0) exit (1);}
225#line 40 "outofscope.pgc"
226
227}

References ECPGdo(), ECPGget_var(), ECPGst_normal, ECPGt_char, ECPGt_double, ECPGt_EOIT, ECPGt_EORT, ECPGt_int, exit(), and sqlca.

Referenced by main().

◆ PGTYPESdecimal_free()

void PGTYPESdecimal_free ( decimal var)

Definition at line 392 of file numeric.c.

393{
394 free(var);
395}

◆ PGTYPESdecimal_new()

decimal * PGTYPESdecimal_new ( void  )

Definition at line 59 of file numeric.c.

60{
61 decimal *var;
62
63 if ((var = (decimal *) pgtypes_alloc(sizeof(decimal))) == NULL)
64 return NULL;
65
66 memset(var, 0, sizeof(decimal));
67
68 return var;
69}
char * pgtypes_alloc(long size)
Definition: common.c:10

◆ PGTYPESnumeric_add()

int PGTYPESnumeric_add ( numeric var1,
numeric var2,
numeric result 
)

Definition at line 637 of file numeric.c.

638{
639 /*
640 * Decide on the signs of the two variables what to do
641 */
642 if (var1->sign == NUMERIC_POS)
643 {
644 if (var2->sign == NUMERIC_POS)
645 {
646 /*
647 * Both are positive result = +(ABS(var1) + ABS(var2))
648 */
649 if (add_abs(var1, var2, result) != 0)
650 return -1;
651 result->sign = NUMERIC_POS;
652 }
653 else
654 {
655 /*
656 * var1 is positive, var2 is negative Must compare absolute values
657 */
658 switch (cmp_abs(var1, var2))
659 {
660 case 0:
661 /* ----------
662 * ABS(var1) == ABS(var2)
663 * result = ZERO
664 * ----------
665 */
666 zero_var(result);
667 result->rscale = Max(var1->rscale, var2->rscale);
668 result->dscale = Max(var1->dscale, var2->dscale);
669 break;
670
671 case 1:
672 /* ----------
673 * ABS(var1) > ABS(var2)
674 * result = +(ABS(var1) - ABS(var2))
675 * ----------
676 */
677 if (sub_abs(var1, var2, result) != 0)
678 return -1;
679 result->sign = NUMERIC_POS;
680 break;
681
682 case -1:
683 /* ----------
684 * ABS(var1) < ABS(var2)
685 * result = -(ABS(var2) - ABS(var1))
686 * ----------
687 */
688 if (sub_abs(var2, var1, result) != 0)
689 return -1;
690 result->sign = NUMERIC_NEG;
691 break;
692 }
693 }
694 }
695 else
696 {
697 if (var2->sign == NUMERIC_POS)
698 {
699 /* ----------
700 * var1 is negative, var2 is positive
701 * Must compare absolute values
702 * ----------
703 */
704 switch (cmp_abs(var1, var2))
705 {
706 case 0:
707 /* ----------
708 * ABS(var1) == ABS(var2)
709 * result = ZERO
710 * ----------
711 */
712 zero_var(result);
713 result->rscale = Max(var1->rscale, var2->rscale);
714 result->dscale = Max(var1->dscale, var2->dscale);
715 break;
716
717 case 1:
718 /* ----------
719 * ABS(var1) > ABS(var2)
720 * result = -(ABS(var1) - ABS(var2))
721 * ----------
722 */
723 if (sub_abs(var1, var2, result) != 0)
724 return -1;
725 result->sign = NUMERIC_NEG;
726 break;
727
728 case -1:
729 /* ----------
730 * ABS(var1) < ABS(var2)
731 * result = +(ABS(var2) - ABS(var1))
732 * ----------
733 */
734 if (sub_abs(var2, var1, result) != 0)
735 return -1;
736 result->sign = NUMERIC_POS;
737 break;
738 }
739 }
740 else
741 {
742 /* ----------
743 * Both are negative
744 * result = -(ABS(var1) + ABS(var2))
745 * ----------
746 */
747 if (add_abs(var1, var2, result) != 0)
748 return -1;
749 result->sign = NUMERIC_NEG;
750 }
751 }
752
753 return 0;
754}
#define NUMERIC_NEG
Definition: numeric.c:169
#define NUMERIC_POS
Definition: numeric.c:168
#define Max(x, y)
Definition: numeric.c:13
static int sub_abs(numeric *var1, numeric *var2, numeric *result)
Definition: numeric.c:553
static int add_abs(numeric *var1, numeric *var2, numeric *result)
Definition: numeric.c:465
static void zero_var(numeric *var)
Definition: numeric.c:374
static int cmp_abs(numeric *var1, numeric *var2)
Definition: numeric.c:407

◆ PGTYPESnumeric_cmp()

int PGTYPESnumeric_cmp ( numeric var1,
numeric var2 
)

Definition at line 1281 of file numeric.c.

1282{
1283 /* use cmp_abs function to calculate the result */
1284
1285 /* both are positive: normal comparison with cmp_abs */
1286 if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_POS)
1287 return cmp_abs(var1, var2);
1288
1289 /* both are negative: return the inverse of the normal comparison */
1290 if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_NEG)
1291 {
1292 /*
1293 * instead of inverting the result, we invert the parameter ordering
1294 */
1295 return cmp_abs(var2, var1);
1296 }
1297
1298 /* one is positive, one is negative: trivial */
1299 if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_NEG)
1300 return 1;
1301 if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_POS)
1302 return -1;
1303
1305 return INT_MAX;
1306}
#define PGTYPES_NUM_BAD_NUMERIC
Definition: pgtypes_error.h:4

◆ PGTYPESnumeric_copy()

int PGTYPESnumeric_copy ( numeric src,
numeric dst 
)

Definition at line 1388 of file numeric.c.

1389{
1390 int i;
1391
1392 if (dst == NULL)
1393 return -1;
1394 zero_var(dst);
1395
1396 dst->weight = src->weight;
1397 dst->rscale = src->rscale;
1398 dst->dscale = src->dscale;
1399 dst->sign = src->sign;
1400
1401 if (alloc_var(dst, src->ndigits) != 0)
1402 return -1;
1403
1404 for (i = 0; i < src->ndigits; i++)
1405 dst->digits[i] = src->digits[i];
1406
1407 return 0;
1408}
static int alloc_var(numeric *var, int ndigits)
Definition: numeric.c:29
int i
Definition: isn.c:72
NumericDigit * digits

◆ PGTYPESnumeric_div()

int PGTYPESnumeric_div ( numeric var1,
numeric var2,
numeric result 
)

Definition at line 1053 of file numeric.c.

1054{
1055 NumericDigit *res_digits;
1056 int res_ndigits;
1057 int res_sign;
1058 int res_weight;
1059 numeric dividend;
1060 numeric divisor[10];
1061 int ndigits_tmp;
1062 int weight_tmp;
1063 int rscale_tmp;
1064 int ri;
1065 long guess;
1066 long first_have;
1067 long first_div;
1068 int first_nextdigit;
1069 int stat = 0;
1070 int rscale;
1071 int res_dscale = select_div_scale(var1, var2, &rscale);
1072 int err = -1;
1073 NumericDigit *tmp_buf;
1074
1075 /*
1076 * First of all division by zero check
1077 */
1078 ndigits_tmp = var2->ndigits + 1;
1079 if (ndigits_tmp == 1)
1080 {
1082 return -1;
1083 }
1084
1085 /*
1086 * Determine the result sign, weight and number of digits to calculate
1087 */
1088 if (var1->sign == var2->sign)
1089 res_sign = NUMERIC_POS;
1090 else
1091 res_sign = NUMERIC_NEG;
1092 res_weight = var1->weight - var2->weight + 1;
1093 res_ndigits = rscale + res_weight;
1094 if (res_ndigits <= 0)
1095 res_ndigits = 1;
1096
1097 /*
1098 * Now result zero check
1099 */
1100 if (var1->ndigits == 0)
1101 {
1102 zero_var(result);
1103 result->rscale = rscale;
1104 return 0;
1105 }
1106
1107 /*
1108 * Initialize local variables
1109 */
1110 init_var(&dividend);
1111 for (int i = 1; i < 10; i++)
1112 init_var(&divisor[i]);
1113
1114 /*
1115 * Make a copy of the divisor which has one leading zero digit
1116 */
1117 divisor[1].ndigits = ndigits_tmp;
1118 divisor[1].rscale = var2->ndigits;
1119 divisor[1].sign = NUMERIC_POS;
1120 divisor[1].buf = digitbuf_alloc(ndigits_tmp);
1121 if (divisor[1].buf == NULL)
1122 goto done;
1123 divisor[1].digits = divisor[1].buf;
1124 divisor[1].digits[0] = 0;
1125 memcpy(&(divisor[1].digits[1]), var2->digits, ndigits_tmp - 1);
1126
1127 /*
1128 * Make a copy of the dividend
1129 */
1130 dividend.ndigits = var1->ndigits;
1131 dividend.weight = 0;
1132 dividend.rscale = var1->ndigits;
1133 dividend.sign = NUMERIC_POS;
1134 dividend.buf = digitbuf_alloc(var1->ndigits);
1135 if (dividend.buf == NULL)
1136 goto done;
1137 dividend.digits = dividend.buf;
1138 memcpy(dividend.digits, var1->digits, var1->ndigits);
1139
1140 /*
1141 * Setup the result. Do the allocation in a temporary buffer first, so we
1142 * don't free result->buf unless we have successfully allocated a buffer
1143 * to replace it with.
1144 */
1145 tmp_buf = digitbuf_alloc(res_ndigits + 2);
1146 if (tmp_buf == NULL)
1147 goto done;
1148 digitbuf_free(result->buf);
1149 result->buf = tmp_buf;
1150 res_digits = result->buf;
1151 result->digits = res_digits;
1152 result->ndigits = res_ndigits;
1153 result->weight = res_weight;
1154 result->rscale = rscale;
1155 result->sign = res_sign;
1156 res_digits[0] = 0;
1157
1158 first_div = divisor[1].digits[1] * 10;
1159 if (ndigits_tmp > 2)
1160 first_div += divisor[1].digits[2];
1161
1162 first_have = 0;
1163 first_nextdigit = 0;
1164
1165 weight_tmp = 1;
1166 rscale_tmp = divisor[1].rscale;
1167
1168 for (ri = 0; ri <= res_ndigits; ri++)
1169 {
1170 first_have = first_have * 10;
1171 if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
1172 first_have += dividend.digits[first_nextdigit];
1173 first_nextdigit++;
1174
1175 guess = (first_have * 10) / first_div + 1;
1176 if (guess > 9)
1177 guess = 9;
1178
1179 while (guess > 0)
1180 {
1181 if (divisor[guess].buf == NULL)
1182 {
1183 int i;
1184 long sum = 0;
1185
1186 memcpy(&divisor[guess], &divisor[1], sizeof(numeric));
1187 divisor[guess].buf = digitbuf_alloc(divisor[guess].ndigits);
1188 if (divisor[guess].buf == NULL)
1189 goto done;
1190 divisor[guess].digits = divisor[guess].buf;
1191 for (i = divisor[1].ndigits - 1; i >= 0; i--)
1192 {
1193 sum += divisor[1].digits[i] * guess;
1194 divisor[guess].digits[i] = sum % 10;
1195 sum /= 10;
1196 }
1197 }
1198
1199 divisor[guess].weight = weight_tmp;
1200 divisor[guess].rscale = rscale_tmp;
1201
1202 stat = cmp_abs(&dividend, &divisor[guess]);
1203 if (stat >= 0)
1204 break;
1205
1206 guess--;
1207 }
1208
1209 res_digits[ri + 1] = guess;
1210 if (stat == 0)
1211 {
1212 ri++;
1213 break;
1214 }
1215
1216 weight_tmp--;
1217 rscale_tmp++;
1218
1219 if (guess == 0)
1220 continue;
1221
1222 if (sub_abs(&dividend, &divisor[guess], &dividend) != 0)
1223 goto done;
1224
1225 first_nextdigit = dividend.weight - weight_tmp;
1226 first_have = 0;
1227 if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
1228 first_have = dividend.digits[first_nextdigit];
1229 first_nextdigit++;
1230 }
1231
1232 result->ndigits = ri + 1;
1233 if (ri == res_ndigits + 1)
1234 {
1235 int carry = (res_digits[ri] > 4) ? 1 : 0;
1236
1237 result->ndigits = ri;
1238 res_digits[ri] = 0;
1239
1240 while (carry && ri > 0)
1241 {
1242 carry += res_digits[--ri];
1243 res_digits[ri] = carry % 10;
1244 carry /= 10;
1245 }
1246 }
1247
1248 while (result->ndigits > 0 && *(result->digits) == 0)
1249 {
1250 (result->digits)++;
1251 (result->weight)--;
1252 (result->ndigits)--;
1253 }
1254 while (result->ndigits > 0 && result->digits[result->ndigits - 1] == 0)
1255 (result->ndigits)--;
1256 if (result->ndigits == 0)
1257 result->sign = NUMERIC_POS;
1258
1259 result->dscale = res_dscale;
1260 err = 0; /* if we've made it this far, return success */
1261
1262done:
1263
1264 /*
1265 * Tidy up
1266 */
1267 if (dividend.buf != NULL)
1268 digitbuf_free(dividend.buf);
1269
1270 for (int i = 1; i < 10; i++)
1271 {
1272 if (divisor[i].buf != NULL)
1273 digitbuf_free(divisor[i].buf);
1274 }
1275
1276 return err;
1277}
int16 NumericDigit
Definition: numeric.c:102
void err(int eval, const char *fmt,...)
Definition: err.c:43
int digits
Definition: informix.c:691
#define digitbuf_free(buf)
Definition: numeric.c:19
#define digitbuf_alloc(size)
Definition: numeric.c:18
static int select_div_scale(numeric *var1, numeric *var2, int *rscale)
Definition: numeric.c:987
#define init_var(v)
Definition: numeric.c:16
static char * buf
Definition: pg_test_fsync.c:72
#define PGTYPES_NUM_DIVIDE_ZERO
Definition: pgtypes_error.h:5
NumericDigit * buf

◆ PGTYPESnumeric_free()

void PGTYPESnumeric_free ( numeric var)

Definition at line 385 of file numeric.c.

386{
387 digitbuf_free(var->buf);
388 free(var);
389}

◆ PGTYPESnumeric_from_asc()

numeric * PGTYPESnumeric_from_asc ( char *  str,
char **  endptr 
)

Definition at line 321 of file numeric.c.

322{
323 numeric *value = (numeric *) pgtypes_alloc(sizeof(numeric));
324 int ret;
325
326 char *realptr;
327 char **ptr = (endptr != NULL) ? endptr : &realptr;
328
329 if (!value)
330 return NULL;
331
332 ret = set_var_from_str(str, ptr, value);
333 if (ret)
334 {
336 return NULL;
337 }
338
339 return value;
340}
const char * str
static struct @162 value
static int set_var_from_str(char *str, char **ptr, numeric *dest)
Definition: numeric.c:78
void PGTYPESnumeric_free(numeric *var)
Definition: numeric.c:385

◆ PGTYPESnumeric_from_decimal()

int PGTYPESnumeric_from_decimal ( decimal src,
numeric dst 
)

Definition at line 1570 of file numeric.c.

1571{
1572 int i;
1573
1574 zero_var(dst);
1575
1576 dst->weight = src->weight;
1577 dst->rscale = src->rscale;
1578 dst->dscale = src->dscale;
1579 dst->sign = src->sign;
1580
1581 if (alloc_var(dst, src->ndigits) != 0)
1582 return -1;
1583
1584 for (i = 0; i < src->ndigits; i++)
1585 dst->digits[i] = src->digits[i];
1586
1587 return 0;
1588}
NumericDigit digits[DECSIZE]

◆ PGTYPESnumeric_from_double()

int PGTYPESnumeric_from_double ( double  d,
numeric dst 
)

Definition at line 1411 of file numeric.c.

1412{
1413 char buffer[DBL_DIG + 100];
1414 numeric *tmp;
1415 int i;
1416
1417 if (sprintf(buffer, "%.*g", DBL_DIG, d) <= 0)
1418 return -1;
1419
1420 if ((tmp = PGTYPESnumeric_from_asc(buffer, NULL)) == NULL)
1421 return -1;
1422 i = PGTYPESnumeric_copy(tmp, dst);
1424 if (i != 0)
1425 return -1;
1426
1427 errno = 0;
1428 return 0;
1429}
int PGTYPESnumeric_copy(numeric *src, numeric *dst)
Definition: numeric.c:1388
numeric * PGTYPESnumeric_from_asc(char *str, char **endptr)
Definition: numeric.c:321
#define sprintf
Definition: port.h:240

◆ PGTYPESnumeric_from_int()

int PGTYPESnumeric_from_int ( signed int  int_val,
numeric var 
)

Definition at line 1309 of file numeric.c.

1310{
1311 /* implicit conversion */
1312 signed long int long_int = int_val;
1313
1314 return PGTYPESnumeric_from_long(long_int, var);
1315}
int PGTYPESnumeric_from_long(signed long int long_val, numeric *var)
Definition: numeric.c:1318

◆ PGTYPESnumeric_from_long()

int PGTYPESnumeric_from_long ( signed long int  long_val,
numeric var 
)

Definition at line 1318 of file numeric.c.

1319{
1320 /* calculate the size of the long int number */
1321 /* a number n needs log_10 n digits */
1322
1323 /*
1324 * however we multiply by 10 each time and compare instead of calculating
1325 * the logarithm
1326 */
1327
1328 int size = 0;
1329 int i;
1330 signed long int abs_long_val = long_val;
1331 signed long int extract;
1332 signed long int reach_limit;
1333
1334 if (abs_long_val < 0)
1335 {
1336 abs_long_val *= -1;
1337 var->sign = NUMERIC_NEG;
1338 }
1339 else
1340 var->sign = NUMERIC_POS;
1341
1342 reach_limit = 1;
1343 do
1344 {
1345 size++;
1346 reach_limit *= 10;
1347 } while (reach_limit - 1 < abs_long_val && reach_limit <= LONG_MAX / 10);
1348
1349 if (reach_limit > LONG_MAX / 10)
1350 {
1351 /* add the first digit and a .0 */
1352 size += 2;
1353 }
1354 else
1355 {
1356 /* always add a .0 */
1357 size++;
1358 reach_limit /= 10;
1359 }
1360
1361 if (alloc_var(var, size) < 0)
1362 return -1;
1363
1364 var->rscale = 1;
1365 var->dscale = 1;
1366 var->weight = size - 2;
1367
1368 i = 0;
1369 do
1370 {
1371 extract = abs_long_val - (abs_long_val % reach_limit);
1372 var->digits[i] = extract / reach_limit;
1373 abs_long_val -= extract;
1374 i++;
1375 reach_limit /= 10;
1376
1377 /*
1378 * we can abandon if abs_long_val reaches 0, because the memory is
1379 * initialized properly and filled with '0', so converting 10000 in
1380 * only one step is no problem
1381 */
1382 } while (abs_long_val > 0);
1383
1384 return 0;
1385}
static pg_noinline void Size size
Definition: slab.c:607

◆ PGTYPESnumeric_mul()

int PGTYPESnumeric_mul ( numeric var1,
numeric var2,
numeric result 
)

Definition at line 896 of file numeric.c.

897{
898 NumericDigit *res_buf;
899 NumericDigit *res_digits;
900 int res_ndigits;
901 int res_weight;
902 int res_sign;
903 int i,
904 ri,
905 i1,
906 i2;
907 long sum = 0;
908 int global_rscale = var1->rscale + var2->rscale;
909
910 res_weight = var1->weight + var2->weight + 2;
911 res_ndigits = var1->ndigits + var2->ndigits + 1;
912 if (var1->sign == var2->sign)
913 res_sign = NUMERIC_POS;
914 else
915 res_sign = NUMERIC_NEG;
916
917 if ((res_buf = digitbuf_alloc(res_ndigits)) == NULL)
918 return -1;
919 res_digits = res_buf;
920 memset(res_digits, 0, res_ndigits);
921
922 ri = res_ndigits;
923 for (i1 = var1->ndigits - 1; i1 >= 0; i1--)
924 {
925 sum = 0;
926 i = --ri;
927
928 for (i2 = var2->ndigits - 1; i2 >= 0; i2--)
929 {
930 sum += res_digits[i] + var1->digits[i1] * var2->digits[i2];
931 res_digits[i--] = sum % 10;
932 sum /= 10;
933 }
934 res_digits[i] = sum;
935 }
936
937 i = res_weight + global_rscale + 2;
938 if (i >= 0 && i < res_ndigits)
939 {
940 sum = (res_digits[i] > 4) ? 1 : 0;
941 res_ndigits = i;
942 i--;
943 while (sum)
944 {
945 sum += res_digits[i];
946 res_digits[i--] = sum % 10;
947 sum /= 10;
948 }
949 }
950
951 while (res_ndigits > 0 && *res_digits == 0)
952 {
953 res_digits++;
954 res_weight--;
955 res_ndigits--;
956 }
957 while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
958 res_ndigits--;
959
960 if (res_ndigits == 0)
961 {
962 res_sign = NUMERIC_POS;
963 res_weight = 0;
964 }
965
966 digitbuf_free(result->buf);
967 result->buf = res_buf;
968 result->digits = res_digits;
969 result->ndigits = res_ndigits;
970 result->weight = res_weight;
971 result->rscale = global_rscale;
972 result->sign = res_sign;
973 result->dscale = var1->dscale + var2->dscale;
974
975 return 0;
976}

◆ PGTYPESnumeric_new()

numeric * PGTYPESnumeric_new ( void  )

Definition at line 42 of file numeric.c.

43{
44 numeric *var;
45
46 if ((var = (numeric *) pgtypes_alloc(sizeof(numeric))) == NULL)
47 return NULL;
48
49 if (alloc_var(var, 0) < 0)
50 {
51 free(var);
52 return NULL;
53 }
54
55 return var;
56}

◆ PGTYPESnumeric_sub()

int PGTYPESnumeric_sub ( numeric var1,
numeric var2,
numeric result 
)

Definition at line 765 of file numeric.c.

766{
767 /*
768 * Decide on the signs of the two variables what to do
769 */
770 if (var1->sign == NUMERIC_POS)
771 {
772 if (var2->sign == NUMERIC_NEG)
773 {
774 /* ----------
775 * var1 is positive, var2 is negative
776 * result = +(ABS(var1) + ABS(var2))
777 * ----------
778 */
779 if (add_abs(var1, var2, result) != 0)
780 return -1;
781 result->sign = NUMERIC_POS;
782 }
783 else
784 {
785 /* ----------
786 * Both are positive
787 * Must compare absolute values
788 * ----------
789 */
790 switch (cmp_abs(var1, var2))
791 {
792 case 0:
793 /* ----------
794 * ABS(var1) == ABS(var2)
795 * result = ZERO
796 * ----------
797 */
798 zero_var(result);
799 result->rscale = Max(var1->rscale, var2->rscale);
800 result->dscale = Max(var1->dscale, var2->dscale);
801 break;
802
803 case 1:
804 /* ----------
805 * ABS(var1) > ABS(var2)
806 * result = +(ABS(var1) - ABS(var2))
807 * ----------
808 */
809 if (sub_abs(var1, var2, result) != 0)
810 return -1;
811 result->sign = NUMERIC_POS;
812 break;
813
814 case -1:
815 /* ----------
816 * ABS(var1) < ABS(var2)
817 * result = -(ABS(var2) - ABS(var1))
818 * ----------
819 */
820 if (sub_abs(var2, var1, result) != 0)
821 return -1;
822 result->sign = NUMERIC_NEG;
823 break;
824 }
825 }
826 }
827 else
828 {
829 if (var2->sign == NUMERIC_NEG)
830 {
831 /* ----------
832 * Both are negative
833 * Must compare absolute values
834 * ----------
835 */
836 switch (cmp_abs(var1, var2))
837 {
838 case 0:
839 /* ----------
840 * ABS(var1) == ABS(var2)
841 * result = ZERO
842 * ----------
843 */
844 zero_var(result);
845 result->rscale = Max(var1->rscale, var2->rscale);
846 result->dscale = Max(var1->dscale, var2->dscale);
847 break;
848
849 case 1:
850 /* ----------
851 * ABS(var1) > ABS(var2)
852 * result = -(ABS(var1) - ABS(var2))
853 * ----------
854 */
855 if (sub_abs(var1, var2, result) != 0)
856 return -1;
857 result->sign = NUMERIC_NEG;
858 break;
859
860 case -1:
861 /* ----------
862 * ABS(var1) < ABS(var2)
863 * result = +(ABS(var2) - ABS(var1))
864 * ----------
865 */
866 if (sub_abs(var2, var1, result) != 0)
867 return -1;
868 result->sign = NUMERIC_POS;
869 break;
870 }
871 }
872 else
873 {
874 /* ----------
875 * var1 is negative, var2 is positive
876 * result = -(ABS(var1) + ABS(var2))
877 * ----------
878 */
879 if (add_abs(var1, var2, result) != 0)
880 return -1;
881 result->sign = NUMERIC_NEG;
882 }
883 }
884
885 return 0;
886}

◆ PGTYPESnumeric_to_asc()

char * PGTYPESnumeric_to_asc ( numeric num,
int  dscale 
)

Definition at line 343 of file numeric.c.

344{
345 numeric *numcopy = PGTYPESnumeric_new();
346 char *s;
347
348 if (numcopy == NULL)
349 return NULL;
350
351 if (PGTYPESnumeric_copy(num, numcopy) < 0)
352 {
353 PGTYPESnumeric_free(numcopy);
354 return NULL;
355 }
356
357 if (dscale < 0)
358 dscale = num->dscale;
359
360 /* get_str_from_var may change its argument */
361 s = get_str_from_var(numcopy, dscale);
362 PGTYPESnumeric_free(numcopy);
363 return s;
364}
numeric * PGTYPESnumeric_new(void)
Definition: numeric.c:42
static char * get_str_from_var(numeric *var, int dscale)
Definition: numeric.c:226

◆ PGTYPESnumeric_to_decimal()

int PGTYPESnumeric_to_decimal ( numeric src,
decimal dst 
)

Definition at line 1547 of file numeric.c.

1548{
1549 int i;
1550
1551 if (src->ndigits > DECSIZE)
1552 {
1553 errno = PGTYPES_NUM_OVERFLOW;
1554 return -1;
1555 }
1556
1557 dst->weight = src->weight;
1558 dst->rscale = src->rscale;
1559 dst->dscale = src->dscale;
1560 dst->sign = src->sign;
1561 dst->ndigits = src->ndigits;
1562
1563 for (i = 0; i < src->ndigits; i++)
1564 dst->digits[i] = src->digits[i];
1565
1566 return 0;
1567}
#define PGTYPES_NUM_OVERFLOW
Definition: pgtypes_error.h:3
#define DECSIZE

◆ PGTYPESnumeric_to_double()

int PGTYPESnumeric_to_double ( numeric nv,
double *  dp 
)

Definition at line 1483 of file numeric.c.

1484{
1485 double tmp;
1486
1487 if (numericvar_to_double(nv, &tmp) != 0)
1488 return -1;
1489 *dp = tmp;
1490 return 0;
1491}
static int numericvar_to_double(numeric *var, double *dp)
Definition: numeric.c:1432

◆ PGTYPESnumeric_to_int()

int PGTYPESnumeric_to_int ( numeric nv,
int *  ip 
)

Definition at line 1494 of file numeric.c.

1495{
1496 long l;
1497 int i;
1498
1499 if ((i = PGTYPESnumeric_to_long(nv, &l)) != 0)
1500 return i;
1501
1502/* silence compilers that might complain about useless tests */
1503#if SIZEOF_LONG > SIZEOF_INT
1504
1505 if (l < INT_MIN || l > INT_MAX)
1506 {
1507 errno = PGTYPES_NUM_OVERFLOW;
1508 return -1;
1509 }
1510
1511#endif
1512
1513 *ip = (int) l;
1514 return 0;
1515}
int PGTYPESnumeric_to_long(numeric *nv, long *lp)
Definition: numeric.c:1518

◆ PGTYPESnumeric_to_long()

int PGTYPESnumeric_to_long ( numeric nv,
long *  lp 
)

Definition at line 1518 of file numeric.c.

1519{
1520 char *s = PGTYPESnumeric_to_asc(nv, 0);
1521 char *endptr;
1522
1523 if (s == NULL)
1524 return -1;
1525
1526 errno = 0;
1527 *lp = strtol(s, &endptr, 10);
1528 if (endptr == s)
1529 {
1530 /* this should not happen actually */
1531 free(s);
1532 return -1;
1533 }
1534 free(s);
1535 if (errno == ERANGE)
1536 {
1537 if (*lp == LONG_MIN)
1538 errno = PGTYPES_NUM_UNDERFLOW;
1539 else
1540 errno = PGTYPES_NUM_OVERFLOW;
1541 return -1;
1542 }
1543 return 0;
1544}
char * PGTYPESnumeric_to_asc(numeric *num, int dscale)
Definition: numeric.c:343
#define PGTYPES_NUM_UNDERFLOW
Definition: pgtypes_error.h:6