-
Notifications
You must be signed in to change notification settings - Fork 15
/
columninfo.c
168 lines (137 loc) · 3.66 KB
/
columninfo.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*-------
* Module: columninfo.c
*
* Description: This module contains routines related to
* reading and storing the field information from a query.
*
* Classes: ColumnInfoClass (Functions prefix: "CI_")
*
* API functions: none
*
* Comments: See "readme.txt" for copyright and license information.
*-------
*/
#include "pgtypes.h"
#include "columninfo.h"
#include "connection.h"
#include <stdlib.h>
#include <string.h>
#include "pgapifunc.h"
#include <libpq-fe.h>
ColumnInfoClass *
CI_Constructor(void)
{
ColumnInfoClass *rv;
rv = (ColumnInfoClass *) malloc(sizeof(ColumnInfoClass));
if (rv)
{
rv->refcount = 0;
rv->num_fields = 0;
rv->coli_array = NULL;
}
return rv;
}
void
CI_Destructor(ColumnInfoClass *self)
{
CI_free_memory(self);
free(self);
}
/*
* Read in field descriptions from a libpq result set.
* If self is not null, then also store the information.
* If self is null, then just read, don't store.
*/
BOOL
CI_read_fields_from_pgres(ColumnInfoClass *self, PGresult *pgres)
{
Int2 lf;
int new_num_fields;
OID new_adtid, new_relid = 0, new_attid = 0;
Int2 new_adtsize;
Int4 new_atttypmod = -1;
char *new_field_name;
/* at first read in the number of fields that are in the query */
new_num_fields = PQnfields(pgres);
QLOG(0, "\tnFields: %d\n", new_num_fields);
if (self)
{
/* according to that allocate memory */
CI_set_num_fields(self, new_num_fields);
if (new_num_fields > 0 && NULL == self->coli_array)
return FALSE;
}
/* now read in the descriptions */
for (lf = 0; lf < new_num_fields; lf++)
{
new_field_name = PQfname(pgres, lf);
new_relid = PQftable(pgres, lf);
new_attid = PQftablecol(pgres, lf);
new_adtid = PQftype(pgres, lf);
new_adtsize = PQfsize(pgres, lf);
MYLOG(0, "READING ATTTYPMOD\n");
new_atttypmod = PQfmod(pgres, lf);
/* Subtract the header length */
switch (new_adtid)
{
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP_NO_TMZONE:
case PG_TYPE_TIME:
case PG_TYPE_TIME_WITH_TMZONE:
break;
default:
new_atttypmod -= 4;
}
if (new_atttypmod < 0)
new_atttypmod = -1;
QLOG(0, "\tfieldname='%s', adtid=%d, adtsize=%d, atttypmod=%d (rel,att)=(%d,%d)\n", new_field_name, new_adtid, new_adtsize, new_atttypmod, new_relid, new_attid);
if (self)
CI_set_field_info(self, lf, new_field_name, new_adtid, new_adtsize, new_atttypmod, new_relid, new_attid);
}
return TRUE;
}
void
CI_free_memory(ColumnInfoClass *self)
{
register Int2 lf;
int num_fields = self->num_fields;
/* Safe to call even if null */
self->num_fields = 0;
if (self->coli_array)
{
for (lf = 0; lf < num_fields; lf++)
{
if (self->coli_array[lf].name)
{
free(self->coli_array[lf].name);
self->coli_array[lf].name = NULL;
}
}
free(self->coli_array);
self->coli_array = NULL;
}
}
void
CI_set_num_fields(ColumnInfoClass *self, int new_num_fields)
{
CI_free_memory(self); /* always safe to call */
self->num_fields = new_num_fields;
self->coli_array = (struct srvr_info *) calloc(sizeof(struct srvr_info), self->num_fields);
}
void
CI_set_field_info(ColumnInfoClass *self, int field_num, const char *new_name,
OID new_adtid, Int2 new_adtsize, Int4 new_atttypmod,
OID new_relid, OID new_attid)
{
/* check bounds */
if ((field_num < 0) || (field_num >= self->num_fields))
return;
/* store the info */
self->coli_array[field_num].name = strdup(new_name);
self->coli_array[field_num].adtid= new_adtid;
self->coli_array[field_num].adtsize = new_adtsize;
self->coli_array[field_num].atttypmod = new_atttypmod;
self->coli_array[field_num].display_size = PG_ADT_UNSET;
self->coli_array[field_num].relid = new_relid;
self->coli_array[field_num].attid = new_attid;
}