mirror of
https://github.com/postgres/postgres.git
synced 2025-06-23 14:01:44 +03:00
psql cleanup
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -11,37 +11,34 @@
|
||||
|
||||
|
||||
|
||||
typedef enum _backslashResult {
|
||||
typedef enum _backslashResult
|
||||
{
|
||||
CMD_UNKNOWN = 0, /* not done parsing yet (internal only) */
|
||||
CMD_SEND, /* query complete; send off */
|
||||
CMD_SKIP_LINE, /* keep building query */
|
||||
CMD_TERMINATE, /* quit program */
|
||||
CMD_NEWEDIT, /* query buffer was changed (e.g., via \e) */
|
||||
CMD_ERROR /* the execution of the backslash command resulted
|
||||
in an error */
|
||||
CMD_ERROR /* the execution of the backslash command
|
||||
* resulted in an error */
|
||||
} backslashResult;
|
||||
|
||||
|
||||
|
||||
backslashResult
|
||||
HandleSlashCmds(PsqlSettings *pset,
|
||||
backslashResult HandleSlashCmds(PsqlSettings *pset,
|
||||
const char *line,
|
||||
PQExpBuffer query_buf,
|
||||
const char ** end_of_cmd);
|
||||
const char **end_of_cmd);
|
||||
|
||||
bool
|
||||
do_connect(const char *new_dbname,
|
||||
bool do_connect(const char *new_dbname,
|
||||
const char *new_user,
|
||||
PsqlSettings *pset);
|
||||
|
||||
bool
|
||||
process_file(const char *filename,
|
||||
bool process_file(const char *filename,
|
||||
PsqlSettings *pset);
|
||||
|
||||
|
||||
bool
|
||||
do_pset(const char * param,
|
||||
const char * value,
|
||||
bool do_pset(const char *param,
|
||||
const char *value,
|
||||
printQueryOpt * popt,
|
||||
bool quiet);
|
||||
|
||||
|
@ -39,15 +39,19 @@
|
||||
* "Safe" wrapper around strdup()
|
||||
* (Using this also avoids writing #ifdef HAVE_STRDUP in every file :)
|
||||
*/
|
||||
char * xstrdup(const char * string)
|
||||
char *
|
||||
xstrdup(const char *string)
|
||||
{
|
||||
char * tmp;
|
||||
if (!string) {
|
||||
char *tmp;
|
||||
|
||||
if (!string)
|
||||
{
|
||||
fprintf(stderr, "xstrdup: Cannot duplicate null pointer.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
tmp = strdup(string);
|
||||
if (!tmp) {
|
||||
if (!tmp)
|
||||
{
|
||||
perror("strdup");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -72,7 +76,8 @@ setQFout(const char *fname, PsqlSettings *pset)
|
||||
#ifdef USE_ASSERT_CHECKING
|
||||
assert(pset);
|
||||
#else
|
||||
if (!pset) return false;
|
||||
if (!pset)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
/* Close old file/pipe */
|
||||
@ -85,14 +90,14 @@ setQFout(const char *fname, PsqlSettings *pset)
|
||||
}
|
||||
|
||||
/* If no filename, set stdout */
|
||||
if (!fname || fname[0]=='\0')
|
||||
if (!fname || fname[0] == '\0')
|
||||
{
|
||||
pset->queryFout = stdout;
|
||||
pset->queryFoutPipe = false;
|
||||
}
|
||||
else if (*fname == '|')
|
||||
{
|
||||
const char * pipename = fname+1;
|
||||
const char *pipename = fname + 1;
|
||||
|
||||
|
||||
#ifndef __CYGWIN32__
|
||||
@ -147,16 +152,19 @@ char *
|
||||
simple_prompt(const char *prompt, int maxlen, bool echo)
|
||||
{
|
||||
int length;
|
||||
char * destination;
|
||||
char *destination;
|
||||
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
struct termios t_orig, t;
|
||||
struct termios t_orig,
|
||||
t;
|
||||
|
||||
#endif
|
||||
|
||||
destination = (char *) malloc(maxlen+2);
|
||||
destination = (char *) malloc(maxlen + 2);
|
||||
if (!destination)
|
||||
return NULL;
|
||||
if (prompt) fputs(prompt, stdout);
|
||||
if (prompt)
|
||||
fputs(prompt, stdout);
|
||||
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
if (!echo)
|
||||
@ -171,17 +179,21 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
|
||||
fgets(destination, maxlen, stdin);
|
||||
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
if (!echo) {
|
||||
if (!echo)
|
||||
{
|
||||
tcsetattr(0, TCSADRAIN, &t_orig);
|
||||
puts("");
|
||||
}
|
||||
#endif
|
||||
|
||||
length = strlen(destination);
|
||||
if (length > 0 && destination[length - 1] != '\n') {
|
||||
if (length > 0 && destination[length - 1] != '\n')
|
||||
{
|
||||
/* eat rest of the line */
|
||||
char buf[512];
|
||||
do {
|
||||
|
||||
do
|
||||
{
|
||||
fgets(buf, 512, stdin);
|
||||
} while (buf[strlen(buf) - 1] != '\n');
|
||||
}
|
||||
@ -205,18 +217,20 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
|
||||
* immediate consumption.
|
||||
*/
|
||||
const char *
|
||||
interpolate_var(const char * name, PsqlSettings * pset)
|
||||
interpolate_var(const char *name, PsqlSettings *pset)
|
||||
{
|
||||
const char * var;
|
||||
const char *var;
|
||||
|
||||
#ifdef USE_ASSERT_CHECKING
|
||||
assert(name);
|
||||
assert(pset);
|
||||
#else
|
||||
if (!name || !pset) return NULL;
|
||||
if (!name || !pset)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
if (strspn(name, VALID_VARIABLE_CHARS) == strlen(name)) {
|
||||
if (strspn(name, VALID_VARIABLE_CHARS) == strlen(name))
|
||||
{
|
||||
var = GetVariable(pset->vars, name);
|
||||
if (var)
|
||||
return var;
|
||||
@ -225,41 +239,50 @@ interpolate_var(const char * name, PsqlSettings * pset)
|
||||
}
|
||||
|
||||
/* 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) */
|
||||
if (strcmp(name, "Version")==0)
|
||||
|
||||
/*
|
||||
* (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)
|
||||
return PG_VERSION_STR;
|
||||
|
||||
if (strcmp(name, "Database")==0) {
|
||||
if (strcmp(name, "Database") == 0)
|
||||
{
|
||||
if (PQdb(pset->db))
|
||||
return PQdb(pset->db);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
if (strcmp(name, "User")==0) {
|
||||
if (strcmp(name, "User") == 0)
|
||||
{
|
||||
if (PQuser(pset->db))
|
||||
return PQuser(pset->db);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
if (strcmp(name, "Host")==0) {
|
||||
if (strcmp(name, "Host") == 0)
|
||||
{
|
||||
if (PQhost(pset->db))
|
||||
return PQhost(pset->db);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
if (strcmp(name, "Port")==0) {
|
||||
if (strcmp(name, "Port") == 0)
|
||||
{
|
||||
if (PQport(pset->db))
|
||||
return PQport(pset->db);
|
||||
else
|
||||
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)))
|
||||
return var;
|
||||
@ -284,7 +307,7 @@ interpolate_var(const char * name, PsqlSettings * pset)
|
||||
* at least avoid trusting printf by using the more primitive fputs().
|
||||
*/
|
||||
|
||||
PGconn * cancelConn;
|
||||
PGconn *cancelConn;
|
||||
|
||||
#ifdef WIN32
|
||||
#define safe_write_stderr(String) fputs(s, stderr)
|
||||
@ -302,7 +325,8 @@ handle_sigint(SIGNAL_ARGS)
|
||||
/* Try to send cancel request */
|
||||
if (PQrequestCancel(cancelConn))
|
||||
safe_write_stderr("\nCANCEL request sent\n");
|
||||
else {
|
||||
else
|
||||
{
|
||||
safe_write_stderr("\nCould not send cancel request: ");
|
||||
safe_write_stderr(PQerrorMessage(cancelConn));
|
||||
}
|
||||
@ -320,20 +344,22 @@ PGresult *
|
||||
PSQLexec(PsqlSettings *pset, const char *query)
|
||||
{
|
||||
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);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
var = GetVariable(pset->vars, "echo_secret");
|
||||
if (var) {
|
||||
if (var)
|
||||
{
|
||||
printf("********* QUERY *********\n%s\n*************************\n\n", query);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
if (var && strcmp(var, "noexec")==0)
|
||||
if (var && strcmp(var, "noexec") == 0)
|
||||
return NULL;
|
||||
|
||||
cancelConn = pset->db;
|
||||
@ -347,7 +373,8 @@ PSQLexec(PsqlSettings *pset, const char *query)
|
||||
{
|
||||
fputs("The connection to the server was lost. Attempting reset: ", stderr);
|
||||
PQreset(pset->db);
|
||||
if (PQstatus(pset->db) == CONNECTION_BAD) {
|
||||
if (PQstatus(pset->db) == CONNECTION_BAD)
|
||||
{
|
||||
fputs("Failed.\n", stderr);
|
||||
PQfinish(pset->db);
|
||||
PQclear(res);
|
||||
@ -364,7 +391,8 @@ PSQLexec(PsqlSettings *pset, const char *query)
|
||||
PQresultStatus(res) == PGRES_COPY_OUT)
|
||||
)
|
||||
return res;
|
||||
else {
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s", PQerrorMessage(pset->db));
|
||||
PQclear(res);
|
||||
return NULL;
|
||||
@ -392,20 +420,23 @@ SendQuery(PsqlSettings *pset, const char *query)
|
||||
PGresult *results;
|
||||
PGnotify *notify;
|
||||
|
||||
if (!pset->db) {
|
||||
if (!pset->db)
|
||||
{
|
||||
fputs("You are not currently connected to a database.\n", stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetVariableBool(pset->vars, "singlestep")) {
|
||||
if (GetVariableBool(pset->vars, "singlestep"))
|
||||
{
|
||||
char buf[3];
|
||||
|
||||
fprintf(stdout, "***(Single step mode: Verify query)*********************************************\n"
|
||||
"QUERY: %s\n"
|
||||
"***(press return to proceed or enter x and return to cancel)********************\n",
|
||||
query);
|
||||
fflush(stdout);
|
||||
fgets(buf, 3, stdin);
|
||||
if (buf[0]=='x')
|
||||
if (buf[0] == 'x')
|
||||
return false;
|
||||
fflush(stdin);
|
||||
}
|
||||
@ -432,7 +463,8 @@ SendQuery(PsqlSettings *pset, const char *query)
|
||||
PsqlSettings settings_copy = *pset;
|
||||
|
||||
settings_copy.queryFout = stdout;
|
||||
if (!setQFout(pset->gfname, &settings_copy)) {
|
||||
if (!setQFout(pset->gfname, &settings_copy))
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
@ -491,7 +523,8 @@ SendQuery(PsqlSettings *pset, const char *query)
|
||||
{
|
||||
fputs("The connection to the server was lost. Attempting reset: ", stderr);
|
||||
PQreset(pset->db);
|
||||
if (PQstatus(pset->db) == CONNECTION_BAD) {
|
||||
if (PQstatus(pset->db) == CONNECTION_BAD)
|
||||
{
|
||||
fputs("Failed.\n", stderr);
|
||||
PQfinish(pset->db);
|
||||
PQclear(results);
|
||||
|
@ -5,21 +5,21 @@
|
||||
#include "settings.h"
|
||||
|
||||
char *
|
||||
xstrdup(const char * string);
|
||||
xstrdup(const char *string);
|
||||
|
||||
bool
|
||||
setQFout(const char *fname, PsqlSettings *pset);
|
||||
setQFout(const char *fname, PsqlSettings *pset);
|
||||
|
||||
char *
|
||||
simple_prompt(const char *prompt, int maxlen, bool echo);
|
||||
simple_prompt(const char *prompt, int maxlen, bool echo);
|
||||
|
||||
const char *
|
||||
interpolate_var(const char * name, PsqlSettings * pset);
|
||||
interpolate_var(const char *name, PsqlSettings *pset);
|
||||
|
||||
PGresult *
|
||||
PSQLexec(PsqlSettings *pset, const char *query);
|
||||
PSQLexec(PsqlSettings *pset, const char *query);
|
||||
|
||||
bool
|
||||
SendQuery(PsqlSettings *pset, const char *query);
|
||||
SendQuery(PsqlSettings *pset, const char *query);
|
||||
|
||||
#endif /* COMMON_H */
|
||||
|
@ -33,13 +33,14 @@
|
||||
* returns a malloc'ed structure with the options, or NULL on parsing error
|
||||
*/
|
||||
|
||||
struct copy_options {
|
||||
char * table;
|
||||
char * file;
|
||||
struct copy_options
|
||||
{
|
||||
char *table;
|
||||
char *file;
|
||||
bool from;
|
||||
bool binary;
|
||||
bool oids;
|
||||
char * delim;
|
||||
char *delim;
|
||||
};
|
||||
|
||||
|
||||
@ -58,15 +59,16 @@ free_copy_options(struct copy_options * ptr)
|
||||
static struct copy_options *
|
||||
parse_slash_copy(const char *args)
|
||||
{
|
||||
struct copy_options * result;
|
||||
char * line;
|
||||
char * token;
|
||||
struct copy_options *result;
|
||||
char *line;
|
||||
char *token;
|
||||
bool error = false;
|
||||
char quote;
|
||||
|
||||
line = xstrdup(args);
|
||||
|
||||
if (!(result = calloc(1, sizeof (struct copy_options)))) {
|
||||
if (!(result = calloc(1, sizeof(struct copy_options))))
|
||||
{
|
||||
perror("calloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -74,8 +76,10 @@ parse_slash_copy(const char *args)
|
||||
token = strtokx(line, " \t", "\"", '\\', "e, NULL);
|
||||
if (!token)
|
||||
error = true;
|
||||
else {
|
||||
if (!quote && strcasecmp(token, "binary")==0) {
|
||||
else
|
||||
{
|
||||
if (!quote && strcasecmp(token, "binary") == 0)
|
||||
{
|
||||
result->binary = true;
|
||||
token = strtokx(NULL, " \t", "\"", '\\', "e, NULL);
|
||||
if (!token)
|
||||
@ -89,56 +93,65 @@ parse_slash_copy(const char *args)
|
||||
assert(error || result->table);
|
||||
#endif
|
||||
|
||||
if (!error) {
|
||||
if (!error)
|
||||
{
|
||||
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
||||
if (!token)
|
||||
error = true;
|
||||
else {
|
||||
if (strcasecmp(token, "with")==0) {
|
||||
else
|
||||
{
|
||||
if (strcasecmp(token, "with") == 0)
|
||||
{
|
||||
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
||||
if (!token || strcasecmp(token, "oids")!=0)
|
||||
if (!token || strcasecmp(token, "oids") != 0)
|
||||
error = true;
|
||||
else
|
||||
result->oids = true;
|
||||
|
||||
if (!error) {
|
||||
if (!error)
|
||||
{
|
||||
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
||||
if (!token)
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!error && strcasecmp(token, "from")==0)
|
||||
if (!error && strcasecmp(token, "from") == 0)
|
||||
result->from = true;
|
||||
else if (!error && strcasecmp(token, "to")==0)
|
||||
else if (!error && strcasecmp(token, "to") == 0)
|
||||
result->from = false;
|
||||
else
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
if (!error)
|
||||
{
|
||||
token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
|
||||
if (!token)
|
||||
error = true;
|
||||
else
|
||||
result->file=xstrdup(token);
|
||||
result->file = xstrdup(token);
|
||||
}
|
||||
|
||||
#ifdef USE_ASSERT_CHECKING
|
||||
assert(error || result->file);
|
||||
#endif
|
||||
|
||||
if (!error) {
|
||||
if (!error)
|
||||
{
|
||||
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
||||
if (token) {
|
||||
if (strcasecmp(token, "using")!=0)
|
||||
if (token)
|
||||
{
|
||||
if (strcasecmp(token, "using") != 0)
|
||||
error = true;
|
||||
else {
|
||||
else
|
||||
{
|
||||
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
|
||||
if (!token || strcasecmp(token, "delimiters")!=0)
|
||||
if (!token || strcasecmp(token, "delimiters") != 0)
|
||||
error = true;
|
||||
else {
|
||||
else
|
||||
{
|
||||
token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
|
||||
if (token)
|
||||
result->delim = xstrdup(token);
|
||||
@ -151,7 +164,8 @@ parse_slash_copy(const char *args)
|
||||
|
||||
free(line);
|
||||
|
||||
if (error) {
|
||||
if (error)
|
||||
{
|
||||
fputs("Parse error at ", stderr);
|
||||
if (!token)
|
||||
fputs("end of line.", stderr);
|
||||
@ -173,7 +187,7 @@ parse_slash_copy(const char *args)
|
||||
* file or route its response into the file.
|
||||
*/
|
||||
bool
|
||||
do_copy(const char * args, PsqlSettings *pset)
|
||||
do_copy(const char *args, PsqlSettings *pset)
|
||||
{
|
||||
char query[128 + NAMEDATALEN];
|
||||
FILE *copystream;
|
||||
@ -204,10 +218,14 @@ do_copy(const char * args, PsqlSettings *pset)
|
||||
strcat(query, "TO stdout");
|
||||
|
||||
|
||||
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) */
|
||||
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)
|
||||
*/
|
||||
strncat(query, " USING DELIMITERS '", 2);
|
||||
strcat(query, options->delim);
|
||||
strcat(query, "'");
|
||||
@ -227,7 +245,8 @@ do_copy(const char * args, PsqlSettings *pset)
|
||||
copystream = fopen(options->file, "wb");
|
||||
#endif
|
||||
|
||||
if (!copystream) {
|
||||
if (!copystream)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Unable to open file %s which to copy: %s\n",
|
||||
options->from ? "from" : "to", strerror(errno));
|
||||
@ -258,7 +277,8 @@ do_copy(const char * args, PsqlSettings *pset)
|
||||
|
||||
PQclear(result);
|
||||
|
||||
if (!GetVariable(pset->vars, "quiet")) {
|
||||
if (!GetVariable(pset->vars, "quiet"))
|
||||
{
|
||||
if (success)
|
||||
puts("Successfully copied.");
|
||||
else
|
||||
@ -337,7 +357,7 @@ handleCopyOut(PGconn *conn, FILE *copystream)
|
||||
*/
|
||||
|
||||
bool
|
||||
handleCopyIn(PGconn *conn, FILE *copystream, const char * prompt)
|
||||
handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
|
||||
{
|
||||
bool copydone = false;
|
||||
bool firstload;
|
||||
|
@ -8,15 +8,15 @@
|
||||
|
||||
/* handler for \copy */
|
||||
bool
|
||||
do_copy(const char *args, PsqlSettings *pset);
|
||||
do_copy(const char *args, PsqlSettings *pset);
|
||||
|
||||
|
||||
/* lower level processors for copy in/out streams */
|
||||
|
||||
bool
|
||||
handleCopyOut(PGconn *conn, FILE *copystream);
|
||||
handleCopyOut(PGconn *conn, FILE *copystream);
|
||||
|
||||
bool
|
||||
handleCopyIn(PGconn *conn, FILE *copystream, const char * prompt);
|
||||
handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt);
|
||||
|
||||
#endif
|
||||
|
@ -34,17 +34,21 @@
|
||||
* takes an optional regexp to match specific aggregates by name
|
||||
*/
|
||||
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 */
|
||||
PGresult * res;
|
||||
char descbuf[384 + 2 * REGEXP_CUTOFF]; /* observe/adjust this
|
||||
* if you change the
|
||||
* query */
|
||||
PGresult *res;
|
||||
bool description = GetVariableBool(pset->vars, "description");
|
||||
printQueryOpt myopt = pset->popt;
|
||||
|
||||
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,
|
||||
"SELECT a.aggname AS \"Name\", t.typname AS \"Type\"");
|
||||
if (description)
|
||||
@ -53,7 +57,8 @@ describeAggregates(const char * name, PsqlSettings * pset)
|
||||
strcat(descbuf,
|
||||
"\nFROM pg_aggregate a, pg_type t\n"
|
||||
"WHERE a.aggbasetype = t.oid\n");
|
||||
if (name) {
|
||||
if (name)
|
||||
{
|
||||
strcat(descbuf, " AND a.aggname ~* '^");
|
||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||
strcat(descbuf, "'\n");
|
||||
@ -96,16 +101,15 @@ describeAggregates(const char * name, PsqlSettings * pset)
|
||||
* takes an optional regexp to narrow down the function name
|
||||
*/
|
||||
bool
|
||||
describeFunctions(const char * name, PsqlSettings * pset)
|
||||
describeFunctions(const char *name, PsqlSettings *pset)
|
||||
{
|
||||
char descbuf[384 + REGEXP_CUTOFF];
|
||||
PGresult * res;
|
||||
PGresult *res;
|
||||
printQueryOpt myopt = pset->popt;
|
||||
|
||||
/*
|
||||
* we skip in/out funcs by excluding functions that take
|
||||
* some arguments, but have no types defined for those
|
||||
* arguments
|
||||
* we skip in/out funcs by excluding functions that take some
|
||||
* arguments, but have no types defined for those arguments
|
||||
*/
|
||||
descbuf[0] = '\0';
|
||||
|
||||
@ -145,10 +149,10 @@ describeFunctions(const char * name, PsqlSettings * pset)
|
||||
* for \dT
|
||||
*/
|
||||
bool
|
||||
describeTypes(const char * name, PsqlSettings * pset)
|
||||
describeTypes(const char *name, PsqlSettings *pset)
|
||||
{
|
||||
char descbuf[256 + REGEXP_CUTOFF];
|
||||
PGresult * res;
|
||||
PGresult *res;
|
||||
printQueryOpt myopt = pset->popt;
|
||||
|
||||
descbuf[0] = '\0';
|
||||
@ -158,7 +162,8 @@ describeTypes(const char * name, PsqlSettings * pset)
|
||||
strcat(descbuf, "\nFROM pg_type\n"
|
||||
"WHERE typrelid = 0 AND typname !~ '^_.*'\n");
|
||||
|
||||
if (name) {
|
||||
if (name)
|
||||
{
|
||||
strcat(descbuf, " AND typname ~* '^");
|
||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||
strcat(descbuf, "' ");
|
||||
@ -187,10 +192,11 @@ describeTypes(const char * name, PsqlSettings * pset)
|
||||
* exact match string.
|
||||
*/
|
||||
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 */
|
||||
PGresult * res;
|
||||
char descbuf[1536 + 3 * 32]; /* 32 is max length for operator
|
||||
* name */
|
||||
PGresult *res;
|
||||
bool description = GetVariableBool(pset->vars, "description");
|
||||
printQueryOpt myopt = pset->popt;
|
||||
|
||||
@ -316,7 +322,7 @@ listAllDbs(PsqlSettings *pset)
|
||||
*
|
||||
*/
|
||||
bool
|
||||
permissionsList(const char * name, PsqlSettings *pset)
|
||||
permissionsList(const char *name, PsqlSettings *pset)
|
||||
{
|
||||
char descbuf[256 + REGEXP_CUTOFF];
|
||||
PGresult *res;
|
||||
@ -329,21 +335,22 @@ permissionsList(const char * name, PsqlSettings *pset)
|
||||
"FROM pg_class\n"
|
||||
"WHERE ( relkind = 'r' OR relkind = 'S') AND\n"
|
||||
" relname !~ '^pg_'\n");
|
||||
if (name) {
|
||||
if (name)
|
||||
{
|
||||
strcat(descbuf, " AND rename ~ '^");
|
||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||
strcat(descbuf, "'\n");
|
||||
}
|
||||
strcat (descbuf, "ORDER BY relname");
|
||||
strcat(descbuf, "ORDER BY relname");
|
||||
|
||||
res = PSQLexec(pset, descbuf);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
if (PQntuples(res) == 0) {
|
||||
if (PQntuples(res) == 0)
|
||||
fputs("Couldn't find any tables.\n", pset->queryFout);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
myopt.topt.tuples_only = false;
|
||||
myopt.nullPrint = NULL;
|
||||
sprintf(descbuf, "Access permissions for database \"%s\"", PQdb(pset->db));
|
||||
@ -368,9 +375,9 @@ permissionsList(const char * name, PsqlSettings *pset)
|
||||
* lists of things, there are other \d? commands.
|
||||
*/
|
||||
bool
|
||||
objectDescription(const char * object, PsqlSettings *pset)
|
||||
objectDescription(const char *object, PsqlSettings *pset)
|
||||
{
|
||||
char descbuf[2048 + 7*REGEXP_CUTOFF];
|
||||
char descbuf[2048 + 7 * REGEXP_CUTOFF];
|
||||
PGresult *res;
|
||||
printQueryOpt myopt = pset->popt;
|
||||
|
||||
@ -380,10 +387,11 @@ objectDescription(const char * object, PsqlSettings *pset)
|
||||
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"
|
||||
"WHERE a.oid = d.objoid\n");
|
||||
if (object) {
|
||||
strcat(descbuf," AND a.aggname ~* '^");
|
||||
if (object)
|
||||
{
|
||||
strcat(descbuf, " AND a.aggname ~* '^");
|
||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||
strcat(descbuf,"'\n");
|
||||
strcat(descbuf, "'\n");
|
||||
}
|
||||
|
||||
/* Function descriptions (except in/outs for datatypes) */
|
||||
@ -391,10 +399,11 @@ objectDescription(const char * object, PsqlSettings *pset)
|
||||
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"
|
||||
"WHERE p.oid = d.objoid AND (p.pronargs = 0 or oid8types(p.proargtypes) != '')\n");
|
||||
if (object) {
|
||||
strcat(descbuf," AND p.proname ~* '^");
|
||||
if (object)
|
||||
{
|
||||
strcat(descbuf, " AND p.proname ~* '^");
|
||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||
strcat(descbuf,"'\n");
|
||||
strcat(descbuf, "'\n");
|
||||
}
|
||||
|
||||
/* Operator descriptions */
|
||||
@ -403,10 +412,11 @@ objectDescription(const char * object, PsqlSettings *pset)
|
||||
"FROM pg_operator o, pg_description d\n"
|
||||
// must get comment via associated function
|
||||
"WHERE RegprocToOid(o.oprcode) = d.objoid\n");
|
||||
if (object) {
|
||||
strcat(descbuf," AND o.oprname = '");
|
||||
if (object)
|
||||
{
|
||||
strcat(descbuf, " AND o.oprname = '");
|
||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||
strcat(descbuf,"'\n");
|
||||
strcat(descbuf, "'\n");
|
||||
}
|
||||
|
||||
/* Type description */
|
||||
@ -414,10 +424,11 @@ objectDescription(const char * object, PsqlSettings *pset)
|
||||
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"
|
||||
"WHERE t.oid = d.objoid\n");
|
||||
if (object) {
|
||||
strcat(descbuf," AND t.typname ~* '^");
|
||||
if (object)
|
||||
{
|
||||
strcat(descbuf, " AND t.typname ~* '^");
|
||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||
strcat(descbuf,"'\n");
|
||||
strcat(descbuf, "'\n");
|
||||
}
|
||||
|
||||
/* Relation (tables, views, indices, sequences) descriptions */
|
||||
@ -425,10 +436,11 @@ 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"
|
||||
"FROM pg_class c, pg_description d\n"
|
||||
"WHERE c.oid = d.objoid\n");
|
||||
if (object) {
|
||||
strcat(descbuf," AND c.relname ~* '^");
|
||||
if (object)
|
||||
{
|
||||
strcat(descbuf, " AND c.relname ~* '^");
|
||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||
strcat(descbuf,"'\n");
|
||||
strcat(descbuf, "'\n");
|
||||
}
|
||||
|
||||
/* Rule description (ignore rules for views) */
|
||||
@ -436,10 +448,11 @@ objectDescription(const char * object, PsqlSettings *pset)
|
||||
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"
|
||||
"WHERE r.oid = d.objoid AND r.rulename !~ '^_RET'\n");
|
||||
if (object) {
|
||||
strcat(descbuf," AND r.rulename ~* '^");
|
||||
if (object)
|
||||
{
|
||||
strcat(descbuf, " AND r.rulename ~* '^");
|
||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||
strcat(descbuf,"'\n");
|
||||
strcat(descbuf, "'\n");
|
||||
}
|
||||
|
||||
/* Trigger description */
|
||||
@ -447,10 +460,11 @@ objectDescription(const char * object, PsqlSettings *pset)
|
||||
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"
|
||||
"WHERE t.oid = d.objoid\n");
|
||||
if (object) {
|
||||
strcat(descbuf," AND t.tgname ~* '^");
|
||||
if (object)
|
||||
{
|
||||
strcat(descbuf, " AND t.tgname ~* '^");
|
||||
strncat(descbuf, object, REGEXP_CUTOFF);
|
||||
strcat(descbuf,"'\n");
|
||||
strcat(descbuf, "'\n");
|
||||
}
|
||||
|
||||
strcat(descbuf, "\nORDER BY \"Name\"");
|
||||
@ -480,11 +494,14 @@ objectDescription(const char * object, PsqlSettings *pset)
|
||||
* 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);
|
||||
if (!tmp) {
|
||||
if (!tmp)
|
||||
{
|
||||
perror("malloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -493,19 +510,21 @@ static void * xmalloc(size_t size)
|
||||
|
||||
|
||||
bool
|
||||
describeTableDetails(const char * name, PsqlSettings * pset)
|
||||
describeTableDetails(const char *name, PsqlSettings *pset)
|
||||
{
|
||||
char descbuf[512 + NAMEDATALEN];
|
||||
PGresult *res = NULL, *res2 = NULL, *res3 = NULL;
|
||||
PGresult *res = NULL,
|
||||
*res2 = NULL,
|
||||
*res3 = NULL;
|
||||
printTableOpt myopt = pset->popt.topt;
|
||||
bool description = GetVariableBool(pset->vars, "description");
|
||||
int i;
|
||||
char * view_def = NULL;
|
||||
char * headers[5];
|
||||
char ** cells = NULL;
|
||||
char * title = NULL;
|
||||
char ** footers = NULL;
|
||||
char ** ptr;
|
||||
char *view_def = NULL;
|
||||
char *headers[5];
|
||||
char **cells = NULL;
|
||||
char *title = NULL;
|
||||
char **footers = NULL;
|
||||
char **ptr;
|
||||
unsigned int cols;
|
||||
|
||||
cols = 3 + (description ? 1 : 0);
|
||||
@ -513,7 +532,8 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
||||
headers[0] = "Attribute";
|
||||
headers[1] = "Type";
|
||||
headers[2] = "Info";
|
||||
if (description) {
|
||||
if (description)
|
||||
{
|
||||
headers[3] = "Description";
|
||||
headers[4] = NULL;
|
||||
}
|
||||
@ -535,7 +555,8 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
||||
return false;
|
||||
|
||||
/* Did we get anything? */
|
||||
if (PQntuples(res)==0) {
|
||||
if (PQntuples(res) == 0)
|
||||
{
|
||||
if (!GetVariableBool(pset->vars, "quiet"))
|
||||
fprintf(stdout, "Did not find any class named \"%s\".\n", name);
|
||||
PQclear(res);
|
||||
@ -551,44 +572,49 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
||||
return false;
|
||||
|
||||
if (PQntuples(res2) > 0)
|
||||
view_def = PQgetvalue(res2,0,0);
|
||||
view_def = PQgetvalue(res2, 0, 0);
|
||||
|
||||
|
||||
|
||||
/* Generate table cells to be printed */
|
||||
cells = calloc(PQntuples(res) * cols + 1, sizeof(*cells));
|
||||
if (!cells) {
|
||||
if (!cells)
|
||||
{
|
||||
perror("calloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; i < PQntuples(res); i++) {
|
||||
for (i = 0; i < PQntuples(res); i++)
|
||||
{
|
||||
int4 attypmod = atoi(PQgetvalue(res, i, 3));
|
||||
char * attype = PQgetvalue(res, i, 1);
|
||||
char *attype = PQgetvalue(res, i, 1);
|
||||
|
||||
/* 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 */
|
||||
cells[i*cols + 1] = xmalloc(NAMEDATALEN + 16);
|
||||
if (strcmp(attype, "bpchar")==0)
|
||||
sprintf(cells[i*cols + 1], "char(%d)", attypmod != -1 ? attypmod - VARHDRSZ : 0);
|
||||
else if (strcmp(attype, "varchar")==0)
|
||||
sprintf(cells[i*cols + 1], "varchar(%d)", attypmod != -1 ? attypmod - VARHDRSZ : 0);
|
||||
else if (strcmp(attype, "numeric")==0)
|
||||
sprintf(cells[i*cols + 1], "numeric(%d,%d)", ((attypmod - VARHDRSZ) >> 16) & 0xffff,
|
||||
(attypmod - VARHDRSZ) & 0xffff );
|
||||
cells[i * cols + 1] = xmalloc(NAMEDATALEN + 16);
|
||||
if (strcmp(attype, "bpchar") == 0)
|
||||
sprintf(cells[i * cols + 1], "char(%d)", attypmod != -1 ? attypmod - VARHDRSZ : 0);
|
||||
else if (strcmp(attype, "varchar") == 0)
|
||||
sprintf(cells[i * cols + 1], "varchar(%d)", attypmod != -1 ? attypmod - VARHDRSZ : 0);
|
||||
else if (strcmp(attype, "numeric") == 0)
|
||||
sprintf(cells[i * cols + 1], "numeric(%d,%d)", ((attypmod - VARHDRSZ) >> 16) & 0xffff,
|
||||
(attypmod - VARHDRSZ) & 0xffff);
|
||||
else if (attype[0] == '_')
|
||||
sprintf(cells[i*cols + 1], "%s[]", attype+1);
|
||||
sprintf(cells[i * cols + 1], "%s[]", attype + 1);
|
||||
else
|
||||
strcpy(cells[i*cols + 1], attype);
|
||||
strcpy(cells[i * cols + 1], attype);
|
||||
|
||||
/* Info */
|
||||
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] = xmalloc(128 + 128); /* I'm cutting off the
|
||||
* default string at 128 */
|
||||
cells[i * cols + 2][0] = '\0';
|
||||
if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
|
||||
strcat(cells[i*cols + 2], "not null");
|
||||
if (strcmp(PQgetvalue(res, i, 5), "t") == 0) {
|
||||
strcat(cells[i * cols + 2], "not null");
|
||||
if (strcmp(PQgetvalue(res, i, 5), "t") == 0)
|
||||
{
|
||||
/* handle "default" here */
|
||||
strcpy(descbuf, "SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c\n"
|
||||
"WHERE c.relname = '");
|
||||
@ -597,15 +623,17 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
||||
strcat(descbuf, PQgetvalue(res, i, 6));
|
||||
|
||||
res3 = PSQLexec(pset, descbuf);
|
||||
if (!res) return false;
|
||||
if (cells[i*cols+2][0]) strcat(cells[i*cols+2], " ");
|
||||
strcat(cells[i*cols + 2], "default ");
|
||||
strcat(cells[i*cols + 2], PQgetvalue(res3, 0, 0));
|
||||
if (!res)
|
||||
return false;
|
||||
if (cells[i * cols + 2][0])
|
||||
strcat(cells[i * cols + 2], " ");
|
||||
strcat(cells[i * cols + 2], "default ");
|
||||
strcat(cells[i * cols + 2], PQgetvalue(res3, 0, 0));
|
||||
}
|
||||
|
||||
/* Description */
|
||||
if (description)
|
||||
cells[i*cols + 3] = PQgetvalue(res, i, 7);
|
||||
cells[i * cols + 3] = PQgetvalue(res, i, 7);
|
||||
}
|
||||
|
||||
/* Make title */
|
||||
@ -616,13 +644,15 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
||||
sprintf(title, "Table \"%s\"", name);
|
||||
|
||||
/* Make footers */
|
||||
if (view_def) {
|
||||
if (view_def)
|
||||
{
|
||||
footers = xmalloc(2 * sizeof(*footers));
|
||||
footers[0] = xmalloc(20 + strlen(view_def));
|
||||
sprintf(footers[0], "View definition: %s", view_def);
|
||||
footers[1] = NULL;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
/* display indices */
|
||||
strcpy(descbuf, "SELECT c2.relname\n"
|
||||
"FROM pg_class c, pg_class c2, pg_index i\n"
|
||||
@ -634,14 +664,16 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
||||
if (!res3)
|
||||
return false;
|
||||
|
||||
if (PQntuples(res3) > 0) {
|
||||
if (PQntuples(res3) > 0)
|
||||
{
|
||||
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);
|
||||
if (PQntuples(res3)==1)
|
||||
if (PQntuples(res3) == 1)
|
||||
sprintf(footers[i], "Index: %s", PQgetvalue(res3, i, 0));
|
||||
else if (i==0)
|
||||
else if (i == 0)
|
||||
sprintf(footers[i], "Indices: %s", PQgetvalue(res3, i, 0));
|
||||
else
|
||||
sprintf(footers[i], " %s", PQgetvalue(res3, i, 0));
|
||||
@ -658,9 +690,10 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
||||
/* clean up */
|
||||
free(title);
|
||||
|
||||
for (i = 0; i<PQntuples(res); i++) {
|
||||
free(cells[i*cols + 1]);
|
||||
free(cells[i*cols + 2]);
|
||||
for (i = 0; i < PQntuples(res); i++)
|
||||
{
|
||||
free(cells[i * cols + 1]);
|
||||
free(cells[i * cols + 2]);
|
||||
}
|
||||
free(cells);
|
||||
|
||||
@ -691,10 +724,10 @@ describeTableDetails(const char * name, PsqlSettings * pset)
|
||||
* (any order of the above is fine)
|
||||
*/
|
||||
bool
|
||||
listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
||||
listTables(const char *infotype, const char *name, PsqlSettings *pset)
|
||||
{
|
||||
bool showTables = strchr(infotype, 't') != NULL;
|
||||
bool showIndices= strchr(infotype, 'i') != NULL;
|
||||
bool showIndices = strchr(infotype, 'i') != NULL;
|
||||
bool showViews = strchr(infotype, 'v') != NULL;
|
||||
bool showSeq = strchr(infotype, 's') != NULL;
|
||||
bool showSystem = strchr(infotype, 'S') != NULL;
|
||||
@ -708,7 +741,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
||||
descbuf[0] = '\0';
|
||||
|
||||
/* tables */
|
||||
if (showTables) {
|
||||
if (showTables)
|
||||
{
|
||||
strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'table'::text as \"Type\"");
|
||||
if (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"
|
||||
" 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");
|
||||
if (name) {
|
||||
if (name)
|
||||
{
|
||||
strcat(descbuf, " AND c.relname ~ '^");
|
||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||
strcat(descbuf, "'\n");
|
||||
@ -724,7 +759,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
||||
}
|
||||
|
||||
/* views */
|
||||
if (showViews) {
|
||||
if (showViews)
|
||||
{
|
||||
if (descbuf[0])
|
||||
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"
|
||||
" 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");
|
||||
if (name) {
|
||||
if (name)
|
||||
{
|
||||
strcat(descbuf, " AND c.relname ~ '^");
|
||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||
strcat(descbuf, "'\n");
|
||||
@ -743,7 +780,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
||||
}
|
||||
|
||||
/* indices, sequences */
|
||||
if (showIndices || showSeq) {
|
||||
if (showIndices || showSeq)
|
||||
{
|
||||
if (descbuf[0])
|
||||
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, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
|
||||
if (name) {
|
||||
if (name)
|
||||
{
|
||||
strcat(descbuf, " AND c.relname ~ '^");
|
||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||
strcat(descbuf, "'\n");
|
||||
@ -774,7 +813,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
||||
}
|
||||
|
||||
/* real system catalogue tables */
|
||||
if (showSystem && showTables) {
|
||||
if (showSystem && showTables)
|
||||
{
|
||||
if (descbuf[0])
|
||||
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, "\nFROM pg_class c, pg_user u\n"
|
||||
"WHERE c.relowner = u.usesysid AND c.relkind = 's'\n");
|
||||
if (name) {
|
||||
if (name)
|
||||
{
|
||||
strcat(descbuf, " AND c.relname ~ '^");
|
||||
strncat(descbuf, name, REGEXP_CUTOFF);
|
||||
strcat(descbuf, "'\n");
|
||||
@ -800,7 +841,8 @@ listTables(const char * infotype, const char * name, PsqlSettings * pset)
|
||||
if (PQntuples(res) == 0)
|
||||
fprintf(pset->queryFout, "No matching classes found.\n");
|
||||
|
||||
else {
|
||||
else
|
||||
{
|
||||
myopt.topt.tuples_only = false;
|
||||
myopt.nullPrint = NULL;
|
||||
myopt.title = "List of classes";
|
||||
|
@ -5,38 +5,38 @@
|
||||
|
||||
/* \da */
|
||||
bool
|
||||
describeAggregates(const char * name, PsqlSettings * pset);
|
||||
describeAggregates(const char *name, PsqlSettings *pset);
|
||||
|
||||
/* \df */
|
||||
bool
|
||||
describeFunctions(const char * name, PsqlSettings * pset);
|
||||
describeFunctions(const char *name, PsqlSettings *pset);
|
||||
|
||||
/* \dT */
|
||||
bool
|
||||
describeTypes(const char * name, PsqlSettings * pset);
|
||||
describeTypes(const char *name, PsqlSettings *pset);
|
||||
|
||||
/* \do */
|
||||
bool
|
||||
describeOperators(const char * name, PsqlSettings * pset);
|
||||
describeOperators(const char *name, PsqlSettings *pset);
|
||||
|
||||
/* \dp (formerly \z) */
|
||||
bool
|
||||
permissionsList(const char * name, PsqlSettings *pset);
|
||||
permissionsList(const char *name, PsqlSettings *pset);
|
||||
|
||||
/* \dd */
|
||||
bool
|
||||
objectDescription(const char * object, PsqlSettings *pset);
|
||||
objectDescription(const char *object, PsqlSettings *pset);
|
||||
|
||||
/* \d foo */
|
||||
bool
|
||||
describeTableDetails(const char * name, PsqlSettings * pset);
|
||||
describeTableDetails(const char *name, PsqlSettings *pset);
|
||||
|
||||
/* \l */
|
||||
bool
|
||||
listAllDbs(PsqlSettings *pset);
|
||||
listAllDbs(PsqlSettings *pset);
|
||||
|
||||
/* \dt, \di, \dS, etc. */
|
||||
bool
|
||||
listTables(const char * infotype, const char * name, PsqlSettings * pset);
|
||||
listTables(const char *infotype, const char *name, PsqlSettings *pset);
|
||||
|
||||
#endif /* DESCRIBE_H */
|
||||
|
@ -34,21 +34,27 @@
|
||||
*/
|
||||
#define ON(var) (var ? "on" : "off")
|
||||
|
||||
void usage(void)
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
const char *env;
|
||||
const char *user;
|
||||
|
||||
#ifndef WIN32
|
||||
struct passwd *pw = NULL;
|
||||
|
||||
#endif
|
||||
|
||||
/* Find default user, in case we need it. */
|
||||
user = getenv("USER");
|
||||
if (!user) {
|
||||
if (!user)
|
||||
{
|
||||
#ifndef WIN32
|
||||
pw = getpwuid(getuid());
|
||||
if (pw) user = pw->pw_name;
|
||||
else {
|
||||
if (pw)
|
||||
user = pw->pw_name;
|
||||
else
|
||||
{
|
||||
perror("getpwuid()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -64,7 +70,8 @@ void usage(void)
|
||||
|
||||
/* Display default database */
|
||||
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, " -e Echo all input in non-interactive mode\n");
|
||||
@ -101,7 +108,8 @@ void usage(void)
|
||||
|
||||
/* Display default user */
|
||||
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, " -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");
|
||||
|
||||
#ifndef WIN32
|
||||
if (pw) free(pw);
|
||||
if (pw)
|
||||
free(pw);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -125,10 +134,12 @@ void usage(void)
|
||||
*/
|
||||
|
||||
#ifndef TIOCGWINSZ
|
||||
struct winsize {
|
||||
struct winsize
|
||||
{
|
||||
int ws_row;
|
||||
int ws_col;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
@ -197,7 +208,8 @@ slashUsage(PsqlSettings *pset)
|
||||
fprintf(fout, " \\z -- list table access permissions\n");
|
||||
fprintf(fout, " \\! [<cmd>] -- shell escape or command\n");
|
||||
|
||||
if (usePipe) {
|
||||
if (usePipe)
|
||||
{
|
||||
pclose(fout);
|
||||
pqsignal(SIGPIPE, SIG_DFL);
|
||||
}
|
||||
@ -212,7 +224,7 @@ slashUsage(PsqlSettings *pset)
|
||||
void
|
||||
helpSQL(const char *topic)
|
||||
{
|
||||
if (!topic || strlen(topic)==0)
|
||||
if (!topic || strlen(topic) == 0)
|
||||
{
|
||||
char left_center_right; /* Which column we're displaying */
|
||||
int i; /* Index into QL_HELP[] */
|
||||
@ -274,33 +286,33 @@ void
|
||||
print_copyright(void)
|
||||
{
|
||||
puts(
|
||||
"
|
||||
PostgreSQL Data Base Management System
|
||||
"
|
||||
PostgreSQL Data Base Management System
|
||||
|
||||
Copyright (c) 1996-9 PostgreSQL Global Development Group
|
||||
Copyright(c) 1996 - 9 PostgreSQL Global Development Group
|
||||
|
||||
This software is based on Postgres95, formerly known as Postgres, which
|
||||
contains the following notice:
|
||||
This software is based on Postgres95, formerly known as Postgres, which
|
||||
contains the following notice:
|
||||
|
||||
Copyright (c) 1994-7 Regents of the University of California
|
||||
Copyright(c) 1994 - 7 Regents of the University of California
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose, without fee, and without a written agreement
|
||||
is hereby granted, provided that the above copyright notice and this paragraph
|
||||
and the following two paragraphs appear in all copies.
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose, without fee, and without a written agreement
|
||||
is hereby granted, provided that the above copyright notice and this paragraph
|
||||
and the following two paragraphs appear in all copies.
|
||||
|
||||
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
|
||||
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
|
||||
PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
|
||||
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
|
||||
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
|
||||
PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
|
||||
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
|
||||
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN \"AS IS\" BASIS,
|
||||
AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
|
||||
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE.THE SOFTWARE PROVIDED HEREUNDER IS ON AN \ "AS IS\" BASIS,
|
||||
AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
|
||||
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
(end of terms)"
|
||||
(end of terms) "
|
||||
);
|
||||
}
|
||||
|
@ -13,4 +13,3 @@ void print_copyright(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -10,9 +10,11 @@
|
||||
/* (of course there is no runtime command for doing that :) */
|
||||
#ifdef USE_READLINE
|
||||
static bool useReadline;
|
||||
|
||||
#endif
|
||||
#ifdef USE_HISTORY
|
||||
static bool useHistory;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -25,15 +27,17 @@ static bool useHistory;
|
||||
char *
|
||||
gets_interactive(const char *prompt)
|
||||
{
|
||||
char * s;
|
||||
char *s;
|
||||
|
||||
#ifdef USE_READLINE
|
||||
if (useReadline) {
|
||||
if (useReadline)
|
||||
{
|
||||
s = readline(prompt);
|
||||
fputc('\r', stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
#endif
|
||||
fputs(prompt, stdout);
|
||||
fflush(stdout);
|
||||
@ -65,10 +69,12 @@ gets_fromFile(FILE *source)
|
||||
|
||||
initPQExpBuffer(&buffer);
|
||||
|
||||
while (fgets(line, 1024, source) != NULL) {
|
||||
while (fgets(line, 1024, source) != NULL)
|
||||
{
|
||||
appendPQExpBufferStr(&buffer, line);
|
||||
if (buffer.data[buffer.len-1] == '\n') {
|
||||
buffer.data[buffer.len-1] = '\0';
|
||||
if (buffer.data[buffer.len - 1] == '\n')
|
||||
{
|
||||
buffer.data[buffer.len - 1] = '\0';
|
||||
return buffer.data;
|
||||
}
|
||||
}
|
||||
@ -93,22 +99,27 @@ void
|
||||
initializeInput(int flags)
|
||||
{
|
||||
#ifdef USE_READLINE
|
||||
if (flags == 1) {
|
||||
if (flags == 1)
|
||||
{
|
||||
useReadline = true;
|
||||
rl_readline_name = "psql";
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_HISTORY
|
||||
if (flags == 1) {
|
||||
const char * home;
|
||||
if (flags == 1)
|
||||
{
|
||||
const char *home;
|
||||
|
||||
useHistory = true;
|
||||
using_history();
|
||||
home = getenv("HOME");
|
||||
if (home) {
|
||||
char * psql_history = (char *) malloc(strlen(home) + 20);
|
||||
if (psql_history) {
|
||||
if (home)
|
||||
{
|
||||
char *psql_history = (char *) malloc(strlen(home) + 20);
|
||||
|
||||
if (psql_history)
|
||||
{
|
||||
sprintf(psql_history, "%s/.psql_history", home);
|
||||
read_history(psql_history);
|
||||
free(psql_history);
|
||||
@ -124,8 +135,10 @@ bool
|
||||
saveHistory(const char *fname)
|
||||
{
|
||||
#ifdef USE_HISTORY
|
||||
if (useHistory) {
|
||||
if (write_history(fname) != 0) {
|
||||
if (useHistory)
|
||||
{
|
||||
if (write_history(fname) != 0)
|
||||
{
|
||||
perror(fname);
|
||||
return false;
|
||||
}
|
||||
@ -144,14 +157,17 @@ void
|
||||
finishInput(void)
|
||||
{
|
||||
#ifdef USE_HISTORY
|
||||
if (useHistory) {
|
||||
char * home;
|
||||
char * psql_history;
|
||||
if (useHistory)
|
||||
{
|
||||
char *home;
|
||||
char *psql_history;
|
||||
|
||||
home = getenv("HOME");
|
||||
if (home) {
|
||||
if (home)
|
||||
{
|
||||
psql_history = (char *) malloc(strlen(home) + 20);
|
||||
if (psql_history) {
|
||||
if (psql_history)
|
||||
{
|
||||
sprintf(psql_history, "%s/.psql_history", home);
|
||||
write_history(psql_history);
|
||||
free(psql_history);
|
||||
|
@ -38,19 +38,19 @@
|
||||
|
||||
|
||||
char *
|
||||
gets_interactive(const char *prompt);
|
||||
gets_interactive(const char *prompt);
|
||||
|
||||
char *
|
||||
gets_fromFile(FILE *source);
|
||||
gets_fromFile(FILE *source);
|
||||
|
||||
|
||||
void
|
||||
initializeInput(int flags);
|
||||
initializeInput(int flags);
|
||||
|
||||
bool
|
||||
saveHistory(const char *fname);
|
||||
saveHistory(const char *fname);
|
||||
|
||||
void
|
||||
finishInput(void);
|
||||
finishInput(void);
|
||||
|
||||
#endif
|
||||
|
@ -24,25 +24,26 @@
|
||||
static char notice[80];
|
||||
|
||||
static void
|
||||
_my_notice_handler(void * arg, const char * message) {
|
||||
(void)arg;
|
||||
_my_notice_handler(void *arg, const char *message)
|
||||
{
|
||||
(void) arg;
|
||||
strncpy(notice, message, 79);
|
||||
notice[79] = '\0';
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
handle_transaction(PsqlSettings * pset)
|
||||
handle_transaction(PsqlSettings *pset)
|
||||
{
|
||||
const char * var = GetVariable(pset->vars, "lo_transaction");
|
||||
PGresult * res;
|
||||
const char *var = GetVariable(pset->vars, "lo_transaction");
|
||||
PGresult *res;
|
||||
bool commit;
|
||||
PQnoticeProcessor old_notice_hook;
|
||||
|
||||
if (var && strcmp(var, "nothing")==0)
|
||||
if (var && strcmp(var, "nothing") == 0)
|
||||
return true;
|
||||
|
||||
commit = (var && strcmp(var, "commit")==0);
|
||||
commit = (var && strcmp(var, "commit") == 0);
|
||||
|
||||
notice[0] = '\0';
|
||||
old_notice_hook = PQsetNoticeProcessor(pset->db, _my_notice_handler, NULL);
|
||||
@ -51,12 +52,14 @@ handle_transaction(PsqlSettings * pset)
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
if (notice[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) )
|
||||
if (notice[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))
|
||||
fputs(notice, stderr);
|
||||
}
|
||||
else if (!GetVariableBool(pset->vars, "quiet")) {
|
||||
else if (!GetVariableBool(pset->vars, "quiet"))
|
||||
{
|
||||
if (commit)
|
||||
puts("Warning: Your transaction in progress has been committed.");
|
||||
else
|
||||
@ -75,22 +78,24 @@ handle_transaction(PsqlSettings * pset)
|
||||
* Write a large object to a file
|
||||
*/
|
||||
bool
|
||||
do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_arg)
|
||||
do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
|
||||
{
|
||||
PGresult * res;
|
||||
PGresult *res;
|
||||
int status;
|
||||
bool own_transaction = true;
|
||||
const char * var = GetVariable(pset->vars, "lo_transaction");
|
||||
const char *var = GetVariable(pset->vars, "lo_transaction");
|
||||
|
||||
if (var && strcmp(var, "nothing")==0)
|
||||
if (var && strcmp(var, "nothing") == 0)
|
||||
own_transaction = false;
|
||||
|
||||
if (!pset->db) {
|
||||
if (!pset->db)
|
||||
{
|
||||
fputs("You are not connected to a database.\n", stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (own_transaction) {
|
||||
if (own_transaction)
|
||||
{
|
||||
if (!handle_transaction(pset))
|
||||
return false;
|
||||
|
||||
@ -100,18 +105,23 @@ do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_a
|
||||
PQclear(res);
|
||||
}
|
||||
|
||||
status = lo_export(pset->db, atol(loid_arg), (char *)filename_arg);
|
||||
if (status != 1) { /* of course this status is documented nowhere :( */
|
||||
status = lo_export(pset->db, atol(loid_arg), (char *) filename_arg);
|
||||
if (status != 1)
|
||||
{ /* of course this status is documented
|
||||
* nowhere :( */
|
||||
fputs(PQerrorMessage(pset->db), stderr);
|
||||
if (own_transaction) {
|
||||
if (own_transaction)
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (own_transaction) {
|
||||
if (!(res = PSQLexec(pset, "COMMIT"))) {
|
||||
if (own_transaction)
|
||||
{
|
||||
if (!(res = PSQLexec(pset, "COMMIT")))
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
return false;
|
||||
@ -133,24 +143,26 @@ do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_a
|
||||
* Copy large object from file to database
|
||||
*/
|
||||
bool
|
||||
do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * comment_arg)
|
||||
do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_arg)
|
||||
{
|
||||
PGresult * res;
|
||||
PGresult *res;
|
||||
Oid loid;
|
||||
char buf[1024];
|
||||
unsigned int i;
|
||||
bool own_transaction = true;
|
||||
const char * var = GetVariable(pset->vars, "lo_transaction");
|
||||
const char *var = GetVariable(pset->vars, "lo_transaction");
|
||||
|
||||
if (var && strcmp(var, "nothing")==0)
|
||||
if (var && strcmp(var, "nothing") == 0)
|
||||
own_transaction = false;
|
||||
|
||||
if (!pset->db) {
|
||||
if (!pset->db)
|
||||
{
|
||||
fputs("You are not connected to a database.\n", stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (own_transaction) {
|
||||
if (own_transaction)
|
||||
{
|
||||
if (!handle_transaction(pset))
|
||||
return false;
|
||||
|
||||
@ -160,10 +172,12 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
|
||||
PQclear(res);
|
||||
}
|
||||
|
||||
loid = lo_import(pset->db, (char *)filename_arg);
|
||||
if (loid == InvalidOid) {
|
||||
loid = lo_import(pset->db, (char *) filename_arg);
|
||||
if (loid == InvalidOid)
|
||||
{
|
||||
fputs(PQerrorMessage(pset->db), stderr);
|
||||
if (own_transaction) {
|
||||
if (own_transaction)
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
}
|
||||
@ -171,17 +185,20 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
|
||||
}
|
||||
|
||||
/* insert description if given */
|
||||
if (comment_arg) {
|
||||
if (comment_arg)
|
||||
{
|
||||
sprintf(buf, "INSERT INTO pg_description VALUES (%d, '", loid);
|
||||
for (i=0; i<strlen(comment_arg); i++)
|
||||
if (comment_arg[i]=='\'')
|
||||
for (i = 0; i < strlen(comment_arg); i++)
|
||||
if (comment_arg[i] == '\'')
|
||||
strcat(buf, "\\'");
|
||||
else
|
||||
strncat(buf, &comment_arg[i], 1);
|
||||
strcat(buf, "')");
|
||||
|
||||
if (!(res = PSQLexec(pset, buf))) {
|
||||
if (own_transaction) {
|
||||
if (!(res = PSQLexec(pset, buf)))
|
||||
{
|
||||
if (own_transaction)
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
}
|
||||
@ -189,8 +206,10 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
|
||||
}
|
||||
}
|
||||
|
||||
if (own_transaction) {
|
||||
if (!(res = PSQLexec(pset, "COMMIT"))) {
|
||||
if (own_transaction)
|
||||
{
|
||||
if (!(res = PSQLexec(pset, "COMMIT")))
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
return false;
|
||||
@ -212,24 +231,27 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
|
||||
*
|
||||
* 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;
|
||||
Oid loid = (Oid)atol(loid_arg);
|
||||
Oid loid = (Oid) atol(loid_arg);
|
||||
char buf[256];
|
||||
bool own_transaction = true;
|
||||
const char * var = GetVariable(pset->vars, "lo_transaction");
|
||||
const char *var = GetVariable(pset->vars, "lo_transaction");
|
||||
|
||||
if (var && strcmp(var, "nothing")==0)
|
||||
if (var && strcmp(var, "nothing") == 0)
|
||||
own_transaction = false;
|
||||
|
||||
if (!pset->db) {
|
||||
if (!pset->db)
|
||||
{
|
||||
fputs("You are not connected to a database.\n", stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (own_transaction) {
|
||||
if (own_transaction)
|
||||
{
|
||||
if (!handle_transaction(pset))
|
||||
return false;
|
||||
|
||||
@ -240,9 +262,11 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
|
||||
}
|
||||
|
||||
status = lo_unlink(pset->db, loid);
|
||||
if (status == -1) {
|
||||
if (status == -1)
|
||||
{
|
||||
fputs(PQerrorMessage(pset->db), stderr);
|
||||
if (own_transaction) {
|
||||
if (own_transaction)
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
}
|
||||
@ -251,8 +275,10 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
|
||||
|
||||
/* remove the comment as well */
|
||||
sprintf(buf, "DELETE FROM pg_description WHERE objoid = %d", loid);
|
||||
if (!(res = PSQLexec(pset, buf))) {
|
||||
if (own_transaction) {
|
||||
if (!(res = PSQLexec(pset, buf)))
|
||||
{
|
||||
if (own_transaction)
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
}
|
||||
@ -260,8 +286,10 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
|
||||
}
|
||||
|
||||
|
||||
if (own_transaction) {
|
||||
if (!(res = PSQLexec(pset, "COMMIT"))) {
|
||||
if (own_transaction)
|
||||
{
|
||||
if (!(res = PSQLexec(pset, "COMMIT")))
|
||||
{
|
||||
res = PQexec(pset->db, "ROLLBACK");
|
||||
PQclear(res);
|
||||
return false;
|
||||
@ -282,9 +310,10 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
|
||||
*
|
||||
* 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];
|
||||
printQueryOpt myopt = pset->popt;
|
||||
|
||||
@ -292,7 +321,7 @@ bool do_lo_list(PsqlSettings * pset)
|
||||
strcat(descbuf, "SELECT usename as \"Owner\", substring(relname from 5) as \"ID\"");
|
||||
if (GetVariableBool(pset->vars, "description"))
|
||||
strcat(descbuf, ",\n obj_description(pg_class.oid) as \"Description\"");
|
||||
strcat(descbuf,"\nFROM pg_class, pg_user\n"
|
||||
strcat(descbuf, "\nFROM pg_class, pg_user\n"
|
||||
"WHERE usesysid = relowner AND relkind = 'l'\n"
|
||||
"ORDER BY \"ID\"");
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
bool do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_arg);
|
||||
bool do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * comment_arg);
|
||||
bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg);
|
||||
bool do_lo_list(PsqlSettings * pset);
|
||||
bool do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg);
|
||||
bool do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_arg);
|
||||
bool do_lo_unlink(PsqlSettings *pset, const char *loid_arg);
|
||||
bool do_lo_list(PsqlSettings *pset);
|
||||
|
||||
#endif /* LARGE_OBJ_H */
|
||||
|
@ -40,7 +40,9 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
int paren_level;
|
||||
unsigned int query_start;
|
||||
|
||||
int i, prevlen, thislen;
|
||||
int i,
|
||||
prevlen,
|
||||
thislen;
|
||||
|
||||
/* Save the prior command source */
|
||||
FILE *prev_cmd_source;
|
||||
@ -60,7 +62,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
|
||||
|
||||
query_buf = createPQExpBuffer();
|
||||
if (!query_buf) {
|
||||
if (!query_buf)
|
||||
{
|
||||
perror("createPQExpBuffer");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -76,6 +79,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
{
|
||||
if (slashCmdStatus == CMD_NEWEDIT)
|
||||
{
|
||||
|
||||
/*
|
||||
* just returned from editing the line? then just copy to the
|
||||
* input buffer
|
||||
@ -89,9 +93,10 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* otherwise, set interactive prompt if necessary
|
||||
* and get another line
|
||||
* otherwise, set interactive prompt if necessary and get
|
||||
* another line
|
||||
*/
|
||||
if (pset->cur_cmd_interactive)
|
||||
{
|
||||
@ -100,7 +105,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
if (in_quote && in_quote == '\'')
|
||||
prompt_status = PROMPT_SINGLEQUOTE;
|
||||
else if (in_quote && in_quote == '"')
|
||||
prompt_status= PROMPT_DOUBLEQUOTE;
|
||||
prompt_status = PROMPT_DOUBLEQUOTE;
|
||||
else if (xcomment != NULL)
|
||||
prompt_status = PROMPT_COMMENT;
|
||||
else if (query_buf->len > 0)
|
||||
@ -121,9 +126,10 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
|
||||
|
||||
/*
|
||||
* query_buf holds query already accumulated. line is the malloc'd
|
||||
* new line of input (note it must be freed before looping around!)
|
||||
* query_start is the next command start location within the line.
|
||||
* query_buf holds query already accumulated. line is the
|
||||
* malloc'd new line of input (note it must be freed before
|
||||
* looping around!) query_start is the next command start location
|
||||
* within the line.
|
||||
*/
|
||||
|
||||
/* 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 */
|
||||
while (1) {
|
||||
char * cp = strrchr(line, '\\');
|
||||
while (1)
|
||||
{
|
||||
char *cp = strrchr(line, '\\');
|
||||
|
||||
if (cp && (*(cp + 1) == '\0'))
|
||||
*cp = '\0';
|
||||
else
|
||||
@ -159,21 +167,26 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
len = strlen(line);
|
||||
thislen = PQmblen(line);
|
||||
|
||||
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;
|
||||
const char * value;
|
||||
char * new;
|
||||
bool closer; /* did we have a closing delimiter or just an end of line? */
|
||||
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;
|
||||
const char *value;
|
||||
char *new;
|
||||
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];
|
||||
line[i + thislen + in_length] = '\0';
|
||||
value = interpolate_var(&line[i + thislen], pset);
|
||||
out_length = strlen(value);
|
||||
|
||||
new = malloc(len + out_length - (in_length + (closer ? 2 : 1)) + 1);
|
||||
if (!new) {
|
||||
if (!new)
|
||||
{
|
||||
perror("malloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -191,7 +204,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
}
|
||||
|
||||
/* nothing left on line? then ignore */
|
||||
if (line[0] == '\0') {
|
||||
if (line[0] == '\0')
|
||||
{
|
||||
free(line);
|
||||
continue;
|
||||
}
|
||||
@ -204,8 +218,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
/*
|
||||
* Parse line, looking for command separators.
|
||||
*
|
||||
* The current character is at line[i], the prior character at
|
||||
* line[i - prevlen], the next character at line[i + thislen].
|
||||
* The current character is at line[i], the prior character at line[i
|
||||
* - prevlen], the next character at line[i + thislen].
|
||||
*/
|
||||
prevlen = 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))
|
||||
|
||||
success = true;
|
||||
for (i = 0; i < len; ADVANCE_1) {
|
||||
for (i = 0; i < len; ADVANCE_1)
|
||||
{
|
||||
if (!success && die_on_error)
|
||||
break;
|
||||
|
||||
@ -226,7 +241,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
|
||||
|
||||
/* in quote? */
|
||||
if (in_quote) {
|
||||
if (in_quote)
|
||||
{
|
||||
/* end of quote */
|
||||
if (line[i] == in_quote && !was_bslash)
|
||||
in_quote = '\0';
|
||||
@ -237,15 +253,18 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
in_quote = line[i];
|
||||
|
||||
/* in extended comment? */
|
||||
else if (xcomment != NULL) {
|
||||
if (line[i] == '*' && line[i + thislen] == '/') {
|
||||
else if (xcomment != NULL)
|
||||
{
|
||||
if (line[i] == '*' && line[i + thislen] == '/')
|
||||
{
|
||||
xcomment = NULL;
|
||||
ADVANCE_1;
|
||||
}
|
||||
}
|
||||
|
||||
/* start of extended comment? */
|
||||
else if (line[i] == '/' && line[i + thislen] == '*') {
|
||||
else if (line[i] == '/' && line[i + thislen] == '*')
|
||||
{
|
||||
xcomment = &line[i];
|
||||
ADVANCE_1;
|
||||
}
|
||||
@ -266,11 +285,17 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
paren_level--;
|
||||
|
||||
/* 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';
|
||||
/* is there anything else on the line? */
|
||||
if (line[query_start + strspn(line + query_start, " \t")]!='\0') {
|
||||
/* insert a cosmetic newline, if this is not the first line in the buffer */
|
||||
if (line[query_start + strspn(line + query_start, " \t")] != '\0')
|
||||
{
|
||||
|
||||
/*
|
||||
* insert a cosmetic newline, if this is not the first
|
||||
* line in the buffer
|
||||
*/
|
||||
if (query_buf->len > 0)
|
||||
appendPQExpBufferChar(query_buf, '\n');
|
||||
/* append the line to the query buffer */
|
||||
@ -285,14 +310,20 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
}
|
||||
|
||||
/* backslash command */
|
||||
else if (was_bslash) {
|
||||
const char * end_of_cmd = NULL;
|
||||
else if (was_bslash)
|
||||
{
|
||||
const char *end_of_cmd = NULL;
|
||||
|
||||
line[i - prevlen] = '\0'; /* overwrites backslash */
|
||||
|
||||
/* is there anything else on the line? */
|
||||
if (line[query_start + strspn(line + query_start, " \t")]!='\0') {
|
||||
/* insert a cosmetic newline, if this is not the first line in the buffer */
|
||||
if (line[query_start + strspn(line + query_start, " \t")] != '\0')
|
||||
{
|
||||
|
||||
/*
|
||||
* insert a cosmetic newline, if this is not the first
|
||||
* line in the buffer
|
||||
*/
|
||||
if (query_buf->len > 0)
|
||||
appendPQExpBufferChar(query_buf, '\n');
|
||||
/* append the line to the query buffer */
|
||||
@ -305,14 +336,16 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
|
||||
success = slashCmdStatus != CMD_ERROR;
|
||||
|
||||
if (slashCmdStatus == CMD_SEND) {
|
||||
if (slashCmdStatus == CMD_SEND)
|
||||
{
|
||||
success = SendQuery(pset, query_buf->data);
|
||||
resetPQExpBuffer(query_buf);
|
||||
query_start = i + thislen;
|
||||
}
|
||||
|
||||
/* is there anything left after the backslash command? */
|
||||
if (end_of_cmd) {
|
||||
if (end_of_cmd)
|
||||
{
|
||||
i += end_of_cmd - &line[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;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (slashCmdStatus == CMD_TERMINATE) {
|
||||
if (slashCmdStatus == CMD_TERMINATE)
|
||||
{
|
||||
successResult = EXIT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
appendPQExpBufferChar(query_buf, '\n');
|
||||
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 */
|
||||
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);
|
||||
resetPQExpBuffer(query_buf);
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
break;
|
||||
}
|
||||
@ -365,4 +403,3 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||
|
||||
return successResult;
|
||||
} /* MainLoop() */
|
||||
|
||||
|
@ -5,6 +5,6 @@
|
||||
#include "settings.h"
|
||||
|
||||
int
|
||||
MainLoop(PsqlSettings *pset, FILE *source);
|
||||
MainLoop(PsqlSettings *pset, FILE *source);
|
||||
|
||||
#endif MAINLOOP_H
|
||||
#endif /* MAINLOOP_H */
|
||||
|
@ -28,13 +28,13 @@
|
||||
|
||||
|
||||
static void
|
||||
print_unaligned_text(const char * title, char ** headers, char ** cells, char ** footers,
|
||||
const char * opt_fieldsep, bool opt_barebones,
|
||||
FILE * fout)
|
||||
print_unaligned_text(const char *title, char **headers, char **cells, char **footers,
|
||||
const char *opt_fieldsep, bool opt_barebones,
|
||||
FILE *fout)
|
||||
{
|
||||
unsigned int col_count = 0;
|
||||
unsigned int i;
|
||||
char ** ptr;
|
||||
char **ptr;
|
||||
|
||||
if (!opt_fieldsep)
|
||||
opt_fieldsep = "";
|
||||
@ -44,10 +44,12 @@ print_unaligned_text(const char * title, char ** headers, char ** cells, char **
|
||||
fprintf(fout, "%s\n", title);
|
||||
|
||||
/* print headers and count columns */
|
||||
for (ptr = headers; *ptr; ptr++) {
|
||||
for (ptr = headers; *ptr; ptr++)
|
||||
{
|
||||
col_count++;
|
||||
if (!opt_barebones) {
|
||||
if (col_count>1)
|
||||
if (!opt_barebones)
|
||||
{
|
||||
if (col_count > 1)
|
||||
fputs(opt_fieldsep, fout);
|
||||
fputs(*ptr, fout);
|
||||
}
|
||||
@ -57,9 +59,10 @@ print_unaligned_text(const char * title, char ** headers, char ** cells, char **
|
||||
|
||||
/* print cells */
|
||||
i = 0;
|
||||
for (ptr = cells; *ptr; ptr++) {
|
||||
for (ptr = cells; *ptr; ptr++)
|
||||
{
|
||||
fputs(*ptr, fout);
|
||||
if ((i+1) % col_count)
|
||||
if ((i + 1) % col_count)
|
||||
fputs(opt_fieldsep, fout);
|
||||
else
|
||||
fputs("\n", fout);
|
||||
@ -77,14 +80,14 @@ print_unaligned_text(const char * title, char ** headers, char ** cells, char **
|
||||
|
||||
|
||||
static void
|
||||
print_unaligned_vertical(const char * title, char ** headers, char ** cells, char ** footers,
|
||||
const char * opt_fieldsep, bool opt_barebones,
|
||||
FILE * fout)
|
||||
print_unaligned_vertical(const char *title, char **headers, char **cells, char **footers,
|
||||
const char *opt_fieldsep, bool opt_barebones,
|
||||
FILE *fout)
|
||||
{
|
||||
unsigned int col_count = 0;
|
||||
unsigned int i;
|
||||
unsigned int record = 1;
|
||||
char ** ptr;
|
||||
char **ptr;
|
||||
|
||||
if (!opt_fieldsep)
|
||||
opt_fieldsep = "";
|
||||
@ -94,24 +97,26 @@ print_unaligned_vertical(const char * title, char ** headers, char ** cells, cha
|
||||
fprintf(fout, "%s\n", title);
|
||||
|
||||
/* count columns */
|
||||
for (ptr = headers; *ptr; ptr++) {
|
||||
for (ptr = headers; *ptr; ptr++)
|
||||
col_count++;
|
||||
}
|
||||
|
||||
/* print records */
|
||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
||||
if (i % col_count == 0) {
|
||||
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||
{
|
||||
if (i % col_count == 0)
|
||||
{
|
||||
if (!opt_barebones)
|
||||
fprintf(fout, "-- RECORD %d\n", record++);
|
||||
else
|
||||
fputc('\n', fout);
|
||||
}
|
||||
fprintf(fout, "%s%s%s\n", headers[i%col_count], opt_fieldsep, *ptr);
|
||||
fprintf(fout, "%s%s%s\n", headers[i % col_count], opt_fieldsep, *ptr);
|
||||
}
|
||||
|
||||
/* print footers */
|
||||
|
||||
if (!opt_barebones && footers) {
|
||||
if (!opt_barebones && footers)
|
||||
{
|
||||
fputs("--- END ---\n", fout);
|
||||
for (ptr = footers; *ptr; ptr++)
|
||||
fprintf(fout, "%s\n", *ptr);
|
||||
@ -127,19 +132,23 @@ print_unaligned_vertical(const char * title, char ** headers, char ** cells, cha
|
||||
|
||||
/* draw "line" */
|
||||
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)
|
||||
fputc('-', fout);
|
||||
else if (border == 2)
|
||||
fputs("+-", fout);
|
||||
|
||||
for (i=0; i<col_count; i++) {
|
||||
for (j=0; j<widths[i]; j++)
|
||||
for (i = 0; i < col_count; i++)
|
||||
{
|
||||
for (j = 0; j < widths[i]; j++)
|
||||
fputc('-', fout);
|
||||
|
||||
if (i<col_count-1) {
|
||||
if (i < col_count - 1)
|
||||
{
|
||||
if (border == 0)
|
||||
fputc(' ', fout);
|
||||
else
|
||||
@ -158,77 +167,84 @@ _print_horizontal_line(const unsigned int col_count, const unsigned int * widths
|
||||
|
||||
|
||||
static void
|
||||
print_aligned_text(const char * title, char ** headers, char ** cells, char ** footers,
|
||||
const char * opt_align, bool opt_barebones, unsigned short int opt_border,
|
||||
FILE * fout)
|
||||
print_aligned_text(const char *title, char **headers, char **cells, char **footers,
|
||||
const char *opt_align, bool opt_barebones, unsigned short int opt_border,
|
||||
FILE *fout)
|
||||
{
|
||||
unsigned int col_count = 0;
|
||||
unsigned int i, tmp;
|
||||
unsigned int * widths, total_w;
|
||||
char ** ptr;
|
||||
unsigned int i,
|
||||
tmp;
|
||||
unsigned int *widths,
|
||||
total_w;
|
||||
char **ptr;
|
||||
|
||||
/* count columns */
|
||||
for (ptr = headers; *ptr; ptr++)
|
||||
col_count++;
|
||||
|
||||
widths = calloc(col_count, sizeof (*widths));
|
||||
if (!widths) {
|
||||
widths = calloc(col_count, sizeof(*widths));
|
||||
if (!widths)
|
||||
{
|
||||
perror("calloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* calc column widths */
|
||||
for (i=0; i<col_count; i++)
|
||||
for (i = 0; i < col_count; i++)
|
||||
if ((tmp = strlen(headers[i])) > widths[i])
|
||||
widths[i] = tmp; /* don't wanna call strlen twice */
|
||||
|
||||
for (i=0, ptr = cells; *ptr; ptr++, i++)
|
||||
for (i = 0, ptr = cells; *ptr; ptr++, i++)
|
||||
if ((tmp = strlen(*ptr)) > widths[i % col_count])
|
||||
widths[i % col_count] = tmp;
|
||||
|
||||
if (opt_border==0)
|
||||
if (opt_border == 0)
|
||||
total_w = col_count - 1;
|
||||
else if (opt_border==1)
|
||||
total_w = col_count*3 - 2;
|
||||
else if (opt_border == 1)
|
||||
total_w = col_count * 3 - 2;
|
||||
else
|
||||
total_w = col_count*3 + 1;
|
||||
total_w = col_count * 3 + 1;
|
||||
|
||||
for (i=0; i<col_count; i++)
|
||||
for (i = 0; i < col_count; i++)
|
||||
total_w += widths[i];
|
||||
|
||||
/* print title */
|
||||
if (title && !opt_barebones) {
|
||||
if (strlen(title)>=total_w)
|
||||
if (title && !opt_barebones)
|
||||
{
|
||||
if (strlen(title) >= total_w)
|
||||
fprintf(fout, "%s\n", title);
|
||||
else
|
||||
fprintf(fout, "%-*s%s\n", (total_w-strlen(title))/2, "", title);
|
||||
fprintf(fout, "%-*s%s\n", (total_w - strlen(title)) / 2, "", title);
|
||||
}
|
||||
|
||||
/* print headers */
|
||||
if (!opt_barebones) {
|
||||
if (opt_border==2)
|
||||
if (!opt_barebones)
|
||||
{
|
||||
if (opt_border == 2)
|
||||
_print_horizontal_line(col_count, widths, opt_border, fout);
|
||||
|
||||
if (opt_border==2)
|
||||
if (opt_border == 2)
|
||||
fputs("| ", fout);
|
||||
else if (opt_border==1)
|
||||
else if (opt_border == 1)
|
||||
fputc(' ', fout);
|
||||
|
||||
for (i=0; i<col_count; i++) {
|
||||
for (i = 0; i < col_count; i++)
|
||||
{
|
||||
/* 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 (opt_border==0)
|
||||
if (i < col_count - 1)
|
||||
{
|
||||
if (opt_border == 0)
|
||||
fputc(' ', fout);
|
||||
else
|
||||
fputs(" | ", fout);
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_border==2)
|
||||
if (opt_border == 2)
|
||||
fputs(" |", fout);
|
||||
else if (opt_border==1)
|
||||
else if (opt_border == 1)
|
||||
fputc(' ', fout);;
|
||||
fputc('\n', fout);
|
||||
|
||||
@ -236,41 +252,46 @@ print_aligned_text(const char * title, char ** headers, char ** cells, char ** f
|
||||
}
|
||||
|
||||
/* print cells */
|
||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
||||
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||
{
|
||||
/* beginning of line */
|
||||
if (i % col_count == 0) {
|
||||
if (opt_border==2)
|
||||
if (i % col_count == 0)
|
||||
{
|
||||
if (opt_border == 2)
|
||||
fputs("| ", fout);
|
||||
else if (opt_border==1)
|
||||
else if (opt_border == 1)
|
||||
fputc(' ', fout);
|
||||
}
|
||||
|
||||
/* content */
|
||||
if (opt_align[(i) % col_count ] == 'r')
|
||||
fprintf(fout, "%*s", widths[i%col_count], cells[i]);
|
||||
else {
|
||||
if ((i+1) % col_count == 0 && opt_border != 2)
|
||||
if (opt_align[(i) % col_count] == 'r')
|
||||
fprintf(fout, "%*s", widths[i % col_count], cells[i]);
|
||||
else
|
||||
{
|
||||
if ((i + 1) % col_count == 0 && opt_border != 2)
|
||||
fputs(cells[i], fout);
|
||||
else
|
||||
fprintf(fout, "%-*s", widths[i%col_count], cells[i]);
|
||||
fprintf(fout, "%-*s", widths[i % col_count], cells[i]);
|
||||
}
|
||||
|
||||
/* divider */
|
||||
if ((i+1) % col_count) {
|
||||
if (opt_border==0)
|
||||
if ((i + 1) % col_count)
|
||||
{
|
||||
if (opt_border == 0)
|
||||
fputc(' ', fout);
|
||||
else
|
||||
fputs(" | ", fout);
|
||||
}
|
||||
/* end of line */
|
||||
else {
|
||||
if (opt_border==2)
|
||||
else
|
||||
{
|
||||
if (opt_border == 2)
|
||||
fputs(" |", fout);
|
||||
fputc('\n', fout);
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_border==2)
|
||||
if (opt_border == 2)
|
||||
_print_horizontal_line(col_count, widths, opt_border, fout);
|
||||
|
||||
/* print footers */
|
||||
@ -287,18 +308,22 @@ print_aligned_text(const char * title, char ** headers, char ** cells, char ** f
|
||||
|
||||
|
||||
static void
|
||||
print_aligned_vertical(const char * title, char ** headers, char ** cells, char ** footers,
|
||||
print_aligned_vertical(const char *title, char **headers, char **cells, char **footers,
|
||||
bool opt_barebones, unsigned short int opt_border,
|
||||
FILE * fout)
|
||||
FILE *fout)
|
||||
{
|
||||
unsigned int col_count = 0;
|
||||
unsigned int record = 1;
|
||||
char ** ptr;
|
||||
unsigned int i, tmp, hwidth=0, dwidth=0;
|
||||
char * divider;
|
||||
char **ptr;
|
||||
unsigned int i,
|
||||
tmp,
|
||||
hwidth = 0,
|
||||
dwidth = 0;
|
||||
char *divider;
|
||||
|
||||
/* count columns and find longest header */
|
||||
for (ptr = headers; *ptr; ptr++) {
|
||||
for (ptr = headers; *ptr; ptr++)
|
||||
{
|
||||
col_count++;
|
||||
if ((tmp = strlen(*ptr)) > hwidth)
|
||||
hwidth = tmp; /* don't wanna call strlen twice */
|
||||
@ -315,45 +340,55 @@ print_aligned_vertical(const char * title, char ** headers, char ** cells, char
|
||||
|
||||
/* make horizontal border */
|
||||
divider = malloc(hwidth + dwidth + 10);
|
||||
if (!divider) {
|
||||
if (!divider)
|
||||
{
|
||||
perror("malloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
divider[0] = '\0';
|
||||
if (opt_border == 2)
|
||||
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)
|
||||
strcat(divider, "-+-");
|
||||
else
|
||||
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)
|
||||
strcat(divider, "-+");
|
||||
|
||||
|
||||
/* print records */
|
||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
||||
if (i % col_count == 0) {
|
||||
if (!opt_barebones) {
|
||||
char * div_copy = strdup(divider);
|
||||
char * record_str = malloc(32);
|
||||
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||
{
|
||||
if (i % col_count == 0)
|
||||
{
|
||||
if (!opt_barebones)
|
||||
{
|
||||
char *div_copy = strdup(divider);
|
||||
char *record_str = malloc(32);
|
||||
size_t record_str_len;
|
||||
|
||||
if (!div_copy || !record_str) {
|
||||
if (!div_copy || !record_str)
|
||||
{
|
||||
perror("malloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (opt_border==0)
|
||||
if (opt_border == 0)
|
||||
sprintf(record_str, "* Record %d", record++);
|
||||
else
|
||||
sprintf(record_str, "[ RECORD %d ]", record++);
|
||||
record_str_len = strlen(record_str);
|
||||
if (record_str_len + opt_border > strlen(div_copy)) {
|
||||
void * new;
|
||||
if (record_str_len + opt_border > strlen(div_copy))
|
||||
{
|
||||
void *new;
|
||||
|
||||
new = realloc(div_copy, record_str_len + opt_border);
|
||||
if (!new) {
|
||||
if (!new)
|
||||
{
|
||||
perror("realloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -369,7 +404,7 @@ print_aligned_vertical(const char * title, char ** headers, char ** cells, char
|
||||
}
|
||||
if (opt_border == 2)
|
||||
fputs("| ", fout);
|
||||
fprintf(fout, "%-*s", hwidth, headers[i%col_count]);
|
||||
fprintf(fout, "%-*s", hwidth, headers[i % col_count]);
|
||||
if (opt_border > 0)
|
||||
fputs(" | ", fout);
|
||||
else
|
||||
@ -387,7 +422,8 @@ print_aligned_vertical(const char * title, char ** headers, char ** cells, char
|
||||
|
||||
/* print footers */
|
||||
|
||||
if (!opt_barebones && footers && *footers) {
|
||||
if (!opt_barebones && footers && *footers)
|
||||
{
|
||||
if (opt_border < 2)
|
||||
fputc('\n', fout);
|
||||
for (ptr = footers; *ptr; ptr++)
|
||||
@ -408,11 +444,13 @@ print_aligned_vertical(const char * title, char ** headers, char ** cells, char
|
||||
|
||||
|
||||
static void
|
||||
html_escaped_print(const char * in, FILE * fout)
|
||||
html_escaped_print(const char *in, FILE *fout)
|
||||
{
|
||||
const char * p;
|
||||
for (p=in; *p; p++)
|
||||
switch (*p) {
|
||||
const char *p;
|
||||
|
||||
for (p = in; *p; p++)
|
||||
switch (*p)
|
||||
{
|
||||
case '&':
|
||||
fputs("&", fout);
|
||||
break;
|
||||
@ -433,14 +471,14 @@ html_escaped_print(const char * in, FILE * fout)
|
||||
|
||||
|
||||
static void
|
||||
print_html_text(const char * title, char ** headers, char ** cells, char ** footers,
|
||||
const char * opt_align, bool opt_barebones, unsigned short int opt_border,
|
||||
char * opt_table_attr,
|
||||
FILE * fout)
|
||||
print_html_text(const char *title, char **headers, char **cells, char **footers,
|
||||
const char *opt_align, bool opt_barebones, unsigned short int opt_border,
|
||||
char *opt_table_attr,
|
||||
FILE *fout)
|
||||
{
|
||||
unsigned int col_count = 0;
|
||||
unsigned int i;
|
||||
char ** ptr;
|
||||
char **ptr;
|
||||
|
||||
fprintf(fout, "<table border=%d", opt_border);
|
||||
if (opt_table_attr)
|
||||
@ -448,7 +486,8 @@ print_html_text(const char * title, char ** headers, char ** cells, char ** foot
|
||||
fputs(">\n", fout);
|
||||
|
||||
/* print title */
|
||||
if (!opt_barebones && title) {
|
||||
if (!opt_barebones && title)
|
||||
{
|
||||
fputs(" <caption>", fout);
|
||||
html_escaped_print(title, 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 */
|
||||
if (!opt_barebones)
|
||||
fputs(" <tr>\n", fout);
|
||||
for (i=0, ptr = headers; *ptr; i++, ptr++) {
|
||||
for (i = 0, ptr = headers; *ptr; i++, ptr++)
|
||||
{
|
||||
col_count++;
|
||||
if (!opt_barebones) {
|
||||
if (!opt_barebones)
|
||||
{
|
||||
fputs(" <th align=center>", fout);
|
||||
html_escaped_print(*ptr, fout);
|
||||
fputs("</th>\n", fout);
|
||||
@ -469,18 +510,20 @@ print_html_text(const char * title, char ** headers, char ** cells, char ** foot
|
||||
fputs(" </tr>\n", fout);
|
||||
|
||||
/* print cells */
|
||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
||||
if ( i % col_count == 0 )
|
||||
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||
{
|
||||
if (i % col_count == 0)
|
||||
fputs(" <tr valign=top>\n", fout);
|
||||
|
||||
fprintf(fout, " <td align=%s>", opt_align[(i)%col_count] == 'r' ? "right" : "left");
|
||||
if ( (*ptr)[strspn(*ptr, " \t")] == '\0' ) /* is string only whitespace? */
|
||||
fprintf(fout, " <td align=%s>", opt_align[(i) % col_count] == 'r' ? "right" : "left");
|
||||
if ((*ptr)[strspn(*ptr, " \t")] == '\0') /* is string only
|
||||
* whitespace? */
|
||||
fputs(" ", fout);
|
||||
else
|
||||
html_escaped_print(*ptr, fout);
|
||||
fputs("</td>\n", fout);
|
||||
|
||||
if ( (i+1) % col_count == 0 )
|
||||
if ((i + 1) % col_count == 0)
|
||||
fputs(" </tr>\n", fout);
|
||||
}
|
||||
|
||||
@ -489,7 +532,8 @@ print_html_text(const char * title, char ** headers, char ** cells, char ** foot
|
||||
/* print footers */
|
||||
|
||||
if (footers && !opt_barebones)
|
||||
for (ptr = footers; *ptr; ptr++) {
|
||||
for (ptr = footers; *ptr; ptr++)
|
||||
{
|
||||
html_escaped_print(*ptr, fout);
|
||||
fputs("<br>\n", fout);
|
||||
}
|
||||
@ -500,15 +544,15 @@ print_html_text(const char * title, char ** headers, char ** cells, char ** foot
|
||||
|
||||
|
||||
static void
|
||||
print_html_vertical(const char * title, char ** headers, char ** cells, char ** footers,
|
||||
const char * opt_align, bool opt_barebones, unsigned short int opt_border,
|
||||
char * opt_table_attr,
|
||||
FILE * fout)
|
||||
print_html_vertical(const char *title, char **headers, char **cells, char **footers,
|
||||
const char *opt_align, bool opt_barebones, unsigned short int opt_border,
|
||||
char *opt_table_attr,
|
||||
FILE *fout)
|
||||
{
|
||||
unsigned int col_count = 0;
|
||||
unsigned int i;
|
||||
unsigned int record = 1;
|
||||
char ** ptr;
|
||||
char **ptr;
|
||||
|
||||
fprintf(fout, "<table border=%d", opt_border);
|
||||
if (opt_table_attr)
|
||||
@ -516,7 +560,8 @@ print_html_vertical(const char * title, char ** headers, char ** cells, char **
|
||||
fputs(">\n", fout);
|
||||
|
||||
/* print title */
|
||||
if (!opt_barebones && title) {
|
||||
if (!opt_barebones && title)
|
||||
{
|
||||
fputs(" <caption>", fout);
|
||||
html_escaped_print(title, fout);
|
||||
fputs("</caption>\n", fout);
|
||||
@ -527,8 +572,10 @@ print_html_vertical(const char * title, char ** headers, char ** cells, char **
|
||||
col_count++;
|
||||
|
||||
/* print records */
|
||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
||||
if (i % col_count == 0) {
|
||||
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||
{
|
||||
if (i % col_count == 0)
|
||||
{
|
||||
if (!opt_barebones)
|
||||
fprintf(fout, "\n <tr><td colspan=2 align=center>Record %d</td></tr>\n", record++);
|
||||
else
|
||||
@ -536,11 +583,12 @@ print_html_vertical(const char * title, char ** headers, char ** cells, char **
|
||||
}
|
||||
fputs(" <tr valign=top>\n"
|
||||
" <th>", fout);
|
||||
html_escaped_print(headers[i%col_count], fout);
|
||||
html_escaped_print(headers[i % col_count], fout);
|
||||
fputs("</th>\n", fout);
|
||||
|
||||
fprintf(fout, " <td align=%s>", opt_align[i%col_count] == 'r' ? "right" : "left");
|
||||
if ( (*ptr)[strspn(*ptr, " \t")] == '\0' ) /* is string only whitespace? */
|
||||
fprintf(fout, " <td align=%s>", opt_align[i % col_count] == 'r' ? "right" : "left");
|
||||
if ((*ptr)[strspn(*ptr, " \t")] == '\0') /* is string only
|
||||
* whitespace? */
|
||||
fputs(" ", fout);
|
||||
else
|
||||
html_escaped_print(*ptr, fout);
|
||||
@ -551,7 +599,8 @@ print_html_vertical(const char * title, char ** headers, char ** cells, char **
|
||||
|
||||
/* print footers */
|
||||
if (footers && !opt_barebones)
|
||||
for (ptr = footers; *ptr; ptr++) {
|
||||
for (ptr = footers; *ptr; ptr++)
|
||||
{
|
||||
html_escaped_print(*ptr, fout);
|
||||
fputs("<br>\n", fout);
|
||||
}
|
||||
@ -567,11 +616,13 @@ print_html_vertical(const char * title, char ** headers, char ** cells, char **
|
||||
|
||||
|
||||
static void
|
||||
latex_escaped_print(const char * in, FILE * fout)
|
||||
latex_escaped_print(const char *in, FILE *fout)
|
||||
{
|
||||
const char * p;
|
||||
for (p=in; *p; p++)
|
||||
switch (*p) {
|
||||
const char *p;
|
||||
|
||||
for (p = in; *p; p++)
|
||||
switch (*p)
|
||||
{
|
||||
case '&':
|
||||
fputs("\\&", fout);
|
||||
break;
|
||||
@ -601,18 +652,19 @@ latex_escaped_print(const char * in, FILE * fout)
|
||||
|
||||
|
||||
static void
|
||||
print_latex_text(const char * title, char ** headers, char ** cells, char ** footers,
|
||||
const char * opt_align, bool opt_barebones, unsigned short int opt_border,
|
||||
FILE * fout)
|
||||
print_latex_text(const char *title, char **headers, char **cells, char **footers,
|
||||
const char *opt_align, bool opt_barebones, unsigned short int opt_border,
|
||||
FILE *fout)
|
||||
{
|
||||
unsigned int col_count = 0;
|
||||
unsigned int i;
|
||||
const char * cp;
|
||||
char ** ptr;
|
||||
const char *cp;
|
||||
char **ptr;
|
||||
|
||||
|
||||
/* print title */
|
||||
if (!opt_barebones && title) {
|
||||
if (!opt_barebones && title)
|
||||
{
|
||||
fputs("\begin{center}\n", fout);
|
||||
latex_escaped_print(title, fout);
|
||||
fputs("\n\end{center}\n\n", fout);
|
||||
@ -620,16 +672,21 @@ print_latex_text(const char * title, char ** headers, char ** cells, char ** foo
|
||||
|
||||
/* begin environment and set alignments and borders */
|
||||
fputs("\\begin{tabular}{", fout);
|
||||
if (opt_border==0)
|
||||
if (opt_border == 0)
|
||||
fputs(opt_align, fout);
|
||||
else if (opt_border==1) {
|
||||
for (cp = opt_align; *cp; cp++) {
|
||||
if (cp != opt_align) fputc('|', fout);
|
||||
else if (opt_border == 1)
|
||||
{
|
||||
for (cp = opt_align; *cp; cp++)
|
||||
{
|
||||
if (cp != opt_align)
|
||||
fputc('|', fout);
|
||||
fputc(*cp, fout);
|
||||
}
|
||||
}
|
||||
else if (opt_border==2) {
|
||||
for (cp = opt_align; *cp; cp++) {
|
||||
else if (opt_border == 2)
|
||||
{
|
||||
for (cp = opt_align; *cp; cp++)
|
||||
{
|
||||
fputc('|', fout);
|
||||
fputc(*cp, fout);
|
||||
}
|
||||
@ -637,35 +694,39 @@ print_latex_text(const char * title, char ** headers, char ** cells, char ** foo
|
||||
}
|
||||
fputs("}\n", fout);
|
||||
|
||||
if (!opt_barebones && opt_border==2)
|
||||
if (!opt_barebones && opt_border == 2)
|
||||
fputs("\\hline\n", fout);
|
||||
|
||||
/* print headers and count columns */
|
||||
for (i=0, ptr = headers; *ptr; i++, ptr++) {
|
||||
for (i = 0, ptr = headers; *ptr; i++, ptr++)
|
||||
{
|
||||
col_count++;
|
||||
if (!opt_barebones) {
|
||||
if (i!=0)
|
||||
if (!opt_barebones)
|
||||
{
|
||||
if (i != 0)
|
||||
fputs(" & ", fout);
|
||||
latex_escaped_print(*ptr, fout);
|
||||
}
|
||||
}
|
||||
|
||||
if (!opt_barebones) {
|
||||
if (!opt_barebones)
|
||||
{
|
||||
fputs(" \\\\\n", fout);
|
||||
fputs("\\hline\n", fout);
|
||||
}
|
||||
|
||||
/* print cells */
|
||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
||||
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||
{
|
||||
latex_escaped_print(*ptr, fout);
|
||||
|
||||
if ( (i+1) % col_count == 0 )
|
||||
if ((i + 1) % col_count == 0)
|
||||
fputs(" \\\\\n", fout);
|
||||
else
|
||||
fputs(" & ", fout);
|
||||
}
|
||||
|
||||
if (opt_border==2)
|
||||
if (opt_border == 2)
|
||||
fputs("\\hline\n", fout);
|
||||
|
||||
fputs("\\end{tabular}\n\n", fout);
|
||||
@ -674,7 +735,8 @@ print_latex_text(const char * title, char ** headers, char ** cells, char ** foo
|
||||
/* print footers */
|
||||
|
||||
if (footers && !opt_barebones)
|
||||
for (ptr = footers; *ptr; ptr++) {
|
||||
for (ptr = footers; *ptr; ptr++)
|
||||
{
|
||||
latex_escaped_print(*ptr, fout);
|
||||
fputs(" \\\\\n", fout);
|
||||
}
|
||||
@ -685,19 +747,20 @@ print_latex_text(const char * title, char ** headers, char ** cells, char ** foo
|
||||
|
||||
|
||||
static void
|
||||
print_latex_vertical(const char * title, char ** headers, char ** cells, char ** footers,
|
||||
const char * opt_align, bool opt_barebones, unsigned short int opt_border,
|
||||
FILE * fout)
|
||||
print_latex_vertical(const char *title, char **headers, char **cells, char **footers,
|
||||
const char *opt_align, bool opt_barebones, unsigned short int opt_border,
|
||||
FILE *fout)
|
||||
{
|
||||
unsigned int col_count = 0;
|
||||
unsigned int i;
|
||||
char ** ptr;
|
||||
char **ptr;
|
||||
unsigned int record = 1;
|
||||
|
||||
(void)opt_align; /* currently unused parameter */
|
||||
(void) opt_align; /* currently unused parameter */
|
||||
|
||||
/* print title */
|
||||
if (!opt_barebones && title) {
|
||||
if (!opt_barebones && title)
|
||||
{
|
||||
fputs("\begin{center}\n", fout);
|
||||
latex_escaped_print(title, fout);
|
||||
fputs("\n\end{center}\n\n", fout);
|
||||
@ -705,11 +768,11 @@ print_latex_vertical(const char * title, char ** headers, char ** cells, char **
|
||||
|
||||
/* begin environment and set alignments and borders */
|
||||
fputs("\\begin{tabular}{", fout);
|
||||
if (opt_border==0)
|
||||
if (opt_border == 0)
|
||||
fputs("cl", fout);
|
||||
else if (opt_border==1)
|
||||
else if (opt_border == 1)
|
||||
fputs("c|l", fout);
|
||||
else if (opt_border==2)
|
||||
else if (opt_border == 2)
|
||||
fputs("|c|l|", fout);
|
||||
fputs("}\n", fout);
|
||||
|
||||
@ -720,10 +783,13 @@ print_latex_vertical(const char * title, char ** headers, char ** cells, char **
|
||||
|
||||
|
||||
/* print records */
|
||||
for (i=0, ptr = cells; *ptr; i++, ptr++) {
|
||||
for (i = 0, ptr = cells; *ptr; i++, ptr++)
|
||||
{
|
||||
/* new record */
|
||||
if (i % col_count == 0) {
|
||||
if (!opt_barebones) {
|
||||
if (i % col_count == 0)
|
||||
{
|
||||
if (!opt_barebones)
|
||||
{
|
||||
if (opt_border == 2)
|
||||
fputs("\\hline\n", fout);
|
||||
fprintf(fout, "\\multicolumn{2}{c}{Record %d} \\\\\n", record++);
|
||||
@ -732,13 +798,13 @@ print_latex_vertical(const char * title, char ** headers, char ** cells, char **
|
||||
fputs("\\hline\n", fout);
|
||||
}
|
||||
|
||||
latex_escaped_print(headers[i%col_count], fout);
|
||||
latex_escaped_print(headers[i % col_count], fout);
|
||||
fputs(" & ", fout);
|
||||
latex_escaped_print(*ptr, fout);
|
||||
fputs(" \\\\\n", fout);
|
||||
}
|
||||
|
||||
if (opt_border==2)
|
||||
if (opt_border == 2)
|
||||
fputs("\\hline\n", fout);
|
||||
|
||||
fputs("\\end{tabular}\n\n", fout);
|
||||
@ -747,7 +813,8 @@ print_latex_vertical(const char * title, char ** headers, char ** cells, char **
|
||||
/* print footers */
|
||||
|
||||
if (footers && !opt_barebones)
|
||||
for (ptr = footers; *ptr; ptr++) {
|
||||
for (ptr = footers; *ptr; ptr++)
|
||||
{
|
||||
latex_escaped_print(*ptr, fout);
|
||||
fputs(" \\\\\n", fout);
|
||||
}
|
||||
@ -766,14 +833,14 @@ print_latex_vertical(const char * title, char ** headers, char ** cells, char **
|
||||
|
||||
|
||||
void
|
||||
printTable(const char * title, char ** headers, char ** cells, char ** footers,
|
||||
const char * align,
|
||||
const printTableOpt * opt, FILE * fout)
|
||||
printTable(const char *title, char **headers, char **cells, char **footers,
|
||||
const char *align,
|
||||
const printTableOpt * opt, FILE *fout)
|
||||
{
|
||||
char * default_footer[] = { NULL };
|
||||
char *default_footer[] = {NULL};
|
||||
unsigned short int border = opt->border;
|
||||
FILE * pager = NULL,
|
||||
* output;
|
||||
FILE *pager = NULL,
|
||||
*output;
|
||||
|
||||
|
||||
if (opt->format == PRINT_NOTHING)
|
||||
@ -795,41 +862,47 @@ printTable(const char * title, char ** headers, char ** cells, char ** footers,
|
||||
#endif
|
||||
)
|
||||
{
|
||||
const char * pagerprog;
|
||||
const char *pagerprog;
|
||||
|
||||
#ifdef TIOCGWINSZ
|
||||
unsigned int col_count=0, row_count=0, lines;
|
||||
char ** ptr;
|
||||
unsigned int col_count = 0,
|
||||
row_count = 0,
|
||||
lines;
|
||||
char **ptr;
|
||||
int result;
|
||||
struct winsize screen_size;
|
||||
|
||||
/* rough estimate of columns and rows */
|
||||
if (headers)
|
||||
for (ptr=headers; *ptr; ptr++)
|
||||
for (ptr = headers; *ptr; ptr++)
|
||||
col_count++;
|
||||
if (cells)
|
||||
for (ptr=cells; *ptr; ptr++)
|
||||
for (ptr = cells; *ptr; ptr++)
|
||||
row_count++;
|
||||
row_count /= col_count;
|
||||
|
||||
if (opt->expanded)
|
||||
lines = (col_count+1) * row_count;
|
||||
lines = (col_count + 1) * row_count;
|
||||
else
|
||||
lines = row_count+1;
|
||||
lines = row_count + 1;
|
||||
if (!opt->tuples_only)
|
||||
lines += 5;
|
||||
|
||||
result = ioctl(fileno(stdout), TIOCGWINSZ, &screen_size);
|
||||
if (result==-1 || lines > screen_size.ws_row) {
|
||||
if (result == -1 || lines > screen_size.ws_row)
|
||||
{
|
||||
#endif
|
||||
pagerprog = getenv("PAGER");
|
||||
if (!pagerprog) pagerprog = DEFAULT_PAGER;
|
||||
if (!pagerprog)
|
||||
pagerprog = DEFAULT_PAGER;
|
||||
pager = popen(pagerprog, "w");
|
||||
#ifdef TIOCGWINSZ
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pager) {
|
||||
if (pager)
|
||||
{
|
||||
output = pager;
|
||||
pqsignal(SIGPIPE, SIG_IGN);
|
||||
}
|
||||
@ -839,7 +912,8 @@ printTable(const char * title, char ** headers, char ** cells, char ** footers,
|
||||
|
||||
/* print the stuff */
|
||||
|
||||
switch (opt->format) {
|
||||
switch (opt->format)
|
||||
{
|
||||
case PRINT_UNALIGNED:
|
||||
if (opt->expanded)
|
||||
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");
|
||||
}
|
||||
|
||||
if (pager) {
|
||||
if (pager)
|
||||
{
|
||||
pclose(pager);
|
||||
pqsignal(SIGPIPE, SIG_DFL);
|
||||
}
|
||||
@ -877,37 +952,40 @@ printTable(const char * title, char ** headers, char ** cells, char ** footers,
|
||||
|
||||
|
||||
void
|
||||
printQuery(PGresult * result, const printQueryOpt * opt, FILE * fout)
|
||||
printQuery(PGresult *result, const printQueryOpt * opt, FILE *fout)
|
||||
{
|
||||
int nfields;
|
||||
char ** headers;
|
||||
char ** cells;
|
||||
char ** footers;
|
||||
char * align;
|
||||
char **headers;
|
||||
char **cells;
|
||||
char **footers;
|
||||
char *align;
|
||||
int i;
|
||||
|
||||
/* extract headers */
|
||||
|
||||
nfields = PQnfields(result);
|
||||
|
||||
headers = calloc(nfields+1, sizeof(*headers));
|
||||
if (!headers) {
|
||||
headers = calloc(nfields + 1, sizeof(*headers));
|
||||
if (!headers)
|
||||
{
|
||||
perror("calloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i=0; i<nfields; i++)
|
||||
for (i = 0; i < nfields; i++)
|
||||
headers[i] = PQfname(result, i);
|
||||
|
||||
/* set cells */
|
||||
|
||||
cells = calloc(nfields * PQntuples(result) + 1, sizeof(*cells));
|
||||
if (!cells) {
|
||||
if (!cells)
|
||||
{
|
||||
perror("calloc");
|
||||
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))
|
||||
cells[i] = opt->nullPrint ? opt->nullPrint : "";
|
||||
else
|
||||
@ -918,15 +996,17 @@ printQuery(PGresult * result, const printQueryOpt * opt, FILE * fout)
|
||||
|
||||
if (opt->footers)
|
||||
footers = opt->footers;
|
||||
else if (!opt->topt.expanded) {
|
||||
else if (!opt->topt.expanded)
|
||||
{
|
||||
footers = calloc(2, sizeof(*footers));
|
||||
if (!footers) {
|
||||
if (!footers)
|
||||
{
|
||||
perror("calloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
footers[0] = malloc(100);
|
||||
if (PQntuples(result)==1)
|
||||
if (PQntuples(result) == 1)
|
||||
strcpy(footers[0], "(1 row)");
|
||||
else
|
||||
sprintf(footers[0], "(%d rows)", PQntuples(result));
|
||||
@ -936,18 +1016,21 @@ printQuery(PGresult * result, const printQueryOpt * opt, FILE * fout)
|
||||
|
||||
/* set alignment */
|
||||
|
||||
align = calloc(nfields+1, sizeof(*align));
|
||||
if (!align) {
|
||||
align = calloc(nfields + 1, sizeof(*align));
|
||||
if (!align)
|
||||
{
|
||||
perror("calloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i=0; i<nfields; i++) {
|
||||
for (i = 0; i < nfields; i++)
|
||||
{
|
||||
Oid ftype = PQftype(result, i);
|
||||
if ( ftype == 20 || /* int8 */
|
||||
|
||||
if (ftype == 20 || /* int8 */
|
||||
ftype == 21 || /* int2 */
|
||||
ftype == 23 || /* int4 */
|
||||
(ftype >=26 && ftype <=30) || /* ?id */
|
||||
(ftype >= 26 && ftype <= 30) || /* ?id */
|
||||
ftype == 700 || /* float4 */
|
||||
ftype == 701 || /* float8 */
|
||||
ftype == 790 || /* money */
|
||||
@ -965,7 +1048,8 @@ printQuery(PGresult * result, const printQueryOpt * opt, FILE * fout)
|
||||
|
||||
free(headers);
|
||||
free(cells);
|
||||
if (footers) {
|
||||
if (footers)
|
||||
{
|
||||
free(footers[0]);
|
||||
free(footers);
|
||||
}
|
||||
|
@ -7,7 +7,8 @@
|
||||
#include <stdio.h>
|
||||
#include <libpq-fe.h>
|
||||
|
||||
enum printFormat {
|
||||
enum printFormat
|
||||
{
|
||||
PRINT_NOTHING = 0, /* to make sure someone initializes this */
|
||||
PRINT_UNALIGNED,
|
||||
PRINT_ALIGNED,
|
||||
@ -17,12 +18,16 @@ enum printFormat {
|
||||
};
|
||||
|
||||
|
||||
typedef struct _printTableOpt {
|
||||
typedef struct _printTableOpt
|
||||
{
|
||||
enum printFormat format; /* one of the above */
|
||||
bool expanded; /* expanded/vertical output (if supported by output format) */
|
||||
bool pager; /* use pager for output (if to stdout and stdout is a tty) */
|
||||
bool expanded; /* expanded/vertical output (if supported
|
||||
* 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. */
|
||||
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 *tableAttr; /* attributes for HTML <table ...> */
|
||||
} printTableOpt;
|
||||
@ -39,19 +44,20 @@ typedef struct _printTableOpt {
|
||||
* - 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.)
|
||||
*/
|
||||
void
|
||||
printTable(const char * title, char ** headers, char ** cells, char ** footers,
|
||||
const char * align,
|
||||
const printTableOpt * opt, FILE * fout);
|
||||
void printTable(const char *title, char **headers, char **cells, char **footers,
|
||||
const char *align,
|
||||
const printTableOpt * opt, FILE *fout);
|
||||
|
||||
|
||||
|
||||
typedef struct _printQueryOpt {
|
||||
typedef struct _printQueryOpt
|
||||
{
|
||||
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 */
|
||||
char * title; /* override title */
|
||||
char ** footers; /* override footer (default is "(xx rows)") */
|
||||
char *title; /* override title */
|
||||
char **footers; /* override footer (default is "(xx
|
||||
* rows)") */
|
||||
} printQueryOpt;
|
||||
|
||||
/*
|
||||
@ -60,7 +66,7 @@ typedef struct _printQueryOpt {
|
||||
* It calls the printTable above with all the things set straight.
|
||||
*/
|
||||
void
|
||||
printQuery(PGresult * result, const printQueryOpt * opt, FILE * fout);
|
||||
printQuery(PGresult *result, const printQueryOpt * opt, FILE *fout);
|
||||
|
||||
|
||||
#endif /* PRINT_H */
|
||||
|
@ -60,11 +60,11 @@ const char *
|
||||
get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
{
|
||||
#define MAX_PROMPT_SIZE 256
|
||||
static char destination[MAX_PROMPT_SIZE+1];
|
||||
char buf[MAX_PROMPT_SIZE+1];
|
||||
static char destination[MAX_PROMPT_SIZE + 1];
|
||||
char buf[MAX_PROMPT_SIZE + 1];
|
||||
bool esc = false;
|
||||
const char *p;
|
||||
const char * prompt_string;
|
||||
const char *prompt_string;
|
||||
|
||||
if (GetVariable(pset->vars, "quiet"))
|
||||
return "";
|
||||
@ -82,10 +82,10 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
destination[0] = '\0';
|
||||
|
||||
for (p = prompt_string;
|
||||
p && *p && strlen(destination)<MAX_PROMPT_SIZE;
|
||||
p && *p && strlen(destination) < MAX_PROMPT_SIZE;
|
||||
p++)
|
||||
{
|
||||
MemSet(buf, 0, MAX_PROMPT_SIZE+1);
|
||||
MemSet(buf, 0, MAX_PROMPT_SIZE + 1);
|
||||
if (esc)
|
||||
{
|
||||
switch (*p)
|
||||
@ -99,11 +99,14 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
if (pset->db)
|
||||
strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE);
|
||||
break;
|
||||
case '~': {
|
||||
const char * var;
|
||||
if (pset->db) {
|
||||
if ( strcmp(PQdb(pset->db), PQuser(pset->db))==0 ||
|
||||
( (var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset->db))==0) )
|
||||
case '~':
|
||||
{
|
||||
const char *var;
|
||||
|
||||
if (pset->db)
|
||||
{
|
||||
if (strcmp(PQdb(pset->db), PQuser(pset->db)) == 0 ||
|
||||
((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset->db)) == 0))
|
||||
strcpy(buf, "~");
|
||||
else
|
||||
strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE);
|
||||
@ -113,11 +116,13 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
/* DB server hostname (long/short) */
|
||||
case 'M':
|
||||
case 'm':
|
||||
if (pset->db) {
|
||||
if (PQhost(pset->db)) {
|
||||
if (pset->db)
|
||||
{
|
||||
if (PQhost(pset->db))
|
||||
{
|
||||
strncpy(buf, PQhost(pset->db), MAX_PROMPT_SIZE);
|
||||
if (*p == 'm')
|
||||
buf[strcspn(buf,".")] = '\0';
|
||||
buf[strcspn(buf, ".")] = '\0';
|
||||
}
|
||||
else
|
||||
buf[0] = '.';
|
||||
@ -125,7 +130,8 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
break;
|
||||
/* DB server port number */
|
||||
case '>':
|
||||
if (pset->db) {
|
||||
if (pset->db)
|
||||
{
|
||||
if (PQhost(pset->db))
|
||||
strncpy(buf, PQport(pset->db), MAX_PROMPT_SIZE);
|
||||
else
|
||||
@ -138,19 +144,29 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
strncpy(buf, PQuser(pset->db), MAX_PROMPT_SIZE);
|
||||
break;
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
{
|
||||
long int l;
|
||||
char * end;
|
||||
char *end;
|
||||
|
||||
l = strtol(p, &end, 0);
|
||||
sprintf(buf, "%c", (unsigned char)l);
|
||||
p = end-1;
|
||||
sprintf(buf, "%c", (unsigned char) l);
|
||||
p = end - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'R':
|
||||
switch(status) {
|
||||
switch (status)
|
||||
{
|
||||
case PROMPT_READY:
|
||||
if (!pset->db)
|
||||
buf[0] = '!';
|
||||
@ -182,7 +198,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
|
||||
case '#':
|
||||
{
|
||||
if (pset->db && strcmp(PQuser(pset->db), "postgres")==0)
|
||||
if (pset->db && strcmp(PQuser(pset->db), "postgres") == 0)
|
||||
buf[0] = '#';
|
||||
else
|
||||
buf[0] = '>';
|
||||
@ -193,21 +209,23 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
/* execute command */
|
||||
case '`':
|
||||
{
|
||||
FILE * fd = NULL;
|
||||
char * file = strdup(p+1);
|
||||
FILE *fd = NULL;
|
||||
char *file = strdup(p + 1);
|
||||
int cmdend;
|
||||
|
||||
cmdend = strcspn(file, "`");
|
||||
file[cmdend] = '\0';
|
||||
if (file)
|
||||
fd = popen(file, "r");
|
||||
if (fd) {
|
||||
fgets(buf, MAX_PROMPT_SIZE-1, fd);
|
||||
if (fd)
|
||||
{
|
||||
fgets(buf, MAX_PROMPT_SIZE - 1, fd);
|
||||
pclose(fd);
|
||||
}
|
||||
if (buf[strlen(buf)-1] == '\n')
|
||||
buf[strlen(buf)-1] = '\0';
|
||||
if (buf[strlen(buf) - 1] == '\n')
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
free(file);
|
||||
p += cmdend+1;
|
||||
p += cmdend + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -217,14 +235,15 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
char *name;
|
||||
const char *val;
|
||||
int nameend;
|
||||
name = strdup(p+1);
|
||||
|
||||
name = strdup(p + 1);
|
||||
nameend = strcspn(name, "$");
|
||||
name[nameend] = '\0';
|
||||
val = interpolate_var(name, pset);
|
||||
if (val)
|
||||
strncpy(buf, val, MAX_PROMPT_SIZE);
|
||||
free(name);
|
||||
p += nameend+1;
|
||||
p += nameend + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -245,12 +264,10 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
|
||||
esc = false;
|
||||
}
|
||||
|
||||
if (!esc) {
|
||||
strncat(destination, buf, MAX_PROMPT_SIZE-strlen(destination));
|
||||
}
|
||||
if (!esc)
|
||||
strncat(destination, buf, MAX_PROMPT_SIZE - strlen(destination));
|
||||
}
|
||||
|
||||
destination[MAX_PROMPT_SIZE] = '\0';
|
||||
return destination;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,8 @@
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
typedef enum _promptStatus {
|
||||
typedef enum _promptStatus
|
||||
{
|
||||
PROMPT_READY,
|
||||
PROMPT_CONTINUE,
|
||||
PROMPT_COMMENT,
|
||||
@ -13,7 +14,7 @@ typedef enum _promptStatus {
|
||||
} promptStatus_t;
|
||||
|
||||
const char *
|
||||
get_prompt(PsqlSettings *pset, promptStatus_t status);
|
||||
get_prompt(PsqlSettings *pset, promptStatus_t status);
|
||||
|
||||
|
||||
#endif /* PROMPT_H */
|
||||
|
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
|
||||
*
|
||||
* $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\
|
||||
\tor\n\
|
||||
\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 */
|
||||
|
||||
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 useHistory;
|
||||
bool getPassword; /* prompt the user for a username and
|
||||
password */
|
||||
FILE * cur_cmd_source; /* describe the status of the current main loop */
|
||||
* password */
|
||||
FILE *cur_cmd_source; /* describe the status of the current main
|
||||
* loop */
|
||||
bool cur_cmd_interactive;
|
||||
|
||||
bool has_client_encoding; /* was PGCLIENTENCODING set on startup? */
|
||||
bool has_client_encoding; /* was PGCLIENTENCODING set on
|
||||
* startup? */
|
||||
} PsqlSettings;
|
||||
|
||||
|
||||
|
@ -14,244 +14,244 @@ struct _helpStruct
|
||||
|
||||
|
||||
static struct _helpStruct QL_HELP[] = {
|
||||
{ "TRUNCATE",
|
||||
{"TRUNCATE",
|
||||
"Empty a table",
|
||||
"TRUNCATE [ TABLE ] name" },
|
||||
"TRUNCATE [ TABLE ] name"},
|
||||
|
||||
{ "ABORT",
|
||||
{"ABORT",
|
||||
"Aborts the current transaction",
|
||||
"ABORT [ WORK | TRANSACTION ]" },
|
||||
"ABORT [ WORK | TRANSACTION ]"},
|
||||
|
||||
{ "ALTER TABLE",
|
||||
{"ALTER TABLE",
|
||||
"Modifies table properties",
|
||||
"ALTER TABLE table\n [ * ] ADD [ COLUMN ] ER\">coBLE> type\nALTER TABLE table\n [ * ] RENAME [ COLUMN ] ER\">coBLE> TO newcolumn\nALTER TABLE table\n RENAME TO newtable" },
|
||||
"ALTER TABLE table\n [ * ] ADD [ COLUMN ] ER\">coBLE> type\nALTER TABLE table\n [ * ] RENAME [ COLUMN ] ER\">coBLE> TO newcolumn\nALTER TABLE table\n RENAME TO newtable"},
|
||||
|
||||
{ "ALTER USER",
|
||||
{"ALTER USER",
|
||||
"Modifies user account information",
|
||||
"ALTER USER username [ WITH PASSWORD password ]\n [ CREATEDB | NOCREATEDB ] [ CREATEUSER | NOCREATEUSER ]\n [ IN GROUP groupname [, ...] ]\n [ VALID UNTIL 'abstime' ]" },
|
||||
"ALTER USER username [ WITH PASSWORD password ]\n [ CREATEDB | NOCREATEDB ] [ CREATEUSER | NOCREATEUSER ]\n [ IN GROUP groupname [, ...] ]\n [ VALID UNTIL 'abstime' ]"},
|
||||
|
||||
{ "BEGIN",
|
||||
{"BEGIN",
|
||||
"Begins a transaction in chained mode",
|
||||
"BEGIN [ WORK | TRANSACTION ]" },
|
||||
"BEGIN [ WORK | TRANSACTION ]"},
|
||||
|
||||
{ "CLOSE",
|
||||
{"CLOSE",
|
||||
"Close a cursor",
|
||||
"CLOSE cursor" },
|
||||
"CLOSE cursor"},
|
||||
|
||||
{ "CLUSTER",
|
||||
{"CLUSTER",
|
||||
"Gives storage clustering advice to the server",
|
||||
"CLUSTER indexname ON table" },
|
||||
"CLUSTER indexname ON table"},
|
||||
|
||||
{ "COMMIT",
|
||||
{"COMMIT",
|
||||
"Commits the current transaction",
|
||||
"COMMIT [ WORK | TRANSACTION ]" },
|
||||
"COMMIT [ WORK | TRANSACTION ]"},
|
||||
|
||||
{ "COPY",
|
||||
{"COPY",
|
||||
"Copies data between files and tables",
|
||||
"COPY [ BINARY ] table [ WITH OIDS ]\n FROM { 'filename' | stdin }\n [ [USING] DELIMITERS 'delimiter' ]\nCOPY [ BINARY ] table [ WITH OIDS ]\n TO { 'filename' | stdout }\n [ [USING] DELIMITERS 'delimiter' ]" },
|
||||
"COPY [ BINARY ] table [ WITH OIDS ]\n FROM { 'filename' | stdin }\n [ [USING] DELIMITERS 'delimiter' ]\nCOPY [ BINARY ] table [ WITH OIDS ]\n TO { 'filename' | stdout }\n [ [USING] DELIMITERS 'delimiter' ]"},
|
||||
|
||||
{ "CREATE AGGREGATE",
|
||||
{"CREATE AGGREGATE",
|
||||
"Defines a new aggregate function",
|
||||
"CREATE AGGREGATE name [ AS ] ( BASETYPE = data_type\n [ , SFUNC1 = sfunc1, STYPE1 = sfunc1_return_type ]\n [ , SFUNC2 = sfunc2, STYPE2 = sfunc2_return_type ]\n [ , FINALFUNC = ffunc ]\n [ , INITCOND1 = initial_condition1 ]\n [ , INITCOND2 = initial_condition2 ] )" },
|
||||
"CREATE AGGREGATE name [ AS ] ( BASETYPE = data_type\n [ , SFUNC1 = sfunc1, STYPE1 = sfunc1_return_type ]\n [ , SFUNC2 = sfunc2, STYPE2 = sfunc2_return_type ]\n [ , FINALFUNC = ffunc ]\n [ , INITCOND1 = initial_condition1 ]\n [ , INITCOND2 = initial_condition2 ] )"},
|
||||
|
||||
{ "CREATE DATABASE",
|
||||
{"CREATE DATABASE",
|
||||
"Creates a new database",
|
||||
"CREATE DATABASE name [ WITH LOCATION = 'dbpath' ]" },
|
||||
"CREATE DATABASE name [ WITH LOCATION = 'dbpath' ]"},
|
||||
|
||||
{ "CREATE FUNCTION",
|
||||
{"CREATE FUNCTION",
|
||||
"Defines a new function",
|
||||
"CREATE FUNCTION name ( [ ftype [, ...] ] )\n RETURNS rtype\n [ WITH ( attribute [, ...] ) ]\n AS definition \n LANGUAGE 'langname'\n\n\nCREATE FUNCTION name ( [ ftype [, ...] ] )\n RETURNS rtype\n [ WITH ( attribute [, ...] ) ]\n AS obj_file , link_symbol \n LANGUAGE 'C'" },
|
||||
"CREATE FUNCTION name ( [ ftype [, ...] ] )\n RETURNS rtype\n [ WITH ( attribute [, ...] ) ]\n AS definition \n LANGUAGE 'langname'\n\n\nCREATE FUNCTION name ( [ ftype [, ...] ] )\n RETURNS rtype\n [ WITH ( attribute [, ...] ) ]\n AS obj_file , link_symbol \n LANGUAGE 'C'"},
|
||||
|
||||
{ "CREATE INDEX",
|
||||
{"CREATE INDEX",
|
||||
"Constructs a secondary index",
|
||||
"CREATE [ UNIQUE ] INDEX index_name ON table\n [ USING acc_name ] ( column [ ops_name] [, ...] )\nCREATE [ UNIQUE ] INDEX index_name ON table\n [ USING acc_name ] ( func_name( r\">colle> [, ... ]) ops_name )" },
|
||||
"CREATE [ UNIQUE ] INDEX index_name ON table\n [ USING acc_name ] ( column [ ops_name] [, ...] )\nCREATE [ UNIQUE ] INDEX index_name ON table\n [ USING acc_name ] ( func_name( r\">colle> [, ... ]) ops_name )"},
|
||||
|
||||
{ "CREATE LANGUAGE",
|
||||
{"CREATE LANGUAGE",
|
||||
"Defines a new language for functions",
|
||||
"CREATE [ TRUSTED ] PROCEDURAL LANGUAGE 'langname'\n HANDLER call_handler\n LANCOMPILER 'comment'" },
|
||||
"CREATE [ TRUSTED ] PROCEDURAL LANGUAGE 'langname'\n HANDLER call_handler\n LANCOMPILER 'comment'"},
|
||||
|
||||
{ "CREATE OPERATOR",
|
||||
{"CREATE OPERATOR",
|
||||
"Defines a new user operator",
|
||||
"CREATE OPERATOR name ( PROCEDURE = func_name\n [, LEFTARG = type1 ] [, RIGHTARG = type2 ]\n [, COMMUTATOR = com_op ] [, NEGATOR = neg_op ]\n [, RESTRICT = res_proc ] [, JOIN = join_proc ]\n [, HASHES ] [, SORT1 = left_sort_op ] [, SORT2 = right_sort_op ] )" },
|
||||
"CREATE OPERATOR name ( PROCEDURE = func_name\n [, LEFTARG = type1 ] [, RIGHTARG = type2 ]\n [, COMMUTATOR = com_op ] [, NEGATOR = neg_op ]\n [, RESTRICT = res_proc ] [, JOIN = join_proc ]\n [, HASHES ] [, SORT1 = left_sort_op ] [, SORT2 = right_sort_op ] )"},
|
||||
|
||||
{ "CREATE RULE",
|
||||
{"CREATE RULE",
|
||||
"Defines a new rule",
|
||||
"CREATE RULE name AS ON event\n TO object [ WHERE condition ]\n DO [ INSTEAD ] [ action | NOTHING ]" },
|
||||
"CREATE RULE name AS ON event\n TO object [ WHERE condition ]\n DO [ INSTEAD ] [ action | NOTHING ]"},
|
||||
|
||||
{ "CREATE SEQUENCE",
|
||||
{"CREATE SEQUENCE",
|
||||
"Creates a new sequence number generator",
|
||||
"CREATE SEQUENCE seqname [ INCREMENT increment ]\n [ MINVALUE minvalue ] [ MAXVALUE maxvalue ]\n [ START start ] [ CACHE cache ] [ CYCLE ]" },
|
||||
"CREATE SEQUENCE seqname [ INCREMENT increment ]\n [ MINVALUE minvalue ] [ MAXVALUE maxvalue ]\n [ START start ] [ CACHE cache ] [ CYCLE ]"},
|
||||
|
||||
{ "CREATE TABLE",
|
||||
{"CREATE TABLE",
|
||||
"Creates a new table",
|
||||
"CREATE [ TEMPORARY | TEMP ] TABLE table (\n column type\n [ NULL | NOT NULL ] [ UNIQUE ] [ DEFAULT value ]\n [column_constraint_clause | PRIMARY KEY } [ ... ] ]\n [, ... ]\n [, PRIMARY KEY ( column [, ...] ) ]\n [, CHECK ( condition ) ]\n [, table_constraint_clause ]\n ) [ INHERITS ( inherited_table [, ...] ) ]" },
|
||||
"CREATE [ TEMPORARY | TEMP ] TABLE table (\n column type\n [ NULL | NOT NULL ] [ UNIQUE ] [ DEFAULT value ]\n [column_constraint_clause | PRIMARY KEY } [ ... ] ]\n [, ... ]\n [, PRIMARY KEY ( column [, ...] ) ]\n [, CHECK ( condition ) ]\n [, table_constraint_clause ]\n ) [ INHERITS ( inherited_table [, ...] ) ]"},
|
||||
|
||||
{ "CREATE TABLE AS",
|
||||
{"CREATE TABLE AS",
|
||||
"Creates a new table",
|
||||
"CREATE TABLE table [ (column [, ...] ) ]\n AS select_clause" },
|
||||
"CREATE TABLE table [ (column [, ...] ) ]\n AS select_clause"},
|
||||
|
||||
{ "CREATE TRIGGER",
|
||||
{"CREATE TRIGGER",
|
||||
"Creates a new trigger",
|
||||
"CREATE TRIGGER name { BEFORE | AFTER } { event [OR ...] }\n ON table FOR EACH { ROW | STATEMENT }\n EXECUTE PROCEDURE ER\">funcBLE> ( arguments )" },
|
||||
"CREATE TRIGGER name { BEFORE | AFTER } { event [OR ...] }\n ON table FOR EACH { ROW | STATEMENT }\n EXECUTE PROCEDURE ER\">funcBLE> ( arguments )"},
|
||||
|
||||
{ "CREATE TYPE",
|
||||
{"CREATE TYPE",
|
||||
"Defines a new base data type",
|
||||
"CREATE TYPE typename ( INPUT = input_function, OUTPUT = output_function\n , INTERNALLENGTH = { internallength | VARIABLE } [ , EXTERNALLENGTH = { externallength | VARIABLE } ]\n [ , DEFAULT = \"default\" ]\n [ , ELEMENT = element ] [ , DELIMITER = delimiter ]\n [ , SEND = send_function ] [ , RECEIVE = receive_function ]\n [ , PASSEDBYVALUE ] )" },
|
||||
"CREATE TYPE typename ( INPUT = input_function, OUTPUT = output_function\n , INTERNALLENGTH = { internallength | VARIABLE } [ , EXTERNALLENGTH = { externallength | VARIABLE } ]\n [ , DEFAULT = \"default\" ]\n [ , ELEMENT = element ] [ , DELIMITER = delimiter ]\n [ , SEND = send_function ] [ , RECEIVE = receive_function ]\n [ , PASSEDBYVALUE ] )"},
|
||||
|
||||
{ "CREATE USER",
|
||||
{"CREATE USER",
|
||||
"Creates account information for a new user",
|
||||
"CREATE USER username\n [ WITH PASSWORD password ]\n [ CREATEDB | NOCREATEDB ] [ CREATEUSER | NOCREATEUSER ]\n [ IN GROUP groupname [, ...] ]\n [ VALID UNTIL 'abstime' ]" },
|
||||
"CREATE USER username\n [ WITH PASSWORD password ]\n [ CREATEDB | NOCREATEDB ] [ CREATEUSER | NOCREATEUSER ]\n [ IN GROUP groupname [, ...] ]\n [ VALID UNTIL 'abstime' ]"},
|
||||
|
||||
{ "CREATE VIEW",
|
||||
{"CREATE VIEW",
|
||||
"Constructs a virtual table",
|
||||
"CREATE VIEW view AS SELECT query" },
|
||||
"CREATE VIEW view AS SELECT query"},
|
||||
|
||||
{ "DECLARE",
|
||||
{"DECLARE",
|
||||
"Defines a cursor for table access",
|
||||
"DECLARE cursor [ BINARY ] [ INSENSITIVE ] [ SCROLL ]\n CURSOR FOR query\n [ FOR { READ ONLY | UPDATE [ OF column [, ...] ] ]" },
|
||||
"DECLARE cursor [ BINARY ] [ INSENSITIVE ] [ SCROLL ]\n CURSOR FOR query\n [ FOR { READ ONLY | UPDATE [ OF column [, ...] ] ]"},
|
||||
|
||||
{ "DELETE",
|
||||
{"DELETE",
|
||||
"Removes rows from a table",
|
||||
"DELETE FROM table [ WHERE condition ]" },
|
||||
"DELETE FROM table [ WHERE condition ]"},
|
||||
|
||||
{ "DROP AGGREGATE",
|
||||
{"DROP AGGREGATE",
|
||||
"Removes the definition of an aggregate function",
|
||||
"DROP AGGREGATE name type" },
|
||||
"DROP AGGREGATE name type"},
|
||||
|
||||
{ "FETCH",
|
||||
{"FETCH",
|
||||
"Gets rows using a cursor",
|
||||
"FETCH [ selector ] [ count ] { IN | FROM } cursor\nFETCH [ RELATIVE ] [ { [ # | ALL | NEXT | PRIOR ] } ] FROM ] cursor" },
|
||||
"FETCH [ selector ] [ count ] { IN | FROM } cursor\nFETCH [ RELATIVE ] [ { [ # | ALL | NEXT | PRIOR ] } ] FROM ] cursor"},
|
||||
|
||||
{ "DROP DATABASE",
|
||||
{"DROP DATABASE",
|
||||
"Destroys an existing database",
|
||||
"DROP DATABASE name" },
|
||||
"DROP DATABASE name"},
|
||||
|
||||
{ "DROP FUNCTION",
|
||||
{"DROP FUNCTION",
|
||||
"Removes a user-defined C function",
|
||||
"DROP FUNCTION name ( [ type [, ...] ] )" },
|
||||
"DROP FUNCTION name ( [ type [, ...] ] )"},
|
||||
|
||||
{ "DROP INDEX",
|
||||
{"DROP INDEX",
|
||||
"Removes an index from a database",
|
||||
"DROP INDEX index_name" },
|
||||
"DROP INDEX index_name"},
|
||||
|
||||
{ "DROP LANGUAGE",
|
||||
{"DROP LANGUAGE",
|
||||
"Removes a user-defined procedural language",
|
||||
"DROP PROCEDURAL LANGUAGE 'name'" },
|
||||
"DROP PROCEDURAL LANGUAGE 'name'"},
|
||||
|
||||
{ "DROP OPERATOR",
|
||||
{"DROP OPERATOR",
|
||||
"Removes an operator from the database",
|
||||
"DROP OPERATOR id ( type | NONE [,...] )" },
|
||||
"DROP OPERATOR id ( type | NONE [,...] )"},
|
||||
|
||||
{ "DROP RULE",
|
||||
{"DROP RULE",
|
||||
"Removes an existing rule from the database",
|
||||
"DROP RULE name" },
|
||||
"DROP RULE name"},
|
||||
|
||||
{ "DROP SEQUENCE",
|
||||
{"DROP SEQUENCE",
|
||||
"Removes an existing sequence",
|
||||
"DROP SEQUENCE name [, ...]" },
|
||||
"DROP SEQUENCE name [, ...]"},
|
||||
|
||||
{ "DROP TABLE",
|
||||
{"DROP TABLE",
|
||||
"Removes existing tables from a database",
|
||||
"DROP TABLE name [, ...]" },
|
||||
"DROP TABLE name [, ...]"},
|
||||
|
||||
{ "DROP TRIGGER",
|
||||
{"DROP TRIGGER",
|
||||
"Removes the definition of a trigger",
|
||||
"DROP TRIGGER name ON table" },
|
||||
"DROP TRIGGER name ON table"},
|
||||
|
||||
{ "DROP TYPE",
|
||||
{"DROP TYPE",
|
||||
"Removes a user-defined type from the system catalogs",
|
||||
"DROP TYPE typename" },
|
||||
"DROP TYPE typename"},
|
||||
|
||||
{ "DROP USER",
|
||||
{"DROP USER",
|
||||
"Removes an user account information",
|
||||
"DROP USER name" },
|
||||
"DROP USER name"},
|
||||
|
||||
{ "DROP VIEW",
|
||||
{"DROP VIEW",
|
||||
"Removes an existing view from a database",
|
||||
"DROP VIEW name" },
|
||||
"DROP VIEW name"},
|
||||
|
||||
{ "EXPLAIN",
|
||||
{"EXPLAIN",
|
||||
"Shows statement execution details",
|
||||
"EXPLAIN [ VERBOSE ] query" },
|
||||
"EXPLAIN [ VERBOSE ] query"},
|
||||
|
||||
{ "GRANT",
|
||||
{"GRANT",
|
||||
"Grants access privilege to a user, a group or all users",
|
||||
"GRANT privilege [, ...] ON object [, ...]\n TO { PUBLIC | GROUP group | username }" },
|
||||
"GRANT privilege [, ...] ON object [, ...]\n TO { PUBLIC | GROUP group | username }"},
|
||||
|
||||
{ "INSERT",
|
||||
{"INSERT",
|
||||
"Inserts new rows into a table",
|
||||
"INSERT INTO table [ ( column [, ...] ) ]\n { VALUES ( expression [, ...] ) | SELECT query }" },
|
||||
"INSERT INTO table [ ( column [, ...] ) ]\n { VALUES ( expression [, ...] ) | SELECT query }"},
|
||||
|
||||
{ "LISTEN",
|
||||
{"LISTEN",
|
||||
"Listen for a response on a notify condition",
|
||||
"LISTEN name" },
|
||||
"LISTEN name"},
|
||||
|
||||
{ "LOAD",
|
||||
{"LOAD",
|
||||
"Dynamically loads an object file",
|
||||
"LOAD 'filename'" },
|
||||
"LOAD 'filename'"},
|
||||
|
||||
{ "LOCK",
|
||||
{"LOCK",
|
||||
"Explicitly lock a table inside a transaction",
|
||||
"LOCK [ TABLE ] name\nLOCK [ TABLE ] name IN [ ROW | ACCESS ] { SHARE | EXCLUSIVE } MODE\nLOCK [ TABLE ] name IN SHARE ROW EXCLUSIVE MODE" },
|
||||
"LOCK [ TABLE ] name\nLOCK [ TABLE ] name IN [ ROW | ACCESS ] { SHARE | EXCLUSIVE } MODE\nLOCK [ TABLE ] name IN SHARE ROW EXCLUSIVE MODE"},
|
||||
|
||||
{ "MOVE",
|
||||
{"MOVE",
|
||||
"Moves cursor position",
|
||||
"MOVE [ selector ] [ count ] \n { IN | FROM } cursor\n FETCH [ RELATIVE ] [ { [ # | ALL | NEXT | PRIOR ] } ] FROM ] cursor" },
|
||||
"MOVE [ selector ] [ count ] \n { IN | FROM } cursor\n FETCH [ RELATIVE ] [ { [ # | ALL | NEXT | PRIOR ] } ] FROM ] cursor"},
|
||||
|
||||
{ "NOTIFY",
|
||||
{"NOTIFY",
|
||||
"Signals all frontends and backends listening on a notify condition",
|
||||
"NOTIFY name" },
|
||||
"NOTIFY name"},
|
||||
|
||||
{ "RESET",
|
||||
{"RESET",
|
||||
"Restores run-time parameters for session to default values",
|
||||
"RESET variable" },
|
||||
"RESET variable"},
|
||||
|
||||
{ "REVOKE",
|
||||
{"REVOKE",
|
||||
"Revokes access privilege from a user, a group or all users.",
|
||||
"REVOKE privilege [, ...]\n ON object [, ...]\n FROM { PUBLIC | GROUP ER\">gBLE> | username }" },
|
||||
"REVOKE privilege [, ...]\n ON object [, ...]\n FROM { PUBLIC | GROUP ER\">gBLE> | username }"},
|
||||
|
||||
{ "ROLLBACK",
|
||||
{"ROLLBACK",
|
||||
"Aborts the current transaction",
|
||||
"ROLLBACK [ WORK | TRANSACTION ]" },
|
||||
"ROLLBACK [ WORK | TRANSACTION ]"},
|
||||
|
||||
{ "SELECT",
|
||||
{"SELECT",
|
||||
"Retrieve rows from a table or view.",
|
||||
"SELECT [ ALL | DISTINCT [ ON column ] ]\n expression [ AS name ] [, ...]\n [ INTO [ TEMPORARY | TEMP ] [ TABLE ] new_table ]\n [ FROM table [ alias ] [, ...] ]\n [ WHERE condition ]\n [ GROUP BY column [, ...] ]\n [ HAVING condition [, ...] ]\n [ { UNION [ ALL ] | INTERSECT | EXCEPT } select ]\n [ ORDER BY column [ ASC | DESC ] [, ...] ]\n [ FOR UPDATE [ OF class_name... ] ]\n [ LIMIT { count | ALL } [ { OFFSET | , } count ] ]" },
|
||||
"SELECT [ ALL | DISTINCT [ ON column ] ]\n expression [ AS name ] [, ...]\n [ INTO [ TEMPORARY | TEMP ] [ TABLE ] new_table ]\n [ FROM table [ alias ] [, ...] ]\n [ WHERE condition ]\n [ GROUP BY column [, ...] ]\n [ HAVING condition [, ...] ]\n [ { UNION [ ALL ] | INTERSECT | EXCEPT } select ]\n [ ORDER BY column [ ASC | DESC ] [, ...] ]\n [ FOR UPDATE [ OF class_name... ] ]\n [ LIMIT { count | ALL } [ { OFFSET | , } count ] ]"},
|
||||
|
||||
{ "SELECT INTO",
|
||||
{"SELECT INTO",
|
||||
"Create a new table from an existing table or view",
|
||||
"SELECT [ ALL | DISTINCT ] expression [ AS name ] [, ...]\n INTO [TEMP] [ TABLE ] new_table ]\n [ FROM table [alias] [, ...] ]\n [ WHERE condition ]\n [ GROUP BY column [, ...] ]\n [ HAVING condition [, ...] ]\n [ { UNION [ALL] | INTERSECT | EXCEPT } select]\n [ ORDER BY column [ ASC | DESC ] [, ...] ]\n [ FOR UPDATE [OF class_name...]]\n [ LIMIT count [OFFSET|, count]]" },
|
||||
"SELECT [ ALL | DISTINCT ] expression [ AS name ] [, ...]\n INTO [TEMP] [ TABLE ] new_table ]\n [ FROM table [alias] [, ...] ]\n [ WHERE condition ]\n [ GROUP BY column [, ...] ]\n [ HAVING condition [, ...] ]\n [ { UNION [ALL] | INTERSECT | EXCEPT } select]\n [ ORDER BY column [ ASC | DESC ] [, ...] ]\n [ FOR UPDATE [OF class_name...]]\n [ LIMIT count [OFFSET|, count]]"},
|
||||
|
||||
{ "SET",
|
||||
{"SET",
|
||||
"Set run-time parameters for session",
|
||||
"SET variable { TO | = } { 'value' | DEFAULT }\nSET TIME ZONE { 'timezone' | LOCAL | DEFAULT }\nSET TRANSACTION ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE }" },
|
||||
"SET variable { TO | = } { 'value' | DEFAULT }\nSET TIME ZONE { 'timezone' | LOCAL | DEFAULT }\nSET TRANSACTION ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE }"},
|
||||
|
||||
{ "SHOW",
|
||||
{"SHOW",
|
||||
"Shows run-time parameters for session",
|
||||
"SHOW keyword" },
|
||||
"SHOW keyword"},
|
||||
|
||||
{ "UNLISTEN",
|
||||
{"UNLISTEN",
|
||||
"Stop listening for notification",
|
||||
"UNLISTEN { notifyname | * }" },
|
||||
"UNLISTEN { notifyname | * }"},
|
||||
|
||||
{ "UPDATE",
|
||||
{"UPDATE",
|
||||
"Replaces values of columns in a table",
|
||||
"UPDATE table SET R\">colle> = expression [, ...]\n [ FROM fromlist ]\n [ WHERE condition ]" },
|
||||
"UPDATE table SET R\">colle> = expression [, ...]\n [ FROM fromlist ]\n [ WHERE condition ]"},
|
||||
|
||||
{ "VACUUM",
|
||||
{"VACUUM",
|
||||
"Clean and analyze a Postgres database",
|
||||
"VACUUM [ VERBOSE ] [ ANALYZE ] [ table ]\nVACUUM [ VERBOSE ] ANALYZE [ ER\">tBLE> [ (column [, ...] ) ] ]" },
|
||||
"VACUUM [ VERBOSE ] [ ANALYZE ] [ table ]\nVACUUM [ VERBOSE ] ANALYZE [ ER\">tBLE> [ (column [, ...] ) ] ]"},
|
||||
|
||||
{ "END",
|
||||
{"END",
|
||||
"Commits the current transaction",
|
||||
"END [ WORK | TRANSACTION ]" },
|
||||
"END [ WORK | TRANSACTION ]"},
|
||||
|
||||
{ "COMMENT",
|
||||
{"COMMENT",
|
||||
"Add comment to an object",
|
||||
"COMMENT ON\n[\n [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]\n object_name |\n COLUMN table_name.column_name|\n AGGREGATE agg_name agg_type|\n FUNCTION func_name (arg1, arg2, ...)|\n OPERATOR op (leftoperand_type rightoperand_type) |\n TRIGGER trigger_name ON table_name\n] IS 'text'" },
|
||||
"COMMENT ON\n[\n [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]\n object_name |\n COLUMN table_name.column_name|\n AGGREGATE agg_name agg_type|\n FUNCTION func_name (arg1, arg2, ...)|\n OPERATOR op (leftoperand_type rightoperand_type) |\n TRIGGER trigger_name ON table_name\n] IS 'text'"},
|
||||
|
||||
|
||||
{ NULL, NULL, NULL } /* End of list marker */
|
||||
{NULL, NULL, NULL} /* End of list marker */
|
||||
};
|
||||
|
||||
#endif /* SQL_HELP_H */
|
||||
|
@ -37,16 +37,18 @@
|
||||
|
||||
|
||||
static void
|
||||
process_psqlrc(PsqlSettings * pset);
|
||||
process_psqlrc(PsqlSettings *pset);
|
||||
|
||||
static void
|
||||
showVersion(PsqlSettings *pset, bool verbose);
|
||||
showVersion(PsqlSettings *pset, bool verbose);
|
||||
|
||||
|
||||
/* Structures to pass information between the option parsing routine
|
||||
* and the main function
|
||||
*/
|
||||
enum _actions { ACT_NOTHING = 0,
|
||||
enum _actions
|
||||
{
|
||||
ACT_NOTHING = 0,
|
||||
ACT_SINGLE_SLASH,
|
||||
ACT_LIST_DB,
|
||||
ACT_SHOW_VER,
|
||||
@ -54,18 +56,19 @@ enum _actions { ACT_NOTHING = 0,
|
||||
ACT_FILE
|
||||
};
|
||||
|
||||
struct adhoc_opts {
|
||||
char * dbname;
|
||||
char * host;
|
||||
char * port;
|
||||
char * username;
|
||||
struct adhoc_opts
|
||||
{
|
||||
char *dbname;
|
||||
char *host;
|
||||
char *port;
|
||||
char *username;
|
||||
enum _actions action;
|
||||
char * action_string;
|
||||
char *action_string;
|
||||
bool no_readline;
|
||||
};
|
||||
|
||||
static void
|
||||
parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * options);
|
||||
parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * options);
|
||||
|
||||
|
||||
|
||||
@ -81,8 +84,8 @@ main(int argc, char **argv)
|
||||
struct adhoc_opts options;
|
||||
int successResult;
|
||||
|
||||
char * username = NULL;
|
||||
char * password = NULL;
|
||||
char *username = NULL;
|
||||
char *password = NULL;
|
||||
bool need_pass;
|
||||
|
||||
MemSet(&settings, 0, sizeof settings);
|
||||
@ -115,11 +118,12 @@ main(int argc, char **argv)
|
||||
|
||||
parse_options(argc, argv, &settings, &options);
|
||||
|
||||
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";
|
||||
|
||||
if (options.username) {
|
||||
if (strcmp(options.username, "?")==0)
|
||||
if (options.username)
|
||||
{
|
||||
if (strcmp(options.username, "?") == 0)
|
||||
username = simple_prompt("Username: ", 100, true);
|
||||
else
|
||||
username = strdup(options.username);
|
||||
@ -129,12 +133,14 @@ main(int argc, char **argv)
|
||||
password = simple_prompt("Password: ", 100, false);
|
||||
|
||||
/* loop until we have a password if requested by backend */
|
||||
do {
|
||||
do
|
||||
{
|
||||
need_pass = false;
|
||||
settings.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.dbname, username, password);
|
||||
|
||||
if (PQstatus(settings.db)==CONNECTION_BAD &&
|
||||
strcmp(PQerrorMessage(settings.db), "fe_sendauth: no password supplied\n")==0) {
|
||||
if (PQstatus(settings.db) == CONNECTION_BAD &&
|
||||
strcmp(PQerrorMessage(settings.db), "fe_sendauth: no password supplied\n") == 0)
|
||||
{
|
||||
need_pass = true;
|
||||
free(password);
|
||||
password = NULL;
|
||||
@ -145,22 +151,26 @@ main(int argc, char **argv)
|
||||
free(username);
|
||||
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));
|
||||
PQfinish(settings.db);
|
||||
exit(EXIT_BADCONN);
|
||||
}
|
||||
|
||||
if (options.action == ACT_LIST_DB) {
|
||||
if (options.action == ACT_LIST_DB)
|
||||
{
|
||||
int success = listAllDbs(&settings);
|
||||
|
||||
PQfinish(settings.db);
|
||||
exit (!success);
|
||||
exit(!success);
|
||||
}
|
||||
|
||||
if (options.action == ACT_SHOW_VER) {
|
||||
if (options.action == ACT_SHOW_VER)
|
||||
{
|
||||
showVersion(&settings, true);
|
||||
PQfinish(settings.db);
|
||||
exit (EXIT_SUCCESS);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
@ -169,7 +179,7 @@ main(int argc, char **argv)
|
||||
puts("Welcome to psql, the PostgreSQL interactive terminal.\n"
|
||||
"(Please type \\copyright to see the distribution terms of PostgreSQL.)");
|
||||
|
||||
// showVersion(&settings, false);
|
||||
//showVersion(&settings, false);
|
||||
|
||||
puts("\n"
|
||||
"Type \\h for help with SQL commands,\n"
|
||||
@ -215,46 +225,48 @@ main(int argc, char **argv)
|
||||
#ifdef WIN32
|
||||
/* getopt is not in the standard includes on Win32 */
|
||||
int getopt(int, char *const[], const char *);
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * options)
|
||||
parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * options)
|
||||
{
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static struct option long_options[] = {
|
||||
{ "no-align", no_argument, NULL, 'A' },
|
||||
{ "command", required_argument, NULL, 'c' },
|
||||
{ "database", required_argument, NULL, 'd' },
|
||||
{ "dbname", required_argument, NULL, 'd' },
|
||||
{ "echo", no_argument, NULL, 'e' },
|
||||
{ "echo-queries", no_argument, NULL, 'e' },
|
||||
{ "echo-all", no_argument, NULL, 'E' },
|
||||
{ "echo-all-queries", no_argument, NULL, 'E' },
|
||||
{ "file", required_argument, NULL, 'f' },
|
||||
{ "field-sep", required_argument, NULL, 'F' },
|
||||
{ "host", required_argument, NULL, 'h' },
|
||||
{ "html", no_argument, NULL, 'H' },
|
||||
{ "list", no_argument, NULL, 'l' },
|
||||
{ "no-readline", no_argument, NULL, 'n' },
|
||||
{ "out", required_argument, NULL, 'o' },
|
||||
{ "to-file", required_argument, NULL, 'o' },
|
||||
{ "port", required_argument, NULL, 'p' },
|
||||
{ "pset", required_argument, NULL, 'P' },
|
||||
{ "quiet", no_argument, NULL, 'q' },
|
||||
{ "single-step", no_argument, NULL, 's' },
|
||||
{ "single-line", no_argument, NULL, 'S' },
|
||||
{ "tuples-only", no_argument, NULL, 't' },
|
||||
{ "table-attr", required_argument, NULL, 'T' },
|
||||
{ "username", required_argument, NULL, 'U' },
|
||||
{ "expanded", no_argument, NULL, 'x' },
|
||||
{ "set", required_argument, NULL, 'v' },
|
||||
{ "variable", required_argument, NULL, 'v' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "password", no_argument, NULL, 'W' },
|
||||
{ "help", no_argument, NULL, '?' },
|
||||
{"no-align", no_argument, NULL, 'A'},
|
||||
{"command", required_argument, NULL, 'c'},
|
||||
{"database", required_argument, NULL, 'd'},
|
||||
{"dbname", required_argument, NULL, 'd'},
|
||||
{"echo", no_argument, NULL, 'e'},
|
||||
{"echo-queries", no_argument, NULL, 'e'},
|
||||
{"echo-all", no_argument, NULL, 'E'},
|
||||
{"echo-all-queries", no_argument, NULL, 'E'},
|
||||
{"file", required_argument, NULL, 'f'},
|
||||
{"field-sep", required_argument, NULL, 'F'},
|
||||
{"host", required_argument, NULL, 'h'},
|
||||
{"html", no_argument, NULL, 'H'},
|
||||
{"list", no_argument, NULL, 'l'},
|
||||
{"no-readline", no_argument, NULL, 'n'},
|
||||
{"out", required_argument, NULL, 'o'},
|
||||
{"to-file", required_argument, NULL, 'o'},
|
||||
{"port", required_argument, NULL, 'p'},
|
||||
{"pset", required_argument, NULL, 'P'},
|
||||
{"quiet", no_argument, NULL, 'q'},
|
||||
{"single-step", no_argument, NULL, 's'},
|
||||
{"single-line", no_argument, NULL, 'S'},
|
||||
{"tuples-only", no_argument, NULL, 't'},
|
||||
{"table-attr", required_argument, NULL, 'T'},
|
||||
{"username", required_argument, NULL, 'U'},
|
||||
{"expanded", no_argument, NULL, 'x'},
|
||||
{"set", required_argument, NULL, 'v'},
|
||||
{"variable", required_argument, NULL, 'v'},
|
||||
{"version", no_argument, NULL, 'V'},
|
||||
{"password", no_argument, NULL, 'W'},
|
||||
{"help", no_argument, NULL, '?'},
|
||||
};
|
||||
|
||||
int optindex;
|
||||
|
||||
#endif
|
||||
|
||||
extern char *optarg;
|
||||
@ -266,7 +278,11 @@ parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * o
|
||||
#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)
|
||||
#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)
|
||||
#endif
|
||||
{
|
||||
@ -326,12 +342,14 @@ parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * o
|
||||
equal_loc = strchr(value, '=');
|
||||
if (!equal_loc)
|
||||
result = do_pset(value, NULL, &pset->popt, true);
|
||||
else {
|
||||
else
|
||||
{
|
||||
*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);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -371,15 +389,19 @@ parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * o
|
||||
|
||||
value = xstrdup(optarg);
|
||||
equal_loc = strchr(value, '=');
|
||||
if (!equal_loc) {
|
||||
if (!DeleteVariable(pset->vars, value)) {
|
||||
if (!equal_loc)
|
||||
{
|
||||
if (!DeleteVariable(pset->vars, value))
|
||||
{
|
||||
fprintf(stderr, "Couldn't delete variable %s.\n", value);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
*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);
|
||||
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)
|
||||
options->dbname = argv[optind];
|
||||
else if (!options->username)
|
||||
@ -431,35 +457,38 @@ parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * o
|
||||
* Load /etc/psqlrc or .psqlrc file, if found.
|
||||
*/
|
||||
static void
|
||||
process_psqlrc(PsqlSettings * pset)
|
||||
process_psqlrc(PsqlSettings *pset)
|
||||
{
|
||||
char *psqlrc;
|
||||
char * home;
|
||||
char *home;
|
||||
|
||||
#ifdef WIN32
|
||||
#define R_OK 0
|
||||
#endif
|
||||
|
||||
/* System-wide startup file */
|
||||
if (access("/etc/psqlrc-"PG_RELEASE"."PG_VERSION"."PG_SUBVERSION, R_OK) == 0)
|
||||
process_file("/etc/psqlrc-"PG_RELEASE"."PG_VERSION"."PG_SUBVERSION, pset);
|
||||
if (access("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, R_OK) == 0)
|
||||
process_file("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, pset);
|
||||
else if (access("/etc/psqlrc", R_OK) == 0)
|
||||
process_file("/etc/psqlrc", pset);
|
||||
|
||||
/* Look for one in the home dir */
|
||||
home = getenv("HOME");
|
||||
|
||||
if (home) {
|
||||
if (home)
|
||||
{
|
||||
psqlrc = (char *) malloc(strlen(home) + 20);
|
||||
if (!psqlrc) {
|
||||
if (!psqlrc)
|
||||
{
|
||||
perror("malloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
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)
|
||||
process_file(psqlrc, pset);
|
||||
else {
|
||||
else
|
||||
{
|
||||
sprintf(psqlrc, "%s/.psqlrc", home);
|
||||
if (access(psqlrc, R_OK) == 0)
|
||||
process_file(psqlrc, pset);
|
||||
@ -484,31 +513,37 @@ showVersion(PsqlSettings *pset, bool verbose)
|
||||
{
|
||||
PGresult *res;
|
||||
char *versionstr = NULL;
|
||||
long int release = 0, version = 0, subversion = 0;
|
||||
long int release = 0,
|
||||
version = 0,
|
||||
subversion = 0;
|
||||
|
||||
/* get backend version */
|
||||
res = PSQLexec(pset, "SELECT version()");
|
||||
if (PQresultStatus(res) == PGRES_TUPLES_OK)
|
||||
versionstr = PQgetvalue(res, 0, 0);
|
||||
|
||||
if (!verbose) {
|
||||
if (versionstr) puts(versionstr);
|
||||
if (!verbose)
|
||||
{
|
||||
if (versionstr)
|
||||
puts(versionstr);
|
||||
PQclear(res);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strncmp(versionstr, "PostgreSQL ", 11) == 0) {
|
||||
if (strncmp(versionstr, "PostgreSQL ", 11) == 0)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
release = strtol(&versionstr[11], &tmp, 10);
|
||||
version = strtol(tmp+1, &tmp, 10);
|
||||
subversion = strtol(tmp+1, &tmp, 10);
|
||||
version = strtol(tmp + 1, &tmp, 10);
|
||||
subversion = strtol(tmp + 1, &tmp, 10);
|
||||
}
|
||||
|
||||
printf("Server: %s\npsql", versionstr ? versionstr : "(could not connected)");
|
||||
|
||||
if (strcmp(versionstr, PG_VERSION_STR) != 0)
|
||||
printf(&PG_VERSION_STR[strcspn(PG_VERSION_STR, " ")]);
|
||||
printf(" ("__DATE__" "__TIME__")");
|
||||
printf(" (" __DATE__ " " __TIME__ ")");
|
||||
|
||||
#ifdef MULTIBYTE
|
||||
printf(", multibyte");
|
||||
@ -535,7 +570,7 @@ showVersion(PsqlSettings *pset, bool verbose)
|
||||
puts("");
|
||||
|
||||
if (release < 6 || (release == 6 && version < 5))
|
||||
puts ("\nWarning: The server you are connected to is potentially too old for this client\n"
|
||||
puts("\nWarning: The server you are connected to is potentially too old for this client\n"
|
||||
"version. You should ideally be using clients and servers from the same\n"
|
||||
"distribution.");
|
||||
|
||||
|
@ -2,11 +2,13 @@
|
||||
#include <c.h>
|
||||
#include "stringutils.h"
|
||||
|
||||
//#include <ctype.h>
|
||||
//
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
//#include <stdio.h>
|
||||
//
|
||||
#include <stdio.h>
|
||||
|
||||
#include <postgres.h>
|
||||
#ifndef HAVE_STRDUP
|
||||
@ -17,7 +19,7 @@
|
||||
|
||||
|
||||
static void
|
||||
unescape_quotes(char *source, char quote, char escape);
|
||||
unescape_quotes(char *source, char quote, char escape);
|
||||
|
||||
|
||||
/*
|
||||
@ -34,21 +36,26 @@ unescape_quotes(char *source, char quote, char escape);
|
||||
*
|
||||
* 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 *quote,
|
||||
char escape,
|
||||
char * was_quoted,
|
||||
unsigned int * token_pos)
|
||||
char *was_quoted,
|
||||
unsigned int *token_pos)
|
||||
{
|
||||
static char * storage = NULL; /* store the local copy of the users string here */
|
||||
static char * string = NULL; /* pointer into storage where to continue on next call */
|
||||
static char *storage = NULL;/* store the local copy of the users
|
||||
* string here */
|
||||
static char *string = NULL; /* pointer into storage where to continue
|
||||
* on next call */
|
||||
|
||||
/* variously abused variables: */
|
||||
unsigned int offset;
|
||||
char * start;
|
||||
char *start;
|
||||
char *cp = NULL;
|
||||
|
||||
if (s) {
|
||||
if (s)
|
||||
{
|
||||
free(storage);
|
||||
storage = strdup(s);
|
||||
string = storage;
|
||||
@ -61,7 +68,8 @@ char * strtokx(const char *s,
|
||||
offset = strspn(string, delim);
|
||||
|
||||
/* end of string reached */
|
||||
if (string[offset] == '\0') {
|
||||
if (string[offset] == '\0')
|
||||
{
|
||||
/* technically we don't need to free here, but we're nice */
|
||||
free(storage);
|
||||
storage = NULL;
|
||||
@ -73,16 +81,18 @@ char * strtokx(const char *s,
|
||||
if (quote)
|
||||
cp = strchr(quote, string[offset]);
|
||||
|
||||
if (cp) {
|
||||
if (cp)
|
||||
{
|
||||
/* okay, we have a quoting character, now scan for the closer */
|
||||
char *p;
|
||||
start = &string[offset+1];
|
||||
|
||||
start = &string[offset + 1];
|
||||
|
||||
if (token_pos)
|
||||
*token_pos = start - storage;
|
||||
|
||||
for(p = start;
|
||||
*p && (*p != *cp || *(p-1) == escape) ;
|
||||
for (p = start;
|
||||
*p && (*p != *cp || *(p - 1) == escape);
|
||||
#ifdef MULTIBYTE
|
||||
p += PQmblen(p)
|
||||
#else
|
||||
@ -91,20 +101,22 @@ char * strtokx(const char *s,
|
||||
);
|
||||
|
||||
/* not yet end of string? */
|
||||
if (*p != '\0') {
|
||||
if (*p != '\0')
|
||||
{
|
||||
*p = '\0';
|
||||
string = p + 1;
|
||||
if (was_quoted)
|
||||
*was_quoted = *cp;
|
||||
unescape_quotes (start, *cp, escape);
|
||||
unescape_quotes(start, *cp, escape);
|
||||
return start;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
if (was_quoted)
|
||||
*was_quoted = *cp;
|
||||
string = p;
|
||||
|
||||
unescape_quotes (start, *cp, escape);
|
||||
unescape_quotes(start, *cp, escape);
|
||||
return start;
|
||||
}
|
||||
}
|
||||
@ -119,13 +131,15 @@ char * strtokx(const char *s,
|
||||
if (was_quoted)
|
||||
*was_quoted = 0;
|
||||
|
||||
if (start[offset] != '\0') {
|
||||
if (start[offset] != '\0')
|
||||
{
|
||||
start[offset] = '\0';
|
||||
string = &start[offset]+1;
|
||||
string = &start[offset] + 1;
|
||||
|
||||
return start;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
string = &start[offset];
|
||||
return start;
|
||||
}
|
||||
@ -143,14 +157,16 @@ static void
|
||||
unescape_quotes(char *source, char quote, char escape)
|
||||
{
|
||||
char *p;
|
||||
char *destination, *tmp;
|
||||
char *destination,
|
||||
*tmp;
|
||||
|
||||
#ifdef USE_ASSERT_CHECKING
|
||||
assert(source);
|
||||
#endif
|
||||
|
||||
destination = (char *) calloc(1, strlen(source)+1);
|
||||
if (!destination) {
|
||||
destination = (char *) calloc(1, strlen(source) + 1);
|
||||
if (!destination)
|
||||
{
|
||||
perror("calloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -161,15 +177,16 @@ unescape_quotes(char *source, char quote, char escape)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (*p == escape && *(p+1) && quote == *(p+1)) {
|
||||
c = *(p+1);
|
||||
if (*p == escape && *(p + 1) && quote == *(p + 1))
|
||||
{
|
||||
c = *(p + 1);
|
||||
p++;
|
||||
}
|
||||
else
|
||||
c = *p;
|
||||
|
||||
*tmp = c;
|
||||
tmp ++;
|
||||
tmp++;
|
||||
}
|
||||
|
||||
/* Terminating null character */
|
||||
|
@ -3,12 +3,11 @@
|
||||
|
||||
/* The cooler version of strtok() which knows about quotes and doesn't
|
||||
* overwrite your input */
|
||||
extern char *
|
||||
strtokx(const char *s,
|
||||
extern char *strtokx(const char *s,
|
||||
const char *delim,
|
||||
const char *quote,
|
||||
char escape,
|
||||
char * was_quoted,
|
||||
unsigned int * token_pos);
|
||||
char *was_quoted,
|
||||
unsigned int *token_pos);
|
||||
|
||||
#endif /* STRINGUTILS_H */
|
||||
|
@ -6,16 +6,19 @@
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
VariableSpace CreateVariableSpace(void)
|
||||
VariableSpace
|
||||
CreateVariableSpace(void)
|
||||
{
|
||||
struct _variable *ptr;
|
||||
|
||||
ptr = calloc(1, sizeof *ptr);
|
||||
if (!ptr) return NULL;
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
|
||||
ptr->name = strdup("@");
|
||||
ptr->value = strdup("");
|
||||
if (!ptr->name || !ptr->value) {
|
||||
if (!ptr->name || !ptr->value)
|
||||
{
|
||||
free(ptr->name);
|
||||
free(ptr->value);
|
||||
free(ptr);
|
||||
@ -27,21 +30,24 @@ VariableSpace CreateVariableSpace(void)
|
||||
|
||||
|
||||
|
||||
const char * GetVariable(VariableSpace space, const char * name)
|
||||
const char *
|
||||
GetVariable(VariableSpace space, const char *name)
|
||||
{
|
||||
struct _variable *current;
|
||||
|
||||
if (!space)
|
||||
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
|
||||
assert(current->name);
|
||||
assert(current->value);
|
||||
#endif
|
||||
if (strcmp(current->name, name)==0)
|
||||
if (strcmp(current->name, name) == 0)
|
||||
return 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)
|
||||
return false;
|
||||
@ -67,15 +76,18 @@ bool SetVariable(VariableSpace space, const char * name, const char * value)
|
||||
if (!value)
|
||||
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
|
||||
assert(current->name);
|
||||
assert(current->value);
|
||||
#endif
|
||||
if (strcmp(current->name, name)==0) {
|
||||
free (current->value);
|
||||
if (strcmp(current->name, name) == 0)
|
||||
{
|
||||
free(current->value);
|
||||
current->value = strdup(value);
|
||||
return current->value ? true : false;
|
||||
}
|
||||
@ -93,23 +105,28 @@ 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)
|
||||
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
|
||||
assert(current->name);
|
||||
assert(current->value);
|
||||
#endif
|
||||
if (strcmp(current->name, name)==0) {
|
||||
free (current->name);
|
||||
free (current->value);
|
||||
if (strcmp(current->name, name) == 0)
|
||||
{
|
||||
free(current->name);
|
||||
free(current->value);
|
||||
if (previous)
|
||||
previous->next = current->next;
|
||||
free(current);
|
||||
@ -122,7 +139,8 @@ bool DeleteVariable(VariableSpace space, const char * name)
|
||||
|
||||
|
||||
|
||||
void DestroyVariableSpace(VariableSpace space)
|
||||
void
|
||||
DestroyVariableSpace(VariableSpace space)
|
||||
{
|
||||
if (!space)
|
||||
return;
|
||||
|
@ -13,20 +13,21 @@
|
||||
|
||||
#define VALID_VARIABLE_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_"
|
||||
|
||||
struct _variable {
|
||||
char * name;
|
||||
char * value;
|
||||
struct _variable * next;
|
||||
struct _variable
|
||||
{
|
||||
char *name;
|
||||
char *value;
|
||||
struct _variable *next;
|
||||
};
|
||||
|
||||
typedef struct _variable * VariableSpace;
|
||||
typedef struct _variable *VariableSpace;
|
||||
|
||||
|
||||
VariableSpace CreateVariableSpace(void);
|
||||
const char * GetVariable(VariableSpace space, const char * name);
|
||||
bool GetVariableBool(VariableSpace space, const char * name);
|
||||
bool SetVariable(VariableSpace space, const char * name, const char * value);
|
||||
bool DeleteVariable(VariableSpace space, const char * name);
|
||||
const char *GetVariable(VariableSpace space, const char *name);
|
||||
bool GetVariableBool(VariableSpace space, const char *name);
|
||||
bool SetVariable(VariableSpace space, const char *name, const char *value);
|
||||
bool DeleteVariable(VariableSpace space, const char *name);
|
||||
void DestroyVariableSpace(VariableSpace space);
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user