* DescribeQuery: describe the result columns of a query, without executing it * * Returns true if the operation executed successfully, false otherwise. * * If pset.timing is on, total query time (exclusive of result-printing) is * stored into *elapsed_msec. */
| 1466 | * stored into *elapsed_msec. |
| 1467 | */ |
| 1468 | static bool |
| 1469 | DescribeQuery(const char *query, double *elapsed_msec) |
| 1470 | { |
| 1471 | PGresult *results; |
| 1472 | bool OK; |
| 1473 | instr_time before, |
| 1474 | after; |
| 1475 | |
| 1476 | *elapsed_msec = 0; |
| 1477 | |
| 1478 | if (pset.timing) |
| 1479 | INSTR_TIME_SET_CURRENT(before); |
| 1480 | |
| 1481 | /* |
| 1482 | * To parse the query but not execute it, we prepare it, using the unnamed |
| 1483 | * prepared statement. This is invisible to psql users, since there's no |
| 1484 | * way to access the unnamed prepared statement from psql user space. The |
| 1485 | * next Parse or Query protocol message would overwrite the statement |
| 1486 | * anyway. (So there's no great need to clear it when done, which is a |
| 1487 | * good thing because libpq provides no easy way to do that.) |
| 1488 | */ |
| 1489 | results = PQprepare(pset.db, "", query, 0, NULL); |
| 1490 | if (PQresultStatus(results) != PGRES_COMMAND_OK) |
| 1491 | { |
| 1492 | pg_log_info("%s", PQerrorMessage(pset.db)); |
| 1493 | SetResultVariables(results, false); |
| 1494 | ClearOrSaveResult(results); |
| 1495 | return false; |
| 1496 | } |
| 1497 | PQclear(results); |
| 1498 | |
| 1499 | results = PQdescribePrepared(pset.db, ""); |
| 1500 | OK = AcceptResult(results) && |
| 1501 | (PQresultStatus(results) == PGRES_COMMAND_OK); |
| 1502 | if (OK && results) |
| 1503 | { |
| 1504 | if (PQnfields(results) > 0) |
| 1505 | { |
| 1506 | PQExpBufferData buf; |
| 1507 | int i; |
| 1508 | |
| 1509 | initPQExpBuffer(&buf); |
| 1510 | |
| 1511 | printfPQExpBuffer(&buf, |
| 1512 | "SELECT name AS \"%s\", pg_catalog.format_type(tp, tpm) AS \"%s\"\n" |
| 1513 | "FROM (VALUES ", |
| 1514 | gettext_noop("Column"), |
| 1515 | gettext_noop("Type")); |
| 1516 | |
| 1517 | for (i = 0; i < PQnfields(results); i++) |
| 1518 | { |
| 1519 | const char *name; |
| 1520 | char *escname; |
| 1521 | |
| 1522 | if (i > 0) |
| 1523 | appendPQExpBufferStr(&buf, ","); |
| 1524 | |
| 1525 | name = PQfname(results, i); |
no test coverage detected