* Detects NULL in type text based fields and replaces them by empty string */
| 182 | * Detects NULL in type text based fields and replaces them by empty string |
| 183 | */ |
| 184 | Datum |
| 185 | orafce_replace_null_strings(PG_FUNCTION_ARGS) |
| 186 | { |
| 187 | TriggerData *trigdata = (TriggerData *) fcinfo->context; |
| 188 | HeapTuple rettuple = NULL; |
| 189 | TupleDesc tupdesc; |
| 190 | int *resetcols = NULL; |
| 191 | Datum *values = NULL; |
| 192 | bool *nulls = NULL; |
| 193 | Oid prev_typid = InvalidOid; |
| 194 | bool is_string = false; |
| 195 | int nresetcols = 0; |
| 196 | int attnum; |
| 197 | bool raise_warning = false; |
| 198 | char *relname = NULL; |
| 199 | |
| 200 | trigger_sanity_check(fcinfo, "replace_null_strings"); |
| 201 | raise_warning = should_raise_warnings(fcinfo); |
| 202 | |
| 203 | rettuple = get_rettuple(fcinfo); |
| 204 | |
| 205 | /* return fast when there are not any NULL */ |
| 206 | if (!HeapTupleHasNulls(rettuple)) |
| 207 | return PointerGetDatum(rettuple); |
| 208 | |
| 209 | tupdesc = trigdata->tg_relation->rd_att; |
| 210 | |
| 211 | /* iterate over record's fields */ |
| 212 | for (attnum = 1; attnum <= tupdesc->natts; attnum++) |
| 213 | { |
| 214 | Oid typid; |
| 215 | |
| 216 | /* simple cache - lot of time columns with same type is side by side */ |
| 217 | typid = SPI_gettypeid(tupdesc, attnum); |
| 218 | if (typid != prev_typid) |
| 219 | { |
| 220 | TYPCATEGORY category; |
| 221 | bool ispreferred; |
| 222 | Oid base_typid; |
| 223 | |
| 224 | base_typid = getBaseType(typid); |
| 225 | get_type_category_preferred(base_typid, &category, &ispreferred); |
| 226 | |
| 227 | is_string = (category == TYPCATEGORY_STRING); |
| 228 | prev_typid = typid; |
| 229 | } |
| 230 | |
| 231 | if (is_string) |
| 232 | { |
| 233 | bool isnull; |
| 234 | |
| 235 | (void) SPI_getbinval(rettuple, tupdesc, attnum, &isnull); |
| 236 | if (isnull) |
| 237 | { |
| 238 | if (!resetcols) |
| 239 | { |
| 240 | /* lazy allocation of dynamic memory */ |
| 241 | resetcols = palloc0(tupdesc->natts * sizeof(int)); |
nothing calls this directly
no test coverage detected