Int4 SOCK_get_response_length(SocketClass *self) { int leng = -1; leng = SOCK_get_int(self, 4) - 4; self->reslen = leng; return leng; }
Int4 SOCK_get_response_length(SocketClass *self) { int leng = -1; if (PG_PROTOCOL_74 == self->pversion) { leng = SOCK_get_int(self, 4) - 4; self->reslen = leng; } return leng; }
/* * Read in field descriptions. * If self is not null, then also store the information. * If self is null, then just read, don't store. */ char CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn) { CSTR func = "CI_read_fields"; Int2 lf; int new_num_fields; OID new_adtid, new_relid = 0, new_attid = 0; Int2 new_adtsize; Int4 new_atttypmod = -1; /* COLUMN_NAME_STORAGE_LEN may be sufficient but for safety */ char new_field_name[2 * COLUMN_NAME_STORAGE_LEN + 1]; SocketClass *sock; ConnInfo *ci; sock = CC_get_socket(conn); ci = &conn->connInfo; /* at first read in the number of fields that are in the query */ new_num_fields = (Int2) SOCK_get_int(sock, sizeof(Int2)); mylog("num_fields = %d\n", new_num_fields); if (self) /* according to that allocate memory */ CI_set_num_fields(self, new_num_fields, PROTOCOL_74(ci)); /* now read in the descriptions */ for (lf = 0; lf < new_num_fields; lf++) { SOCK_get_string(sock, new_field_name, 2 * COLUMN_NAME_STORAGE_LEN); if (PROTOCOL_74(ci)) /* tableid & columnid */ { new_relid = SOCK_get_int(sock, sizeof(Int4)); new_attid = SOCK_get_int(sock, sizeof(Int2)); } new_adtid = (OID) SOCK_get_int(sock, 4); new_adtsize = (Int2) SOCK_get_int(sock, 2); /* If 6.4 protocol, then read the atttypmod field */ if (PG_VERSION_GE(conn, 6.4)) { mylog("READING ATTTYPMOD\n"); new_atttypmod = (Int4) SOCK_get_int(sock, 4); /* 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; if (PROTOCOL_74(ci)) /* format */ SOCK_get_int(sock, sizeof(Int2)); } mylog("%s: fieldname='%s', adtid=%d, adtsize=%d, atttypmod=%d (rel,att)=(%d,%d)\n", func, 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 (SOCK_get_errcode(sock) == 0); }
char QR_read_tuple(QResultClass *self, char binary) { Int2 field_lf; TupleField *this_tuplefield; char bmp, bitmap[MAX_FIELDS]; /* Max. len of the bitmap */ Int2 bitmaplen; /* len of the bitmap in bytes */ Int2 bitmap_pos; Int2 bitcnt; Int4 len; char *buffer; int num_fields = self->num_fields; /* speed up access */ SocketClass *sock = CC_get_socket(self->conn); ColumnInfoClass *flds; /* set the current row to read the fields into */ this_tuplefield = self->backend_tuples + (self->fcount * num_fields); bitmaplen = (Int2) num_fields / BYTELEN; if ((num_fields % BYTELEN) > 0) bitmaplen++; /* At first the server sends a bitmap that indicates which database fields are null */ SOCK_get_n_char(sock, bitmap, bitmaplen); bitmap_pos = 0; bitcnt = 0; bmp = bitmap[bitmap_pos]; for(field_lf = 0; field_lf < num_fields; field_lf++) { /* Check if the current field is NULL */ if(!(bmp & 0200)) { /* YES, it is NULL ! */ this_tuplefield[field_lf].len = 0; this_tuplefield[field_lf].value = 0; } else { /* NO, the field is not null. so get at first the length of the field (four bytes) */ len = SOCK_get_int(sock, VARHDRSZ); if (!binary) len -= VARHDRSZ; buffer = (char *)malloc(len+1); SOCK_get_n_char(sock, buffer, len); buffer[len] = '\0'; mylog("qresult: len=%d, buffer='%s'\n", len, buffer); this_tuplefield[field_lf].len = len; this_tuplefield[field_lf].value = buffer; /* This can be used to set the longest length of the column for any row in the tuple cache. It would not be accurate for varchar and text fields to use this since a tuple cache is only 100 rows. Bpchar can be handled since the strlen of all rows is fixed, assuming there are not 100 nulls in a row! */ flds = self->fields; if (flds->display_size[field_lf] < len) flds->display_size[field_lf] = len; } /* Now adjust for the next bit to be scanned in the next loop. */ bitcnt++; if (BYTELEN == bitcnt) { bitmap_pos++; bmp = bitmap[bitmap_pos]; bitcnt = 0; } else bmp <<= 1; } self->currTuple++; return TRUE; }