📄 command.c
字号:
break; default: /* not set or unrecognized value */ pset.verbosity = PQERRORS_DEFAULT; break; } PQsetErrorVerbosity(pset.db, pset.verbosity);}/* * do_edit -- handler for \e * * If you do not specify a filename, the current query buffer will be copied * into a temporary one. */static booleditFile(const char *fname){ const char *editorName; char *sys; int result; psql_assert(fname); /* Find an editor to use */ editorName = getenv("PSQL_EDITOR"); if (!editorName) editorName = getenv("EDITOR"); if (!editorName) editorName = getenv("VISUAL"); if (!editorName) editorName = DEFAULT_EDITOR; /* * On Unix the EDITOR value should *not* be quoted, since it might include * switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it * if necessary. But this policy is not very workable on Windows, due to * severe brain damage in their command shell plus the fact that standard * program paths include spaces. */ sys = pg_malloc(strlen(editorName) + strlen(fname) + 10 + 1);#ifndef WIN32 sprintf(sys, "exec %s '%s'", editorName, fname);#else sprintf(sys, "%s\"%s\" \"%s\"%s", SYSTEMQUOTE, editorName, fname, SYSTEMQUOTE);#endif result = system(sys); if (result == -1) psql_error("could not start editor \"%s\"\n", editorName); else if (result == 127) psql_error("could not start /bin/sh\n"); free(sys); return result == 0;}/* call this one */static booldo_edit(const char *filename_arg, PQExpBuffer query_buf){ char fnametmp[MAXPGPATH]; FILE *stream = NULL; const char *fname; bool error = false; int fd;#ifndef WIN32_CLIENT_ONLY struct stat before, after;#endif if (filename_arg) fname = filename_arg; else { /* make a temp file to edit */#ifndef WIN32 const char *tmpdir = getenv("TMPDIR"); if (!tmpdir) tmpdir = "/tmp";#else char tmpdir[MAXPGPATH]; int ret; ret = GetTempPath(MAXPGPATH, tmpdir); if (ret == 0 || ret > MAXPGPATH) { psql_error("cannot locate temporary directory: %s", !ret ? strerror(errno) : ""); return false; } /* * No canonicalize_path() here. EDIT.EXE run from CMD.EXE prepends the * current directory to the supplied path unless we use only * backslashes, so we do that. */#endif#ifndef WIN32 snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d", tmpdir, "/", (int) getpid());#else snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d", tmpdir, "" /* trailing separator already present */ , (int) getpid());#endif fname = (const char *) fnametmp; fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd != -1) stream = fdopen(fd, "w"); if (fd == -1 || !stream) { psql_error("could not open temporary file \"%s\": %s\n", fname, strerror(errno)); error = true; } else { unsigned int ql = query_buf->len; if (ql == 0 || query_buf->data[ql - 1] != '\n') { appendPQExpBufferChar(query_buf, '\n'); ql++; } if (fwrite(query_buf->data, 1, ql, stream) != ql) { psql_error("%s: %s\n", fname, strerror(errno)); fclose(stream); remove(fname); error = true; } else if (fclose(stream) != 0) { psql_error("%s: %s\n", fname, strerror(errno)); remove(fname); error = true; } } }#ifndef WIN32_CLIENT_ONLY if (!error && stat(fname, &before) != 0) { psql_error("%s: %s\n", fname, strerror(errno)); error = true; }#endif /* call editor */ if (!error) error = !editFile(fname);#ifndef WIN32_CLIENT_ONLY if (!error && stat(fname, &after) != 0) { psql_error("%s: %s\n", fname, strerror(errno)); error = true; } if (!error && before.st_mtime != after.st_mtime) {#else if (!error) {#endif stream = fopen(fname, PG_BINARY_R); if (!stream) { psql_error("%s: %s\n", fname, strerror(errno)); error = true; } else { /* read file back in */ char line[1024]; resetPQExpBuffer(query_buf); while (fgets(line, sizeof(line), stream) != NULL) appendPQExpBufferStr(query_buf, line); if (ferror(stream)) { psql_error("%s: %s\n", fname, strerror(errno)); error = true; }#ifdef USE_READLINE#ifdef HAVE_REPLACE_HISTORY_ENTRY replace_history_entry(where_history(), query_buf->data, NULL);#else add_history(query_buf->data);#endif#endif fclose(stream); } } /* remove temp file */ if (!filename_arg) { if (remove(fname) == -1) { psql_error("%s: %s\n", fname, strerror(errno)); error = true; } } return !error;}/* * process_file * * Read commands from filename and then them to the main processing loop * Handler for \i, but can be used for other things as well. Returns * MainLoop() error code. */intprocess_file(char *filename){ FILE *fd; int result; char *oldfilename; if (!filename) return EXIT_FAILURE; canonicalize_path(filename); fd = fopen(filename, PG_BINARY_R); if (!fd) { psql_error("%s: %s\n", filename, strerror(errno)); return EXIT_FAILURE; } oldfilename = pset.inputfile; pset.inputfile = filename; result = MainLoop(fd); fclose(fd); pset.inputfile = oldfilename; return result;}/* * do_pset * */static const char *_align2string(enum printFormat in){ switch (in) { case PRINT_NOTHING: return "nothing"; break; case PRINT_UNALIGNED: return "unaligned"; break; case PRINT_ALIGNED: return "aligned"; break; case PRINT_HTML: return "html"; break; case PRINT_LATEX: return "latex"; break; case PRINT_TROFF_MS: return "troff-ms"; break; } return "unknown";}booldo_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet){ size_t vallen = 0; psql_assert(param); if (value) vallen = strlen(value); /* set format */ if (strcmp(param, "format") == 0) { if (!value) ; else if (pg_strncasecmp("unaligned", value, vallen) == 0) popt->topt.format = PRINT_UNALIGNED; else if (pg_strncasecmp("aligned", value, vallen) == 0) popt->topt.format = PRINT_ALIGNED; else if (pg_strncasecmp("html", value, vallen) == 0) popt->topt.format = PRINT_HTML; else if (pg_strncasecmp("latex", value, vallen) == 0) popt->topt.format = PRINT_LATEX; else if (pg_strncasecmp("troff-ms", value, vallen) == 0) popt->topt.format = PRINT_TROFF_MS; else { psql_error("\\pset: allowed formats are unaligned, aligned, html, latex, troff-ms\n"); return false; } if (!quiet) printf(_("Output format is %s.\n"), _align2string(popt->topt.format)); } /* set border style/width */ else if (strcmp(param, "border") == 0) { if (value) popt->topt.border = atoi(value); if (!quiet) printf(_("Border style is %d.\n"), popt->topt.border); } /* set expanded/vertical mode */ else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0) { popt->topt.expanded = !popt->topt.expanded; if (!quiet) printf(popt->topt.expanded ? _("Expanded display is on.\n") : _("Expanded display is off.\n")); } /* locale-aware numeric output */ else if (strcmp(param, "numericlocale") == 0) { popt->topt.numericLocale = !popt->topt.numericLocale; if (!quiet) { if (popt->topt.numericLocale) puts(_("Showing locale-adjusted numeric output.")); else puts(_("Locale-adjusted numeric output is off.")); } } /* null display */ else if (strcmp(param, "null") == 0) { if (value) { free(popt->nullPrint); popt->nullPrint = pg_strdup(value); } if (!quiet) printf(_("Null display is \"%s\".\n"), popt->nullPrint ? popt->nullPrint : ""); } /* field separator for unaligned text */ else if (strcmp(param, "fieldsep") == 0) { if (value) { free(popt->topt.fieldSep); popt->topt.fieldSep = pg_strdup(value); } if (!quiet) printf(_("Field separator is \"%s\".\n"), popt->topt.fieldSep); } /* record separator for unaligned text */ else if (strcmp(param, "recordsep") == 0) { if (value) { free(popt->topt.recordSep); popt->topt.recordSep = pg_strdup(value); } if (!quiet) { if (strcmp(popt->topt.recordSep, "\n") == 0) printf(_("Record separator is <newline>.")); else printf(_("Record separator is \"%s\".\n"), popt->topt.recordSep); } } /* toggle between full and tuples-only format */ else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0) { popt->topt.tuples_only = !popt->topt.tuples_only; if (!quiet) { if (popt->topt.tuples_only) puts(_("Showing only tuples.")); else puts(_("Tuples only is off.")); } } /* set title override */ else if (strcmp(param, "title") == 0) { free(popt->title); if (!value) popt->title = NULL; else popt->title = pg_strdup(value); if (!quiet) { if (popt->title) printf(_("Title is \"%s\".\n"), popt->title); else printf(_("Title is unset.\n")); } } /* set HTML table tag options */ else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0) { free(popt->topt.tableAttr); if (!value) popt->topt.tableAttr = NULL; else popt->topt.tableAttr = pg_strdup(value); if (!quiet) { if (popt->topt.tableAttr) printf(_("Table attribute is \"%s\".\n"), popt->topt.tableAttr); else printf(_("Table attributes unset.\n")); } } /* toggle use of pager */ else if (strcmp(param, "pager") == 0) { if (value && pg_strcasecmp(value, "always") == 0) popt->topt.pager = 2; else if (popt->topt.pager == 1) popt->topt.pager = 0; else popt->topt.pager = 1; if (!quiet) { if (popt->topt.pager == 1) puts(_("Pager is used for long output.")); else if (popt->topt.pager == 2) puts(_("Pager is always used.")); else puts(_("Pager usage is off.")); } } /* disable "(x rows)" footer */ else if (strcmp(param, "footer") == 0) { popt->default_footer = !popt->default_footer; if (!quiet) { if (popt->default_footer) puts(_("Default footer is on.")); else puts(_("Default footer is off.")); } } else { psql_error("\\pset: unknown option: %s\n", param); return false; } return true;}#ifndef WIN32#define DEFAULT_SHELL "/bin/sh"#else/* * CMD.EXE is in different places in different Win32 releases so we * have to rely on the path to find it. */#define DEFAULT_SHELL "cmd.exe"#endifstatic booldo_shell(const char *command){ int result; if (!command) { char *sys; const char *shellName; shellName = getenv("SHELL");#ifdef WIN32 if (shellName == NULL) shellName = getenv("COMSPEC");#endif if (shellName == NULL) shellName = DEFAULT_SHELL; sys = pg_malloc(strlen(shellName) + 16);#ifndef WIN32 sprintf(sys, /* See EDITOR handling comment for an explaination */ "exec %s", shellName);#else sprintf(sys, /* See EDITOR handling comment for an explaination */ "%s\"%s\"%s", SYSTEMQUOTE, shellName, SYSTEMQUOTE);#endif result = system(sys); free(sys); } else result = system(command); if (result == 127 || result == -1) { psql_error("\\!: failed\n"); return false; } return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -