📄 psql.c
字号:
/* * we skip in/out funcs by excluding functions that take * some arguments, but have no types defined for those * arguments */ descbuf[0] = '\0'; strcat(descbuf, "SELECT t.typname as result, "); strcat(descbuf, " p.proname as function, "); if (screen_size.ws_col <= 80) strcat(descbuf, " substr(oid8types(p.proargtypes),1,14) as arguments, "); else strcat(descbuf, " oid8types(p.proargtypes) as arguments, "); if (screen_size.ws_col <= 80) strcat(descbuf, " substr(obj_description(p.oid),1,34) as description "); else strcat(descbuf, " obj_description(p.oid) as description "); strcat(descbuf, "FROM pg_proc p, pg_type t "); strcat(descbuf, "WHERE p.prorettype = t.oid and "); strcat(descbuf, "(pronargs = 0 or oid8types(p.proargtypes) != '') "); if (optarg2) { strcat(descbuf, "AND p.proname ~ '^"); strcat(descbuf, optarg2); strcat(descbuf, "' "); } strcat(descbuf, "ORDER BY result, function, arguments;"); success = SendQuery(pset, descbuf, NULL, NULL); } else if (strncmp(cmd, "di", 2) == 0) /* only indices */ tableList(pset, false, 'i', false); else if (strncmp(cmd, "do", 2) == 0) { char descbuf[4096]; /* operators */ descbuf[0] = '\0'; strcat(descbuf, "SELECT o.oprname AS op, "); strcat(descbuf, " t1.typname AS left_arg, "); strcat(descbuf, " t2.typname AS right_arg, "); strcat(descbuf, " t0.typname AS result, "); if (screen_size.ws_col <= 80) strcat(descbuf, " substr(obj_description(p.oid),1,41) as description "); else strcat(descbuf, " obj_description(p.oid) as description "); strcat(descbuf, "FROM pg_proc p, pg_type t0, "); strcat(descbuf, " pg_type t1, pg_type t2, "); strcat(descbuf, " pg_operator o "); strcat(descbuf, "WHERE p.prorettype = t0.oid AND "); strcat(descbuf, " RegprocToOid(o.oprcode) = p.oid AND "); strcat(descbuf, " p.pronargs = 2 AND "); strcat(descbuf, " o.oprleft = t1.oid AND "); strcat(descbuf, " o.oprright = t2.oid "); if (optarg2) { strcat(descbuf, "AND o.oprname ~ '^"); strcat(descbuf, optarg2); strcat(descbuf, "' "); } strcat(descbuf, "UNION "); strcat(descbuf, "SELECT o.oprname as op, "); strcat(descbuf, " ''::name AS left_arg, "); strcat(descbuf, " t1.typname AS right_arg, "); strcat(descbuf, " t0.typname AS result, "); if (screen_size.ws_col <= 80) strcat(descbuf, " substr(obj_description(p.oid),1,41) as description "); else strcat(descbuf, " obj_description(p.oid) as description "); strcat(descbuf, "FROM pg_operator o, pg_proc p, pg_type t0, pg_type t1 "); strcat(descbuf, "WHERE RegprocToOid(o.oprcode) = p.oid AND "); strcat(descbuf, " o.oprresult = t0.oid AND "); strcat(descbuf, " o.oprkind = 'l' AND "); strcat(descbuf, " o.oprright = t1.oid "); if (optarg2) { strcat(descbuf, "AND o.oprname ~ '^"); strcat(descbuf, optarg2); strcat(descbuf, "' "); } strcat(descbuf, "UNION "); strcat(descbuf, "SELECT o.oprname as op, "); strcat(descbuf, " t1.typname AS left_arg, "); strcat(descbuf, " ''::name AS right_arg, "); strcat(descbuf, " t0.typname AS result, "); if (screen_size.ws_col <= 80) strcat(descbuf, " substr(obj_description(p.oid),1,41) as description "); else strcat(descbuf, " obj_description(p.oid) as description "); strcat(descbuf, "FROM pg_operator o, pg_proc p, pg_type t0, pg_type t1 "); strcat(descbuf, "WHERE RegprocToOid(o.oprcode) = p.oid AND "); strcat(descbuf, " o.oprresult = t0.oid AND "); strcat(descbuf, " o.oprkind = 'r' AND "); strcat(descbuf, " o.oprleft = t1.oid "); if (optarg2) { strcat(descbuf, "AND o.oprname ~ '^"); strcat(descbuf, optarg2); strcat(descbuf, "' "); } strcat(descbuf, "ORDER BY op, left_arg, right_arg, result;"); success = SendQuery(pset, descbuf, NULL, NULL); } else if (strncmp(cmd, "ds", 2) == 0) /* only sequences */ tableList(pset, false, 'S', false); else if (strncmp(cmd, "dS", 2) == 0) /* system tables */ tableList(pset, false, 'b', true); else if (strncmp(cmd, "dt", 2) == 0) /* only tables */ tableList(pset, false, 't', false); else if (strncmp(cmd, "dT", 2) == 0) { char descbuf[4096]; /* types */ descbuf[0] = '\0'; strcat(descbuf, "SELECT typname AS type, "); strcat(descbuf, " obj_description(oid) as description "); strcat(descbuf, "FROM pg_type "); strcat(descbuf, "WHERE typrelid = 0 AND "); strcat(descbuf, " typname !~ '^_.*' "); strcat(descbuf, "ORDER BY type;"); if (optarg2) { strcat(descbuf, "AND typname ~ '^"); strcat(descbuf, optarg2); strcat(descbuf, "' "); } success = SendQuery(pset, descbuf, NULL, NULL); } else if (!optarg) /* show tables, sequences and indices */ tableList(pset, false, 'b', false); else if (strcmp(optarg, "*") == 0) { /* show everything */ if (tableList(pset, false, 'b', false) == 0) tableList(pset, true, 'b', false); } else if (strncmp(cmd, "d ", 2) == 0) /* describe the specified table */ tableDesc(pset, optarg, NULL); else slashUsage(pset); break; case 'e': /* edit */ { do_edit(optarg, query, &status); break; } case 'E': { FILE *fd; static char *lastfile; struct stat st, st2; if (optarg) { if (lastfile) free(lastfile); lastfile = malloc(strlen(optarg + 1)); if (!lastfile) { perror("malloc"); exit(CMD_TERMINATE); } strcpy(lastfile, optarg); } else if (!lastfile) { fprintf(stderr, "\\r must be followed by a file name initially\n"); break; } stat(lastfile, &st); editFile(lastfile);#ifndef __CYGWIN32__ if ((stat(lastfile, &st2) == -1) || ((fd = fopen(lastfile, "r")) == NULL))#else if ((stat(lastfile, &st2) == -1) || ((fd = fopen(lastfile, "rb")) == NULL))#endif { perror(lastfile); break; } if (st2.st_mtime == st.st_mtime) { if (!pset->quiet) fprintf(stderr, "warning: %s not modified. query not executed\n", lastfile); fclose(fd); break; } MainLoop(pset, query, fd); fclose(fd); break; } case 'f': { char *fs = DEFAULT_FIELD_SEP; if (optarg) fs = optarg; /* handle \f \{space} */ if (optarg && !*optarg && strlen(cmd) > 1) { int i; /* line and cmd match until the first blank space */ for (i = 2; isspace(line[i]); i++) ; fs = cmd + i - 1; } if (pset->opt.fieldSep) free(pset->opt.fieldSep); if (!(pset->opt.fieldSep = strdup(fs))) { perror("malloc"); exit(CMD_TERMINATE); } if (!pset->quiet) printf("field separator changed to '%s'\n", pset->opt.fieldSep); break; } case 'g': /* \g means send query */ if (!optarg) pset->gfname = NULL; else if (!(pset->gfname = strdup(optarg))) { perror("malloc"); exit(CMD_TERMINATE); } status = CMD_SEND; break; case 'h': /* help */ { do_help(pset, optarg); break; } case 'i': /* \i is include file */ { FILE *fd; if (!optarg) { fprintf(stderr, "\\i must be followed by a file name\n"); break; }#ifndef __CYGWIN32__ if ((fd = fopen(optarg, "r")) == NULL)#else if ((fd = fopen(optarg, "rb")) == NULL)#endif { fprintf(stderr, "file named %s could not be opened\n", optarg); break; } MainLoop(pset, query, fd); fclose(fd); break; } case 'H': if (toggle(pset, &pset->opt.html3, "HTML3.0 tabular output")) pset->opt.standard = 0; break; case 'l': /* \l is list database */ listAllDbs(pset); break; case 'm': /* monitor like type-setting */ if (toggle(pset, &pset->opt.standard, "standard SQL separaters and padding")) { pset->opt.html3 = pset->opt.expanded = 0; pset->opt.align = pset->opt.header = 1; if (pset->opt.fieldSep) free(pset->opt.fieldSep); pset->opt.fieldSep = strdup("|"); if (!pset->quiet) printf("field separator changed to '%s'\n", pset->opt.fieldSep); } else { if (pset->opt.fieldSep) free(pset->opt.fieldSep); pset->opt.fieldSep = strdup(DEFAULT_FIELD_SEP); if (!pset->quiet) printf("field separator changed to '%s'\n", pset->opt.fieldSep); } break; case 'o': setFout(pset, optarg); break; case 'p': if (query) { fputs(query, stdout); fputc('\n', stdout); } break; case 'q': /* \q is quit */ status = CMD_TERMINATE; break; case 'r': /* reset(clear) the buffer */ query[0] = '\0'; if (!pset->quiet) printf("buffer reset(cleared)\n"); break; case 's': /* \s is save history to a file */ if (!optarg) optarg = "/dev/tty";#ifdef USE_HISTORY if (write_history(optarg) != 0) fprintf(stderr, "cannot write history to %s\n", optarg);#endif break; case 't': /* toggle headers */ toggle(pset, &pset->opt.header, "output headings and row count"); break; case 'T': /* define html <table ...> option */ if (pset->opt.tableOpt) free(pset->opt.tableOpt); if (!optarg) pset->opt.tableOpt = NULL; else if (!(pset->opt.tableOpt = strdup(optarg))) { perror("malloc"); exit(CMD_TERMINATE); } break; case 'w': { FILE *fd; if (!optarg) { fprintf(stderr, "\\w must be followed by a file name\n"); break; }#ifndef __CYGWIN32__ if ((fd = fopen(optarg, "w")) == NULL)#else if ((fd = fopen(optarg, "w")) == NULL)#endif { fprintf(stderr, "file named %s could not be opened\n", optarg); break; } fputs(query, fd); fputs("\n", fd); fclose(fd); break; } case 'x': toggle(pset, &pset->opt.expanded, "expanded table representation"); break; case 'z': /* list table rights (grant/revoke) */ rightsList(pset); break; case '!': do_shell(optarg); break; default: case '?': /* \? is help */ slashUsage(pset); break; } free(cmd); return status;}/* MainLoop() * Main processing loop for reading lines of input * and sending them to the backend. * * This loop is re-entrant. May be called by \i command * which reads input from a file. * db_ptr must be initialized and set. */static intMainLoop(PsqlSettings *pset, char *query, FILE *source){ char *line; /* line of input */ char *xcomment; /* start of extended comment */ int len; /* length of the line */ int successResult = 1; int slashCmdStatus = CMD_SEND; /*-------------------------------------------------------------- * slashCmdStatus can be: * CMD_UNKNOWN - send currently constructed query to backend * (i.e. we got a \g) * CMD_SEND - send currently constructed query to backend * (i.e. we got a \g) * CMD_SKIP_LINE - skip processing of this line, continue building * up query * CMD_TERMINATE - terminate processing of this query entirely * CMD_NEWEDIT - new query supplied by edit *--------------------------------------------------------------- */ bool querySent = false; READ_ROUTINE GetNextLine; bool eof = false; /* end of our command input? */ bool success; char in_quote; /* == 0 for no in_quote */ bool was_bslash; /* backslash */ int paren_level; char *query_start; /* Stack the prior command source */ FILE *prev_cmd_source = cur_cmd_source; bool prev_cmd_interactive = cur_cmd_interactive; /* Establish new source */ cur_cmd_source = source; cur_cmd_interactive = ((source == stdin) && !pset->notty); if ((query = malloc(MAX_QUERY_BUFFER)) == NULL) perror("Memory Allocation Failed"); if (cur_cmd_interactive) { if (pset->prompt) free(pset->prompt); pset->prompt = malloc(strlen(PQdb(pset->db)) + strlen(PROMPT) + 1); if (pset->quiet) pset->prompt[0] = '\0'; else sprintf(pset->prompt, "%s%s", PQdb(pset->db), PROMPT); if (pset->useReadline) {#ifdef USE_HISTORY using_history();#endif GetNextLine = gets_readline; } else GetNextLine = gets_noreadline; } else GetNextLine = gets_fromFile; query[0] = '\0'; xcomment = NULL; in_quote = false; paren_level = 0; slashCmdStatus = CMD_UNKNOWN; /* set default */ /* main loop to get queries and execute them */ while (!eof) { /* * just returned from editing the line? then just copy to the * input buffer */ if (slashCmdStatus == CMD_NEWEDIT) { paren_level = 0; line = strdup(query); query[0] = '\0'; /* * otherwise, get another line and set interactive prompt if * necessary */ } else { if (cur_cmd_interactive && !pset->quiet) { if (in_quote && in_quote == PROMPT_SINGLEQUOTE) pset->prompt[strlen(pset->prompt) - 3] = PROMPT_SINGLEQUOTE; else if (in_quote && in_quote == PROMPT_DOUBLEQUOTE) pset->prompt[strlen(pset->prompt) - 3] = PROMPT_DOUBLEQUOTE; else if (xcomment != NULL) pset->prompt[strlen(pset->prompt) - 3] = PROMPT_COMMENT; else if (query[0] != '\0' && !querySent) pset->prompt[strlen(pset->prompt) - 3] = PROMPT_CONTINUE; else pset->prompt[strlen(pset->prompt) - 3] = PROMPT_READY; } line = GetNextLine(pset->prompt, source);#ifdef USE_HISTORY if (cur_cmd_interactive && pset->useReadline && line != NULL) add_history(line); /* save non-empty lines in history */#endif } /* * query - pointer to current command query_start - placeholder * for next command */ if (line == NULL || (!cur_cm
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -