📄 psql.c
字号:
strcat(descbuf, " and pg_class.oid = pg_description.objoid "); if (!(res = PSQLexec(pset, descbuf))) return -1; else if (PQntuples(res) <= 0) { PQclear(res); descbuf[0] = '\0'; strcat(descbuf, "SELECT DISTINCT description "); strcat(descbuf, "FROM pg_type, pg_description "); strcat(descbuf, "WHERE pg_type.typname ~ '^"); strcat(descbuf, object); strcat(descbuf, "' and "); strcat(descbuf, " pg_type.oid = pg_description.objoid "); if (!(res = PSQLexec(pset, descbuf))) return -1; else if (PQntuples(res) <= 0) { PQclear(res); descbuf[0] = '\0'; strcat(descbuf, "SELECT DISTINCT description "); strcat(descbuf, "FROM pg_proc, pg_description "); strcat(descbuf, "WHERE pg_proc.proname ~ '^"); strcat(descbuf, object); strcat(descbuf, "'"); strcat(descbuf, " and pg_proc.oid = pg_description.objoid "); if (!(res = PSQLexec(pset, descbuf))) return -1; else if (PQntuples(res) <= 0) { PQclear(res); descbuf[0] = '\0'; strcat(descbuf, "SELECT DISTINCT description "); strcat(descbuf, "FROM pg_operator, pg_description "); strcat(descbuf, "WHERE pg_operator.oprname ~ '^"); strcat(descbuf, object); strcat(descbuf, "'"); /* operator descriptions are attached to the proc */ strcat(descbuf, " and RegprocToOid(pg_operator.oprcode) = pg_description.objoid "); if (!(res = PSQLexec(pset, descbuf))) return -1; else if (PQntuples(res) <= 0) { PQclear(res); descbuf[0] = '\0'; strcat(descbuf, "SELECT DISTINCT description "); strcat(descbuf, "FROM pg_aggregate, pg_description "); strcat(descbuf, "WHERE pg_aggregate.aggname ~ '^"); strcat(descbuf, object); strcat(descbuf, "'"); strcat(descbuf, " and pg_aggregate.oid = pg_description.objoid "); if (!(res = PSQLexec(pset, descbuf))) return -1; else if (PQntuples(res) <= 0) { PQclear(res); descbuf[0] = '\0'; strcat(descbuf, "SELECT 'no description' as description "); if (!(res = PSQLexec(pset, descbuf))) return -1; } } } } } } PQclear(res); success = SendQuery(pset, descbuf, NULL, NULL); return 0;}typedef char *(*READ_ROUTINE) (char *prompt, FILE *source);/* * gets_noreadline prompt source gets a line of input without calling * readline, the source is ignored */static char *gets_noreadline(char *prompt, FILE *source){ fputs(prompt, stdout); fflush(stdout); return gets_fromFile(prompt, stdin);}/* * gets_readline prompt source the routine to get input from GNU readline(), * the source is ignored the prompt argument is used as the prompting string */static char *gets_readline(char *prompt, FILE *source){ char *s;#ifdef USE_READLINE s = readline(prompt);#else char buf[500]; printf("%s", prompt); s = fgets(buf, 500, stdin);#endif fputc('\r', stdout); fflush(stdout); return s;}/* * gets_fromFile prompt source * * the routine to read from a file, the prompt argument is ignored the source * argument is a FILE * */static char *gets_fromFile(char *prompt, FILE *source){ char *line; line = malloc(MAX_QUERY_BUFFER); /* read up to MAX_QUERY_BUFFER characters */ if (fgets(line, MAX_QUERY_BUFFER, source) == NULL) { free(line); return NULL; } line[MAX_QUERY_BUFFER - 1] = '\0'; /* this is unnecessary, I think */ if (strlen(line) == MAX_QUERY_BUFFER - 1) { fprintf(stderr, "line read exceeds maximum length. Truncating at %d\n", MAX_QUERY_BUFFER - 1); } return line;}/* * SendQuery: send the query string to the backend. * * Return true if the query executed successfully, false otherwise. * * If not NULL, copy_in_stream and copy_out_stream are files to redirect * copy in/out data to. */static boolSendQuery(PsqlSettings *pset, const char *query, FILE *copy_in_stream, FILE *copy_out_stream){ bool success = false; PGresult *results; PGnotify *notify; if (pset->singleStep) fprintf(stdout, "\n**************************************" "*****************************************\n"); if (pset->echoQuery || pset->singleStep) { fprintf(stderr, "QUERY: %s\n", query); fflush(stderr); } if (pset->singleStep) { fprintf(stdout, "\n**************************************" "*****************************************\n"); fflush(stdout); printf("\npress return to continue ..\n"); gets_fromFile("", stdin); } results = PQexec(pset->db, query); if (results == NULL) { fprintf(stderr, "%s", PQerrorMessage(pset->db)); success = false; } else { switch (PQresultStatus(results)) { case PGRES_TUPLES_OK: if (pset->gfname) { PsqlSettings settings_copy = *pset; FILE *fp; settings_copy.queryFout = stdout; fp = setFout(&settings_copy, pset->gfname); if (!fp || fp == stdout) { success = false; break; } PQprint(fp, results, &pset->opt); if (settings_copy.pipe) pclose(fp); else fclose(fp); free(pset->gfname); pset->gfname = NULL; success = true; break; } else { success = true; PQprint(pset->queryFout, results, &(pset->opt)); fflush(pset->queryFout); } break; case PGRES_EMPTY_QUERY: success = true; break; case PGRES_COMMAND_OK: success = true; if (!pset->quiet) printf("%s\n", PQcmdStatus(results)); break; case PGRES_COPY_OUT: if (copy_out_stream) success = handleCopyOut(pset->db, copy_out_stream); else { if (pset->queryFout == stdout && !pset->quiet) printf("Copy command returns...\n"); success = handleCopyOut(pset->db, pset->queryFout); } break; case PGRES_COPY_IN: if (copy_in_stream) success = handleCopyIn(pset->db, false, copy_in_stream); else success = handleCopyIn(pset->db, cur_cmd_interactive && !pset->quiet, cur_cmd_source); break; case PGRES_NONFATAL_ERROR: case PGRES_FATAL_ERROR: case PGRES_BAD_RESPONSE: success = false; fprintf(stderr, "%s", PQerrorMessage(pset->db)); break; } if (PQstatus(pset->db) == CONNECTION_BAD) { fprintf(stderr, "We have lost the connection to the backend, so " "further processing is impossible. " "Terminating.\n"); exit(2); /* we are out'ta here */ } /* check for asynchronous returns */ while ((notify = PQnotifies(pset->db)) != NULL) { fprintf(stderr, "ASYNC NOTIFY of '%s' from backend pid '%d' received\n", notify->relname, notify->be_pid); free(notify); } if (results) PQclear(results); } return success;}static voideditFile(char *fname){ char *editorName; char *sys; editorName = getenv("EDITOR"); if (!editorName) editorName = DEFAULT_EDITOR; sys = malloc(strlen(editorName) + strlen(fname) + 32 + 1); if (!sys) { perror("malloc"); exit(1); } sprintf(sys, "exec '%s' '%s'", editorName, fname); system(sys); free(sys);}static booltoggle(PsqlSettings *pset, bool *sw, char *msg){ *sw = !*sw; if (!pset->quiet) printf("turned %s %s\n", on(*sw), msg); return *sw;}static voidunescape(char *dest, const char *source){ /*----------------------------------------------------------------------------- Return as the string <dest> the value of string <source> with escape sequences turned into the bytes they represent. -----------------------------------------------------------------------------*/ char *p; bool esc; /* Last character we saw was the escape * character (/) */ esc = false; /* Haven't seen escape character yet */ for (p = (char *) source; *p; p++) { char c; /* Our output character */ if (esc) { switch (*p) { case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'f': c = '\f'; break; case '\\': c = '\\'; break; default: c = *p; } esc = false; } else if (*p == '\\') { esc = true; c = ' '; /* meaningless, but compiler doesn't know * that */ } else { c = *p; esc = false; } if (!esc) *dest++ = c; } *dest = '\0'; /* Terminating null character */}static voidparse_slash_copy(const char *args, char *table, const int table_len, char *file, const int file_len, bool *from_p, bool *error_p){ char work_args[200]; /* * A copy of the \copy command arguments, except that we modify it as * we parse to suit our parsing needs. */ char *table_tok, *fromto_tok; strncpy(work_args, args, sizeof(work_args)); work_args[sizeof(work_args) - 1] = '\0'; *error_p = false; /* initial assumption */ table_tok = strtok(work_args, " "); if (table_tok == NULL) { fprintf(stderr, "\\copy needs arguments.\n"); *error_p = true; } else { strncpy(table, table_tok, table_len); file[table_len - 1] = '\0'; fromto_tok = strtok(NULL, " "); if (fromto_tok == NULL) { fprintf(stderr, "'FROM' or 'TO' must follow table name.\n"); *error_p = true; } else { if (strcasecmp(fromto_tok, "from") == 0) *from_p = true; else if (strcasecmp(fromto_tok, "to") == 0) *from_p = false; else { fprintf(stderr, "Unrecognized token found where " "'FROM' or 'TO' expected: '%s'.\n", fromto_tok); *error_p = true; } if (!*error_p) { char *file_tok; file_tok = strtok(NULL, " "); if (file_tok == NULL) { fprintf(stderr, "A file pathname must follow '%s'.\n", fromto_tok); *error_p = true; } else { strncpy(file, file_tok, file_len); file[file_len - 1] = '\0'; if (strtok(NULL, " ") != NULL) { fprintf(stderr, "You have extra tokens after the filename.\n"); *error_p = true; } } } } }}static voiddo_copy(const char *args, PsqlSettings *pset){ /*--------------------------------------------------------------------------- Execute a \copy command (frontend copy). We have to open a file, then submit a COPY query to the backend and either feed it data from the file or route its response into the file. We do a text copy with default (tab) column delimiters. Some day, we should do all the things a backend copy can do. ----------------------------------------------------------------------------*/ char query[200]; /* The COPY command we send to the back end */ bool from; /* The direction of the copy is from a file to a table. */ char file[MAXPATHLEN + 1]; /* The pathname of the file from/to which we copy */ char table[NAMEDATALEN]; /* The name of the table from/to which we copy */ bool syntax_error; /* The \c command has invalid syntax */ FILE *copystream; parse_slash_copy(args, table, sizeof(table), file, sizeof(file), &from, &syntax_error); if (!syntax_error) { strcpy(query, "COPY "); strcat(query, table); if (from) strcat(query, " FROM stdin"); else strcat(query, " TO stdout"); if (from)#ifndef __CYGWIN32__ copystream = fopen(file, "r");#else copystream = fopen(file, "rb");#endif else#ifndef __CYGWIN32__ copystream = fopen(file, "w");#else copystream = fopen(file, "wb");#endif if (copystream == NULL) fprintf(stderr, "Unable to open file %s which to copy, errno = %s (%d).", from ? "from" : "to", strerror(errno), errno); else { bool success;/* The query succeeded at the backend */ success = SendQuery(pset, query, from ? copystream : (FILE *) NULL, !from ? copystream : (FILE *) NULL); fclose(copystream); if (!pset->quiet) { if (success) printf("Successfully copied.\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -