* PQfnumber: find column number given column name * * The column name is parsed as if it were in a SQL statement, including * case-folding and double-quote processing. But note a possible gotcha: * downcasing in the frontend might follow different locale rules than * downcasing in the backend... * * Returns -1 if no match. In the present backend it is also possible * to have multiple mat
| 3392 | * to have multiple matches, in which case the first one is found. |
| 3393 | */ |
| 3394 | int |
| 3395 | PQfnumber(const PGresult *res, const char *field_name) |
| 3396 | { |
| 3397 | char *field_case; |
| 3398 | bool in_quotes; |
| 3399 | bool all_lower = true; |
| 3400 | const char *iptr; |
| 3401 | char *optr; |
| 3402 | int i; |
| 3403 | |
| 3404 | if (!res) |
| 3405 | return -1; |
| 3406 | |
| 3407 | /* |
| 3408 | * Note: it is correct to reject a zero-length input string; the proper |
| 3409 | * input to match a zero-length field name would be "". |
| 3410 | */ |
| 3411 | if (field_name == NULL || |
| 3412 | field_name[0] == '\0' || |
| 3413 | res->attDescs == NULL) |
| 3414 | return -1; |
| 3415 | |
| 3416 | /* |
| 3417 | * Check if we can avoid the strdup() and related work because the |
| 3418 | * passed-in string wouldn't be changed before we do the check anyway. |
| 3419 | */ |
| 3420 | for (iptr = field_name; *iptr; iptr++) |
| 3421 | { |
| 3422 | char c = *iptr; |
| 3423 | |
| 3424 | if (c == '"' || c != pg_tolower((unsigned char) c)) |
| 3425 | { |
| 3426 | all_lower = false; |
| 3427 | break; |
| 3428 | } |
| 3429 | } |
| 3430 | |
| 3431 | if (all_lower) |
| 3432 | for (i = 0; i < res->numAttributes; i++) |
| 3433 | if (strcmp(field_name, res->attDescs[i].name) == 0) |
| 3434 | return i; |
| 3435 | |
| 3436 | /* Fall through to the normal check if that didn't work out. */ |
| 3437 | |
| 3438 | /* |
| 3439 | * Note: this code will not reject partially quoted strings, eg |
| 3440 | * foo"BAR"foo will become fooBARfoo when it probably ought to be an error |
| 3441 | * condition. |
| 3442 | */ |
| 3443 | field_case = strdup(field_name); |
| 3444 | if (field_case == NULL) |
| 3445 | return -1; /* grotty */ |
| 3446 | |
| 3447 | in_quotes = false; |
| 3448 | optr = field_case; |
| 3449 | for (iptr = field_case; *iptr; iptr++) |
| 3450 | { |
| 3451 | char c = *iptr; |