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 90 of file preproc-outofscope.c.

◆ MYTYPE

typedef struct mytype MYTYPE

Definition at line 90 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 
256 if (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 
245 if (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 
195 if (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 
275 if (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 
283 if (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 
291 if (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 
299 if (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 
305 if (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 
311 if (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 
319 if (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 
351 if (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 
359 if (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 
367 if (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 
224 if (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 
1304  errno = PGTYPES_NUM_BAD_NUMERIC;
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  {
1081  errno = PGTYPES_NUM_DIVIDE_ZERO;
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 
1262 done:
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 @160 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);
1423  PGTYPESnumeric_free(tmp);
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 }
static char * get_str_from_var(numeric *var, int dscale)
Definition: numeric.c:226
numeric * PGTYPESnumeric_new(void)
Definition: numeric.c:42

◆ 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