mirror of
https://github.com/postgres/postgres.git
synced 2025-06-23 14:01:44 +03:00
psql cleanup
This commit is contained in:
@ -35,8 +35,7 @@
|
|||||||
|
|
||||||
/* functions for use in this file only */
|
/* functions for use in this file only */
|
||||||
|
|
||||||
static backslashResult
|
static backslashResult exec_command(const char *cmd,
|
||||||
exec_command(const char * cmd,
|
|
||||||
char *const * options,
|
char *const * options,
|
||||||
const char *options_string,
|
const char *options_string,
|
||||||
PQExpBuffer query_buf,
|
PQExpBuffer query_buf,
|
||||||
@ -84,32 +83,40 @@ HandleSlashCmds(PsqlSettings *pset,
|
|||||||
const char *cmd;
|
const char *cmd;
|
||||||
size_t blank_loc;
|
size_t blank_loc;
|
||||||
int i;
|
int i;
|
||||||
const char * continue_parse = NULL; /* tell the mainloop where the backslash command ended */
|
const char *continue_parse = NULL; /* tell the mainloop where the
|
||||||
|
* backslash command ended */
|
||||||
|
|
||||||
my_line = xstrdup(line);
|
my_line = xstrdup(line);
|
||||||
|
|
||||||
/* Find the first whitespace (or backslash)
|
/*
|
||||||
line[blank_loc] will now be the whitespace character
|
* Find the first whitespace (or backslash) line[blank_loc] will now
|
||||||
or the \0 at the end */
|
* be the whitespace character or the \0 at the end
|
||||||
|
*/
|
||||||
blank_loc = strcspn(my_line, " \t");
|
blank_loc = strcspn(my_line, " \t");
|
||||||
|
|
||||||
/* do we have an option string? */
|
/* do we have an option string? */
|
||||||
if (my_line[blank_loc] != '\0') {
|
if (my_line[blank_loc] != '\0')
|
||||||
|
{
|
||||||
options_string = &my_line[blank_loc + 1];
|
options_string = &my_line[blank_loc + 1];
|
||||||
|
|
||||||
my_line[blank_loc] = '\0';
|
my_line[blank_loc] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options_string) {
|
if (options_string)
|
||||||
|
{
|
||||||
char quote;
|
char quote;
|
||||||
unsigned int pos;
|
unsigned int pos;
|
||||||
options_string = &options_string[strspn(options_string, " \t")]; /* skip leading whitespace */
|
|
||||||
|
options_string = &options_string[strspn(options_string, " \t")]; /* skip leading
|
||||||
|
* whitespace */
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
token = strtokx(options_string, " \t", "\"'`", '\\', "e, &pos);
|
token = strtokx(options_string, " \t", "\"'`", '\\', "e, &pos);
|
||||||
|
|
||||||
for (i = 0; token && i<16; i++) {
|
for (i = 0; token && i < 16; i++)
|
||||||
switch(quote) {
|
{
|
||||||
|
switch (quote)
|
||||||
|
{
|
||||||
case '"':
|
case '"':
|
||||||
options[i] = unescape(token, pset);
|
options[i] = unescape(token, pset);
|
||||||
break;
|
break;
|
||||||
@ -126,17 +133,21 @@ HandleSlashCmds(PsqlSettings *pset,
|
|||||||
size_t result;
|
size_t result;
|
||||||
|
|
||||||
fd = popen(file, "r");
|
fd = popen(file, "r");
|
||||||
if (!fd) {
|
if (!fd)
|
||||||
|
{
|
||||||
perror(file);
|
perror(file);
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error) {
|
if (!error)
|
||||||
|
{
|
||||||
initPQExpBuffer(&output);
|
initPQExpBuffer(&output);
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
result = fread(buf, 1, 512, fd);
|
result = fread(buf, 1, 512, fd);
|
||||||
if (ferror(fd)) {
|
if (ferror(fd))
|
||||||
|
{
|
||||||
perror(file);
|
perror(file);
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
@ -145,13 +156,15 @@ HandleSlashCmds(PsqlSettings *pset,
|
|||||||
} while (!feof(fd));
|
} while (!feof(fd));
|
||||||
appendPQExpBufferChar(&output, '\0');
|
appendPQExpBufferChar(&output, '\0');
|
||||||
|
|
||||||
if (pclose(fd) == -1) {
|
if (pclose(fd) == -1)
|
||||||
|
{
|
||||||
perror(file);
|
perror(file);
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error) {
|
if (!error)
|
||||||
|
{
|
||||||
if (output.data[strlen(output.data) - 1] == '\n')
|
if (output.data[strlen(output.data) - 1] == '\n')
|
||||||
output.data[strlen(output.data) - 1] = '\0';
|
output.data[strlen(output.data) - 1] = '\0';
|
||||||
}
|
}
|
||||||
@ -159,7 +172,8 @@ HandleSlashCmds(PsqlSettings *pset,
|
|||||||
free(file);
|
free(file);
|
||||||
if (!error)
|
if (!error)
|
||||||
options[i] = output.data;
|
options[i] = output.data;
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
options[i] = xstrdup("");
|
options[i] = xstrdup("");
|
||||||
termPQExpBuffer(&output);
|
termPQExpBuffer(&output);
|
||||||
}
|
}
|
||||||
@ -187,11 +201,15 @@ HandleSlashCmds(PsqlSettings *pset,
|
|||||||
|
|
||||||
status = exec_command(cmd, options, options_string, query_buf, pset);
|
status = exec_command(cmd, options, options_string, query_buf, pset);
|
||||||
|
|
||||||
if (status == CMD_UNKNOWN) {
|
if (status == CMD_UNKNOWN)
|
||||||
/* If the command was not recognized, try inserting a space after
|
{
|
||||||
the first letter and call again. The one letter commands
|
|
||||||
allow arguments to start immediately after the command,
|
/*
|
||||||
but that is no longer encouraged. */
|
* If the command was not recognized, try inserting a space after
|
||||||
|
* the first letter and call again. The one letter commands allow
|
||||||
|
* arguments to start immediately after the command, but that is
|
||||||
|
* no longer encouraged.
|
||||||
|
*/
|
||||||
const char *new_options[17];
|
const char *new_options[17];
|
||||||
char new_cmd[2];
|
char new_cmd[2];
|
||||||
int i;
|
int i;
|
||||||
@ -206,7 +224,8 @@ HandleSlashCmds(PsqlSettings *pset,
|
|||||||
status = exec_command(new_cmd, (char *const *) new_options, my_line + 2, query_buf, pset);
|
status = exec_command(new_cmd, (char *const *) new_options, my_line + 2, query_buf, pset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == CMD_UNKNOWN) {
|
if (status == CMD_UNKNOWN)
|
||||||
|
{
|
||||||
fprintf(stderr, "Unrecognized command: \\%s. Try \\? for help.\n", cmd);
|
fprintf(stderr, "Unrecognized command: \\%s. Try \\? for help.\n", cmd);
|
||||||
status = CMD_ERROR;
|
status = CMD_ERROR;
|
||||||
}
|
}
|
||||||
@ -215,7 +234,8 @@ HandleSlashCmds(PsqlSettings *pset,
|
|||||||
continue_parse += 2;
|
continue_parse += 2;
|
||||||
|
|
||||||
|
|
||||||
if (end_of_cmd) {
|
if (end_of_cmd)
|
||||||
|
{
|
||||||
if (continue_parse)
|
if (continue_parse)
|
||||||
*end_of_cmd = line + (continue_parse - my_line);
|
*end_of_cmd = line + (continue_parse - my_line);
|
||||||
else
|
else
|
||||||
@ -241,15 +261,19 @@ exec_command(const char * cmd,
|
|||||||
PQExpBuffer query_buf,
|
PQExpBuffer query_buf,
|
||||||
PsqlSettings *pset)
|
PsqlSettings *pset)
|
||||||
{
|
{
|
||||||
bool success = true; /* indicate here if the command ran ok or failed */
|
bool success = true; /* indicate here if the command ran ok or
|
||||||
|
* failed */
|
||||||
bool quiet = GetVariableBool(pset->vars, "quiet");
|
bool quiet = GetVariableBool(pset->vars, "quiet");
|
||||||
|
|
||||||
backslashResult status = CMD_SKIP_LINE;
|
backslashResult status = CMD_SKIP_LINE;
|
||||||
|
|
||||||
|
|
||||||
/* \a -- toggle field alignment
|
/*
|
||||||
This is deprecated and makes no sense, but we keep it around. */
|
* \a -- toggle field alignment This is deprecated and makes no sense,
|
||||||
if (strcmp(cmd, "a") == 0) {
|
* but we keep it around.
|
||||||
|
*/
|
||||||
|
if (strcmp(cmd, "a") == 0)
|
||||||
|
{
|
||||||
if (pset->popt.topt.format != PRINT_ALIGNED)
|
if (pset->popt.topt.format != PRINT_ALIGNED)
|
||||||
success = do_pset("format", "aligned", &pset->popt, quiet);
|
success = do_pset("format", "aligned", &pset->popt, quiet);
|
||||||
else
|
else
|
||||||
@ -257,30 +281,36 @@ exec_command(const char * cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* \C -- override table title
|
/*
|
||||||
(formerly change HTML caption) This is deprecated. */
|
* \C -- override table title (formerly change HTML caption) This is
|
||||||
|
* deprecated.
|
||||||
|
*/
|
||||||
else if (strcmp(cmd, "C") == 0)
|
else if (strcmp(cmd, "C") == 0)
|
||||||
success = do_pset("title", options[0], &pset->popt, quiet);
|
success = do_pset("title", options[0], &pset->popt, quiet);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* \c or \connect -- connect to new database or as different user
|
/*
|
||||||
|
* \c or \connect -- connect to new database or as different user
|
||||||
*
|
*
|
||||||
* \c foo bar : connect to db "foo" as user "bar"
|
* \c foo bar : connect to db "foo" as user "bar" \c foo [-] :
|
||||||
* \c foo [-] : connect to db "foo" as current user
|
* connect to db "foo" as current user \c - bar : connect to
|
||||||
* \c - bar : connect to current db as user "bar"
|
* current db as user "bar" \c : connect to default db as
|
||||||
* \c : connect to default db as default user
|
* default user
|
||||||
*/
|
*/
|
||||||
else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
|
else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
|
||||||
{
|
{
|
||||||
if (options[1])
|
if (options[1])
|
||||||
/* gave username */
|
/* gave username */
|
||||||
success = do_connect(options[0], options[1], pset);
|
success = do_connect(options[0], options[1], pset);
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
if (options[0])
|
if (options[0])
|
||||||
/* gave database name */
|
/* gave database name */
|
||||||
success = do_connect(options[0], "", pset); /* empty string is same username as before,
|
success = do_connect(options[0], "", pset); /* empty string is same
|
||||||
NULL would mean libpq default */
|
* username as before,
|
||||||
|
* NULL would mean libpq
|
||||||
|
* default */
|
||||||
else
|
else
|
||||||
/* connect to default db as default user */
|
/* connect to default db as default user */
|
||||||
success = do_connect(NULL, NULL, pset);
|
success = do_connect(NULL, NULL, pset);
|
||||||
@ -297,13 +327,16 @@ exec_command(const char * cmd,
|
|||||||
print_copyright();
|
print_copyright();
|
||||||
|
|
||||||
/* \d* commands */
|
/* \d* commands */
|
||||||
else if (cmd[0] == 'd') {
|
else if (cmd[0] == 'd')
|
||||||
switch(cmd[1]) {
|
{
|
||||||
|
switch (cmd[1])
|
||||||
|
{
|
||||||
case '\0':
|
case '\0':
|
||||||
if (options[0])
|
if (options[0])
|
||||||
success = describeTableDetails(options[0], pset);
|
success = describeTableDetails(options[0], pset);
|
||||||
else
|
else
|
||||||
success = listTables("tvs", NULL, pset); /* standard listing of interesting things */
|
success = listTables("tvs", NULL, pset); /* standard listing of
|
||||||
|
* interesting things */
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
success = describeAggregates(options[0], pset);
|
success = describeAggregates(options[0], pset);
|
||||||
@ -326,7 +359,11 @@ exec_command(const char * cmd,
|
|||||||
case 'T':
|
case 'T':
|
||||||
success = describeTypes(options[0], pset);
|
success = describeTypes(options[0], pset);
|
||||||
break;
|
break;
|
||||||
case 't': case 'v': case 'i': case 's': case 'S':
|
case 't':
|
||||||
|
case 'v':
|
||||||
|
case 'i':
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
if (cmd[1] == 'S' && cmd[2] == '\0')
|
if (cmd[1] == 'S' && cmd[2] == '\0')
|
||||||
success = listTables("Stvs", NULL, pset);
|
success = listTables("Stvs", NULL, pset);
|
||||||
else
|
else
|
||||||
@ -338,28 +375,35 @@ exec_command(const char * cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* \e or \edit -- edit the current query buffer (or a file and make it the
|
/*
|
||||||
query buffer */
|
* \e or \edit -- edit the current query buffer (or a file and make it
|
||||||
|
* the query buffer
|
||||||
|
*/
|
||||||
else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
|
else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
|
||||||
status = do_edit(options[0], query_buf) ? CMD_NEWEDIT : CMD_ERROR;
|
status = do_edit(options[0], query_buf) ? CMD_NEWEDIT : CMD_ERROR;
|
||||||
|
|
||||||
|
|
||||||
/* \echo */
|
/* \echo */
|
||||||
else if (strcmp(cmd, "echo") == 0) {
|
else if (strcmp(cmd, "echo") == 0)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 16 && options[i]; i++)
|
for (i = 0; i < 16 && options[i]; i++)
|
||||||
fputs(options[i], stdout);
|
fputs(options[i], stdout);
|
||||||
fputs("\n", stdout);
|
fputs("\n", stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \f -- change field separator
|
/*
|
||||||
(This is deprecated in favour of \pset.) */
|
* \f -- change field separator (This is deprecated in favour of
|
||||||
|
* \pset.)
|
||||||
|
*/
|
||||||
else if (strcmp(cmd, "f") == 0)
|
else if (strcmp(cmd, "f") == 0)
|
||||||
success = do_pset("fieldsep", options[0], &pset->popt, quiet);
|
success = do_pset("fieldsep", options[0], &pset->popt, quiet);
|
||||||
|
|
||||||
|
|
||||||
/* \g means send query */
|
/* \g means send query */
|
||||||
else if (strcmp(cmd, "g") == 0) {
|
else if (strcmp(cmd, "g") == 0)
|
||||||
|
{
|
||||||
if (!options[0])
|
if (!options[0])
|
||||||
pset->gfname = NULL;
|
pset->gfname = NULL;
|
||||||
else
|
else
|
||||||
@ -380,7 +424,8 @@ exec_command(const char * cmd,
|
|||||||
/* \i is include file */
|
/* \i is include file */
|
||||||
else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
|
else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
|
||||||
{
|
{
|
||||||
if (!options[0]) {
|
if (!options[0])
|
||||||
|
{
|
||||||
fputs("Usage: \\i <filename>\n", stderr);
|
fputs("Usage: \\i <filename>\n", stderr);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
@ -394,9 +439,12 @@ exec_command(const char * cmd,
|
|||||||
|
|
||||||
|
|
||||||
/* large object things */
|
/* large object things */
|
||||||
else if (strncmp(cmd, "lo_", 3)==0) {
|
else if (strncmp(cmd, "lo_", 3) == 0)
|
||||||
if (strcmp(cmd+3, "export") == 0) {
|
{
|
||||||
if (!options[1]) {
|
if (strcmp(cmd + 3, "export") == 0)
|
||||||
|
{
|
||||||
|
if (!options[1])
|
||||||
|
{
|
||||||
fputs("Usage: \\lo_export <loid> <filename>\n", stderr);
|
fputs("Usage: \\lo_export <loid> <filename>\n", stderr);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
@ -404,8 +452,10 @@ exec_command(const char * cmd,
|
|||||||
success = do_lo_export(pset, options[0], options[1]);
|
success = do_lo_export(pset, options[0], options[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp(cmd+3, "import") == 0) {
|
else if (strcmp(cmd + 3, "import") == 0)
|
||||||
if (!options[0]) {
|
{
|
||||||
|
if (!options[0])
|
||||||
|
{
|
||||||
fputs("Usage: \\lo_import <filename> [<description>]\n", stderr);
|
fputs("Usage: \\lo_import <filename> [<description>]\n", stderr);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
@ -416,8 +466,10 @@ exec_command(const char * cmd,
|
|||||||
else if (strcmp(cmd + 3, "list") == 0)
|
else if (strcmp(cmd + 3, "list") == 0)
|
||||||
success = do_lo_list(pset);
|
success = do_lo_list(pset);
|
||||||
|
|
||||||
else if (strcmp(cmd+3, "unlink") == 0) {
|
else if (strcmp(cmd + 3, "unlink") == 0)
|
||||||
if (!options[0]) {
|
{
|
||||||
|
if (!options[0])
|
||||||
|
{
|
||||||
fputs("Usage: \\lo_unlink <loid>\n", stderr);
|
fputs("Usage: \\lo_unlink <loid>\n", stderr);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
@ -444,8 +496,10 @@ exec_command(const char * cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* \pset -- set printing parameters */
|
/* \pset -- set printing parameters */
|
||||||
else if (strcmp(cmd, "pset")==0) {
|
else if (strcmp(cmd, "pset") == 0)
|
||||||
if (!options[0]) {
|
{
|
||||||
|
if (!options[0])
|
||||||
|
{
|
||||||
fputs("Usage: \\pset <parameter> [<value>]\n", stderr);
|
fputs("Usage: \\pset <parameter> [<value>]\n", stderr);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
@ -458,8 +512,10 @@ exec_command(const char * cmd,
|
|||||||
status = CMD_TERMINATE;
|
status = CMD_TERMINATE;
|
||||||
|
|
||||||
/* \qecho */
|
/* \qecho */
|
||||||
else if (strcmp(cmd, "qecho") == 0) {
|
else if (strcmp(cmd, "qecho") == 0)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 16 && options[i]; i++)
|
for (i = 0; i < 16 && options[i]; i++)
|
||||||
fputs(options[i], pset->queryFout);
|
fputs(options[i], pset->queryFout);
|
||||||
fputs("\n", pset->queryFout);
|
fputs("\n", pset->queryFout);
|
||||||
@ -469,7 +525,8 @@ exec_command(const char * cmd,
|
|||||||
else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
|
else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
|
||||||
{
|
{
|
||||||
resetPQExpBuffer(query_buf);
|
resetPQExpBuffer(query_buf);
|
||||||
if (!quiet) puts("Query buffer reset (cleared).");
|
if (!quiet)
|
||||||
|
puts("Query buffer reset (cleared).");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -477,6 +534,7 @@ exec_command(const char * cmd,
|
|||||||
else if (strcmp(cmd, "s") == 0)
|
else if (strcmp(cmd, "s") == 0)
|
||||||
{
|
{
|
||||||
const char *fname;
|
const char *fname;
|
||||||
|
|
||||||
if (!options[0])
|
if (!options[0])
|
||||||
fname = "/dev/tty";
|
fname = "/dev/tty";
|
||||||
else
|
else
|
||||||
@ -492,17 +550,24 @@ exec_command(const char * cmd,
|
|||||||
/* \set -- generalized set option command */
|
/* \set -- generalized set option command */
|
||||||
else if (strcmp(cmd, "set") == 0)
|
else if (strcmp(cmd, "set") == 0)
|
||||||
{
|
{
|
||||||
if (!options[0]) {
|
if (!options[0])
|
||||||
|
{
|
||||||
/* list all variables */
|
/* list all variables */
|
||||||
/* (This is in utter violation of the GetVariable abstraction, but
|
|
||||||
I have not dreamt up a better way.) */
|
/*
|
||||||
|
* (This is in utter violation of the GetVariable abstraction,
|
||||||
|
* but I have not dreamt up a better way.)
|
||||||
|
*/
|
||||||
struct _variable *ptr;
|
struct _variable *ptr;
|
||||||
|
|
||||||
for (ptr = pset->vars; ptr->next; ptr = ptr->next)
|
for (ptr = pset->vars; ptr->next; ptr = ptr->next)
|
||||||
fprintf(stdout, "%s = '%s'\n", ptr->next->name, ptr->next->value);
|
fprintf(stdout, "%s = '%s'\n", ptr->next->name, ptr->next->value);
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
if (!SetVariable(pset->vars, options[0], options[1])) {
|
{
|
||||||
|
if (!SetVariable(pset->vars, options[0], options[1]))
|
||||||
|
{
|
||||||
fprintf(stderr, "Set variable failed.\n");
|
fprintf(stderr, "Set variable failed.\n");
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
@ -525,12 +590,15 @@ exec_command(const char * cmd,
|
|||||||
FILE *fd = NULL;
|
FILE *fd = NULL;
|
||||||
bool pipe = false;
|
bool pipe = false;
|
||||||
|
|
||||||
if (!options[0]) {
|
if (!options[0])
|
||||||
|
{
|
||||||
fprintf(stderr, "Usage \\%s <filename>\n", cmd);
|
fprintf(stderr, "Usage \\%s <filename>\n", cmd);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
if (options[0][0] == '|') {
|
{
|
||||||
|
if (options[0][0] == '|')
|
||||||
|
{
|
||||||
pipe = true;
|
pipe = true;
|
||||||
#ifndef __CYGWIN32__
|
#ifndef __CYGWIN32__
|
||||||
fd = popen(&options[0][1], "w");
|
fd = popen(&options[0][1], "w");
|
||||||
@ -538,7 +606,8 @@ exec_command(const char * cmd,
|
|||||||
fd = popen(&options[0][1], "wb");
|
fd = popen(&options[0][1], "wb");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
#ifndef __CYGWIN32__
|
#ifndef __CYGWIN32__
|
||||||
fd = fopen(options[0], "w");
|
fd = fopen(options[0], "w");
|
||||||
#else
|
#else
|
||||||
@ -546,13 +615,15 @@ exec_command(const char * cmd,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fd) {
|
if (!fd)
|
||||||
|
{
|
||||||
perror(options[0]);
|
perror(options[0]);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd) {
|
if (fd)
|
||||||
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (query_buf && query_buf->len > 0)
|
if (query_buf && query_buf->len > 0)
|
||||||
@ -563,7 +634,8 @@ exec_command(const char * cmd,
|
|||||||
else
|
else
|
||||||
result = fclose(fd);
|
result = fclose(fd);
|
||||||
|
|
||||||
if (result == EOF) {
|
if (result == EOF)
|
||||||
|
{
|
||||||
perror("close");
|
perror("close");
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
@ -588,21 +660,26 @@ exec_command(const char * cmd,
|
|||||||
|
|
||||||
|
|
||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
/* These commands don't do anything. I just use them to test the parser. */
|
|
||||||
|
/*
|
||||||
|
* These commands don't do anything. I just use them to test the
|
||||||
|
* parser.
|
||||||
|
*/
|
||||||
else if (strcmp(cmd, "void") == 0 || strcmp(cmd, "#") == 0)
|
else if (strcmp(cmd, "void") == 0 || strcmp(cmd, "#") == 0)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fprintf(stderr, "+ optline = |%s|\n", options_string);
|
fprintf(stderr, "+ optline = |%s|\n", options_string);
|
||||||
for (i = 0; options[i]; i++)
|
for (i = 0; options[i]; i++)
|
||||||
fprintf(stderr, "+ opt%d = |%s|\n", i, options[i]);
|
fprintf(stderr, "+ opt%d = |%s|\n", i, options[i]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
else {
|
else
|
||||||
status = CMD_UNKNOWN;
|
status = CMD_UNKNOWN;
|
||||||
}
|
|
||||||
|
|
||||||
if (!success) status = CMD_ERROR;
|
if (!success)
|
||||||
|
status = CMD_ERROR;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,9 +697,10 @@ static char *
|
|||||||
unescape(const char *source, PsqlSettings *pset)
|
unescape(const char *source, PsqlSettings *pset)
|
||||||
{
|
{
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
bool esc = false; /* Last character we saw was the
|
bool esc = false; /* Last character we saw was the escape
|
||||||
escape character */
|
* character */
|
||||||
char *destination, *tmp;
|
char *destination,
|
||||||
|
*tmp;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
|
||||||
#ifdef USE_ASSERT_CHECKING
|
#ifdef USE_ASSERT_CHECKING
|
||||||
@ -632,13 +710,16 @@ unescape(const char * source, PsqlSettings * pset)
|
|||||||
length = strlen(source) + 1;
|
length = strlen(source) + 1;
|
||||||
|
|
||||||
tmp = destination = (char *) malloc(length);
|
tmp = destination = (char *) malloc(length);
|
||||||
if (!tmp) {
|
if (!tmp)
|
||||||
|
{
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (p = (char *) source; *p; p += PQmblen(p)) {
|
for (p = (char *) source; *p; p += PQmblen(p))
|
||||||
if (esc) {
|
{
|
||||||
|
if (esc)
|
||||||
|
{
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
switch (*p)
|
switch (*p)
|
||||||
@ -655,11 +736,20 @@ unescape(const char * source, PsqlSettings * pset)
|
|||||||
case 'f':
|
case 'f':
|
||||||
c = '\f';
|
c = '\f';
|
||||||
break;
|
break;
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case '0':
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
case '8':
|
||||||
|
case '9':
|
||||||
{
|
{
|
||||||
long int l;
|
long int l;
|
||||||
char *end;
|
char *end;
|
||||||
|
|
||||||
l = strtol(p, &end, 0);
|
l = strtol(p, &end, 0);
|
||||||
c = l;
|
c = l;
|
||||||
p = end - 1;
|
p = end - 1;
|
||||||
@ -672,17 +762,18 @@ unescape(const char * source, PsqlSettings * pset)
|
|||||||
esc = false;
|
esc = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (*p == '\\') {
|
else if (*p == '\\')
|
||||||
esc = true;
|
esc = true;
|
||||||
}
|
|
||||||
|
|
||||||
else if (*p == '$')
|
else if (*p == '$')
|
||||||
{
|
{
|
||||||
if (*(p+1) == '{') {
|
if (*(p + 1) == '{')
|
||||||
|
{
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
char *copy;
|
char *copy;
|
||||||
const char *value;
|
const char *value;
|
||||||
void *new;
|
void *new;
|
||||||
|
|
||||||
len = strcspn(p + 2, "}");
|
len = strcspn(p + 2, "}");
|
||||||
copy = xstrdup(p + 2);
|
copy = xstrdup(p + 2);
|
||||||
copy[len] = '\0';
|
copy[len] = '\0';
|
||||||
@ -690,7 +781,8 @@ unescape(const char * source, PsqlSettings * pset)
|
|||||||
|
|
||||||
length += strlen(value) - (len + 3);
|
length += strlen(value) - (len + 3);
|
||||||
new = realloc(destination, length);
|
new = realloc(destination, length);
|
||||||
if (!new) {
|
if (!new)
|
||||||
|
{
|
||||||
perror("realloc");
|
perror("realloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -702,12 +794,12 @@ unescape(const char * source, PsqlSettings * pset)
|
|||||||
p += len + 2;
|
p += len + 2;
|
||||||
free(copy);
|
free(copy);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
*tmp++ = '$';
|
*tmp++ = '$';
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
*tmp++ = *p;
|
*tmp++ = *p;
|
||||||
esc = false;
|
esc = false;
|
||||||
}
|
}
|
||||||
@ -749,9 +841,8 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings * pset)
|
|||||||
dbparam = new_dbname;
|
dbparam = new_dbname;
|
||||||
|
|
||||||
/* If user is "" or "-" then use the old one */
|
/* If user is "" or "-" then use the old one */
|
||||||
if ( new_user && PQuser(oldconn) && ( strcmp(new_user, "")==0 || strcmp(new_user, "-")==0 || strcmp(new_user, PQuser(oldconn))==0 )) {
|
if (new_user && PQuser(oldconn) && (strcmp(new_user, "") == 0 || strcmp(new_user, "-") == 0 || strcmp(new_user, PQuser(oldconn)) == 0))
|
||||||
userparam = PQuser(oldconn);
|
userparam = PQuser(oldconn);
|
||||||
}
|
|
||||||
/* If username is "?" then prompt */
|
/* If username is "?" then prompt */
|
||||||
else if (new_user && strcmp(new_user, "?") == 0)
|
else if (new_user && strcmp(new_user, "?") == 0)
|
||||||
userparam = prompted_user = simple_prompt("Username: ", 100, true); /* save for free() */
|
userparam = prompted_user = simple_prompt("Username: ", 100, true); /* save for free() */
|
||||||
@ -760,33 +851,39 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings * pset)
|
|||||||
|
|
||||||
/* need to prompt for password? */
|
/* need to prompt for password? */
|
||||||
if (pset->getPassword)
|
if (pset->getPassword)
|
||||||
pwparam = prompted_password = simple_prompt("Password: ", 100, false); /* need to save for free() */
|
pwparam = prompted_password = simple_prompt("Password: ", 100, false); /* need to save for
|
||||||
|
* free() */
|
||||||
|
|
||||||
/* Use old password if no new one given (if you didn't have an old one, fine) */
|
/*
|
||||||
|
* Use old password if no new one given (if you didn't have an old
|
||||||
|
* one, fine)
|
||||||
|
*/
|
||||||
if (!pwparam)
|
if (!pwparam)
|
||||||
pwparam = PQpass(oldconn);
|
pwparam = PQpass(oldconn);
|
||||||
|
|
||||||
|
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PGCLIENTENCODING may be set by the previous connection. if a
|
* PGCLIENTENCODING may be set by the previous connection. if a user
|
||||||
* user does not explicitly set PGCLIENTENCODING, we should
|
* does not explicitly set PGCLIENTENCODING, we should discard
|
||||||
* discard PGCLIENTENCODING so that libpq could get the backend
|
* PGCLIENTENCODING so that libpq could get the backend encoding as
|
||||||
* encoding as the default PGCLIENTENCODING value. -- 1998/12/12
|
* the default PGCLIENTENCODING value. -- 1998/12/12 Tatsuo Ishii
|
||||||
* Tatsuo Ishii
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!pset->has_client_encoding)
|
if (!pset->has_client_encoding)
|
||||||
putenv("PGCLIENTENCODING=");
|
putenv("PGCLIENTENCODING=");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
need_pass = false;
|
need_pass = false;
|
||||||
pset->db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn),
|
pset->db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn),
|
||||||
NULL, NULL, dbparam, userparam, pwparam);
|
NULL, NULL, dbparam, userparam, pwparam);
|
||||||
|
|
||||||
if (PQstatus(pset->db) == CONNECTION_BAD &&
|
if (PQstatus(pset->db) == CONNECTION_BAD &&
|
||||||
strcmp(PQerrorMessage(pset->db), "fe_sendauth: no password supplied\n")==0) {
|
strcmp(PQerrorMessage(pset->db), "fe_sendauth: no password supplied\n") == 0)
|
||||||
|
{
|
||||||
need_pass = true;
|
need_pass = true;
|
||||||
free(prompted_password);
|
free(prompted_password);
|
||||||
prompted_password = NULL;
|
prompted_password = NULL;
|
||||||
@ -797,32 +894,38 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings * pset)
|
|||||||
free(prompted_password);
|
free(prompted_password);
|
||||||
free(prompted_user);
|
free(prompted_user);
|
||||||
|
|
||||||
/* If connection failed, try at least keep the old one.
|
/*
|
||||||
That's probably more convenient than just kicking you out of the
|
* If connection failed, try at least keep the old one. That's
|
||||||
program. */
|
* probably more convenient than just kicking you out of the program.
|
||||||
|
*/
|
||||||
if (!pset->db || PQstatus(pset->db) == CONNECTION_BAD)
|
if (!pset->db || PQstatus(pset->db) == CONNECTION_BAD)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not establish database connection.\n%s", PQerrorMessage(pset->db));
|
fprintf(stderr, "Could not establish database connection.\n%s", PQerrorMessage(pset->db));
|
||||||
PQfinish(pset->db);
|
PQfinish(pset->db);
|
||||||
if (!oldconn || !pset->cur_cmd_interactive) { /* we don't want unpredictable things to happen
|
if (!oldconn || !pset->cur_cmd_interactive)
|
||||||
in scripting mode */
|
{ /* we don't want unpredictable things to
|
||||||
|
* happen in scripting mode */
|
||||||
fputs("Terminating.\n", stderr);
|
fputs("Terminating.\n", stderr);
|
||||||
if (oldconn)
|
if (oldconn)
|
||||||
PQfinish(oldconn);
|
PQfinish(oldconn);
|
||||||
pset->db = NULL;
|
pset->db = NULL;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
fputs("Keeping old connection.\n", stderr);
|
fputs("Keeping old connection.\n", stderr);
|
||||||
pset->db = oldconn;
|
pset->db = oldconn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
if (!GetVariable(pset->vars, "quiet")) {
|
{
|
||||||
|
if (!GetVariable(pset->vars, "quiet"))
|
||||||
|
{
|
||||||
if (userparam != new_user) /* no new user */
|
if (userparam != new_user) /* no new user */
|
||||||
printf("You are now connected to database %s.\n", dbparam);
|
printf("You are now connected to database %s.\n", dbparam);
|
||||||
else if (dbparam != new_dbname) /* no new db */
|
else if (dbparam != new_dbname) /* no new db */
|
||||||
printf("You are now connected as new user %s.\n", new_user);
|
printf("You are now connected as new user %s.\n", new_user);
|
||||||
else /* both new */
|
else
|
||||||
|
/* both new */
|
||||||
printf("You are now connected to database %s as user %s.\n",
|
printf("You are now connected to database %s as user %s.\n",
|
||||||
PQdb(pset->db), PQuser(pset->db));
|
PQdb(pset->db), PQuser(pset->db));
|
||||||
}
|
}
|
||||||
@ -855,7 +958,8 @@ editFile(const char *fname)
|
|||||||
#ifdef USE_ASSERT_CHECKING
|
#ifdef USE_ASSERT_CHECKING
|
||||||
assert(fname);
|
assert(fname);
|
||||||
#else
|
#else
|
||||||
if (!fname) return false;
|
if (!fname)
|
||||||
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Find an editor to use */
|
/* Find an editor to use */
|
||||||
@ -888,21 +992,26 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
|
|||||||
FILE *stream;
|
FILE *stream;
|
||||||
const char *fname;
|
const char *fname;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
struct stat before, after;
|
struct stat before,
|
||||||
|
after;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_ASSERT_CHECKING
|
#ifdef USE_ASSERT_CHECKING
|
||||||
assert(query_buf);
|
assert(query_buf);
|
||||||
#else
|
#else
|
||||||
if (!query_buf) return false;
|
if (!query_buf)
|
||||||
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (filename_arg)
|
if (filename_arg)
|
||||||
fname = filename_arg;
|
fname = filename_arg;
|
||||||
|
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
/* make a temp file to edit */
|
/* make a temp file to edit */
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
mode_t oldumask;
|
mode_t oldumask;
|
||||||
@ -921,18 +1030,23 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
|
|||||||
umask(oldumask);
|
umask(oldumask);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!stream) {
|
if (!stream)
|
||||||
|
{
|
||||||
perror(fname);
|
perror(fname);
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
unsigned int ql = query_buf->len;
|
unsigned int ql = query_buf->len;
|
||||||
if (ql == 0 || query_buf->data[ql - 1] != '\n') {
|
|
||||||
|
if (ql == 0 || query_buf->data[ql - 1] != '\n')
|
||||||
|
{
|
||||||
appendPQExpBufferChar(query_buf, '\n');
|
appendPQExpBufferChar(query_buf, '\n');
|
||||||
ql++;
|
ql++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fwrite(query_buf->data, 1, ql, stream) != ql) {
|
if (fwrite(query_buf->data, 1, ql, stream) != ql)
|
||||||
|
{
|
||||||
perror(fname);
|
perror(fname);
|
||||||
fclose(stream);
|
fclose(stream);
|
||||||
remove(fname);
|
remove(fname);
|
||||||
@ -944,7 +1058,8 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
if (!error && stat(fname, &before) != 0) {
|
if (!error && stat(fname, &before) != 0)
|
||||||
|
{
|
||||||
perror(fname);
|
perror(fname);
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
@ -955,29 +1070,36 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
|
|||||||
error = !editFile(fname);
|
error = !editFile(fname);
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
if (!error && stat(fname, &after) !=0) {
|
if (!error && stat(fname, &after) != 0)
|
||||||
|
{
|
||||||
perror(fname);
|
perror(fname);
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error && before.st_mtime != after.st_mtime) {
|
if (!error && before.st_mtime != after.st_mtime)
|
||||||
|
{
|
||||||
#else
|
#else
|
||||||
if (!error) {
|
if (!error)
|
||||||
|
{
|
||||||
#endif
|
#endif
|
||||||
stream = fopen(fname, "r");
|
stream = fopen(fname, "r");
|
||||||
if (!stream) {
|
if (!stream)
|
||||||
|
{
|
||||||
perror(fname);
|
perror(fname);
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
/* read file back in */
|
/* read file back in */
|
||||||
char line[1024];
|
char line[1024];
|
||||||
size_t result;
|
size_t result;
|
||||||
|
|
||||||
resetPQExpBuffer(query_buf);
|
resetPQExpBuffer(query_buf);
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
result = fread(line, 1, 1024, stream);
|
result = fread(line, 1, 1024, stream);
|
||||||
if (ferror(stream)) {
|
if (ferror(stream))
|
||||||
|
{
|
||||||
perror(fname);
|
perror(fname);
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
@ -1020,7 +1142,8 @@ process_file(const char *filename, PsqlSettings *pset)
|
|||||||
fd = fopen(filename, "r");
|
fd = fopen(filename, "r");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!fd) {
|
if (!fd)
|
||||||
|
{
|
||||||
perror(filename);
|
perror(filename);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1039,7 +1162,8 @@ process_file(const char *filename, PsqlSettings *pset)
|
|||||||
static const char *
|
static const char *
|
||||||
_align2string(enum printFormat in)
|
_align2string(enum printFormat in)
|
||||||
{
|
{
|
||||||
switch (in) {
|
switch (in)
|
||||||
|
{
|
||||||
case PRINT_NOTHING:
|
case PRINT_NOTHING:
|
||||||
return "nothing";
|
return "nothing";
|
||||||
break;
|
break;
|
||||||
@ -1064,17 +1188,20 @@ bool
|
|||||||
do_pset(const char *param, const char *value, printQueryOpt * popt, bool quiet)
|
do_pset(const char *param, const char *value, printQueryOpt * popt, bool quiet)
|
||||||
{
|
{
|
||||||
size_t vallen = 0;
|
size_t vallen = 0;
|
||||||
|
|
||||||
#ifdef USE_ASSERT_CHECKING
|
#ifdef USE_ASSERT_CHECKING
|
||||||
assert(param);
|
assert(param);
|
||||||
#else
|
#else
|
||||||
if (!param) return false;
|
if (!param)
|
||||||
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (value)
|
if (value)
|
||||||
vallen = strlen(value);
|
vallen = strlen(value);
|
||||||
|
|
||||||
/* set format */
|
/* set format */
|
||||||
if (strcmp(param, "format")==0) {
|
if (strcmp(param, "format") == 0)
|
||||||
|
{
|
||||||
if (!value)
|
if (!value)
|
||||||
;
|
;
|
||||||
else if (strncasecmp("unaligned", value, vallen) == 0)
|
else if (strncasecmp("unaligned", value, vallen) == 0)
|
||||||
@ -1085,7 +1212,8 @@ do_pset(const char * param, const char * value, printQueryOpt * popt, bool quiet
|
|||||||
popt->topt.format = PRINT_HTML;
|
popt->topt.format = PRINT_HTML;
|
||||||
else if (strncasecmp("latex", value, vallen) == 0)
|
else if (strncasecmp("latex", value, vallen) == 0)
|
||||||
popt->topt.format = PRINT_LATEX;
|
popt->topt.format = PRINT_LATEX;
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
fprintf(stderr, "Allowed formats are unaligned, aligned, html, latex.\n");
|
fprintf(stderr, "Allowed formats are unaligned, aligned, html, latex.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1095,7 +1223,8 @@ do_pset(const char * param, const char * value, printQueryOpt * popt, bool quiet
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* set border style/width */
|
/* set border style/width */
|
||||||
else if (strcmp(param, "border")==0) {
|
else if (strcmp(param, "border") == 0)
|
||||||
|
{
|
||||||
if (value)
|
if (value)
|
||||||
popt->topt.border = atoi(value);
|
popt->topt.border = atoi(value);
|
||||||
|
|
||||||
@ -1104,15 +1233,18 @@ do_pset(const char * param, const char * value, printQueryOpt * popt, bool quiet
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* set expanded/vertical mode */
|
/* set expanded/vertical mode */
|
||||||
else if (strcmp(param, "x")==0 || strcmp(param, "expanded")==0 || strcmp(param, "vertical")==0) {
|
else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
|
||||||
|
{
|
||||||
popt->topt.expanded = !popt->topt.expanded;
|
popt->topt.expanded = !popt->topt.expanded;
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
printf("Expanded display is %s.\n", popt->topt.expanded ? "on" : "off");
|
printf("Expanded display is %s.\n", popt->topt.expanded ? "on" : "off");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* null display */
|
/* null display */
|
||||||
else if (strcmp(param, "null")==0) {
|
else if (strcmp(param, "null") == 0)
|
||||||
if (value) {
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
free(popt->nullPrint);
|
free(popt->nullPrint);
|
||||||
popt->nullPrint = xstrdup(value);
|
popt->nullPrint = xstrdup(value);
|
||||||
}
|
}
|
||||||
@ -1121,8 +1253,10 @@ do_pset(const char * param, const char * value, printQueryOpt * popt, bool quiet
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* field separator for unaligned text */
|
/* field separator for unaligned text */
|
||||||
else if (strcmp(param, "fieldsep")==0) {
|
else if (strcmp(param, "fieldsep") == 0)
|
||||||
if (value) {
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
free(popt->topt.fieldSep);
|
free(popt->topt.fieldSep);
|
||||||
popt->topt.fieldSep = xstrdup(value);
|
popt->topt.fieldSep = xstrdup(value);
|
||||||
}
|
}
|
||||||
@ -1131,9 +1265,11 @@ do_pset(const char * param, const char * value, printQueryOpt * popt, bool quiet
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* toggle between full and barebones format */
|
/* toggle between full and barebones format */
|
||||||
else if (strcmp(param, "t")==0 || strcmp(param, "tuples_only")==0) {
|
else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
|
||||||
|
{
|
||||||
popt->topt.tuples_only = !popt->topt.tuples_only;
|
popt->topt.tuples_only = !popt->topt.tuples_only;
|
||||||
if (!quiet) {
|
if (!quiet)
|
||||||
|
{
|
||||||
if (popt->topt.tuples_only)
|
if (popt->topt.tuples_only)
|
||||||
puts("Showing only tuples.");
|
puts("Showing only tuples.");
|
||||||
else
|
else
|
||||||
@ -1142,14 +1278,16 @@ do_pset(const char * param, const char * value, printQueryOpt * popt, bool quiet
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* set title override */
|
/* set title override */
|
||||||
else if (strcmp(param, "title")==0) {
|
else if (strcmp(param, "title") == 0)
|
||||||
|
{
|
||||||
free(popt->title);
|
free(popt->title);
|
||||||
if (!value)
|
if (!value)
|
||||||
popt->title = NULL;
|
popt->title = NULL;
|
||||||
else
|
else
|
||||||
popt->title = xstrdup(value);
|
popt->title = xstrdup(value);
|
||||||
|
|
||||||
if (!quiet) {
|
if (!quiet)
|
||||||
|
{
|
||||||
if (popt->title)
|
if (popt->title)
|
||||||
printf("Title is \"%s\".\n", popt->title);
|
printf("Title is \"%s\".\n", popt->title);
|
||||||
else
|
else
|
||||||
@ -1158,14 +1296,16 @@ do_pset(const char * param, const char * value, printQueryOpt * popt, bool quiet
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* set HTML table tag options */
|
/* set HTML table tag options */
|
||||||
else if (strcmp(param, "T")==0 || strcmp(param, "tableattr")==0) {
|
else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
|
||||||
|
{
|
||||||
free(popt->topt.tableAttr);
|
free(popt->topt.tableAttr);
|
||||||
if (!value)
|
if (!value)
|
||||||
popt->topt.tableAttr = NULL;
|
popt->topt.tableAttr = NULL;
|
||||||
else
|
else
|
||||||
popt->topt.tableAttr = xstrdup(value);
|
popt->topt.tableAttr = xstrdup(value);
|
||||||
|
|
||||||
if (!quiet) {
|
if (!quiet)
|
||||||
|
{
|
||||||
if (popt->topt.tableAttr)
|
if (popt->topt.tableAttr)
|
||||||
printf("Table attribute is \"%s\".\n", popt->topt.tableAttr);
|
printf("Table attribute is \"%s\".\n", popt->topt.tableAttr);
|
||||||
else
|
else
|
||||||
@ -1174,9 +1314,11 @@ do_pset(const char * param, const char * value, printQueryOpt * popt, bool quiet
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* toggle use of pager */
|
/* toggle use of pager */
|
||||||
else if (strcmp(param, "pager")==0) {
|
else if (strcmp(param, "pager") == 0)
|
||||||
|
{
|
||||||
popt->topt.pager = !popt->topt.pager;
|
popt->topt.pager = !popt->topt.pager;
|
||||||
if (!quiet) {
|
if (!quiet)
|
||||||
|
{
|
||||||
if (popt->topt.pager)
|
if (popt->topt.pager)
|
||||||
puts("Using pager is on.");
|
puts("Using pager is on.");
|
||||||
else
|
else
|
||||||
@ -1185,7 +1327,8 @@ do_pset(const char * param, const char * value, printQueryOpt * popt, bool quiet
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
fprintf(stderr, "Unknown option: %s\n", param);
|
fprintf(stderr, "Unknown option: %s\n", param);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1202,7 +1345,8 @@ do_shell(const char *command)
|
|||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (!command) {
|
if (!command)
|
||||||
|
{
|
||||||
char *sys;
|
char *sys;
|
||||||
char *shellName;
|
char *shellName;
|
||||||
|
|
||||||
@ -1220,7 +1364,8 @@ do_shell(const char *command)
|
|||||||
else
|
else
|
||||||
result = system(command);
|
result = system(command);
|
||||||
|
|
||||||
if (result==127 || result==-1) {
|
if (result == 127 || result == -1)
|
||||||
|
{
|
||||||
perror("system");
|
perror("system");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -11,36 +11,33 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum _backslashResult {
|
typedef enum _backslashResult
|
||||||
|
{
|
||||||
CMD_UNKNOWN = 0, /* not done parsing yet (internal only) */
|
CMD_UNKNOWN = 0, /* not done parsing yet (internal only) */
|
||||||
CMD_SEND, /* query complete; send off */
|
CMD_SEND, /* query complete; send off */
|
||||||
CMD_SKIP_LINE, /* keep building query */
|
CMD_SKIP_LINE, /* keep building query */
|
||||||
CMD_TERMINATE, /* quit program */
|
CMD_TERMINATE, /* quit program */
|
||||||
CMD_NEWEDIT, /* query buffer was changed (e.g., via \e) */
|
CMD_NEWEDIT, /* query buffer was changed (e.g., via \e) */
|
||||||
CMD_ERROR /* the execution of the backslash command resulted
|
CMD_ERROR /* the execution of the backslash command
|
||||||
in an error */
|
* resulted in an error */
|
||||||
} backslashResult;
|
} backslashResult;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
backslashResult
|
backslashResult HandleSlashCmds(PsqlSettings *pset,
|
||||||
HandleSlashCmds(PsqlSettings *pset,
|
|
||||||
const char *line,
|
const char *line,
|
||||||
PQExpBuffer query_buf,
|
PQExpBuffer query_buf,
|
||||||
const char **end_of_cmd);
|
const char **end_of_cmd);
|
||||||
|
|
||||||
bool
|
bool do_connect(const char *new_dbname,
|
||||||
do_connect(const char *new_dbname,
|
|
||||||
const char *new_user,
|
const char *new_user,
|
||||||
PsqlSettings *pset);
|
PsqlSettings *pset);
|
||||||
|
|
||||||
bool
|
bool process_file(const char *filename,
|
||||||
process_file(const char *filename,
|
|
||||||
PsqlSettings *pset);
|
PsqlSettings *pset);
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool do_pset(const char *param,
|
||||||
do_pset(const char * param,
|
|
||||||
const char *value,
|
const char *value,
|
||||||
printQueryOpt * popt,
|
printQueryOpt * popt,
|
||||||
bool quiet);
|
bool quiet);
|
||||||
|
@ -39,15 +39,19 @@
|
|||||||
* "Safe" wrapper around strdup()
|
* "Safe" wrapper around strdup()
|
||||||
* (Using this also avoids writing #ifdef HAVE_STRDUP in every file :)
|
* (Using this also avoids writing #ifdef HAVE_STRDUP in every file :)
|
||||||
*/
|
*/
|
||||||
char * xstrdup(const char * string)
|
char *
|
||||||
|
xstrdup(const char *string)
|
||||||
{
|
{
|
||||||
char *tmp;
|
char *tmp;
|
||||||
if (!string) {
|
|
||||||
|
if (!string)
|
||||||
|
{
|
||||||
fprintf(stderr, "xstrdup: Cannot duplicate null pointer.\n");
|
fprintf(stderr, "xstrdup: Cannot duplicate null pointer.\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
tmp = strdup(string);
|
tmp = strdup(string);
|
||||||
if (!tmp) {
|
if (!tmp)
|
||||||
|
{
|
||||||
perror("strdup");
|
perror("strdup");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -72,7 +76,8 @@ setQFout(const char *fname, PsqlSettings *pset)
|
|||||||
#ifdef USE_ASSERT_CHECKING
|
#ifdef USE_ASSERT_CHECKING
|
||||||
assert(pset);
|
assert(pset);
|
||||||
#else
|
#else
|
||||||
if (!pset) return false;
|
if (!pset)
|
||||||
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Close old file/pipe */
|
/* Close old file/pipe */
|
||||||
@ -150,13 +155,16 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
|
|||||||
char *destination;
|
char *destination;
|
||||||
|
|
||||||
#ifdef HAVE_TERMIOS_H
|
#ifdef HAVE_TERMIOS_H
|
||||||
struct termios t_orig, t;
|
struct termios t_orig,
|
||||||
|
t;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
destination = (char *) malloc(maxlen + 2);
|
destination = (char *) malloc(maxlen + 2);
|
||||||
if (!destination)
|
if (!destination)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (prompt) fputs(prompt, stdout);
|
if (prompt)
|
||||||
|
fputs(prompt, stdout);
|
||||||
|
|
||||||
#ifdef HAVE_TERMIOS_H
|
#ifdef HAVE_TERMIOS_H
|
||||||
if (!echo)
|
if (!echo)
|
||||||
@ -171,17 +179,21 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
|
|||||||
fgets(destination, maxlen, stdin);
|
fgets(destination, maxlen, stdin);
|
||||||
|
|
||||||
#ifdef HAVE_TERMIOS_H
|
#ifdef HAVE_TERMIOS_H
|
||||||
if (!echo) {
|
if (!echo)
|
||||||
|
{
|
||||||
tcsetattr(0, TCSADRAIN, &t_orig);
|
tcsetattr(0, TCSADRAIN, &t_orig);
|
||||||
puts("");
|
puts("");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
length = strlen(destination);
|
length = strlen(destination);
|
||||||
if (length > 0 && destination[length - 1] != '\n') {
|
if (length > 0 && destination[length - 1] != '\n')
|
||||||
|
{
|
||||||
/* eat rest of the line */
|
/* eat rest of the line */
|
||||||
char buf[512];
|
char buf[512];
|
||||||
do {
|
|
||||||
|
do
|
||||||
|
{
|
||||||
fgets(buf, 512, stdin);
|
fgets(buf, 512, stdin);
|
||||||
} while (buf[strlen(buf) - 1] != '\n');
|
} while (buf[strlen(buf) - 1] != '\n');
|
||||||
}
|
}
|
||||||
@ -213,10 +225,12 @@ interpolate_var(const char * name, PsqlSettings * pset)
|
|||||||
assert(name);
|
assert(name);
|
||||||
assert(pset);
|
assert(pset);
|
||||||
#else
|
#else
|
||||||
if (!name || !pset) return NULL;
|
if (!name || !pset)
|
||||||
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (strspn(name, VALID_VARIABLE_CHARS) == strlen(name)) {
|
if (strspn(name, VALID_VARIABLE_CHARS) == strlen(name))
|
||||||
|
{
|
||||||
var = GetVariable(pset->vars, name);
|
var = GetVariable(pset->vars, name);
|
||||||
if (var)
|
if (var)
|
||||||
return var;
|
return var;
|
||||||
@ -225,41 +239,50 @@ interpolate_var(const char * name, PsqlSettings * pset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* otherwise return magic variable */
|
/* otherwise return magic variable */
|
||||||
/* (by convention these should be capitalized (but not all caps), to not be
|
|
||||||
shadowed by regular vars or to shadow env vars) */
|
/*
|
||||||
|
* (by convention these should be capitalized (but not all caps), to
|
||||||
|
* not be shadowed by regular vars or to shadow env vars)
|
||||||
|
*/
|
||||||
if (strcmp(name, "Version") == 0)
|
if (strcmp(name, "Version") == 0)
|
||||||
return PG_VERSION_STR;
|
return PG_VERSION_STR;
|
||||||
|
|
||||||
if (strcmp(name, "Database")==0) {
|
if (strcmp(name, "Database") == 0)
|
||||||
|
{
|
||||||
if (PQdb(pset->db))
|
if (PQdb(pset->db))
|
||||||
return PQdb(pset->db);
|
return PQdb(pset->db);
|
||||||
else
|
else
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(name, "User")==0) {
|
if (strcmp(name, "User") == 0)
|
||||||
|
{
|
||||||
if (PQuser(pset->db))
|
if (PQuser(pset->db))
|
||||||
return PQuser(pset->db);
|
return PQuser(pset->db);
|
||||||
else
|
else
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(name, "Host")==0) {
|
if (strcmp(name, "Host") == 0)
|
||||||
|
{
|
||||||
if (PQhost(pset->db))
|
if (PQhost(pset->db))
|
||||||
return PQhost(pset->db);
|
return PQhost(pset->db);
|
||||||
else
|
else
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(name, "Port")==0) {
|
if (strcmp(name, "Port") == 0)
|
||||||
|
{
|
||||||
if (PQport(pset->db))
|
if (PQport(pset->db))
|
||||||
return PQport(pset->db);
|
return PQport(pset->db);
|
||||||
else
|
else
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* env vars (if env vars are all caps there should be no prob, otherwise
|
/*
|
||||||
you're on your own */
|
* env vars (if env vars are all caps there should be no prob,
|
||||||
|
* otherwise you're on your own
|
||||||
|
*/
|
||||||
|
|
||||||
if ((var = getenv(name)))
|
if ((var = getenv(name)))
|
||||||
return var;
|
return var;
|
||||||
@ -302,7 +325,8 @@ handle_sigint(SIGNAL_ARGS)
|
|||||||
/* Try to send cancel request */
|
/* Try to send cancel request */
|
||||||
if (PQrequestCancel(cancelConn))
|
if (PQrequestCancel(cancelConn))
|
||||||
safe_write_stderr("\nCANCEL request sent\n");
|
safe_write_stderr("\nCANCEL request sent\n");
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
safe_write_stderr("\nCould not send cancel request: ");
|
safe_write_stderr("\nCould not send cancel request: ");
|
||||||
safe_write_stderr(PQerrorMessage(cancelConn));
|
safe_write_stderr(PQerrorMessage(cancelConn));
|
||||||
}
|
}
|
||||||
@ -322,13 +346,15 @@ PSQLexec(PsqlSettings *pset, const char *query)
|
|||||||
PGresult *res;
|
PGresult *res;
|
||||||
const char *var;
|
const char *var;
|
||||||
|
|
||||||
if (!pset->db) {
|
if (!pset->db)
|
||||||
|
{
|
||||||
fputs("You are not currently connected to a database.\n", stderr);
|
fputs("You are not currently connected to a database.\n", stderr);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
var = GetVariable(pset->vars, "echo_secret");
|
var = GetVariable(pset->vars, "echo_secret");
|
||||||
if (var) {
|
if (var)
|
||||||
|
{
|
||||||
printf("********* QUERY *********\n%s\n*************************\n\n", query);
|
printf("********* QUERY *********\n%s\n*************************\n\n", query);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
@ -347,7 +373,8 @@ PSQLexec(PsqlSettings *pset, const char *query)
|
|||||||
{
|
{
|
||||||
fputs("The connection to the server was lost. Attempting reset: ", stderr);
|
fputs("The connection to the server was lost. Attempting reset: ", stderr);
|
||||||
PQreset(pset->db);
|
PQreset(pset->db);
|
||||||
if (PQstatus(pset->db) == CONNECTION_BAD) {
|
if (PQstatus(pset->db) == CONNECTION_BAD)
|
||||||
|
{
|
||||||
fputs("Failed.\n", stderr);
|
fputs("Failed.\n", stderr);
|
||||||
PQfinish(pset->db);
|
PQfinish(pset->db);
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
@ -364,7 +391,8 @@ PSQLexec(PsqlSettings *pset, const char *query)
|
|||||||
PQresultStatus(res) == PGRES_COPY_OUT)
|
PQresultStatus(res) == PGRES_COPY_OUT)
|
||||||
)
|
)
|
||||||
return res;
|
return res;
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
fprintf(stderr, "%s", PQerrorMessage(pset->db));
|
fprintf(stderr, "%s", PQerrorMessage(pset->db));
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -392,13 +420,16 @@ SendQuery(PsqlSettings *pset, const char *query)
|
|||||||
PGresult *results;
|
PGresult *results;
|
||||||
PGnotify *notify;
|
PGnotify *notify;
|
||||||
|
|
||||||
if (!pset->db) {
|
if (!pset->db)
|
||||||
|
{
|
||||||
fputs("You are not currently connected to a database.\n", stderr);
|
fputs("You are not currently connected to a database.\n", stderr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetVariableBool(pset->vars, "singlestep")) {
|
if (GetVariableBool(pset->vars, "singlestep"))
|
||||||
|
{
|
||||||
char buf[3];
|
char buf[3];
|
||||||
|
|
||||||
fprintf(stdout, "***(Single step mode: Verify query)*********************************************\n"
|
fprintf(stdout, "***(Single step mode: Verify query)*********************************************\n"
|
||||||
"QUERY: %s\n"
|
"QUERY: %s\n"
|
||||||
"***(press return to proceed or enter x and return to cancel)********************\n",
|
"***(press return to proceed or enter x and return to cancel)********************\n",
|
||||||
@ -432,7 +463,8 @@ SendQuery(PsqlSettings *pset, const char *query)
|
|||||||
PsqlSettings settings_copy = *pset;
|
PsqlSettings settings_copy = *pset;
|
||||||
|
|
||||||
settings_copy.queryFout = stdout;
|
settings_copy.queryFout = stdout;
|
||||||
if (!setQFout(pset->gfname, &settings_copy)) {
|
if (!setQFout(pset->gfname, &settings_copy))
|
||||||
|
{
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -491,7 +523,8 @@ SendQuery(PsqlSettings *pset, const char *query)
|
|||||||
{
|
{
|
||||||
fputs("The connection to the server was lost. Attempting reset: ", stderr);
|
fputs("The connection to the server was lost. Attempting reset: ", stderr);
|
||||||
PQreset(pset->db);
|
PQreset(pset->db);
|
||||||
if (PQstatus(pset->db) == CONNECTION_BAD) {
|
if (PQstatus(pset->db) == CONNECTION_BAD)
|
||||||
|
{
|
||||||
fputs("Failed.\n", stderr);
|
fputs("Failed.\n", stderr);
|
||||||
PQfinish(pset->db);
|
PQfinish(pset->db);
|
||||||
PQclear(results);
|
PQclear(results);
|
||||||
|
@ -33,7 +33,8 @@
|
|||||||
* returns a malloc'ed structure with the options, or NULL on parsing error
|
* returns a malloc'ed structure with the options, or NULL on parsing error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct copy_options {
|
struct copy_options
|
||||||
|
{
|
||||||
char *table;
|
char *table;
|
||||||
char *file;
|
char *file;
|
||||||
bool from;
|
bool from;
|
||||||
@ -66,7 +67,8 @@ parse_slash_copy(const char *args)
|
|||||||
|
|
||||||
line = xstrdup(args);
|
line = xstrdup(args);
|
||||||
|
|
||||||
if (!(result = calloc(1, sizeof (struct copy_options)))) {
|
if (!(result = calloc(1, sizeof(struct copy_options))))
|
||||||
|
{
|
||||||
perror("calloc");
|
perror("calloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -74,8 +76,10 @@ parse_slash_copy(const char *args)
|
|||||||
token = strtokx(line, " \t", "\"", '\\', "e, NULL);
|
token = strtokx(line, " \t", "\"", '\\', "e, NULL);
|
||||||
if (!token)
|
if (!token)
|
||||||
error = true;
|
error = true;
|
||||||
else {
|
else
|
||||||
if (!quote && strcasecmp(token, "binary")==0) {
|
{
|
||||||
|
if (!quote && strcasecmp(token, "binary") == 0)
|
||||||
|
{
|
||||||
result->binary = true;
|
result->binary = true;
|
||||||
token = strtokx(NULL, " \t", "\"", '\\', "e, NULL);
|
token = strtokx(NULL, " \t", "\"", '\\', "e, NULL);
|
||||||
if (!token)
|
if (!token)
|
||||||
@ -89,19 +93,23 @@ parse_slash_copy(const char *args)
|
|||||||
assert(error || result->table);
|
assert(error || result->table);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!error) {
|
if (!error)
|
||||||
|
{
|
||||||
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
||||||
if (!token)
|
if (!token)
|
||||||
error = true;
|
error = true;
|
||||||
else {
|
else
|
||||||
if (strcasecmp(token, "with")==0) {
|
{
|
||||||
|
if (strcasecmp(token, "with") == 0)
|
||||||
|
{
|
||||||
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
||||||
if (!token || strcasecmp(token, "oids") != 0)
|
if (!token || strcasecmp(token, "oids") != 0)
|
||||||
error = true;
|
error = true;
|
||||||
else
|
else
|
||||||
result->oids = true;
|
result->oids = true;
|
||||||
|
|
||||||
if (!error) {
|
if (!error)
|
||||||
|
{
|
||||||
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
||||||
if (!token)
|
if (!token)
|
||||||
error = true;
|
error = true;
|
||||||
@ -117,7 +125,8 @@ parse_slash_copy(const char *args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error) {
|
if (!error)
|
||||||
|
{
|
||||||
token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
|
token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
|
||||||
if (!token)
|
if (!token)
|
||||||
error = true;
|
error = true;
|
||||||
@ -129,16 +138,20 @@ parse_slash_copy(const char *args)
|
|||||||
assert(error || result->file);
|
assert(error || result->file);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!error) {
|
if (!error)
|
||||||
|
{
|
||||||
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
||||||
if (token) {
|
if (token)
|
||||||
|
{
|
||||||
if (strcasecmp(token, "using") != 0)
|
if (strcasecmp(token, "using") != 0)
|
||||||
error = true;
|
error = true;
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
||||||
if (!token || strcasecmp(token, "delimiters") != 0)
|
if (!token || strcasecmp(token, "delimiters") != 0)
|
||||||
error = true;
|
error = true;
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
|
token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
|
||||||
if (token)
|
if (token)
|
||||||
result->delim = xstrdup(token);
|
result->delim = xstrdup(token);
|
||||||
@ -151,7 +164,8 @@ parse_slash_copy(const char *args)
|
|||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
|
|
||||||
if (error) {
|
if (error)
|
||||||
|
{
|
||||||
fputs("Parse error at ", stderr);
|
fputs("Parse error at ", stderr);
|
||||||
if (!token)
|
if (!token)
|
||||||
fputs("end of line.", stderr);
|
fputs("end of line.", stderr);
|
||||||
@ -204,10 +218,14 @@ do_copy(const char * args, PsqlSettings *pset)
|
|||||||
strcat(query, "TO stdout");
|
strcat(query, "TO stdout");
|
||||||
|
|
||||||
|
|
||||||
if (options->delim) {
|
if (options->delim)
|
||||||
/* backend copy only uses the first character here,
|
{
|
||||||
but that might be the escape backslash
|
|
||||||
(makes me wonder though why it's called delimiterS) */
|
/*
|
||||||
|
* backend copy only uses the first character here, but that might
|
||||||
|
* be the escape backslash (makes me wonder though why it's called
|
||||||
|
* delimiterS)
|
||||||
|
*/
|
||||||
strncat(query, " USING DELIMITERS '", 2);
|
strncat(query, " USING DELIMITERS '", 2);
|
||||||
strcat(query, options->delim);
|
strcat(query, options->delim);
|
||||||
strcat(query, "'");
|
strcat(query, "'");
|
||||||
@ -227,7 +245,8 @@ do_copy(const char * args, PsqlSettings *pset)
|
|||||||
copystream = fopen(options->file, "wb");
|
copystream = fopen(options->file, "wb");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!copystream) {
|
if (!copystream)
|
||||||
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Unable to open file %s which to copy: %s\n",
|
"Unable to open file %s which to copy: %s\n",
|
||||||
options->from ? "from" : "to", strerror(errno));
|
options->from ? "from" : "to", strerror(errno));
|
||||||
@ -258,7 +277,8 @@ do_copy(const char * args, PsqlSettings *pset)
|
|||||||
|
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
|
|
||||||
if (!GetVariable(pset->vars, "quiet")) {
|
if (!GetVariable(pset->vars, "quiet"))
|
||||||
|
{
|
||||||
if (success)
|
if (success)
|
||||||
puts("Successfully copied.");
|
puts("Successfully copied.");
|
||||||
else
|
else
|
||||||
|
@ -36,15 +36,19 @@
|
|||||||
bool
|
bool
|
||||||
describeAggregates(const char *name, PsqlSettings *pset)
|
describeAggregates(const char *name, PsqlSettings *pset)
|
||||||
{
|
{
|
||||||
char descbuf[384 + 2*REGEXP_CUTOFF]; /* observe/adjust this if you change the query */
|
char descbuf[384 + 2 * REGEXP_CUTOFF]; /* observe/adjust this
|
||||||
|
* if you change the
|
||||||
|
* query */
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
bool description = GetVariableBool(pset->vars, "description");
|
bool description = GetVariableBool(pset->vars, "description");
|
||||||
printQueryOpt myopt = pset->popt;
|
printQueryOpt myopt = pset->popt;
|
||||||
|
|
||||||
descbuf[0] = '\0';
|
descbuf[0] = '\0';
|
||||||
|
|
||||||
/* There are two kinds of aggregates: ones that work on particular types
|
/*
|
||||||
ones that work on all */
|
* There are two kinds of aggregates: ones that work on particular
|
||||||
|
* types ones that work on all
|
||||||
|
*/
|
||||||
strcat(descbuf,
|
strcat(descbuf,
|
||||||
"SELECT a.aggname AS \"Name\", t.typname AS \"Type\"");
|
"SELECT a.aggname AS \"Name\", t.typname AS \"Type\"");
|
||||||
if (description)
|
if (description)
|
||||||
@ -53,7 +57,8 @@ describeAggregates(const char * name, PsqlSettings * pset)
|
|||||||
strcat(descbuf,
|
strcat(descbuf,
|
||||||
"\nFROM pg_aggregate a, pg_type t\n"
|
"\nFROM pg_aggregate a, pg_type t\n"
|
||||||
"WHERE a.aggbasetype = t.oid\n");
|
"WHERE a.aggbasetype = t.oid\n");
|
||||||
if (name) {
|
if (name)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND a.aggname ~* '^");
|
strcat(descbuf, " AND a.aggname ~* '^");
|
||||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "'\n");
|
strcat(descbuf, "'\n");
|
||||||
@ -103,9 +108,8 @@ describeFunctions(const char * name, PsqlSettings * pset)
|
|||||||
printQueryOpt myopt = pset->popt;
|
printQueryOpt myopt = pset->popt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we skip in/out funcs by excluding functions that take
|
* we skip in/out funcs by excluding functions that take some
|
||||||
* some arguments, but have no types defined for those
|
* arguments, but have no types defined for those arguments
|
||||||
* arguments
|
|
||||||
*/
|
*/
|
||||||
descbuf[0] = '\0';
|
descbuf[0] = '\0';
|
||||||
|
|
||||||
@ -158,7 +162,8 @@ describeTypes(const char * name, PsqlSettings * pset)
|
|||||||
strcat(descbuf, "\nFROM pg_type\n"
|
strcat(descbuf, "\nFROM pg_type\n"
|
||||||
"WHERE typrelid = 0 AND typname !~ '^_.*'\n");
|
"WHERE typrelid = 0 AND typname !~ '^_.*'\n");
|
||||||
|
|
||||||
if (name) {
|
if (name)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND typname ~* '^");
|
strcat(descbuf, " AND typname ~* '^");
|
||||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "' ");
|
strcat(descbuf, "' ");
|
||||||
@ -189,7 +194,8 @@ describeTypes(const char * name, PsqlSettings * pset)
|
|||||||
bool
|
bool
|
||||||
describeOperators(const char *name, PsqlSettings *pset)
|
describeOperators(const char *name, PsqlSettings *pset)
|
||||||
{
|
{
|
||||||
char descbuf[1536 + 3 * 32]; /* 32 is max length for operator name */
|
char descbuf[1536 + 3 * 32]; /* 32 is max length for operator
|
||||||
|
* name */
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
bool description = GetVariableBool(pset->vars, "description");
|
bool description = GetVariableBool(pset->vars, "description");
|
||||||
printQueryOpt myopt = pset->popt;
|
printQueryOpt myopt = pset->popt;
|
||||||
@ -329,7 +335,8 @@ permissionsList(const char * name, PsqlSettings *pset)
|
|||||||
"FROM pg_class\n"
|
"FROM pg_class\n"
|
||||||
"WHERE ( relkind = 'r' OR relkind = 'S') AND\n"
|
"WHERE ( relkind = 'r' OR relkind = 'S') AND\n"
|
||||||
" relname !~ '^pg_'\n");
|
" relname !~ '^pg_'\n");
|
||||||
if (name) {
|
if (name)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND rename ~ '^");
|
strcat(descbuf, " AND rename ~ '^");
|
||||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "'\n");
|
strcat(descbuf, "'\n");
|
||||||
@ -340,10 +347,10 @@ permissionsList(const char * name, PsqlSettings *pset)
|
|||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (PQntuples(res) == 0) {
|
if (PQntuples(res) == 0)
|
||||||
fputs("Couldn't find any tables.\n", pset->queryFout);
|
fputs("Couldn't find any tables.\n", pset->queryFout);
|
||||||
}
|
else
|
||||||
else {
|
{
|
||||||
myopt.topt.tuples_only = false;
|
myopt.topt.tuples_only = false;
|
||||||
myopt.nullPrint = NULL;
|
myopt.nullPrint = NULL;
|
||||||
sprintf(descbuf, "Access permissions for database \"%s\"", PQdb(pset->db));
|
sprintf(descbuf, "Access permissions for database \"%s\"", PQdb(pset->db));
|
||||||
@ -380,7 +387,8 @@ objectDescription(const char * object, PsqlSettings *pset)
|
|||||||
strcat(descbuf, "SELECT DISTINCT a.aggname as \"Name\", 'aggregate'::text as \"What\", d.description as \"Description\"\n"
|
strcat(descbuf, "SELECT DISTINCT a.aggname as \"Name\", 'aggregate'::text as \"What\", d.description as \"Description\"\n"
|
||||||
"FROM pg_aggregate a, pg_description d\n"
|
"FROM pg_aggregate a, pg_description d\n"
|
||||||
"WHERE a.oid = d.objoid\n");
|
"WHERE a.oid = d.objoid\n");
|
||||||
if (object) {
|
if (object)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND a.aggname ~* '^");
|
strcat(descbuf, " AND a.aggname ~* '^");
|
||||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "'\n");
|
strcat(descbuf, "'\n");
|
||||||
@ -391,7 +399,8 @@ objectDescription(const char * object, PsqlSettings *pset)
|
|||||||
strcat(descbuf, "SELECT DISTINCT p.proname as \"Name\", 'function'::text as \"What\", d.description as \"Description\"\n"
|
strcat(descbuf, "SELECT DISTINCT p.proname as \"Name\", 'function'::text as \"What\", d.description as \"Description\"\n"
|
||||||
"FROM pg_proc p, pg_description d\n"
|
"FROM pg_proc p, pg_description d\n"
|
||||||
"WHERE p.oid = d.objoid AND (p.pronargs = 0 or oid8types(p.proargtypes) != '')\n");
|
"WHERE p.oid = d.objoid AND (p.pronargs = 0 or oid8types(p.proargtypes) != '')\n");
|
||||||
if (object) {
|
if (object)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND p.proname ~* '^");
|
strcat(descbuf, " AND p.proname ~* '^");
|
||||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "'\n");
|
strcat(descbuf, "'\n");
|
||||||
@ -403,7 +412,8 @@ objectDescription(const char * object, PsqlSettings *pset)
|
|||||||
"FROM pg_operator o, pg_description d\n"
|
"FROM pg_operator o, pg_description d\n"
|
||||||
// must get comment via associated function
|
// must get comment via associated function
|
||||||
"WHERE RegprocToOid(o.oprcode) = d.objoid\n");
|
"WHERE RegprocToOid(o.oprcode) = d.objoid\n");
|
||||||
if (object) {
|
if (object)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND o.oprname = '");
|
strcat(descbuf, " AND o.oprname = '");
|
||||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "'\n");
|
strcat(descbuf, "'\n");
|
||||||
@ -414,7 +424,8 @@ objectDescription(const char * object, PsqlSettings *pset)
|
|||||||
strcat(descbuf, "SELECT DISTINCT t.typname as \"Name\", 'type'::text as \"What\", d.description as \"Description\"\n"
|
strcat(descbuf, "SELECT DISTINCT t.typname as \"Name\", 'type'::text as \"What\", d.description as \"Description\"\n"
|
||||||
"FROM pg_type t, pg_description d\n"
|
"FROM pg_type t, pg_description d\n"
|
||||||
"WHERE t.oid = d.objoid\n");
|
"WHERE t.oid = d.objoid\n");
|
||||||
if (object) {
|
if (object)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND t.typname ~* '^");
|
strcat(descbuf, " AND t.typname ~* '^");
|
||||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "'\n");
|
strcat(descbuf, "'\n");
|
||||||
@ -425,7 +436,8 @@ objectDescription(const char * object, PsqlSettings *pset)
|
|||||||
strcat(descbuf, "SELECT DISTINCT c.relname as \"Name\", 'relation'::text||'('||c.relkind||')' as \"What\", d.description as \"Description\"\n"
|
strcat(descbuf, "SELECT DISTINCT c.relname as \"Name\", 'relation'::text||'('||c.relkind||')' as \"What\", d.description as \"Description\"\n"
|
||||||
"FROM pg_class c, pg_description d\n"
|
"FROM pg_class c, pg_description d\n"
|
||||||
"WHERE c.oid = d.objoid\n");
|
"WHERE c.oid = d.objoid\n");
|
||||||
if (object) {
|
if (object)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND c.relname ~* '^");
|
strcat(descbuf, " AND c.relname ~* '^");
|
||||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "'\n");
|
strcat(descbuf, "'\n");
|
||||||
@ -436,7 +448,8 @@ objectDescription(const char * object, PsqlSettings *pset)
|
|||||||
strcat(descbuf, "SELECT DISTINCT r.rulename as \"Name\", 'rule'::text as \"What\", d.description as \"Description\"\n"
|
strcat(descbuf, "SELECT DISTINCT r.rulename as \"Name\", 'rule'::text as \"What\", d.description as \"Description\"\n"
|
||||||
"FROM pg_rewrite r, pg_description d\n"
|
"FROM pg_rewrite r, pg_description d\n"
|
||||||
"WHERE r.oid = d.objoid AND r.rulename !~ '^_RET'\n");
|
"WHERE r.oid = d.objoid AND r.rulename !~ '^_RET'\n");
|
||||||
if (object) {
|
if (object)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND r.rulename ~* '^");
|
strcat(descbuf, " AND r.rulename ~* '^");
|
||||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "'\n");
|
strcat(descbuf, "'\n");
|
||||||
@ -447,7 +460,8 @@ objectDescription(const char * object, PsqlSettings *pset)
|
|||||||
strcat(descbuf, "SELECT DISTINCT t.tgname as \"Name\", 'trigger'::text as \"What\", d.description as \"Description\"\n"
|
strcat(descbuf, "SELECT DISTINCT t.tgname as \"Name\", 'trigger'::text as \"What\", d.description as \"Description\"\n"
|
||||||
"FROM pg_trigger t, pg_description d\n"
|
"FROM pg_trigger t, pg_description d\n"
|
||||||
"WHERE t.oid = d.objoid\n");
|
"WHERE t.oid = d.objoid\n");
|
||||||
if (object) {
|
if (object)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND t.tgname ~* '^");
|
strcat(descbuf, " AND t.tgname ~* '^");
|
||||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "'\n");
|
strcat(descbuf, "'\n");
|
||||||
@ -480,11 +494,14 @@ objectDescription(const char * object, PsqlSettings *pset)
|
|||||||
* and pass it to the underlying printTable() function.
|
* and pass it to the underlying printTable() function.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void * xmalloc(size_t size)
|
static void *
|
||||||
|
xmalloc(size_t size)
|
||||||
{
|
{
|
||||||
void *tmp;
|
void *tmp;
|
||||||
|
|
||||||
tmp = malloc(size);
|
tmp = malloc(size);
|
||||||
if (!tmp) {
|
if (!tmp)
|
||||||
|
{
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -496,7 +513,9 @@ bool
|
|||||||
describeTableDetails(const char *name, PsqlSettings *pset)
|
describeTableDetails(const char *name, PsqlSettings *pset)
|
||||||
{
|
{
|
||||||
char descbuf[512 + NAMEDATALEN];
|
char descbuf[512 + NAMEDATALEN];
|
||||||
PGresult *res = NULL, *res2 = NULL, *res3 = NULL;
|
PGresult *res = NULL,
|
||||||
|
*res2 = NULL,
|
||||||
|
*res3 = NULL;
|
||||||
printTableOpt myopt = pset->popt.topt;
|
printTableOpt myopt = pset->popt.topt;
|
||||||
bool description = GetVariableBool(pset->vars, "description");
|
bool description = GetVariableBool(pset->vars, "description");
|
||||||
int i;
|
int i;
|
||||||
@ -513,7 +532,8 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
|||||||
headers[0] = "Attribute";
|
headers[0] = "Attribute";
|
||||||
headers[1] = "Type";
|
headers[1] = "Type";
|
||||||
headers[2] = "Info";
|
headers[2] = "Info";
|
||||||
if (description) {
|
if (description)
|
||||||
|
{
|
||||||
headers[3] = "Description";
|
headers[3] = "Description";
|
||||||
headers[4] = NULL;
|
headers[4] = NULL;
|
||||||
}
|
}
|
||||||
@ -535,7 +555,8 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Did we get anything? */
|
/* Did we get anything? */
|
||||||
if (PQntuples(res)==0) {
|
if (PQntuples(res) == 0)
|
||||||
|
{
|
||||||
if (!GetVariableBool(pset->vars, "quiet"))
|
if (!GetVariableBool(pset->vars, "quiet"))
|
||||||
fprintf(stdout, "Did not find any class named \"%s\".\n", name);
|
fprintf(stdout, "Did not find any class named \"%s\".\n", name);
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
@ -557,17 +578,20 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
|||||||
|
|
||||||
/* Generate table cells to be printed */
|
/* Generate table cells to be printed */
|
||||||
cells = calloc(PQntuples(res) * cols + 1, sizeof(*cells));
|
cells = calloc(PQntuples(res) * cols + 1, sizeof(*cells));
|
||||||
if (!cells) {
|
if (!cells)
|
||||||
|
{
|
||||||
perror("calloc");
|
perror("calloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < PQntuples(res); i++) {
|
for (i = 0; i < PQntuples(res); i++)
|
||||||
|
{
|
||||||
int4 attypmod = atoi(PQgetvalue(res, i, 3));
|
int4 attypmod = atoi(PQgetvalue(res, i, 3));
|
||||||
char *attype = PQgetvalue(res, i, 1);
|
char *attype = PQgetvalue(res, i, 1);
|
||||||
|
|
||||||
/* Name */
|
/* Name */
|
||||||
cells[i*cols + 0] = PQgetvalue(res, i, 0); /* don't free this afterwards */
|
cells[i * cols + 0] = PQgetvalue(res, i, 0); /* don't free this
|
||||||
|
* afterwards */
|
||||||
|
|
||||||
/* Type */
|
/* Type */
|
||||||
cells[i * cols + 1] = xmalloc(NAMEDATALEN + 16);
|
cells[i * cols + 1] = xmalloc(NAMEDATALEN + 16);
|
||||||
@ -584,11 +608,13 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
|||||||
strcpy(cells[i * cols + 1], attype);
|
strcpy(cells[i * cols + 1], attype);
|
||||||
|
|
||||||
/* Info */
|
/* Info */
|
||||||
cells[i*cols + 2] = xmalloc(128 + 128); /* I'm cutting off the default string at 128 */
|
cells[i * cols + 2] = xmalloc(128 + 128); /* I'm cutting off the
|
||||||
|
* default string at 128 */
|
||||||
cells[i * cols + 2][0] = '\0';
|
cells[i * cols + 2][0] = '\0';
|
||||||
if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
|
if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
|
||||||
strcat(cells[i * cols + 2], "not null");
|
strcat(cells[i * cols + 2], "not null");
|
||||||
if (strcmp(PQgetvalue(res, i, 5), "t") == 0) {
|
if (strcmp(PQgetvalue(res, i, 5), "t") == 0)
|
||||||
|
{
|
||||||
/* handle "default" here */
|
/* handle "default" here */
|
||||||
strcpy(descbuf, "SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c\n"
|
strcpy(descbuf, "SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c\n"
|
||||||
"WHERE c.relname = '");
|
"WHERE c.relname = '");
|
||||||
@ -597,8 +623,10 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
|||||||
strcat(descbuf, PQgetvalue(res, i, 6));
|
strcat(descbuf, PQgetvalue(res, i, 6));
|
||||||
|
|
||||||
res3 = PSQLexec(pset, descbuf);
|
res3 = PSQLexec(pset, descbuf);
|
||||||
if (!res) return false;
|
if (!res)
|
||||||
if (cells[i*cols+2][0]) strcat(cells[i*cols+2], " ");
|
return false;
|
||||||
|
if (cells[i * cols + 2][0])
|
||||||
|
strcat(cells[i * cols + 2], " ");
|
||||||
strcat(cells[i * cols + 2], "default ");
|
strcat(cells[i * cols + 2], "default ");
|
||||||
strcat(cells[i * cols + 2], PQgetvalue(res3, 0, 0));
|
strcat(cells[i * cols + 2], PQgetvalue(res3, 0, 0));
|
||||||
}
|
}
|
||||||
@ -616,13 +644,15 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
|||||||
sprintf(title, "Table \"%s\"", name);
|
sprintf(title, "Table \"%s\"", name);
|
||||||
|
|
||||||
/* Make footers */
|
/* Make footers */
|
||||||
if (view_def) {
|
if (view_def)
|
||||||
|
{
|
||||||
footers = xmalloc(2 * sizeof(*footers));
|
footers = xmalloc(2 * sizeof(*footers));
|
||||||
footers[0] = xmalloc(20 + strlen(view_def));
|
footers[0] = xmalloc(20 + strlen(view_def));
|
||||||
sprintf(footers[0], "View definition: %s", view_def);
|
sprintf(footers[0], "View definition: %s", view_def);
|
||||||
footers[1] = NULL;
|
footers[1] = NULL;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
/* display indices */
|
/* display indices */
|
||||||
strcpy(descbuf, "SELECT c2.relname\n"
|
strcpy(descbuf, "SELECT c2.relname\n"
|
||||||
"FROM pg_class c, pg_class c2, pg_index i\n"
|
"FROM pg_class c, pg_class c2, pg_index i\n"
|
||||||
@ -634,10 +664,12 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
|||||||
if (!res3)
|
if (!res3)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (PQntuples(res3) > 0) {
|
if (PQntuples(res3) > 0)
|
||||||
|
{
|
||||||
footers = xmalloc((PQntuples(res3) + 1) * sizeof(*footers));
|
footers = xmalloc((PQntuples(res3) + 1) * sizeof(*footers));
|
||||||
|
|
||||||
for (i=0; i<PQntuples(res3); i++) {
|
for (i = 0; i < PQntuples(res3); i++)
|
||||||
|
{
|
||||||
footers[i] = xmalloc(10 + NAMEDATALEN);
|
footers[i] = xmalloc(10 + NAMEDATALEN);
|
||||||
if (PQntuples(res3) == 1)
|
if (PQntuples(res3) == 1)
|
||||||
sprintf(footers[i], "Index: %s", PQgetvalue(res3, i, 0));
|
sprintf(footers[i], "Index: %s", PQgetvalue(res3, i, 0));
|
||||||
@ -658,7 +690,8 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
|||||||
/* clean up */
|
/* clean up */
|
||||||
free(title);
|
free(title);
|
||||||
|
|
||||||
for (i = 0; i<PQntuples(res); i++) {
|
for (i = 0; i < PQntuples(res); i++)
|
||||||
|
{
|
||||||
free(cells[i * cols + 1]);
|
free(cells[i * cols + 1]);
|
||||||
free(cells[i * cols + 2]);
|
free(cells[i * cols + 2]);
|
||||||
}
|
}
|
||||||
@ -708,7 +741,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
|||||||
descbuf[0] = '\0';
|
descbuf[0] = '\0';
|
||||||
|
|
||||||
/* tables */
|
/* tables */
|
||||||
if (showTables) {
|
if (showTables)
|
||||||
|
{
|
||||||
strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'table'::text as \"Type\"");
|
strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'table'::text as \"Type\"");
|
||||||
if (description)
|
if (description)
|
||||||
strcat(descbuf, ", obj_description(c.oid) as \"Description\"");
|
strcat(descbuf, ", obj_description(c.oid) as \"Description\"");
|
||||||
@ -716,7 +750,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
|||||||
"WHERE c.relowner = u.usesysid AND c.relkind = 'r'\n"
|
"WHERE c.relowner = u.usesysid AND c.relkind = 'r'\n"
|
||||||
" AND not exists (select 1 from pg_views where viewname = c.relname)\n");
|
" AND not exists (select 1 from pg_views where viewname = c.relname)\n");
|
||||||
strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
|
strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
|
||||||
if (name) {
|
if (name)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND c.relname ~ '^");
|
strcat(descbuf, " AND c.relname ~ '^");
|
||||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "'\n");
|
strcat(descbuf, "'\n");
|
||||||
@ -724,7 +759,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* views */
|
/* views */
|
||||||
if (showViews) {
|
if (showViews)
|
||||||
|
{
|
||||||
if (descbuf[0])
|
if (descbuf[0])
|
||||||
strcat(descbuf, "\nUNION\n\n");
|
strcat(descbuf, "\nUNION\n\n");
|
||||||
|
|
||||||
@ -735,7 +771,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
|||||||
"WHERE c.relowner = u.usesysid AND c.relkind = 'r'\n"
|
"WHERE c.relowner = u.usesysid AND c.relkind = 'r'\n"
|
||||||
" AND exists (select 1 from pg_views where viewname = c.relname)\n");
|
" AND exists (select 1 from pg_views where viewname = c.relname)\n");
|
||||||
strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
|
strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
|
||||||
if (name) {
|
if (name)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND c.relname ~ '^");
|
strcat(descbuf, " AND c.relname ~ '^");
|
||||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "'\n");
|
strcat(descbuf, "'\n");
|
||||||
@ -743,7 +780,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* indices, sequences */
|
/* indices, sequences */
|
||||||
if (showIndices || showSeq) {
|
if (showIndices || showSeq)
|
||||||
|
{
|
||||||
if (descbuf[0])
|
if (descbuf[0])
|
||||||
strcat(descbuf, "\nUNION\n\n");
|
strcat(descbuf, "\nUNION\n\n");
|
||||||
|
|
||||||
@ -766,7 +804,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
|||||||
strcat(descbuf, " AND (c.relkind != 'i' OR c.relname !~ '^xinx')\n");
|
strcat(descbuf, " AND (c.relkind != 'i' OR c.relname !~ '^xinx')\n");
|
||||||
|
|
||||||
strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
|
strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
|
||||||
if (name) {
|
if (name)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND c.relname ~ '^");
|
strcat(descbuf, " AND c.relname ~ '^");
|
||||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "'\n");
|
strcat(descbuf, "'\n");
|
||||||
@ -774,7 +813,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* real system catalogue tables */
|
/* real system catalogue tables */
|
||||||
if (showSystem && showTables) {
|
if (showSystem && showTables)
|
||||||
|
{
|
||||||
if (descbuf[0])
|
if (descbuf[0])
|
||||||
strcat(descbuf, "\nUNION\n\n");
|
strcat(descbuf, "\nUNION\n\n");
|
||||||
|
|
||||||
@ -783,7 +823,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
|||||||
strcat(descbuf, ", obj_description(c.oid) as \"Description\"");
|
strcat(descbuf, ", obj_description(c.oid) as \"Description\"");
|
||||||
strcat(descbuf, "\nFROM pg_class c, pg_user u\n"
|
strcat(descbuf, "\nFROM pg_class c, pg_user u\n"
|
||||||
"WHERE c.relowner = u.usesysid AND c.relkind = 's'\n");
|
"WHERE c.relowner = u.usesysid AND c.relkind = 's'\n");
|
||||||
if (name) {
|
if (name)
|
||||||
|
{
|
||||||
strcat(descbuf, " AND c.relname ~ '^");
|
strcat(descbuf, " AND c.relname ~ '^");
|
||||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||||
strcat(descbuf, "'\n");
|
strcat(descbuf, "'\n");
|
||||||
@ -800,7 +841,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
|||||||
if (PQntuples(res) == 0)
|
if (PQntuples(res) == 0)
|
||||||
fprintf(pset->queryFout, "No matching classes found.\n");
|
fprintf(pset->queryFout, "No matching classes found.\n");
|
||||||
|
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
myopt.topt.tuples_only = false;
|
myopt.topt.tuples_only = false;
|
||||||
myopt.nullPrint = NULL;
|
myopt.nullPrint = NULL;
|
||||||
myopt.title = "List of classes";
|
myopt.title = "List of classes";
|
||||||
|
@ -34,21 +34,27 @@
|
|||||||
*/
|
*/
|
||||||
#define ON(var) (var ? "on" : "off")
|
#define ON(var) (var ? "on" : "off")
|
||||||
|
|
||||||
void usage(void)
|
void
|
||||||
|
usage(void)
|
||||||
{
|
{
|
||||||
const char *env;
|
const char *env;
|
||||||
const char *user;
|
const char *user;
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
struct passwd *pw = NULL;
|
struct passwd *pw = NULL;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Find default user, in case we need it. */
|
/* Find default user, in case we need it. */
|
||||||
user = getenv("USER");
|
user = getenv("USER");
|
||||||
if (!user) {
|
if (!user)
|
||||||
|
{
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
pw = getpwuid(getuid());
|
pw = getpwuid(getuid());
|
||||||
if (pw) user = pw->pw_name;
|
if (pw)
|
||||||
else {
|
user = pw->pw_name;
|
||||||
|
else
|
||||||
|
{
|
||||||
perror("getpwuid()");
|
perror("getpwuid()");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -64,7 +70,8 @@ void usage(void)
|
|||||||
|
|
||||||
/* Display default database */
|
/* Display default database */
|
||||||
env = getenv("PGDATABASE");
|
env = getenv("PGDATABASE");
|
||||||
if (!env) env=user;
|
if (!env)
|
||||||
|
env = user;
|
||||||
fprintf(stderr, " -d dbname Specify database name to connect to (default: %s)\n", env);
|
fprintf(stderr, " -d dbname Specify database name to connect to (default: %s)\n", env);
|
||||||
|
|
||||||
fprintf(stderr, " -e Echo all input in non-interactive mode\n");
|
fprintf(stderr, " -e Echo all input in non-interactive mode\n");
|
||||||
@ -101,7 +108,8 @@ void usage(void)
|
|||||||
|
|
||||||
/* Display default user */
|
/* Display default user */
|
||||||
env = getenv("PGUSER");
|
env = getenv("PGUSER");
|
||||||
if (!env) env=user;
|
if (!env)
|
||||||
|
env = user;
|
||||||
fprintf(stderr, " -U [username] Specifiy username, \"?\"=prompt (default user: %s)\n", env);
|
fprintf(stderr, " -U [username] Specifiy username, \"?\"=prompt (default user: %s)\n", env);
|
||||||
|
|
||||||
fprintf(stderr, " -x Turn on expanded table output (-P expanded)\n");
|
fprintf(stderr, " -x Turn on expanded table output (-P expanded)\n");
|
||||||
@ -112,7 +120,8 @@ void usage(void)
|
|||||||
fprintf(stderr, "Consult the documentation for the complete details.\n");
|
fprintf(stderr, "Consult the documentation for the complete details.\n");
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
if (pw) free(pw);
|
if (pw)
|
||||||
|
free(pw);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,10 +134,12 @@ void usage(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TIOCGWINSZ
|
#ifndef TIOCGWINSZ
|
||||||
struct winsize {
|
struct winsize
|
||||||
|
{
|
||||||
int ws_row;
|
int ws_row;
|
||||||
int ws_col;
|
int ws_col;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -197,7 +208,8 @@ slashUsage(PsqlSettings *pset)
|
|||||||
fprintf(fout, " \\z -- list table access permissions\n");
|
fprintf(fout, " \\z -- list table access permissions\n");
|
||||||
fprintf(fout, " \\! [<cmd>] -- shell escape or command\n");
|
fprintf(fout, " \\! [<cmd>] -- shell escape or command\n");
|
||||||
|
|
||||||
if (usePipe) {
|
if (usePipe)
|
||||||
|
{
|
||||||
pclose(fout);
|
pclose(fout);
|
||||||
pqsignal(SIGPIPE, SIG_DFL);
|
pqsignal(SIGPIPE, SIG_DFL);
|
||||||
}
|
}
|
||||||
|
@ -13,4 +13,3 @@ void print_copyright(void);
|
|||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -10,9 +10,11 @@
|
|||||||
/* (of course there is no runtime command for doing that :) */
|
/* (of course there is no runtime command for doing that :) */
|
||||||
#ifdef USE_READLINE
|
#ifdef USE_READLINE
|
||||||
static bool useReadline;
|
static bool useReadline;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_HISTORY
|
#ifdef USE_HISTORY
|
||||||
static bool useHistory;
|
static bool useHistory;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -28,12 +30,14 @@ gets_interactive(const char *prompt)
|
|||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
#ifdef USE_READLINE
|
#ifdef USE_READLINE
|
||||||
if (useReadline) {
|
if (useReadline)
|
||||||
|
{
|
||||||
s = readline(prompt);
|
s = readline(prompt);
|
||||||
fputc('\r', stdout);
|
fputc('\r', stdout);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
#endif
|
#endif
|
||||||
fputs(prompt, stdout);
|
fputs(prompt, stdout);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
@ -65,9 +69,11 @@ gets_fromFile(FILE *source)
|
|||||||
|
|
||||||
initPQExpBuffer(&buffer);
|
initPQExpBuffer(&buffer);
|
||||||
|
|
||||||
while (fgets(line, 1024, source) != NULL) {
|
while (fgets(line, 1024, source) != NULL)
|
||||||
|
{
|
||||||
appendPQExpBufferStr(&buffer, line);
|
appendPQExpBufferStr(&buffer, line);
|
||||||
if (buffer.data[buffer.len-1] == '\n') {
|
if (buffer.data[buffer.len - 1] == '\n')
|
||||||
|
{
|
||||||
buffer.data[buffer.len - 1] = '\0';
|
buffer.data[buffer.len - 1] = '\0';
|
||||||
return buffer.data;
|
return buffer.data;
|
||||||
}
|
}
|
||||||
@ -93,22 +99,27 @@ void
|
|||||||
initializeInput(int flags)
|
initializeInput(int flags)
|
||||||
{
|
{
|
||||||
#ifdef USE_READLINE
|
#ifdef USE_READLINE
|
||||||
if (flags == 1) {
|
if (flags == 1)
|
||||||
|
{
|
||||||
useReadline = true;
|
useReadline = true;
|
||||||
rl_readline_name = "psql";
|
rl_readline_name = "psql";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_HISTORY
|
#ifdef USE_HISTORY
|
||||||
if (flags == 1) {
|
if (flags == 1)
|
||||||
|
{
|
||||||
const char *home;
|
const char *home;
|
||||||
|
|
||||||
useHistory = true;
|
useHistory = true;
|
||||||
using_history();
|
using_history();
|
||||||
home = getenv("HOME");
|
home = getenv("HOME");
|
||||||
if (home) {
|
if (home)
|
||||||
|
{
|
||||||
char *psql_history = (char *) malloc(strlen(home) + 20);
|
char *psql_history = (char *) malloc(strlen(home) + 20);
|
||||||
if (psql_history) {
|
|
||||||
|
if (psql_history)
|
||||||
|
{
|
||||||
sprintf(psql_history, "%s/.psql_history", home);
|
sprintf(psql_history, "%s/.psql_history", home);
|
||||||
read_history(psql_history);
|
read_history(psql_history);
|
||||||
free(psql_history);
|
free(psql_history);
|
||||||
@ -124,8 +135,10 @@ bool
|
|||||||
saveHistory(const char *fname)
|
saveHistory(const char *fname)
|
||||||
{
|
{
|
||||||
#ifdef USE_HISTORY
|
#ifdef USE_HISTORY
|
||||||
if (useHistory) {
|
if (useHistory)
|
||||||
if (write_history(fname) != 0) {
|
{
|
||||||
|
if (write_history(fname) != 0)
|
||||||
|
{
|
||||||
perror(fname);
|
perror(fname);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -144,14 +157,17 @@ void
|
|||||||
finishInput(void)
|
finishInput(void)
|
||||||
{
|
{
|
||||||
#ifdef USE_HISTORY
|
#ifdef USE_HISTORY
|
||||||
if (useHistory) {
|
if (useHistory)
|
||||||
|
{
|
||||||
char *home;
|
char *home;
|
||||||
char *psql_history;
|
char *psql_history;
|
||||||
|
|
||||||
home = getenv("HOME");
|
home = getenv("HOME");
|
||||||
if (home) {
|
if (home)
|
||||||
|
{
|
||||||
psql_history = (char *) malloc(strlen(home) + 20);
|
psql_history = (char *) malloc(strlen(home) + 20);
|
||||||
if (psql_history) {
|
if (psql_history)
|
||||||
|
{
|
||||||
sprintf(psql_history, "%s/.psql_history", home);
|
sprintf(psql_history, "%s/.psql_history", home);
|
||||||
write_history(psql_history);
|
write_history(psql_history);
|
||||||
free(psql_history);
|
free(psql_history);
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
static char notice[80];
|
static char notice[80];
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_my_notice_handler(void * arg, const char * message) {
|
_my_notice_handler(void *arg, const char *message)
|
||||||
|
{
|
||||||
(void) arg;
|
(void) arg;
|
||||||
strncpy(notice, message, 79);
|
strncpy(notice, message, 79);
|
||||||
notice[79] = '\0';
|
notice[79] = '\0';
|
||||||
@ -51,12 +52,14 @@ handle_transaction(PsqlSettings * pset)
|
|||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (notice[0]) {
|
if (notice[0])
|
||||||
|
{
|
||||||
if ((!commit && strcmp(notice, "NOTICE: UserAbortTransactionBlock and not in in-progress state\n") != 0) ||
|
if ((!commit && strcmp(notice, "NOTICE: UserAbortTransactionBlock and not in in-progress state\n") != 0) ||
|
||||||
(commit && strcmp(notice, "NOTICE: EndTransactionBlock and not inprogress/abort state\n") != 0))
|
(commit && strcmp(notice, "NOTICE: EndTransactionBlock and not inprogress/abort state\n") != 0))
|
||||||
fputs(notice, stderr);
|
fputs(notice, stderr);
|
||||||
}
|
}
|
||||||
else if (!GetVariableBool(pset->vars, "quiet")) {
|
else if (!GetVariableBool(pset->vars, "quiet"))
|
||||||
|
{
|
||||||
if (commit)
|
if (commit)
|
||||||
puts("Warning: Your transaction in progress has been committed.");
|
puts("Warning: Your transaction in progress has been committed.");
|
||||||
else
|
else
|
||||||
@ -85,12 +88,14 @@ do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_a
|
|||||||
if (var && strcmp(var, "nothing") == 0)
|
if (var && strcmp(var, "nothing") == 0)
|
||||||
own_transaction = false;
|
own_transaction = false;
|
||||||
|
|
||||||
if (!pset->db) {
|
if (!pset->db)
|
||||||
|
{
|
||||||
fputs("You are not connected to a database.\n", stderr);
|
fputs("You are not connected to a database.\n", stderr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (own_transaction) {
|
if (own_transaction)
|
||||||
|
{
|
||||||
if (!handle_transaction(pset))
|
if (!handle_transaction(pset))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -101,17 +106,22 @@ do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_a
|
|||||||
}
|
}
|
||||||
|
|
||||||
status = lo_export(pset->db, atol(loid_arg), (char *) filename_arg);
|
status = lo_export(pset->db, atol(loid_arg), (char *) filename_arg);
|
||||||
if (status != 1) { /* of course this status is documented nowhere :( */
|
if (status != 1)
|
||||||
|
{ /* of course this status is documented
|
||||||
|
* nowhere :( */
|
||||||
fputs(PQerrorMessage(pset->db), stderr);
|
fputs(PQerrorMessage(pset->db), stderr);
|
||||||
if (own_transaction) {
|
if (own_transaction)
|
||||||
|
{
|
||||||
res = PQexec(pset->db, "ROLLBACK");
|
res = PQexec(pset->db, "ROLLBACK");
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (own_transaction) {
|
if (own_transaction)
|
||||||
if (!(res = PSQLexec(pset, "COMMIT"))) {
|
{
|
||||||
|
if (!(res = PSQLexec(pset, "COMMIT")))
|
||||||
|
{
|
||||||
res = PQexec(pset->db, "ROLLBACK");
|
res = PQexec(pset->db, "ROLLBACK");
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
return false;
|
return false;
|
||||||
@ -145,12 +155,14 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
|
|||||||
if (var && strcmp(var, "nothing") == 0)
|
if (var && strcmp(var, "nothing") == 0)
|
||||||
own_transaction = false;
|
own_transaction = false;
|
||||||
|
|
||||||
if (!pset->db) {
|
if (!pset->db)
|
||||||
|
{
|
||||||
fputs("You are not connected to a database.\n", stderr);
|
fputs("You are not connected to a database.\n", stderr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (own_transaction) {
|
if (own_transaction)
|
||||||
|
{
|
||||||
if (!handle_transaction(pset))
|
if (!handle_transaction(pset))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -161,9 +173,11 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
|
|||||||
}
|
}
|
||||||
|
|
||||||
loid = lo_import(pset->db, (char *) filename_arg);
|
loid = lo_import(pset->db, (char *) filename_arg);
|
||||||
if (loid == InvalidOid) {
|
if (loid == InvalidOid)
|
||||||
|
{
|
||||||
fputs(PQerrorMessage(pset->db), stderr);
|
fputs(PQerrorMessage(pset->db), stderr);
|
||||||
if (own_transaction) {
|
if (own_transaction)
|
||||||
|
{
|
||||||
res = PQexec(pset->db, "ROLLBACK");
|
res = PQexec(pset->db, "ROLLBACK");
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
}
|
}
|
||||||
@ -171,7 +185,8 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* insert description if given */
|
/* insert description if given */
|
||||||
if (comment_arg) {
|
if (comment_arg)
|
||||||
|
{
|
||||||
sprintf(buf, "INSERT INTO pg_description VALUES (%d, '", loid);
|
sprintf(buf, "INSERT INTO pg_description VALUES (%d, '", loid);
|
||||||
for (i = 0; i < strlen(comment_arg); i++)
|
for (i = 0; i < strlen(comment_arg); i++)
|
||||||
if (comment_arg[i] == '\'')
|
if (comment_arg[i] == '\'')
|
||||||
@ -180,8 +195,10 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
|
|||||||
strncat(buf, &comment_arg[i], 1);
|
strncat(buf, &comment_arg[i], 1);
|
||||||
strcat(buf, "')");
|
strcat(buf, "')");
|
||||||
|
|
||||||
if (!(res = PSQLexec(pset, buf))) {
|
if (!(res = PSQLexec(pset, buf)))
|
||||||
if (own_transaction) {
|
{
|
||||||
|
if (own_transaction)
|
||||||
|
{
|
||||||
res = PQexec(pset->db, "ROLLBACK");
|
res = PQexec(pset->db, "ROLLBACK");
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
}
|
}
|
||||||
@ -189,8 +206,10 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (own_transaction) {
|
if (own_transaction)
|
||||||
if (!(res = PSQLexec(pset, "COMMIT"))) {
|
{
|
||||||
|
if (!(res = PSQLexec(pset, "COMMIT")))
|
||||||
|
{
|
||||||
res = PQexec(pset->db, "ROLLBACK");
|
res = PQexec(pset->db, "ROLLBACK");
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
return false;
|
return false;
|
||||||
@ -212,7 +231,8 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
|
|||||||
*
|
*
|
||||||
* removes a large object out of the database
|
* removes a large object out of the database
|
||||||
*/
|
*/
|
||||||
bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
|
bool
|
||||||
|
do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
|
||||||
{
|
{
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
int status;
|
int status;
|
||||||
@ -224,12 +244,14 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
|
|||||||
if (var && strcmp(var, "nothing") == 0)
|
if (var && strcmp(var, "nothing") == 0)
|
||||||
own_transaction = false;
|
own_transaction = false;
|
||||||
|
|
||||||
if (!pset->db) {
|
if (!pset->db)
|
||||||
|
{
|
||||||
fputs("You are not connected to a database.\n", stderr);
|
fputs("You are not connected to a database.\n", stderr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (own_transaction) {
|
if (own_transaction)
|
||||||
|
{
|
||||||
if (!handle_transaction(pset))
|
if (!handle_transaction(pset))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -240,9 +262,11 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
status = lo_unlink(pset->db, loid);
|
status = lo_unlink(pset->db, loid);
|
||||||
if (status == -1) {
|
if (status == -1)
|
||||||
|
{
|
||||||
fputs(PQerrorMessage(pset->db), stderr);
|
fputs(PQerrorMessage(pset->db), stderr);
|
||||||
if (own_transaction) {
|
if (own_transaction)
|
||||||
|
{
|
||||||
res = PQexec(pset->db, "ROLLBACK");
|
res = PQexec(pset->db, "ROLLBACK");
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
}
|
}
|
||||||
@ -251,8 +275,10 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
|
|||||||
|
|
||||||
/* remove the comment as well */
|
/* remove the comment as well */
|
||||||
sprintf(buf, "DELETE FROM pg_description WHERE objoid = %d", loid);
|
sprintf(buf, "DELETE FROM pg_description WHERE objoid = %d", loid);
|
||||||
if (!(res = PSQLexec(pset, buf))) {
|
if (!(res = PSQLexec(pset, buf)))
|
||||||
if (own_transaction) {
|
{
|
||||||
|
if (own_transaction)
|
||||||
|
{
|
||||||
res = PQexec(pset->db, "ROLLBACK");
|
res = PQexec(pset->db, "ROLLBACK");
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
}
|
}
|
||||||
@ -260,8 +286,10 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (own_transaction) {
|
if (own_transaction)
|
||||||
if (!(res = PSQLexec(pset, "COMMIT"))) {
|
{
|
||||||
|
if (!(res = PSQLexec(pset, "COMMIT")))
|
||||||
|
{
|
||||||
res = PQexec(pset->db, "ROLLBACK");
|
res = PQexec(pset->db, "ROLLBACK");
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
return false;
|
return false;
|
||||||
@ -282,7 +310,8 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
|
|||||||
*
|
*
|
||||||
* Show all large objects in database, with comments if desired
|
* Show all large objects in database, with comments if desired
|
||||||
*/
|
*/
|
||||||
bool do_lo_list(PsqlSettings * pset)
|
bool
|
||||||
|
do_lo_list(PsqlSettings *pset)
|
||||||
{
|
{
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
char descbuf[512];
|
char descbuf[512];
|
||||||
|
@ -40,7 +40,9 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
int paren_level;
|
int paren_level;
|
||||||
unsigned int query_start;
|
unsigned int query_start;
|
||||||
|
|
||||||
int i, prevlen, thislen;
|
int i,
|
||||||
|
prevlen,
|
||||||
|
thislen;
|
||||||
|
|
||||||
/* Save the prior command source */
|
/* Save the prior command source */
|
||||||
FILE *prev_cmd_source;
|
FILE *prev_cmd_source;
|
||||||
@ -60,7 +62,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
|
|
||||||
|
|
||||||
query_buf = createPQExpBuffer();
|
query_buf = createPQExpBuffer();
|
||||||
if (!query_buf) {
|
if (!query_buf)
|
||||||
|
{
|
||||||
perror("createPQExpBuffer");
|
perror("createPQExpBuffer");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -76,6 +79,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
{
|
{
|
||||||
if (slashCmdStatus == CMD_NEWEDIT)
|
if (slashCmdStatus == CMD_NEWEDIT)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* just returned from editing the line? then just copy to the
|
* just returned from editing the line? then just copy to the
|
||||||
* input buffer
|
* input buffer
|
||||||
@ -89,9 +93,10 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* otherwise, set interactive prompt if necessary
|
* otherwise, set interactive prompt if necessary and get
|
||||||
* and get another line
|
* another line
|
||||||
*/
|
*/
|
||||||
if (pset->cur_cmd_interactive)
|
if (pset->cur_cmd_interactive)
|
||||||
{
|
{
|
||||||
@ -121,9 +126,10 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* query_buf holds query already accumulated. line is the malloc'd
|
* query_buf holds query already accumulated. line is the
|
||||||
* new line of input (note it must be freed before looping around!)
|
* malloc'd new line of input (note it must be freed before
|
||||||
* query_start is the next command start location within the line.
|
* looping around!) query_start is the next command start location
|
||||||
|
* within the line.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* No more input. Time to quit, or \i done */
|
/* No more input. Time to quit, or \i done */
|
||||||
@ -141,8 +147,10 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
|
|
||||||
|
|
||||||
/* strip trailing backslashes, they don't have a clear meaning */
|
/* strip trailing backslashes, they don't have a clear meaning */
|
||||||
while (1) {
|
while (1)
|
||||||
|
{
|
||||||
char *cp = strrchr(line, '\\');
|
char *cp = strrchr(line, '\\');
|
||||||
|
|
||||||
if (cp && (*(cp + 1) == '\0'))
|
if (cp && (*(cp + 1) == '\0'))
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
else
|
else
|
||||||
@ -159,12 +167,16 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
len = strlen(line);
|
len = strlen(line);
|
||||||
thislen = PQmblen(line);
|
thislen = PQmblen(line);
|
||||||
|
|
||||||
for (i = 0; line[i]; i += (thislen = PQmblen(&line[i])) ) {
|
for (i = 0; line[i]; i += (thislen = PQmblen(&line[i])))
|
||||||
if (interpol_char && interpol_char[0] != '\0' && interpol_char[0] == line[i]) {
|
{
|
||||||
size_t in_length, out_length;
|
if (interpol_char && interpol_char[0] != '\0' && interpol_char[0] == line[i])
|
||||||
|
{
|
||||||
|
size_t in_length,
|
||||||
|
out_length;
|
||||||
const char *value;
|
const char *value;
|
||||||
char *new;
|
char *new;
|
||||||
bool closer; /* did we have a closing delimiter or just an end of line? */
|
bool closer; /* did we have a closing delimiter
|
||||||
|
* or just an end of line? */
|
||||||
|
|
||||||
in_length = strcspn(&line[i + thislen], interpol_char);
|
in_length = strcspn(&line[i + thislen], interpol_char);
|
||||||
closer = line[i + thislen + in_length] == line[i];
|
closer = line[i + thislen + in_length] == line[i];
|
||||||
@ -173,7 +185,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
out_length = strlen(value);
|
out_length = strlen(value);
|
||||||
|
|
||||||
new = malloc(len + out_length - (in_length + (closer ? 2 : 1)) + 1);
|
new = malloc(len + out_length - (in_length + (closer ? 2 : 1)) + 1);
|
||||||
if (!new) {
|
if (!new)
|
||||||
|
{
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -191,7 +204,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* nothing left on line? then ignore */
|
/* nothing left on line? then ignore */
|
||||||
if (line[0] == '\0') {
|
if (line[0] == '\0')
|
||||||
|
{
|
||||||
free(line);
|
free(line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -204,8 +218,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
/*
|
/*
|
||||||
* Parse line, looking for command separators.
|
* Parse line, looking for command separators.
|
||||||
*
|
*
|
||||||
* The current character is at line[i], the prior character at
|
* The current character is at line[i], the prior character at line[i
|
||||||
* line[i - prevlen], the next character at line[i + thislen].
|
* - prevlen], the next character at line[i + thislen].
|
||||||
*/
|
*/
|
||||||
prevlen = 0;
|
prevlen = 0;
|
||||||
thislen = (len > 0) ? PQmblen(line) : 0;
|
thislen = (len > 0) ? PQmblen(line) : 0;
|
||||||
@ -213,7 +227,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
#define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i))
|
#define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i))
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
for (i = 0; i < len; ADVANCE_1) {
|
for (i = 0; i < len; ADVANCE_1)
|
||||||
|
{
|
||||||
if (!success && die_on_error)
|
if (!success && die_on_error)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -226,7 +241,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
|
|
||||||
|
|
||||||
/* in quote? */
|
/* in quote? */
|
||||||
if (in_quote) {
|
if (in_quote)
|
||||||
|
{
|
||||||
/* end of quote */
|
/* end of quote */
|
||||||
if (line[i] == in_quote && !was_bslash)
|
if (line[i] == in_quote && !was_bslash)
|
||||||
in_quote = '\0';
|
in_quote = '\0';
|
||||||
@ -237,15 +253,18 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
in_quote = line[i];
|
in_quote = line[i];
|
||||||
|
|
||||||
/* in extended comment? */
|
/* in extended comment? */
|
||||||
else if (xcomment != NULL) {
|
else if (xcomment != NULL)
|
||||||
if (line[i] == '*' && line[i + thislen] == '/') {
|
{
|
||||||
|
if (line[i] == '*' && line[i + thislen] == '/')
|
||||||
|
{
|
||||||
xcomment = NULL;
|
xcomment = NULL;
|
||||||
ADVANCE_1;
|
ADVANCE_1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start of extended comment? */
|
/* start of extended comment? */
|
||||||
else if (line[i] == '/' && line[i + thislen] == '*') {
|
else if (line[i] == '/' && line[i + thislen] == '*')
|
||||||
|
{
|
||||||
xcomment = &line[i];
|
xcomment = &line[i];
|
||||||
ADVANCE_1;
|
ADVANCE_1;
|
||||||
}
|
}
|
||||||
@ -266,11 +285,17 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
paren_level--;
|
paren_level--;
|
||||||
|
|
||||||
/* semicolon? then send query */
|
/* semicolon? then send query */
|
||||||
else if (line[i] == ';' && !was_bslash && paren_level==0) {
|
else if (line[i] == ';' && !was_bslash && paren_level == 0)
|
||||||
|
{
|
||||||
line[i] = '\0';
|
line[i] = '\0';
|
||||||
/* is there anything else on the line? */
|
/* is there anything else on the line? */
|
||||||
if (line[query_start + strspn(line + query_start, " \t")]!='\0') {
|
if (line[query_start + strspn(line + query_start, " \t")] != '\0')
|
||||||
/* insert a cosmetic newline, if this is not the first line in the buffer */
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* insert a cosmetic newline, if this is not the first
|
||||||
|
* line in the buffer
|
||||||
|
*/
|
||||||
if (query_buf->len > 0)
|
if (query_buf->len > 0)
|
||||||
appendPQExpBufferChar(query_buf, '\n');
|
appendPQExpBufferChar(query_buf, '\n');
|
||||||
/* append the line to the query buffer */
|
/* append the line to the query buffer */
|
||||||
@ -285,14 +310,20 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* backslash command */
|
/* backslash command */
|
||||||
else if (was_bslash) {
|
else if (was_bslash)
|
||||||
|
{
|
||||||
const char *end_of_cmd = NULL;
|
const char *end_of_cmd = NULL;
|
||||||
|
|
||||||
line[i - prevlen] = '\0'; /* overwrites backslash */
|
line[i - prevlen] = '\0'; /* overwrites backslash */
|
||||||
|
|
||||||
/* is there anything else on the line? */
|
/* is there anything else on the line? */
|
||||||
if (line[query_start + strspn(line + query_start, " \t")]!='\0') {
|
if (line[query_start + strspn(line + query_start, " \t")] != '\0')
|
||||||
/* insert a cosmetic newline, if this is not the first line in the buffer */
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* insert a cosmetic newline, if this is not the first
|
||||||
|
* line in the buffer
|
||||||
|
*/
|
||||||
if (query_buf->len > 0)
|
if (query_buf->len > 0)
|
||||||
appendPQExpBufferChar(query_buf, '\n');
|
appendPQExpBufferChar(query_buf, '\n');
|
||||||
/* append the line to the query buffer */
|
/* append the line to the query buffer */
|
||||||
@ -305,14 +336,16 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
|
|
||||||
success = slashCmdStatus != CMD_ERROR;
|
success = slashCmdStatus != CMD_ERROR;
|
||||||
|
|
||||||
if (slashCmdStatus == CMD_SEND) {
|
if (slashCmdStatus == CMD_SEND)
|
||||||
|
{
|
||||||
success = SendQuery(pset, query_buf->data);
|
success = SendQuery(pset, query_buf->data);
|
||||||
resetPQExpBuffer(query_buf);
|
resetPQExpBuffer(query_buf);
|
||||||
query_start = i + thislen;
|
query_start = i + thislen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* is there anything left after the backslash command? */
|
/* is there anything left after the backslash command? */
|
||||||
if (end_of_cmd) {
|
if (end_of_cmd)
|
||||||
|
{
|
||||||
i += end_of_cmd - &line[i];
|
i += end_of_cmd - &line[i];
|
||||||
query_start = i;
|
query_start = i;
|
||||||
}
|
}
|
||||||
@ -322,20 +355,23 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!success && die_on_error && !pset->cur_cmd_interactive) {
|
if (!success && die_on_error && !pset->cur_cmd_interactive)
|
||||||
|
{
|
||||||
successResult = EXIT_USER;
|
successResult = EXIT_USER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (slashCmdStatus == CMD_TERMINATE) {
|
if (slashCmdStatus == CMD_TERMINATE)
|
||||||
|
{
|
||||||
successResult = EXIT_SUCCESS;
|
successResult = EXIT_SUCCESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Put the rest of the line in the query buffer. */
|
/* Put the rest of the line in the query buffer. */
|
||||||
if (line[query_start + strspn(line + query_start, " \t")]!='\0') {
|
if (line[query_start + strspn(line + query_start, " \t")] != '\0')
|
||||||
|
{
|
||||||
if (query_buf->len > 0)
|
if (query_buf->len > 0)
|
||||||
appendPQExpBufferChar(query_buf, '\n');
|
appendPQExpBufferChar(query_buf, '\n');
|
||||||
appendPQExpBufferStr(query_buf, line + query_start);
|
appendPQExpBufferStr(query_buf, line + query_start);
|
||||||
@ -345,14 +381,16 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
|
|
||||||
|
|
||||||
/* In single line mode, send off the query if any */
|
/* In single line mode, send off the query if any */
|
||||||
if (query_buf->data[0] != '\0' && GetVariableBool(pset->vars, "singleline")) {
|
if (query_buf->data[0] != '\0' && GetVariableBool(pset->vars, "singleline"))
|
||||||
|
{
|
||||||
success = SendQuery(pset, query_buf->data);
|
success = SendQuery(pset, query_buf->data);
|
||||||
resetPQExpBuffer(query_buf);
|
resetPQExpBuffer(query_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Have we lost the db connection? */
|
/* Have we lost the db connection? */
|
||||||
if (pset->db == NULL && !pset->cur_cmd_interactive) {
|
if (pset->db == NULL && !pset->cur_cmd_interactive)
|
||||||
|
{
|
||||||
successResult = EXIT_BADCONN;
|
successResult = EXIT_BADCONN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -365,4 +403,3 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
|||||||
|
|
||||||
return successResult;
|
return successResult;
|
||||||
} /* MainLoop() */
|
} /* MainLoop() */
|
||||||
|
|
||||||
|
@ -7,4 +7,4 @@
|
|||||||
int
|
int
|
||||||
MainLoop(PsqlSettings *pset, FILE *source);
|
MainLoop(PsqlSettings *pset, FILE *source);
|
||||||
|
|
||||||
#endif MAINLOOP_H
|
#endif /* MAINLOOP_H */
|
||||||
|
@ -44,9 +44,11 @@ print_unaligned_text(const char * title, char ** headers, char ** cells, char **
|
|||||||
fprintf(fout, "%s\n", title);
|
fprintf(fout, "%s\n", title);
|
||||||
|
|
||||||
/* print headers and count columns */
|
/* print headers and count columns */
|
||||||
for (ptr = headers; *ptr; ptr++) {
|
for (ptr = headers; *ptr; ptr++)
|
||||||
|
{
|
||||||
col_count++;
|
col_count++;
|
||||||
if (!opt_barebones) {
|
if (!opt_barebones)
|
||||||
|
{
|
||||||
if (col_count > 1)
|
if (col_count > 1)
|
||||||
fputs(opt_fieldsep, fout);
|
fputs(opt_fieldsep, fout);
|
||||||
fputs(*ptr, fout);
|
fputs(*ptr, fout);
|
||||||
@ -57,7 +59,8 @@ print_unaligned_text(const char * title, char ** headers, char ** cells, char **
|
|||||||
|
|
||||||
/* print cells */
|
/* print cells */
|
||||||
i = 0;
|
i = 0;
|
||||||
for (ptr = cells; *ptr; ptr++) {
|
for (ptr = cells; *ptr; ptr++)
|
||||||
|
{
|
||||||
fputs(*ptr, fout);
|
fputs(*ptr, fout);
|
||||||
if ((i + 1) % col_count)
|
if ((i + 1) % col_count)
|
||||||
fputs(opt_fieldsep, fout);
|
fputs(opt_fieldsep, fout);
|
||||||
@ -94,13 +97,14 @@ print_unaligned_vertical(const char * title, char ** headers, char ** cells, cha
|
|||||||
fprintf(fout, "%s\n", title);
|
fprintf(fout, "%s\n", title);
|
||||||
|
|
||||||
/* count columns */
|
/* count columns */
|
||||||
for (ptr = headers; *ptr; ptr++) {
|
for (ptr = headers; *ptr; ptr++)
|
||||||
col_count++;
|
col_count++;
|
||||||
}
|
|
||||||
|
|
||||||
/* print records */
|
/* print records */
|
||||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||||
if (i % col_count == 0) {
|
{
|
||||||
|
if (i % col_count == 0)
|
||||||
|
{
|
||||||
if (!opt_barebones)
|
if (!opt_barebones)
|
||||||
fprintf(fout, "-- RECORD %d\n", record++);
|
fprintf(fout, "-- RECORD %d\n", record++);
|
||||||
else
|
else
|
||||||
@ -111,7 +115,8 @@ print_unaligned_vertical(const char * title, char ** headers, char ** cells, cha
|
|||||||
|
|
||||||
/* print footers */
|
/* print footers */
|
||||||
|
|
||||||
if (!opt_barebones && footers) {
|
if (!opt_barebones && footers)
|
||||||
|
{
|
||||||
fputs("--- END ---\n", fout);
|
fputs("--- END ---\n", fout);
|
||||||
for (ptr = footers; *ptr; ptr++)
|
for (ptr = footers; *ptr; ptr++)
|
||||||
fprintf(fout, "%s\n", *ptr);
|
fprintf(fout, "%s\n", *ptr);
|
||||||
@ -129,17 +134,21 @@ print_unaligned_vertical(const char * title, char ** headers, char ** cells, cha
|
|||||||
static void
|
static void
|
||||||
_print_horizontal_line(const unsigned int col_count, const unsigned int *widths, unsigned short border, FILE *fout)
|
_print_horizontal_line(const unsigned int col_count, const unsigned int *widths, unsigned short border, FILE *fout)
|
||||||
{
|
{
|
||||||
unsigned int i, j;
|
unsigned int i,
|
||||||
|
j;
|
||||||
|
|
||||||
if (border == 1)
|
if (border == 1)
|
||||||
fputc('-', fout);
|
fputc('-', fout);
|
||||||
else if (border == 2)
|
else if (border == 2)
|
||||||
fputs("+-", fout);
|
fputs("+-", fout);
|
||||||
|
|
||||||
for (i=0; i<col_count; i++) {
|
for (i = 0; i < col_count; i++)
|
||||||
|
{
|
||||||
for (j = 0; j < widths[i]; j++)
|
for (j = 0; j < widths[i]; j++)
|
||||||
fputc('-', fout);
|
fputc('-', fout);
|
||||||
|
|
||||||
if (i<col_count-1) {
|
if (i < col_count - 1)
|
||||||
|
{
|
||||||
if (border == 0)
|
if (border == 0)
|
||||||
fputc(' ', fout);
|
fputc(' ', fout);
|
||||||
else
|
else
|
||||||
@ -163,8 +172,10 @@ print_aligned_text(const char * title, char ** headers, char ** cells, char ** f
|
|||||||
FILE *fout)
|
FILE *fout)
|
||||||
{
|
{
|
||||||
unsigned int col_count = 0;
|
unsigned int col_count = 0;
|
||||||
unsigned int i, tmp;
|
unsigned int i,
|
||||||
unsigned int * widths, total_w;
|
tmp;
|
||||||
|
unsigned int *widths,
|
||||||
|
total_w;
|
||||||
char **ptr;
|
char **ptr;
|
||||||
|
|
||||||
/* count columns */
|
/* count columns */
|
||||||
@ -172,7 +183,8 @@ print_aligned_text(const char * title, char ** headers, char ** cells, char ** f
|
|||||||
col_count++;
|
col_count++;
|
||||||
|
|
||||||
widths = calloc(col_count, sizeof(*widths));
|
widths = calloc(col_count, sizeof(*widths));
|
||||||
if (!widths) {
|
if (!widths)
|
||||||
|
{
|
||||||
perror("calloc");
|
perror("calloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -197,7 +209,8 @@ print_aligned_text(const char * title, char ** headers, char ** cells, char ** f
|
|||||||
total_w += widths[i];
|
total_w += widths[i];
|
||||||
|
|
||||||
/* print title */
|
/* print title */
|
||||||
if (title && !opt_barebones) {
|
if (title && !opt_barebones)
|
||||||
|
{
|
||||||
if (strlen(title) >= total_w)
|
if (strlen(title) >= total_w)
|
||||||
fprintf(fout, "%s\n", title);
|
fprintf(fout, "%s\n", title);
|
||||||
else
|
else
|
||||||
@ -205,7 +218,8 @@ print_aligned_text(const char * title, char ** headers, char ** cells, char ** f
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* print headers */
|
/* print headers */
|
||||||
if (!opt_barebones) {
|
if (!opt_barebones)
|
||||||
|
{
|
||||||
if (opt_border == 2)
|
if (opt_border == 2)
|
||||||
_print_horizontal_line(col_count, widths, opt_border, fout);
|
_print_horizontal_line(col_count, widths, opt_border, fout);
|
||||||
|
|
||||||
@ -214,11 +228,13 @@ print_aligned_text(const char * title, char ** headers, char ** cells, char ** f
|
|||||||
else if (opt_border == 1)
|
else if (opt_border == 1)
|
||||||
fputc(' ', fout);
|
fputc(' ', fout);
|
||||||
|
|
||||||
for (i=0; i<col_count; i++) {
|
for (i = 0; i < col_count; i++)
|
||||||
|
{
|
||||||
/* centered */
|
/* centered */
|
||||||
fprintf(fout, "%-*s%s%-*s", (int) floor((widths[i] - strlen(headers[i])) / 2.0), "", headers[i], (int) ceil((widths[i] - strlen(headers[i])) / 2.0), "");
|
fprintf(fout, "%-*s%s%-*s", (int) floor((widths[i] - strlen(headers[i])) / 2.0), "", headers[i], (int) ceil((widths[i] - strlen(headers[i])) / 2.0), "");
|
||||||
|
|
||||||
if (i<col_count-1) {
|
if (i < col_count - 1)
|
||||||
|
{
|
||||||
if (opt_border == 0)
|
if (opt_border == 0)
|
||||||
fputc(' ', fout);
|
fputc(' ', fout);
|
||||||
else
|
else
|
||||||
@ -236,9 +252,11 @@ print_aligned_text(const char * title, char ** headers, char ** cells, char ** f
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* print cells */
|
/* print cells */
|
||||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||||
|
{
|
||||||
/* beginning of line */
|
/* beginning of line */
|
||||||
if (i % col_count == 0) {
|
if (i % col_count == 0)
|
||||||
|
{
|
||||||
if (opt_border == 2)
|
if (opt_border == 2)
|
||||||
fputs("| ", fout);
|
fputs("| ", fout);
|
||||||
else if (opt_border == 1)
|
else if (opt_border == 1)
|
||||||
@ -248,7 +266,8 @@ print_aligned_text(const char * title, char ** headers, char ** cells, char ** f
|
|||||||
/* content */
|
/* content */
|
||||||
if (opt_align[(i) % col_count] == 'r')
|
if (opt_align[(i) % col_count] == 'r')
|
||||||
fprintf(fout, "%*s", widths[i % col_count], cells[i]);
|
fprintf(fout, "%*s", widths[i % col_count], cells[i]);
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
if ((i + 1) % col_count == 0 && opt_border != 2)
|
if ((i + 1) % col_count == 0 && opt_border != 2)
|
||||||
fputs(cells[i], fout);
|
fputs(cells[i], fout);
|
||||||
else
|
else
|
||||||
@ -256,14 +275,16 @@ print_aligned_text(const char * title, char ** headers, char ** cells, char ** f
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* divider */
|
/* divider */
|
||||||
if ((i+1) % col_count) {
|
if ((i + 1) % col_count)
|
||||||
|
{
|
||||||
if (opt_border == 0)
|
if (opt_border == 0)
|
||||||
fputc(' ', fout);
|
fputc(' ', fout);
|
||||||
else
|
else
|
||||||
fputs(" | ", fout);
|
fputs(" | ", fout);
|
||||||
}
|
}
|
||||||
/* end of line */
|
/* end of line */
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
if (opt_border == 2)
|
if (opt_border == 2)
|
||||||
fputs(" |", fout);
|
fputs(" |", fout);
|
||||||
fputc('\n', fout);
|
fputc('\n', fout);
|
||||||
@ -294,11 +315,15 @@ print_aligned_vertical(const char * title, char ** headers, char ** cells, char
|
|||||||
unsigned int col_count = 0;
|
unsigned int col_count = 0;
|
||||||
unsigned int record = 1;
|
unsigned int record = 1;
|
||||||
char **ptr;
|
char **ptr;
|
||||||
unsigned int i, tmp, hwidth=0, dwidth=0;
|
unsigned int i,
|
||||||
|
tmp,
|
||||||
|
hwidth = 0,
|
||||||
|
dwidth = 0;
|
||||||
char *divider;
|
char *divider;
|
||||||
|
|
||||||
/* count columns and find longest header */
|
/* count columns and find longest header */
|
||||||
for (ptr = headers; *ptr; ptr++) {
|
for (ptr = headers; *ptr; ptr++)
|
||||||
|
{
|
||||||
col_count++;
|
col_count++;
|
||||||
if ((tmp = strlen(*ptr)) > hwidth)
|
if ((tmp = strlen(*ptr)) > hwidth)
|
||||||
hwidth = tmp; /* don't wanna call strlen twice */
|
hwidth = tmp; /* don't wanna call strlen twice */
|
||||||
@ -315,32 +340,39 @@ print_aligned_vertical(const char * title, char ** headers, char ** cells, char
|
|||||||
|
|
||||||
/* make horizontal border */
|
/* make horizontal border */
|
||||||
divider = malloc(hwidth + dwidth + 10);
|
divider = malloc(hwidth + dwidth + 10);
|
||||||
if (!divider) {
|
if (!divider)
|
||||||
|
{
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
divider[0] = '\0';
|
divider[0] = '\0';
|
||||||
if (opt_border == 2)
|
if (opt_border == 2)
|
||||||
strcat(divider, "+-");
|
strcat(divider, "+-");
|
||||||
for (i=0; i<hwidth; i++) strcat(divider, opt_border > 0 ? "-" : " ");
|
for (i = 0; i < hwidth; i++)
|
||||||
|
strcat(divider, opt_border > 0 ? "-" : " ");
|
||||||
if (opt_border > 0)
|
if (opt_border > 0)
|
||||||
strcat(divider, "-+-");
|
strcat(divider, "-+-");
|
||||||
else
|
else
|
||||||
strcat(divider, " ");
|
strcat(divider, " ");
|
||||||
for (i=0; i<dwidth; i++) strcat(divider, opt_border > 0 ? "-" : " ");
|
for (i = 0; i < dwidth; i++)
|
||||||
|
strcat(divider, opt_border > 0 ? "-" : " ");
|
||||||
if (opt_border == 2)
|
if (opt_border == 2)
|
||||||
strcat(divider, "-+");
|
strcat(divider, "-+");
|
||||||
|
|
||||||
|
|
||||||
/* print records */
|
/* print records */
|
||||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||||
if (i % col_count == 0) {
|
{
|
||||||
if (!opt_barebones) {
|
if (i % col_count == 0)
|
||||||
|
{
|
||||||
|
if (!opt_barebones)
|
||||||
|
{
|
||||||
char *div_copy = strdup(divider);
|
char *div_copy = strdup(divider);
|
||||||
char *record_str = malloc(32);
|
char *record_str = malloc(32);
|
||||||
size_t record_str_len;
|
size_t record_str_len;
|
||||||
|
|
||||||
if (!div_copy || !record_str) {
|
if (!div_copy || !record_str)
|
||||||
|
{
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -350,10 +382,13 @@ print_aligned_vertical(const char * title, char ** headers, char ** cells, char
|
|||||||
else
|
else
|
||||||
sprintf(record_str, "[ RECORD %d ]", record++);
|
sprintf(record_str, "[ RECORD %d ]", record++);
|
||||||
record_str_len = strlen(record_str);
|
record_str_len = strlen(record_str);
|
||||||
if (record_str_len + opt_border > strlen(div_copy)) {
|
if (record_str_len + opt_border > strlen(div_copy))
|
||||||
|
{
|
||||||
void *new;
|
void *new;
|
||||||
|
|
||||||
new = realloc(div_copy, record_str_len + opt_border);
|
new = realloc(div_copy, record_str_len + opt_border);
|
||||||
if (!new) {
|
if (!new)
|
||||||
|
{
|
||||||
perror("realloc");
|
perror("realloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -387,7 +422,8 @@ print_aligned_vertical(const char * title, char ** headers, char ** cells, char
|
|||||||
|
|
||||||
/* print footers */
|
/* print footers */
|
||||||
|
|
||||||
if (!opt_barebones && footers && *footers) {
|
if (!opt_barebones && footers && *footers)
|
||||||
|
{
|
||||||
if (opt_border < 2)
|
if (opt_border < 2)
|
||||||
fputc('\n', fout);
|
fputc('\n', fout);
|
||||||
for (ptr = footers; *ptr; ptr++)
|
for (ptr = footers; *ptr; ptr++)
|
||||||
@ -411,8 +447,10 @@ static void
|
|||||||
html_escaped_print(const char *in, FILE *fout)
|
html_escaped_print(const char *in, FILE *fout)
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
for (p = in; *p; p++)
|
for (p = in; *p; p++)
|
||||||
switch (*p) {
|
switch (*p)
|
||||||
|
{
|
||||||
case '&':
|
case '&':
|
||||||
fputs("&", fout);
|
fputs("&", fout);
|
||||||
break;
|
break;
|
||||||
@ -448,7 +486,8 @@ print_html_text(const char * title, char ** headers, char ** cells, char ** foot
|
|||||||
fputs(">\n", fout);
|
fputs(">\n", fout);
|
||||||
|
|
||||||
/* print title */
|
/* print title */
|
||||||
if (!opt_barebones && title) {
|
if (!opt_barebones && title)
|
||||||
|
{
|
||||||
fputs(" <caption>", fout);
|
fputs(" <caption>", fout);
|
||||||
html_escaped_print(title, fout);
|
html_escaped_print(title, fout);
|
||||||
fputs("</caption>\n", fout);
|
fputs("</caption>\n", fout);
|
||||||
@ -457,9 +496,11 @@ print_html_text(const char * title, char ** headers, char ** cells, char ** foot
|
|||||||
/* print headers and count columns */
|
/* print headers and count columns */
|
||||||
if (!opt_barebones)
|
if (!opt_barebones)
|
||||||
fputs(" <tr>\n", fout);
|
fputs(" <tr>\n", fout);
|
||||||
for (i=0, ptr = headers; *ptr; i++, ptr++) {
|
for (i = 0, ptr = headers; *ptr; i++, ptr++)
|
||||||
|
{
|
||||||
col_count++;
|
col_count++;
|
||||||
if (!opt_barebones) {
|
if (!opt_barebones)
|
||||||
|
{
|
||||||
fputs(" <th align=center>", fout);
|
fputs(" <th align=center>", fout);
|
||||||
html_escaped_print(*ptr, fout);
|
html_escaped_print(*ptr, fout);
|
||||||
fputs("</th>\n", fout);
|
fputs("</th>\n", fout);
|
||||||
@ -469,12 +510,14 @@ print_html_text(const char * title, char ** headers, char ** cells, char ** foot
|
|||||||
fputs(" </tr>\n", fout);
|
fputs(" </tr>\n", fout);
|
||||||
|
|
||||||
/* print cells */
|
/* print cells */
|
||||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||||
|
{
|
||||||
if (i % col_count == 0)
|
if (i % col_count == 0)
|
||||||
fputs(" <tr valign=top>\n", fout);
|
fputs(" <tr valign=top>\n", fout);
|
||||||
|
|
||||||
fprintf(fout, " <td align=%s>", opt_align[(i) % col_count] == 'r' ? "right" : "left");
|
fprintf(fout, " <td align=%s>", opt_align[(i) % col_count] == 'r' ? "right" : "left");
|
||||||
if ( (*ptr)[strspn(*ptr, " \t")] == '\0' ) /* is string only whitespace? */
|
if ((*ptr)[strspn(*ptr, " \t")] == '\0') /* is string only
|
||||||
|
* whitespace? */
|
||||||
fputs(" ", fout);
|
fputs(" ", fout);
|
||||||
else
|
else
|
||||||
html_escaped_print(*ptr, fout);
|
html_escaped_print(*ptr, fout);
|
||||||
@ -489,7 +532,8 @@ print_html_text(const char * title, char ** headers, char ** cells, char ** foot
|
|||||||
/* print footers */
|
/* print footers */
|
||||||
|
|
||||||
if (footers && !opt_barebones)
|
if (footers && !opt_barebones)
|
||||||
for (ptr = footers; *ptr; ptr++) {
|
for (ptr = footers; *ptr; ptr++)
|
||||||
|
{
|
||||||
html_escaped_print(*ptr, fout);
|
html_escaped_print(*ptr, fout);
|
||||||
fputs("<br>\n", fout);
|
fputs("<br>\n", fout);
|
||||||
}
|
}
|
||||||
@ -516,7 +560,8 @@ print_html_vertical(const char * title, char ** headers, char ** cells, char **
|
|||||||
fputs(">\n", fout);
|
fputs(">\n", fout);
|
||||||
|
|
||||||
/* print title */
|
/* print title */
|
||||||
if (!opt_barebones && title) {
|
if (!opt_barebones && title)
|
||||||
|
{
|
||||||
fputs(" <caption>", fout);
|
fputs(" <caption>", fout);
|
||||||
html_escaped_print(title, fout);
|
html_escaped_print(title, fout);
|
||||||
fputs("</caption>\n", fout);
|
fputs("</caption>\n", fout);
|
||||||
@ -527,8 +572,10 @@ print_html_vertical(const char * title, char ** headers, char ** cells, char **
|
|||||||
col_count++;
|
col_count++;
|
||||||
|
|
||||||
/* print records */
|
/* print records */
|
||||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||||
if (i % col_count == 0) {
|
{
|
||||||
|
if (i % col_count == 0)
|
||||||
|
{
|
||||||
if (!opt_barebones)
|
if (!opt_barebones)
|
||||||
fprintf(fout, "\n <tr><td colspan=2 align=center>Record %d</td></tr>\n", record++);
|
fprintf(fout, "\n <tr><td colspan=2 align=center>Record %d</td></tr>\n", record++);
|
||||||
else
|
else
|
||||||
@ -540,7 +587,8 @@ print_html_vertical(const char * title, char ** headers, char ** cells, char **
|
|||||||
fputs("</th>\n", fout);
|
fputs("</th>\n", fout);
|
||||||
|
|
||||||
fprintf(fout, " <td align=%s>", opt_align[i % col_count] == 'r' ? "right" : "left");
|
fprintf(fout, " <td align=%s>", opt_align[i % col_count] == 'r' ? "right" : "left");
|
||||||
if ( (*ptr)[strspn(*ptr, " \t")] == '\0' ) /* is string only whitespace? */
|
if ((*ptr)[strspn(*ptr, " \t")] == '\0') /* is string only
|
||||||
|
* whitespace? */
|
||||||
fputs(" ", fout);
|
fputs(" ", fout);
|
||||||
else
|
else
|
||||||
html_escaped_print(*ptr, fout);
|
html_escaped_print(*ptr, fout);
|
||||||
@ -551,7 +599,8 @@ print_html_vertical(const char * title, char ** headers, char ** cells, char **
|
|||||||
|
|
||||||
/* print footers */
|
/* print footers */
|
||||||
if (footers && !opt_barebones)
|
if (footers && !opt_barebones)
|
||||||
for (ptr = footers; *ptr; ptr++) {
|
for (ptr = footers; *ptr; ptr++)
|
||||||
|
{
|
||||||
html_escaped_print(*ptr, fout);
|
html_escaped_print(*ptr, fout);
|
||||||
fputs("<br>\n", fout);
|
fputs("<br>\n", fout);
|
||||||
}
|
}
|
||||||
@ -570,8 +619,10 @@ static void
|
|||||||
latex_escaped_print(const char *in, FILE *fout)
|
latex_escaped_print(const char *in, FILE *fout)
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
for (p = in; *p; p++)
|
for (p = in; *p; p++)
|
||||||
switch (*p) {
|
switch (*p)
|
||||||
|
{
|
||||||
case '&':
|
case '&':
|
||||||
fputs("\\&", fout);
|
fputs("\\&", fout);
|
||||||
break;
|
break;
|
||||||
@ -612,7 +663,8 @@ print_latex_text(const char * title, char ** headers, char ** cells, char ** foo
|
|||||||
|
|
||||||
|
|
||||||
/* print title */
|
/* print title */
|
||||||
if (!opt_barebones && title) {
|
if (!opt_barebones && title)
|
||||||
|
{
|
||||||
fputs("\begin{center}\n", fout);
|
fputs("\begin{center}\n", fout);
|
||||||
latex_escaped_print(title, fout);
|
latex_escaped_print(title, fout);
|
||||||
fputs("\n\end{center}\n\n", fout);
|
fputs("\n\end{center}\n\n", fout);
|
||||||
@ -622,14 +674,19 @@ print_latex_text(const char * title, char ** headers, char ** cells, char ** foo
|
|||||||
fputs("\\begin{tabular}{", fout);
|
fputs("\\begin{tabular}{", fout);
|
||||||
if (opt_border == 0)
|
if (opt_border == 0)
|
||||||
fputs(opt_align, fout);
|
fputs(opt_align, fout);
|
||||||
else if (opt_border==1) {
|
else if (opt_border == 1)
|
||||||
for (cp = opt_align; *cp; cp++) {
|
{
|
||||||
if (cp != opt_align) fputc('|', fout);
|
for (cp = opt_align; *cp; cp++)
|
||||||
|
{
|
||||||
|
if (cp != opt_align)
|
||||||
|
fputc('|', fout);
|
||||||
fputc(*cp, fout);
|
fputc(*cp, fout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (opt_border==2) {
|
else if (opt_border == 2)
|
||||||
for (cp = opt_align; *cp; cp++) {
|
{
|
||||||
|
for (cp = opt_align; *cp; cp++)
|
||||||
|
{
|
||||||
fputc('|', fout);
|
fputc('|', fout);
|
||||||
fputc(*cp, fout);
|
fputc(*cp, fout);
|
||||||
}
|
}
|
||||||
@ -641,22 +698,26 @@ print_latex_text(const char * title, char ** headers, char ** cells, char ** foo
|
|||||||
fputs("\\hline\n", fout);
|
fputs("\\hline\n", fout);
|
||||||
|
|
||||||
/* print headers and count columns */
|
/* print headers and count columns */
|
||||||
for (i=0, ptr = headers; *ptr; i++, ptr++) {
|
for (i = 0, ptr = headers; *ptr; i++, ptr++)
|
||||||
|
{
|
||||||
col_count++;
|
col_count++;
|
||||||
if (!opt_barebones) {
|
if (!opt_barebones)
|
||||||
|
{
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
fputs(" & ", fout);
|
fputs(" & ", fout);
|
||||||
latex_escaped_print(*ptr, fout);
|
latex_escaped_print(*ptr, fout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opt_barebones) {
|
if (!opt_barebones)
|
||||||
|
{
|
||||||
fputs(" \\\\\n", fout);
|
fputs(" \\\\\n", fout);
|
||||||
fputs("\\hline\n", fout);
|
fputs("\\hline\n", fout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* print cells */
|
/* print cells */
|
||||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||||
|
{
|
||||||
latex_escaped_print(*ptr, fout);
|
latex_escaped_print(*ptr, fout);
|
||||||
|
|
||||||
if ((i + 1) % col_count == 0)
|
if ((i + 1) % col_count == 0)
|
||||||
@ -674,7 +735,8 @@ print_latex_text(const char * title, char ** headers, char ** cells, char ** foo
|
|||||||
/* print footers */
|
/* print footers */
|
||||||
|
|
||||||
if (footers && !opt_barebones)
|
if (footers && !opt_barebones)
|
||||||
for (ptr = footers; *ptr; ptr++) {
|
for (ptr = footers; *ptr; ptr++)
|
||||||
|
{
|
||||||
latex_escaped_print(*ptr, fout);
|
latex_escaped_print(*ptr, fout);
|
||||||
fputs(" \\\\\n", fout);
|
fputs(" \\\\\n", fout);
|
||||||
}
|
}
|
||||||
@ -697,7 +759,8 @@ print_latex_vertical(const char * title, char ** headers, char ** cells, char **
|
|||||||
(void) opt_align; /* currently unused parameter */
|
(void) opt_align; /* currently unused parameter */
|
||||||
|
|
||||||
/* print title */
|
/* print title */
|
||||||
if (!opt_barebones && title) {
|
if (!opt_barebones && title)
|
||||||
|
{
|
||||||
fputs("\begin{center}\n", fout);
|
fputs("\begin{center}\n", fout);
|
||||||
latex_escaped_print(title, fout);
|
latex_escaped_print(title, fout);
|
||||||
fputs("\n\end{center}\n\n", fout);
|
fputs("\n\end{center}\n\n", fout);
|
||||||
@ -720,10 +783,13 @@ print_latex_vertical(const char * title, char ** headers, char ** cells, char **
|
|||||||
|
|
||||||
|
|
||||||
/* print records */
|
/* print records */
|
||||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||||
|
{
|
||||||
/* new record */
|
/* new record */
|
||||||
if (i % col_count == 0) {
|
if (i % col_count == 0)
|
||||||
if (!opt_barebones) {
|
{
|
||||||
|
if (!opt_barebones)
|
||||||
|
{
|
||||||
if (opt_border == 2)
|
if (opt_border == 2)
|
||||||
fputs("\\hline\n", fout);
|
fputs("\\hline\n", fout);
|
||||||
fprintf(fout, "\\multicolumn{2}{c}{Record %d} \\\\\n", record++);
|
fprintf(fout, "\\multicolumn{2}{c}{Record %d} \\\\\n", record++);
|
||||||
@ -747,7 +813,8 @@ print_latex_vertical(const char * title, char ** headers, char ** cells, char **
|
|||||||
/* print footers */
|
/* print footers */
|
||||||
|
|
||||||
if (footers && !opt_barebones)
|
if (footers && !opt_barebones)
|
||||||
for (ptr = footers; *ptr; ptr++) {
|
for (ptr = footers; *ptr; ptr++)
|
||||||
|
{
|
||||||
latex_escaped_print(*ptr, fout);
|
latex_escaped_print(*ptr, fout);
|
||||||
fputs(" \\\\\n", fout);
|
fputs(" \\\\\n", fout);
|
||||||
}
|
}
|
||||||
@ -796,8 +863,11 @@ printTable(const char * title, char ** headers, char ** cells, char ** footers,
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
const char *pagerprog;
|
const char *pagerprog;
|
||||||
|
|
||||||
#ifdef TIOCGWINSZ
|
#ifdef TIOCGWINSZ
|
||||||
unsigned int col_count=0, row_count=0, lines;
|
unsigned int col_count = 0,
|
||||||
|
row_count = 0,
|
||||||
|
lines;
|
||||||
char **ptr;
|
char **ptr;
|
||||||
int result;
|
int result;
|
||||||
struct winsize screen_size;
|
struct winsize screen_size;
|
||||||
@ -819,17 +889,20 @@ printTable(const char * title, char ** headers, char ** cells, char ** footers,
|
|||||||
lines += 5;
|
lines += 5;
|
||||||
|
|
||||||
result = ioctl(fileno(stdout), TIOCGWINSZ, &screen_size);
|
result = ioctl(fileno(stdout), TIOCGWINSZ, &screen_size);
|
||||||
if (result==-1 || lines > screen_size.ws_row) {
|
if (result == -1 || lines > screen_size.ws_row)
|
||||||
|
{
|
||||||
#endif
|
#endif
|
||||||
pagerprog = getenv("PAGER");
|
pagerprog = getenv("PAGER");
|
||||||
if (!pagerprog) pagerprog = DEFAULT_PAGER;
|
if (!pagerprog)
|
||||||
|
pagerprog = DEFAULT_PAGER;
|
||||||
pager = popen(pagerprog, "w");
|
pager = popen(pagerprog, "w");
|
||||||
#ifdef TIOCGWINSZ
|
#ifdef TIOCGWINSZ
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pager) {
|
if (pager)
|
||||||
|
{
|
||||||
output = pager;
|
output = pager;
|
||||||
pqsignal(SIGPIPE, SIG_IGN);
|
pqsignal(SIGPIPE, SIG_IGN);
|
||||||
}
|
}
|
||||||
@ -839,7 +912,8 @@ printTable(const char * title, char ** headers, char ** cells, char ** footers,
|
|||||||
|
|
||||||
/* print the stuff */
|
/* print the stuff */
|
||||||
|
|
||||||
switch (opt->format) {
|
switch (opt->format)
|
||||||
|
{
|
||||||
case PRINT_UNALIGNED:
|
case PRINT_UNALIGNED:
|
||||||
if (opt->expanded)
|
if (opt->expanded)
|
||||||
print_unaligned_vertical(title, headers, cells, footers, opt->fieldSep, opt->tuples_only, output);
|
print_unaligned_vertical(title, headers, cells, footers, opt->fieldSep, opt->tuples_only, output);
|
||||||
@ -868,7 +942,8 @@ printTable(const char * title, char ** headers, char ** cells, char ** footers,
|
|||||||
fprintf(stderr, "+ Oops, you shouldn't see this!\n");
|
fprintf(stderr, "+ Oops, you shouldn't see this!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pager) {
|
if (pager)
|
||||||
|
{
|
||||||
pclose(pager);
|
pclose(pager);
|
||||||
pqsignal(SIGPIPE, SIG_DFL);
|
pqsignal(SIGPIPE, SIG_DFL);
|
||||||
}
|
}
|
||||||
@ -891,7 +966,8 @@ printQuery(PGresult * result, const printQueryOpt * opt, FILE * fout)
|
|||||||
nfields = PQnfields(result);
|
nfields = PQnfields(result);
|
||||||
|
|
||||||
headers = calloc(nfields + 1, sizeof(*headers));
|
headers = calloc(nfields + 1, sizeof(*headers));
|
||||||
if (!headers) {
|
if (!headers)
|
||||||
|
{
|
||||||
perror("calloc");
|
perror("calloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -902,12 +978,14 @@ printQuery(PGresult * result, const printQueryOpt * opt, FILE * fout)
|
|||||||
/* set cells */
|
/* set cells */
|
||||||
|
|
||||||
cells = calloc(nfields * PQntuples(result) + 1, sizeof(*cells));
|
cells = calloc(nfields * PQntuples(result) + 1, sizeof(*cells));
|
||||||
if (!cells) {
|
if (!cells)
|
||||||
|
{
|
||||||
perror("calloc");
|
perror("calloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i< nfields * PQntuples(result); i++) {
|
for (i = 0; i < nfields * PQntuples(result); i++)
|
||||||
|
{
|
||||||
if (PQgetisnull(result, i / nfields, i % nfields))
|
if (PQgetisnull(result, i / nfields, i % nfields))
|
||||||
cells[i] = opt->nullPrint ? opt->nullPrint : "";
|
cells[i] = opt->nullPrint ? opt->nullPrint : "";
|
||||||
else
|
else
|
||||||
@ -918,9 +996,11 @@ printQuery(PGresult * result, const printQueryOpt * opt, FILE * fout)
|
|||||||
|
|
||||||
if (opt->footers)
|
if (opt->footers)
|
||||||
footers = opt->footers;
|
footers = opt->footers;
|
||||||
else if (!opt->topt.expanded) {
|
else if (!opt->topt.expanded)
|
||||||
|
{
|
||||||
footers = calloc(2, sizeof(*footers));
|
footers = calloc(2, sizeof(*footers));
|
||||||
if (!footers) {
|
if (!footers)
|
||||||
|
{
|
||||||
perror("calloc");
|
perror("calloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -937,13 +1017,16 @@ printQuery(PGresult * result, const printQueryOpt * opt, FILE * fout)
|
|||||||
/* set alignment */
|
/* set alignment */
|
||||||
|
|
||||||
align = calloc(nfields + 1, sizeof(*align));
|
align = calloc(nfields + 1, sizeof(*align));
|
||||||
if (!align) {
|
if (!align)
|
||||||
|
{
|
||||||
perror("calloc");
|
perror("calloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<nfields; i++) {
|
for (i = 0; i < nfields; i++)
|
||||||
|
{
|
||||||
Oid ftype = PQftype(result, i);
|
Oid ftype = PQftype(result, i);
|
||||||
|
|
||||||
if (ftype == 20 || /* int8 */
|
if (ftype == 20 || /* int8 */
|
||||||
ftype == 21 || /* int2 */
|
ftype == 21 || /* int2 */
|
||||||
ftype == 23 || /* int4 */
|
ftype == 23 || /* int4 */
|
||||||
@ -965,7 +1048,8 @@ printQuery(PGresult * result, const printQueryOpt * opt, FILE * fout)
|
|||||||
|
|
||||||
free(headers);
|
free(headers);
|
||||||
free(cells);
|
free(cells);
|
||||||
if (footers) {
|
if (footers)
|
||||||
|
{
|
||||||
free(footers[0]);
|
free(footers[0]);
|
||||||
free(footers);
|
free(footers);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <libpq-fe.h>
|
#include <libpq-fe.h>
|
||||||
|
|
||||||
enum printFormat {
|
enum printFormat
|
||||||
|
{
|
||||||
PRINT_NOTHING = 0, /* to make sure someone initializes this */
|
PRINT_NOTHING = 0, /* to make sure someone initializes this */
|
||||||
PRINT_UNALIGNED,
|
PRINT_UNALIGNED,
|
||||||
PRINT_ALIGNED,
|
PRINT_ALIGNED,
|
||||||
@ -17,12 +18,16 @@ enum printFormat {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef struct _printTableOpt {
|
typedef struct _printTableOpt
|
||||||
|
{
|
||||||
enum printFormat format; /* one of the above */
|
enum printFormat format; /* one of the above */
|
||||||
bool expanded; /* expanded/vertical output (if supported by output format) */
|
bool expanded; /* expanded/vertical output (if supported
|
||||||
bool pager; /* use pager for output (if to stdout and stdout is a tty) */
|
* by output format) */
|
||||||
|
bool pager; /* use pager for output (if to stdout and
|
||||||
|
* stdout is a tty) */
|
||||||
bool tuples_only; /* don't output headers, row counts, etc. */
|
bool tuples_only; /* don't output headers, row counts, etc. */
|
||||||
unsigned short int border; /* Print a border around the table. 0=none, 1=dividing lines, 2=full */
|
unsigned short int border; /* Print a border around the table.
|
||||||
|
* 0=none, 1=dividing lines, 2=full */
|
||||||
char *fieldSep; /* field separator for unaligned text mode */
|
char *fieldSep; /* field separator for unaligned text mode */
|
||||||
char *tableAttr; /* attributes for HTML <table ...> */
|
char *tableAttr; /* attributes for HTML <table ...> */
|
||||||
} printTableOpt;
|
} printTableOpt;
|
||||||
@ -39,19 +44,20 @@ typedef struct _printTableOpt {
|
|||||||
* - align is an 'l' or an 'r' for every column, if the output format needs it.
|
* - align is an 'l' or an 'r' for every column, if the output format needs it.
|
||||||
* (You must specify this long enough. Otherwise anything could happen.)
|
* (You must specify this long enough. Otherwise anything could happen.)
|
||||||
*/
|
*/
|
||||||
void
|
void printTable(const char *title, char **headers, char **cells, char **footers,
|
||||||
printTable(const char * title, char ** headers, char ** cells, char ** footers,
|
|
||||||
const char *align,
|
const char *align,
|
||||||
const printTableOpt * opt, FILE *fout);
|
const printTableOpt * opt, FILE *fout);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct _printQueryOpt {
|
typedef struct _printQueryOpt
|
||||||
|
{
|
||||||
printTableOpt topt; /* the options above */
|
printTableOpt topt; /* the options above */
|
||||||
char *nullPrint; /* how to print null entities */
|
char *nullPrint; /* how to print null entities */
|
||||||
bool quote; /* quote all values as much as possible */
|
bool quote; /* quote all values as much as possible */
|
||||||
char *title; /* override title */
|
char *title; /* override title */
|
||||||
char ** footers; /* override footer (default is "(xx rows)") */
|
char **footers; /* override footer (default is "(xx
|
||||||
|
* rows)") */
|
||||||
} printQueryOpt;
|
} printQueryOpt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -99,9 +99,12 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
|||||||
if (pset->db)
|
if (pset->db)
|
||||||
strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE);
|
strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE);
|
||||||
break;
|
break;
|
||||||
case '~': {
|
case '~':
|
||||||
|
{
|
||||||
const char *var;
|
const char *var;
|
||||||
if (pset->db) {
|
|
||||||
|
if (pset->db)
|
||||||
|
{
|
||||||
if (strcmp(PQdb(pset->db), PQuser(pset->db)) == 0 ||
|
if (strcmp(PQdb(pset->db), PQuser(pset->db)) == 0 ||
|
||||||
((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset->db)) == 0))
|
((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset->db)) == 0))
|
||||||
strcpy(buf, "~");
|
strcpy(buf, "~");
|
||||||
@ -113,8 +116,10 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
|||||||
/* DB server hostname (long/short) */
|
/* DB server hostname (long/short) */
|
||||||
case 'M':
|
case 'M':
|
||||||
case 'm':
|
case 'm':
|
||||||
if (pset->db) {
|
if (pset->db)
|
||||||
if (PQhost(pset->db)) {
|
{
|
||||||
|
if (PQhost(pset->db))
|
||||||
|
{
|
||||||
strncpy(buf, PQhost(pset->db), MAX_PROMPT_SIZE);
|
strncpy(buf, PQhost(pset->db), MAX_PROMPT_SIZE);
|
||||||
if (*p == 'm')
|
if (*p == 'm')
|
||||||
buf[strcspn(buf, ".")] = '\0';
|
buf[strcspn(buf, ".")] = '\0';
|
||||||
@ -125,7 +130,8 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
|||||||
break;
|
break;
|
||||||
/* DB server port number */
|
/* DB server port number */
|
||||||
case '>':
|
case '>':
|
||||||
if (pset->db) {
|
if (pset->db)
|
||||||
|
{
|
||||||
if (PQhost(pset->db))
|
if (PQhost(pset->db))
|
||||||
strncpy(buf, PQport(pset->db), MAX_PROMPT_SIZE);
|
strncpy(buf, PQport(pset->db), MAX_PROMPT_SIZE);
|
||||||
else
|
else
|
||||||
@ -138,11 +144,20 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
|||||||
strncpy(buf, PQuser(pset->db), MAX_PROMPT_SIZE);
|
strncpy(buf, PQuser(pset->db), MAX_PROMPT_SIZE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case '0':
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
case '8':
|
||||||
|
case '9':
|
||||||
{
|
{
|
||||||
long int l;
|
long int l;
|
||||||
char *end;
|
char *end;
|
||||||
|
|
||||||
l = strtol(p, &end, 0);
|
l = strtol(p, &end, 0);
|
||||||
sprintf(buf, "%c", (unsigned char) l);
|
sprintf(buf, "%c", (unsigned char) l);
|
||||||
p = end - 1;
|
p = end - 1;
|
||||||
@ -150,7 +165,8 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'R':
|
case 'R':
|
||||||
switch(status) {
|
switch (status)
|
||||||
|
{
|
||||||
case PROMPT_READY:
|
case PROMPT_READY:
|
||||||
if (!pset->db)
|
if (!pset->db)
|
||||||
buf[0] = '!';
|
buf[0] = '!';
|
||||||
@ -196,11 +212,13 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
|||||||
FILE *fd = NULL;
|
FILE *fd = NULL;
|
||||||
char *file = strdup(p + 1);
|
char *file = strdup(p + 1);
|
||||||
int cmdend;
|
int cmdend;
|
||||||
|
|
||||||
cmdend = strcspn(file, "`");
|
cmdend = strcspn(file, "`");
|
||||||
file[cmdend] = '\0';
|
file[cmdend] = '\0';
|
||||||
if (file)
|
if (file)
|
||||||
fd = popen(file, "r");
|
fd = popen(file, "r");
|
||||||
if (fd) {
|
if (fd)
|
||||||
|
{
|
||||||
fgets(buf, MAX_PROMPT_SIZE - 1, fd);
|
fgets(buf, MAX_PROMPT_SIZE - 1, fd);
|
||||||
pclose(fd);
|
pclose(fd);
|
||||||
}
|
}
|
||||||
@ -217,6 +235,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
|||||||
char *name;
|
char *name;
|
||||||
const char *val;
|
const char *val;
|
||||||
int nameend;
|
int nameend;
|
||||||
|
|
||||||
name = strdup(p + 1);
|
name = strdup(p + 1);
|
||||||
nameend = strcspn(name, "$");
|
nameend = strcspn(name, "$");
|
||||||
name[nameend] = '\0';
|
name[nameend] = '\0';
|
||||||
@ -245,12 +264,10 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
|||||||
esc = false;
|
esc = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!esc) {
|
if (!esc)
|
||||||
strncat(destination, buf, MAX_PROMPT_SIZE - strlen(destination));
|
strncat(destination, buf, MAX_PROMPT_SIZE - strlen(destination));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
destination[MAX_PROMPT_SIZE] = '\0';
|
destination[MAX_PROMPT_SIZE] = '\0';
|
||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
typedef enum _promptStatus {
|
typedef enum _promptStatus
|
||||||
|
{
|
||||||
PROMPT_READY,
|
PROMPT_READY,
|
||||||
PROMPT_CONTINUE,
|
PROMPT_CONTINUE,
|
||||||
PROMPT_COMMENT,
|
PROMPT_COMMENT,
|
||||||
|
3297
src/bin/psql/psql.c
3297
src/bin/psql/psql.c
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: psqlHelp.h,v 1.80 1999/10/29 23:52:22 momjian Exp $
|
* $Id: psqlHelp.h,v 1.81 1999/11/04 23:14:29 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -384,5 +384,6 @@ TIMEZONE|XACTISOLEVEL|CLIENT_ENCODING|SERVER_ENCODING"},
|
|||||||
\tVACUUM [VERBOSE] [ANALYZE] [table]\n\
|
\tVACUUM [VERBOSE] [ANALYZE] [table]\n\
|
||||||
\tor\n\
|
\tor\n\
|
||||||
\tVACUUM [VERBOSE] ANALYZE [table [(column_name1, ...column_nameN)]];"},
|
\tVACUUM [VERBOSE] ANALYZE [table [(column_name1, ...column_nameN)]];"},
|
||||||
{NULL, NULL, NULL} /* important to keep a NULL terminator here!*/
|
{NULL, NULL, NULL} /* important to keep a NULL terminator
|
||||||
|
* here! */
|
||||||
};
|
};
|
||||||
|
@ -29,15 +29,18 @@ typedef struct _psqlSettings
|
|||||||
|
|
||||||
char *gfname; /* one-shot file output argument for \g */
|
char *gfname; /* one-shot file output argument for \g */
|
||||||
|
|
||||||
bool notty; /* stdin or stdout is not a tty (as determined on startup) */
|
bool notty; /* stdin or stdout is not a tty (as
|
||||||
|
* determined on startup) */
|
||||||
bool useReadline; /* use libreadline routines */
|
bool useReadline; /* use libreadline routines */
|
||||||
bool useHistory;
|
bool useHistory;
|
||||||
bool getPassword; /* prompt the user for a username and
|
bool getPassword; /* prompt the user for a username and
|
||||||
password */
|
* password */
|
||||||
FILE * cur_cmd_source; /* describe the status of the current main loop */
|
FILE *cur_cmd_source; /* describe the status of the current main
|
||||||
|
* loop */
|
||||||
bool cur_cmd_interactive;
|
bool cur_cmd_interactive;
|
||||||
|
|
||||||
bool has_client_encoding; /* was PGCLIENTENCODING set on startup? */
|
bool has_client_encoding; /* was PGCLIENTENCODING set on
|
||||||
|
* startup? */
|
||||||
} PsqlSettings;
|
} PsqlSettings;
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +46,9 @@ showVersion(PsqlSettings *pset, bool verbose);
|
|||||||
/* Structures to pass information between the option parsing routine
|
/* Structures to pass information between the option parsing routine
|
||||||
* and the main function
|
* and the main function
|
||||||
*/
|
*/
|
||||||
enum _actions { ACT_NOTHING = 0,
|
enum _actions
|
||||||
|
{
|
||||||
|
ACT_NOTHING = 0,
|
||||||
ACT_SINGLE_SLASH,
|
ACT_SINGLE_SLASH,
|
||||||
ACT_LIST_DB,
|
ACT_LIST_DB,
|
||||||
ACT_SHOW_VER,
|
ACT_SHOW_VER,
|
||||||
@ -54,7 +56,8 @@ enum _actions { ACT_NOTHING = 0,
|
|||||||
ACT_FILE
|
ACT_FILE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct adhoc_opts {
|
struct adhoc_opts
|
||||||
|
{
|
||||||
char *dbname;
|
char *dbname;
|
||||||
char *host;
|
char *host;
|
||||||
char *port;
|
char *port;
|
||||||
@ -118,7 +121,8 @@ main(int argc, char **argv)
|
|||||||
if (options.action == ACT_LIST_DB || options.action == ACT_SHOW_VER)
|
if (options.action == ACT_LIST_DB || options.action == ACT_SHOW_VER)
|
||||||
options.dbname = "template1";
|
options.dbname = "template1";
|
||||||
|
|
||||||
if (options.username) {
|
if (options.username)
|
||||||
|
{
|
||||||
if (strcmp(options.username, "?") == 0)
|
if (strcmp(options.username, "?") == 0)
|
||||||
username = simple_prompt("Username: ", 100, true);
|
username = simple_prompt("Username: ", 100, true);
|
||||||
else
|
else
|
||||||
@ -129,12 +133,14 @@ main(int argc, char **argv)
|
|||||||
password = simple_prompt("Password: ", 100, false);
|
password = simple_prompt("Password: ", 100, false);
|
||||||
|
|
||||||
/* loop until we have a password if requested by backend */
|
/* loop until we have a password if requested by backend */
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
need_pass = false;
|
need_pass = false;
|
||||||
settings.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.dbname, username, password);
|
settings.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.dbname, username, password);
|
||||||
|
|
||||||
if (PQstatus(settings.db) == CONNECTION_BAD &&
|
if (PQstatus(settings.db) == CONNECTION_BAD &&
|
||||||
strcmp(PQerrorMessage(settings.db), "fe_sendauth: no password supplied\n")==0) {
|
strcmp(PQerrorMessage(settings.db), "fe_sendauth: no password supplied\n") == 0)
|
||||||
|
{
|
||||||
need_pass = true;
|
need_pass = true;
|
||||||
free(password);
|
free(password);
|
||||||
password = NULL;
|
password = NULL;
|
||||||
@ -145,19 +151,23 @@ main(int argc, char **argv)
|
|||||||
free(username);
|
free(username);
|
||||||
free(password);
|
free(password);
|
||||||
|
|
||||||
if (PQstatus(settings.db) == CONNECTION_BAD) {
|
if (PQstatus(settings.db) == CONNECTION_BAD)
|
||||||
|
{
|
||||||
fprintf(stderr, "Connection to database '%s' failed.\n%s\n", PQdb(settings.db), PQerrorMessage(settings.db));
|
fprintf(stderr, "Connection to database '%s' failed.\n%s\n", PQdb(settings.db), PQerrorMessage(settings.db));
|
||||||
PQfinish(settings.db);
|
PQfinish(settings.db);
|
||||||
exit(EXIT_BADCONN);
|
exit(EXIT_BADCONN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.action == ACT_LIST_DB) {
|
if (options.action == ACT_LIST_DB)
|
||||||
|
{
|
||||||
int success = listAllDbs(&settings);
|
int success = listAllDbs(&settings);
|
||||||
|
|
||||||
PQfinish(settings.db);
|
PQfinish(settings.db);
|
||||||
exit(!success);
|
exit(!success);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.action == ACT_SHOW_VER) {
|
if (options.action == ACT_SHOW_VER)
|
||||||
|
{
|
||||||
showVersion(&settings, true);
|
showVersion(&settings, true);
|
||||||
PQfinish(settings.db);
|
PQfinish(settings.db);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
@ -215,6 +225,7 @@ main(int argc, char **argv)
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
/* getopt is not in the standard includes on Win32 */
|
/* getopt is not in the standard includes on Win32 */
|
||||||
int getopt(int, char *const[], const char *);
|
int getopt(int, char *const[], const char *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -255,6 +266,7 @@ parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * o
|
|||||||
};
|
};
|
||||||
|
|
||||||
int optindex;
|
int optindex;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
@ -266,7 +278,11 @@ parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * o
|
|||||||
#ifdef HAVE_GETOPT_LONG
|
#ifdef HAVE_GETOPT_LONG
|
||||||
while ((c = getopt_long(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qsStT:uU:v:VWx?", long_options, &optindex)) != -1)
|
while ((c = getopt_long(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qsStT:uU:v:VWx?", long_options, &optindex)) != -1)
|
||||||
#else
|
#else
|
||||||
/* Be sure to leave the '-' in here, so we can catch accidental long options. */
|
|
||||||
|
/*
|
||||||
|
* Be sure to leave the '-' in here, so we can catch accidental long
|
||||||
|
* options.
|
||||||
|
*/
|
||||||
while ((c = getopt(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qsStT:uU:v:VWx?-")) != -1)
|
while ((c = getopt(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qsStT:uU:v:VWx?-")) != -1)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -326,12 +342,14 @@ parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * o
|
|||||||
equal_loc = strchr(value, '=');
|
equal_loc = strchr(value, '=');
|
||||||
if (!equal_loc)
|
if (!equal_loc)
|
||||||
result = do_pset(value, NULL, &pset->popt, true);
|
result = do_pset(value, NULL, &pset->popt, true);
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
*equal_loc = '\0';
|
*equal_loc = '\0';
|
||||||
result = do_pset(value, equal_loc + 1, &pset->popt, true);
|
result = do_pset(value, equal_loc + 1, &pset->popt, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result) {
|
if (!result)
|
||||||
|
{
|
||||||
fprintf(stderr, "Couldn't set printing paramter %s.\n", value);
|
fprintf(stderr, "Couldn't set printing paramter %s.\n", value);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -371,15 +389,19 @@ parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * o
|
|||||||
|
|
||||||
value = xstrdup(optarg);
|
value = xstrdup(optarg);
|
||||||
equal_loc = strchr(value, '=');
|
equal_loc = strchr(value, '=');
|
||||||
if (!equal_loc) {
|
if (!equal_loc)
|
||||||
if (!DeleteVariable(pset->vars, value)) {
|
{
|
||||||
|
if (!DeleteVariable(pset->vars, value))
|
||||||
|
{
|
||||||
fprintf(stderr, "Couldn't delete variable %s.\n", value);
|
fprintf(stderr, "Couldn't delete variable %s.\n", value);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
*equal_loc = '\0';
|
*equal_loc = '\0';
|
||||||
if (!SetVariable(pset->vars, value, equal_loc+1)) {
|
if (!SetVariable(pset->vars, value, equal_loc + 1))
|
||||||
|
{
|
||||||
fprintf(stderr, "Couldn't set variable %s to %s.\n", value, equal_loc);
|
fprintf(stderr, "Couldn't set variable %s to %s.\n", value, equal_loc);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -412,8 +434,12 @@ parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * o
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we still have arguments, use it as the database name and username */
|
/*
|
||||||
while (argc - optind >= 1) {
|
* if we still have arguments, use it as the database name and
|
||||||
|
* username
|
||||||
|
*/
|
||||||
|
while (argc - optind >= 1)
|
||||||
|
{
|
||||||
if (!options->dbname)
|
if (!options->dbname)
|
||||||
options->dbname = argv[optind];
|
options->dbname = argv[optind];
|
||||||
else if (!options->username)
|
else if (!options->username)
|
||||||
@ -449,9 +475,11 @@ process_psqlrc(PsqlSettings * pset)
|
|||||||
/* Look for one in the home dir */
|
/* Look for one in the home dir */
|
||||||
home = getenv("HOME");
|
home = getenv("HOME");
|
||||||
|
|
||||||
if (home) {
|
if (home)
|
||||||
|
{
|
||||||
psqlrc = (char *) malloc(strlen(home) + 20);
|
psqlrc = (char *) malloc(strlen(home) + 20);
|
||||||
if (!psqlrc) {
|
if (!psqlrc)
|
||||||
|
{
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -459,7 +487,8 @@ process_psqlrc(PsqlSettings * pset)
|
|||||||
sprintf(psqlrc, "%s/.psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, home);
|
sprintf(psqlrc, "%s/.psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, home);
|
||||||
if (access(psqlrc, R_OK) == 0)
|
if (access(psqlrc, R_OK) == 0)
|
||||||
process_file(psqlrc, pset);
|
process_file(psqlrc, pset);
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
sprintf(psqlrc, "%s/.psqlrc", home);
|
sprintf(psqlrc, "%s/.psqlrc", home);
|
||||||
if (access(psqlrc, R_OK) == 0)
|
if (access(psqlrc, R_OK) == 0)
|
||||||
process_file(psqlrc, pset);
|
process_file(psqlrc, pset);
|
||||||
@ -484,21 +513,27 @@ showVersion(PsqlSettings *pset, bool verbose)
|
|||||||
{
|
{
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
char *versionstr = NULL;
|
char *versionstr = NULL;
|
||||||
long int release = 0, version = 0, subversion = 0;
|
long int release = 0,
|
||||||
|
version = 0,
|
||||||
|
subversion = 0;
|
||||||
|
|
||||||
/* get backend version */
|
/* get backend version */
|
||||||
res = PSQLexec(pset, "SELECT version()");
|
res = PSQLexec(pset, "SELECT version()");
|
||||||
if (PQresultStatus(res) == PGRES_TUPLES_OK)
|
if (PQresultStatus(res) == PGRES_TUPLES_OK)
|
||||||
versionstr = PQgetvalue(res, 0, 0);
|
versionstr = PQgetvalue(res, 0, 0);
|
||||||
|
|
||||||
if (!verbose) {
|
if (!verbose)
|
||||||
if (versionstr) puts(versionstr);
|
{
|
||||||
|
if (versionstr)
|
||||||
|
puts(versionstr);
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(versionstr, "PostgreSQL ", 11) == 0) {
|
if (strncmp(versionstr, "PostgreSQL ", 11) == 0)
|
||||||
|
{
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
|
||||||
release = strtol(&versionstr[11], &tmp, 10);
|
release = strtol(&versionstr[11], &tmp, 10);
|
||||||
version = strtol(tmp + 1, &tmp, 10);
|
version = strtol(tmp + 1, &tmp, 10);
|
||||||
subversion = strtol(tmp + 1, &tmp, 10);
|
subversion = strtol(tmp + 1, &tmp, 10);
|
||||||
|
@ -2,11 +2,13 @@
|
|||||||
#include <c.h>
|
#include <c.h>
|
||||||
#include "stringutils.h"
|
#include "stringutils.h"
|
||||||
|
|
||||||
//#include <ctype.h>
|
//
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
//#include <stdio.h>
|
//
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <postgres.h>
|
#include <postgres.h>
|
||||||
#ifndef HAVE_STRDUP
|
#ifndef HAVE_STRDUP
|
||||||
@ -34,21 +36,26 @@ unescape_quotes(char *source, char quote, char escape);
|
|||||||
*
|
*
|
||||||
* Note that the string s is _not_ overwritten in this implementation.
|
* Note that the string s is _not_ overwritten in this implementation.
|
||||||
*/
|
*/
|
||||||
char * strtokx(const char *s,
|
char *
|
||||||
|
strtokx(const char *s,
|
||||||
const char *delim,
|
const char *delim,
|
||||||
const char *quote,
|
const char *quote,
|
||||||
char escape,
|
char escape,
|
||||||
char *was_quoted,
|
char *was_quoted,
|
||||||
unsigned int *token_pos)
|
unsigned int *token_pos)
|
||||||
{
|
{
|
||||||
static char * storage = NULL; /* store the local copy of the users string here */
|
static char *storage = NULL;/* store the local copy of the users
|
||||||
static char * string = NULL; /* pointer into storage where to continue on next call */
|
* string here */
|
||||||
|
static char *string = NULL; /* pointer into storage where to continue
|
||||||
|
* on next call */
|
||||||
|
|
||||||
/* variously abused variables: */
|
/* variously abused variables: */
|
||||||
unsigned int offset;
|
unsigned int offset;
|
||||||
char *start;
|
char *start;
|
||||||
char *cp = NULL;
|
char *cp = NULL;
|
||||||
|
|
||||||
if (s) {
|
if (s)
|
||||||
|
{
|
||||||
free(storage);
|
free(storage);
|
||||||
storage = strdup(s);
|
storage = strdup(s);
|
||||||
string = storage;
|
string = storage;
|
||||||
@ -61,7 +68,8 @@ char * strtokx(const char *s,
|
|||||||
offset = strspn(string, delim);
|
offset = strspn(string, delim);
|
||||||
|
|
||||||
/* end of string reached */
|
/* end of string reached */
|
||||||
if (string[offset] == '\0') {
|
if (string[offset] == '\0')
|
||||||
|
{
|
||||||
/* technically we don't need to free here, but we're nice */
|
/* technically we don't need to free here, but we're nice */
|
||||||
free(storage);
|
free(storage);
|
||||||
storage = NULL;
|
storage = NULL;
|
||||||
@ -73,9 +81,11 @@ char * strtokx(const char *s,
|
|||||||
if (quote)
|
if (quote)
|
||||||
cp = strchr(quote, string[offset]);
|
cp = strchr(quote, string[offset]);
|
||||||
|
|
||||||
if (cp) {
|
if (cp)
|
||||||
|
{
|
||||||
/* okay, we have a quoting character, now scan for the closer */
|
/* okay, we have a quoting character, now scan for the closer */
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
start = &string[offset + 1];
|
start = &string[offset + 1];
|
||||||
|
|
||||||
if (token_pos)
|
if (token_pos)
|
||||||
@ -91,7 +101,8 @@ char * strtokx(const char *s,
|
|||||||
);
|
);
|
||||||
|
|
||||||
/* not yet end of string? */
|
/* not yet end of string? */
|
||||||
if (*p != '\0') {
|
if (*p != '\0')
|
||||||
|
{
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
string = p + 1;
|
string = p + 1;
|
||||||
if (was_quoted)
|
if (was_quoted)
|
||||||
@ -99,7 +110,8 @@ char * strtokx(const char *s,
|
|||||||
unescape_quotes(start, *cp, escape);
|
unescape_quotes(start, *cp, escape);
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
if (was_quoted)
|
if (was_quoted)
|
||||||
*was_quoted = *cp;
|
*was_quoted = *cp;
|
||||||
string = p;
|
string = p;
|
||||||
@ -119,13 +131,15 @@ char * strtokx(const char *s,
|
|||||||
if (was_quoted)
|
if (was_quoted)
|
||||||
*was_quoted = 0;
|
*was_quoted = 0;
|
||||||
|
|
||||||
if (start[offset] != '\0') {
|
if (start[offset] != '\0')
|
||||||
|
{
|
||||||
start[offset] = '\0';
|
start[offset] = '\0';
|
||||||
string = &start[offset] + 1;
|
string = &start[offset] + 1;
|
||||||
|
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
string = &start[offset];
|
string = &start[offset];
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
@ -143,14 +157,16 @@ static void
|
|||||||
unescape_quotes(char *source, char quote, char escape)
|
unescape_quotes(char *source, char quote, char escape)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
char *destination, *tmp;
|
char *destination,
|
||||||
|
*tmp;
|
||||||
|
|
||||||
#ifdef USE_ASSERT_CHECKING
|
#ifdef USE_ASSERT_CHECKING
|
||||||
assert(source);
|
assert(source);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
destination = (char *) calloc(1, strlen(source) + 1);
|
destination = (char *) calloc(1, strlen(source) + 1);
|
||||||
if (!destination) {
|
if (!destination)
|
||||||
|
{
|
||||||
perror("calloc");
|
perror("calloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -161,7 +177,8 @@ unescape_quotes(char *source, char quote, char escape)
|
|||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
if (*p == escape && *(p+1) && quote == *(p+1)) {
|
if (*p == escape && *(p + 1) && quote == *(p + 1))
|
||||||
|
{
|
||||||
c = *(p + 1);
|
c = *(p + 1);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
|
|
||||||
/* The cooler version of strtok() which knows about quotes and doesn't
|
/* The cooler version of strtok() which knows about quotes and doesn't
|
||||||
* overwrite your input */
|
* overwrite your input */
|
||||||
extern char *
|
extern char *strtokx(const char *s,
|
||||||
strtokx(const char *s,
|
|
||||||
const char *delim,
|
const char *delim,
|
||||||
const char *quote,
|
const char *quote,
|
||||||
char escape,
|
char escape,
|
||||||
|
@ -6,16 +6,19 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
VariableSpace CreateVariableSpace(void)
|
VariableSpace
|
||||||
|
CreateVariableSpace(void)
|
||||||
{
|
{
|
||||||
struct _variable *ptr;
|
struct _variable *ptr;
|
||||||
|
|
||||||
ptr = calloc(1, sizeof *ptr);
|
ptr = calloc(1, sizeof *ptr);
|
||||||
if (!ptr) return NULL;
|
if (!ptr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
ptr->name = strdup("@");
|
ptr->name = strdup("@");
|
||||||
ptr->value = strdup("");
|
ptr->value = strdup("");
|
||||||
if (!ptr->name || !ptr->value) {
|
if (!ptr->name || !ptr->value)
|
||||||
|
{
|
||||||
free(ptr->name);
|
free(ptr->name);
|
||||||
free(ptr->value);
|
free(ptr->value);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
@ -27,16 +30,19 @@ VariableSpace CreateVariableSpace(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char * GetVariable(VariableSpace space, const char * name)
|
const char *
|
||||||
|
GetVariable(VariableSpace space, const char *name)
|
||||||
{
|
{
|
||||||
struct _variable *current;
|
struct _variable *current;
|
||||||
|
|
||||||
if (!space)
|
if (!space)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (strspn(name, VALID_VARIABLE_CHARS) != strlen(name)) return NULL;
|
if (strspn(name, VALID_VARIABLE_CHARS) != strlen(name))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
for (current = space; current; current = current->next) {
|
for (current = space; current; current = current->next)
|
||||||
|
{
|
||||||
#ifdef USE_ASSERT_CHECKING
|
#ifdef USE_ASSERT_CHECKING
|
||||||
assert(current->name);
|
assert(current->name);
|
||||||
assert(current->value);
|
assert(current->value);
|
||||||
@ -50,16 +56,19 @@ const char * GetVariable(VariableSpace space, const char * name)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool GetVariableBool(VariableSpace space, const char * name)
|
bool
|
||||||
|
GetVariableBool(VariableSpace space, const char *name)
|
||||||
{
|
{
|
||||||
return GetVariable(space, name) != NULL ? true : false;
|
return GetVariable(space, name) != NULL ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool SetVariable(VariableSpace space, const char * name, const char * value)
|
bool
|
||||||
|
SetVariable(VariableSpace space, const char *name, const char *value)
|
||||||
{
|
{
|
||||||
struct _variable *current, *previous;
|
struct _variable *current,
|
||||||
|
*previous;
|
||||||
|
|
||||||
if (!space)
|
if (!space)
|
||||||
return false;
|
return false;
|
||||||
@ -67,14 +76,17 @@ bool SetVariable(VariableSpace space, const char * name, const char * value)
|
|||||||
if (!value)
|
if (!value)
|
||||||
return DeleteVariable(space, name);
|
return DeleteVariable(space, name);
|
||||||
|
|
||||||
if (strspn(name, VALID_VARIABLE_CHARS) != strlen(name)) return false;
|
if (strspn(name, VALID_VARIABLE_CHARS) != strlen(name))
|
||||||
|
return false;
|
||||||
|
|
||||||
for (current = space; current; previous = current, current = current->next) {
|
for (current = space; current; previous = current, current = current->next)
|
||||||
|
{
|
||||||
#ifdef USE_ASSERT_CHECKING
|
#ifdef USE_ASSERT_CHECKING
|
||||||
assert(current->name);
|
assert(current->name);
|
||||||
assert(current->value);
|
assert(current->value);
|
||||||
#endif
|
#endif
|
||||||
if (strcmp(current->name, name)==0) {
|
if (strcmp(current->name, name) == 0)
|
||||||
|
{
|
||||||
free(current->value);
|
free(current->value);
|
||||||
current->value = strdup(value);
|
current->value = strdup(value);
|
||||||
return current->value ? true : false;
|
return current->value ? true : false;
|
||||||
@ -93,21 +105,26 @@ bool SetVariable(VariableSpace space, const char * name, const char * value)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool DeleteVariable(VariableSpace space, const char * name)
|
bool
|
||||||
|
DeleteVariable(VariableSpace space, const char *name)
|
||||||
{
|
{
|
||||||
struct _variable *current, *previous;
|
struct _variable *current,
|
||||||
|
*previous;
|
||||||
|
|
||||||
if (!space)
|
if (!space)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (strspn(name, VALID_VARIABLE_CHARS) != strlen(name)) return false;
|
if (strspn(name, VALID_VARIABLE_CHARS) != strlen(name))
|
||||||
|
return false;
|
||||||
|
|
||||||
for (current = space, previous = NULL; current; previous = current, current = current->next) {
|
for (current = space, previous = NULL; current; previous = current, current = current->next)
|
||||||
|
{
|
||||||
#ifdef USE_ASSERT_CHECKING
|
#ifdef USE_ASSERT_CHECKING
|
||||||
assert(current->name);
|
assert(current->name);
|
||||||
assert(current->value);
|
assert(current->value);
|
||||||
#endif
|
#endif
|
||||||
if (strcmp(current->name, name)==0) {
|
if (strcmp(current->name, name) == 0)
|
||||||
|
{
|
||||||
free(current->name);
|
free(current->name);
|
||||||
free(current->value);
|
free(current->value);
|
||||||
if (previous)
|
if (previous)
|
||||||
@ -122,7 +139,8 @@ bool DeleteVariable(VariableSpace space, const char * name)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void DestroyVariableSpace(VariableSpace space)
|
void
|
||||||
|
DestroyVariableSpace(VariableSpace space)
|
||||||
{
|
{
|
||||||
if (!space)
|
if (!space)
|
||||||
return;
|
return;
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
|
|
||||||
#define VALID_VARIABLE_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_"
|
#define VALID_VARIABLE_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_"
|
||||||
|
|
||||||
struct _variable {
|
struct _variable
|
||||||
|
{
|
||||||
char *name;
|
char *name;
|
||||||
char *value;
|
char *value;
|
||||||
struct _variable *next;
|
struct _variable *next;
|
||||||
|
Reference in New Issue
Block a user