void test_add_tuple_desc_httpheader(void **state) { /* setup mock data and expectations */ CHURL_HEADERS headers = (CHURL_HEADERS) palloc0(sizeof(CHURL_HEADERS)); Relation rel = (Relation) palloc0(sizeof(RelationData)); struct tupleDesc tuple; tuple.natts = 4; rel->rd_id = 56; rel->rd_att = &tuple; expect_headers_append(headers, "X-GP-ATTRS", "4"); FormData_pg_attribute attrs[4]; Form_pg_attribute attrs_ptr[4]; tuple.attrs = attrs_ptr; /* define first attribute */ attrs_ptr[0] = &attrs[0]; char data0[10] = "name0"; snprintf(NameStr(attrs[0].attname), sizeof(data0), data0); char typename0[12] = "NUMERICOID"; attrs[0].atttypid = NUMERICOID; attrs[0].atttypmod = 10; char typecode0[10]; pg_ltoa(attrs[0].atttypid, typecode0); expect_value(TypeOidGetTypename, typid, NUMERICOID); will_return(TypeOidGetTypename, &typename0); expect_headers_append(headers, "X-GP-ATTR-NAME0", data0); expect_headers_append(headers, "X-GP-ATTR-TYPECODE0", typecode0); expect_headers_append(headers, "X-GP-ATTR-TYPENAME0", typename0); expect_headers_append(headers, "X-GP-ATTR-TYPEMOD0-COUNT", "2"); char typemod00[10]; pg_ltoa((attrs[0].atttypmod >> 16) & 0xffff, typemod00); expect_headers_append(headers, "X-GP-ATTR-TYPEMOD0-0", typemod00); char typemod01[10]; pg_ltoa((attrs[0].atttypmod - VARHDRSZ) & 0xffff, typemod01); expect_headers_append(headers, "X-GP-ATTR-TYPEMOD0-1", typemod01); /* define second attribute */ attrs_ptr[1] = &attrs[1]; char data1[10] = "name1"; snprintf(NameStr(attrs[1].attname), sizeof(data1), data1); char typename1[12] = "CHAROID"; attrs[1].atttypid = CHAROID; attrs[1].atttypmod = 10; char typecode1[10]; pg_ltoa(attrs[1].atttypid, typecode1); expect_value(TypeOidGetTypename, typid, CHAROID); will_return(TypeOidGetTypename, &typename1); expect_headers_append(headers, "X-GP-ATTR-NAME1", data1); expect_headers_append(headers, "X-GP-ATTR-TYPECODE1", typecode1); expect_headers_append(headers, "X-GP-ATTR-TYPENAME1", typename1); expect_headers_append(headers, "X-GP-ATTR-TYPEMOD1-COUNT", "1"); char typemod10[10]; pg_ltoa((attrs[1].atttypmod - VARHDRSZ), typemod10); expect_headers_append(headers, "X-GP-ATTR-TYPEMOD1-0", typemod10); /* define third attribute */ attrs_ptr[2] = &attrs[2]; char data2[10] = "name2"; snprintf(NameStr(attrs[2].attname), sizeof(data2), data2); char typename2[12] = "TIMEOID"; attrs[2].atttypid = TIMEOID; attrs[2].atttypmod = 10; char typecode2[10]; pg_ltoa(attrs[2].atttypid, typecode2); expect_value(TypeOidGetTypename, typid, TIMEOID); will_return(TypeOidGetTypename, &typename2); expect_headers_append(headers, "X-GP-ATTR-NAME2", data2); expect_headers_append(headers, "X-GP-ATTR-TYPECODE2", typecode2); expect_headers_append(headers, "X-GP-ATTR-TYPENAME2", typename2); expect_headers_append(headers, "X-GP-ATTR-TYPEMOD2-COUNT", "1"); char typemod20[10]; pg_ltoa(attrs[2].atttypmod, typemod20); expect_headers_append(headers, "X-GP-ATTR-TYPEMOD2-0", typemod20); /* define fourth attribute */ attrs_ptr[3] = &attrs[3]; char data3[10] = "name3"; snprintf(NameStr(attrs[3].attname), sizeof(data3), data3); char typename3[12] = "INTERVALOID"; attrs[3].atttypid = INTERVALOID; attrs[3].atttypmod = 10; char typecode3[10]; pg_ltoa(attrs[3].atttypid, typecode3); expect_value(TypeOidGetTypename, typid, INTERVALOID); will_return(TypeOidGetTypename, &typename3); expect_headers_append(headers, "X-GP-ATTR-NAME3", data3); expect_headers_append(headers, "X-GP-ATTR-TYPECODE3", typecode3); expect_headers_append(headers, "X-GP-ATTR-TYPENAME3", typename3); expect_headers_append(headers, "X-GP-ATTR-TYPEMOD3-COUNT", "1"); char typemod30[10]; pg_ltoa(INTERVAL_PRECISION(attrs[3].atttypmod), typemod30); expect_headers_append(headers, "X-GP-ATTR-TYPEMOD3-0", typemod30); /* call function under test */ add_tuple_desc_httpheader(headers, rel); /* no asserts as the function just calls to set headers */ /* cleanup */ pfree(rel); pfree(headers); }
/* * Add key/value pairs to connection header. * These values are the context of the query and used * by the remote component. */ void build_http_header(PxfInputData *input) { extvar_t ev; CHURL_HEADERS headers = input->headers; GPHDUri *gphduri = input->gphduri; Relation rel = input->rel; char *filterstr = input->filterstr; ProjectionInfo *proj_info = input->proj_info; if (rel != NULL) { /* format */ ExtTableEntry *exttbl = GetExtTableEntry(rel->rd_id); /* pxf treats CSV as TEXT */ char* format = get_format_name(exttbl->fmtcode); churl_headers_append(headers, "X-GP-FORMAT", format); /* Record fields - name and type of each field */ add_tuple_desc_httpheader(headers, rel); } if (proj_info != NULL && proj_info->pi_isVarList) { List* qualsAttributes = extractPxfAttributes(input->quals); /* projection information is incomplete if columns from WHERE clause wasn't extracted */ if (qualsAttributes != NIL || list_length(input->quals) == 0) { add_projection_desc_httpheader(headers, proj_info, qualsAttributes); } else elog(DEBUG2, "Query will not be optimized to use projection information"); } /* GP cluster configuration */ external_set_env_vars(&ev, gphduri->uri, false, NULL, NULL, false, 0); churl_headers_append(headers, "X-GP-SEGMENT-ID", ev.GP_SEGMENT_ID); churl_headers_append(headers, "X-GP-SEGMENT-COUNT", ev.GP_SEGMENT_COUNT); churl_headers_append(headers, "X-GP-XID", ev.GP_XID); /* Report alignment size to remote component * GPDBWritable uses alignment that has to be the same as * in the C code. * Since the C code can be compiled for both 32 and 64 bits, * the alignment can be either 4 or 8. */ add_alignment_size_httpheader(headers); /* headers for uri data */ churl_headers_append(headers, "X-GP-URL-HOST", gphduri->host); churl_headers_append(headers, "X-GP-URL-PORT", gphduri->port); churl_headers_append(headers, "X-GP-DATA-DIR", gphduri->data); /* location options */ add_location_options_httpheader(headers, gphduri); /* full uri */ churl_headers_append(headers, "X-GP-URI", gphduri->uri); /* filters */ if (filterstr) { churl_headers_append(headers, "X-GP-HAS-FILTER", "1"); churl_headers_append(headers, "X-GP-FILTER", filterstr); } else churl_headers_append(headers, "X-GP-HAS-FILTER", "0"); add_delegation_token_headers(headers, input); add_remote_credentials(headers); }