/* Allocate a new compressor */ CompressorState * AllocateCompressor(int compression, WriteFunc writeF) { CompressorState *cs; CompressionAlgorithm alg; int level; ParseCompressionOption(compression, &alg, &level); #ifndef HAVE_LIBZ if (alg == COMPR_ALG_LIBZ) exit_horribly(modulename, "not built with zlib support\n"); #endif cs = (CompressorState *) pg_calloc(1, sizeof(CompressorState)); cs->writeF = writeF; cs->comprAlg = alg; /* * Perform compression algorithm specific initialization. */ #ifdef HAVE_LIBZ if (alg == COMPR_ALG_LIBZ) InitCompressorZlib(cs, level); #endif return cs; }
static struct copy_options * parse_slash_copy(const char *args) { struct copy_options *result; char* token; const char *whitespace = " \t\n\r"; char nonstd_backslash = standard_strings() ? 0 : '\\'; if (!args) { psql_error("\\copy: arguments required\n"); return NULL; } result = pg_calloc(1, sizeof(struct copy_options)); result->before_tofrom = pg_strdup(""); /* initialize for appending */ token = strtokx(args, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token) goto error; /* The following can be removed when we drop 7.3 syntax support */ if (pg_strcasecmp(token, "binary") == 0) { xstrcat(&result->before_tofrom, token); token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token) goto error; } /* Handle COPY (SELECT) case */ if (token[0] == '(') { int parens = 1; while (parens > 0) { xstrcat(&result->before_tofrom, " "); xstrcat(&result->before_tofrom, token); token = strtokx(NULL, whitespace, "()", "\"'", nonstd_backslash, true, false, pset.encoding); if (!token) goto error; if (token[0] == '(') parens++; else if (token[0] == ')') parens--; } } xstrcat(&result->before_tofrom, " "); xstrcat(&result->before_tofrom, token); token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token) goto error; /* * strtokx() will not have returned a multi-character token starting with * '.', so we don't need strcmp() here. Likewise for '(', etc, below. */ if (token[0] == '.') { /* handle schema . table */ xstrcat(&result->before_tofrom, token); token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token) goto error; xstrcat(&result->before_tofrom, token); token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token) goto error; } if (token[0] == '(') { /* handle parenthesized column list */ for (;;) { xstrcat(&result->before_tofrom, " "); xstrcat(&result->before_tofrom, token); token = strtokx(NULL, whitespace, "()", "\"", 0, false, false, pset.encoding); if (!token) goto error; if (token[0] == ')') break; } xstrcat(&result->before_tofrom, " "); xstrcat(&result->before_tofrom, token); token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token) goto error; } if (pg_strcasecmp(token, "from") == 0) result->from = true; else if (pg_strcasecmp(token, "to") == 0) result->from = false; else goto error; token = strtokx(NULL, whitespace, NULL, "'", 0, false, true, pset.encoding); if (!token) goto error; if (pg_strcasecmp(token, "stdin") == 0 || pg_strcasecmp(token, "stdout") == 0) { result->psql_inout = false; result->file = NULL; } else if (pg_strcasecmp(token, "pstdin") == 0 || pg_strcasecmp(token, "pstdout") == 0) { result->psql_inout = true; result->file = NULL; } else { result->psql_inout = false; result->file = pg_strdup(token); expand_tilde(&result->file); } /* Collect the rest of the line (COPY options) */ token = strtokx(NULL, "", NULL, NULL, 0, false, false, pset.encoding); if (token) result->after_tofrom = pg_strdup(token); return result; error: if (token) psql_error("\\copy: parse error at \"%s\"\n", token); else psql_error("\\copy: parse error at end of line\n"); free_copy_options(result); return NULL; }
static struct copy_options * parse_slash_copy(const char *args) { struct copy_options *result; char *line; char *token; const char *whitespace = " \t\n\r"; char nonstd_backslash = standard_strings() ? 0 : '\\'; if (args) line = pg_strdup(args); else { psql_error("\\copy: arguments required\n"); return NULL; } result = pg_calloc(1, sizeof(struct copy_options)); token = strtokx(line, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token) goto error; if (pg_strcasecmp(token, "binary") == 0) { result->binary = true; token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token) goto error; } result->table = pg_strdup(token); /* Handle COPY (SELECT) case */ if (token[0] == '(') { int parens = 1; while (parens > 0) { token = strtokx(NULL, whitespace, "()", "\"'", nonstd_backslash, true, false, pset.encoding); if (!token) goto error; if (token[0] == '(') parens++; else if (token[0] == ')') parens--; xstrcat(&result->table, " "); xstrcat(&result->table, token); } } token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token) goto error; /* * strtokx() will not have returned a multi-character token starting with * '.', so we don't need strcmp() here. Likewise for '(', etc, below. */ if (token[0] == '.') { /* handle schema . table */ xstrcat(&result->table, token); token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token) goto error; xstrcat(&result->table, token); token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token) goto error; } if (token[0] == '(') { /* handle parenthesized column list */ result->column_list = pg_strdup(token); for (;;) { token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token || strchr(".,()", token[0])) goto error; xstrcat(&result->column_list, token); token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token) goto error; xstrcat(&result->column_list, token); if (token[0] == ')') break; if (token[0] != ',') goto error; } token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); if (!token) goto error; } /* * Allows old COPY syntax for backward compatibility 2002-06-19 */ if (pg_strcasecmp(token, "with") == 0) { token = strtokx(NULL, whitespace, NULL, NULL, 0, false, false, pset.encoding); if (!token || pg_strcasecmp(token, "oids") != 0) goto error; result->oids = true; token = strtokx(NULL, whitespace, NULL, NULL, 0, false, false, pset.encoding); if (!token) goto error; } if (pg_strcasecmp(token, "from") == 0) result->from = true; else if (pg_strcasecmp(token, "to") == 0) result->from = false; else goto error; token = strtokx(NULL, whitespace, NULL, "'", 0, false, true, pset.encoding); if (!token) goto error; if (pg_strcasecmp(token, "stdin") == 0 || pg_strcasecmp(token, "stdout") == 0) { result->psql_inout = false; result->file = NULL; } else if (pg_strcasecmp(token, "pstdin") == 0 || pg_strcasecmp(token, "pstdout") == 0) { result->psql_inout = true; result->file = NULL; } else { result->psql_inout = false; result->file = pg_strdup(token); expand_tilde(&result->file); } token = strtokx(NULL, whitespace, NULL, NULL, 0, false, false, pset.encoding); /* * Allows old COPY syntax for backward compatibility. */ if (token && pg_strcasecmp(token, "using") == 0) { token = strtokx(NULL, whitespace, NULL, NULL, 0, false, false, pset.encoding); if (!(token && pg_strcasecmp(token, "delimiters") == 0)) goto error; } if (token && pg_strcasecmp(token, "delimiters") == 0) { token = strtokx(NULL, whitespace, NULL, "'", nonstd_backslash, true, false, pset.encoding); if (!token) goto error; result->delim = pg_strdup(token); token = strtokx(NULL, whitespace, NULL, NULL, 0, false, false, pset.encoding); } if (token) { /* * WITH is optional. Also, the backend will allow WITH followed by * nothing, so we do too. */ if (pg_strcasecmp(token, "with") == 0) token = strtokx(NULL, whitespace, NULL, NULL, 0, false, false, pset.encoding); while (token) { bool fetch_next; fetch_next = true; if (pg_strcasecmp(token, "oids") == 0) result->oids = true; else if (pg_strcasecmp(token, "binary") == 0) result->binary = true; else if (pg_strcasecmp(token, "csv") == 0) result->csv_mode = true; else if (pg_strcasecmp(token, "header") == 0) result->header = true; else if (pg_strcasecmp(token, "delimiter") == 0) { token = strtokx(NULL, whitespace, NULL, "'", nonstd_backslash, true, false, pset.encoding); if (token && pg_strcasecmp(token, "as") == 0) token = strtokx(NULL, whitespace, NULL, "'", nonstd_backslash, true, false, pset.encoding); if (token) result->delim = pg_strdup(token); else goto error; } else if (pg_strcasecmp(token, "null") == 0) { token = strtokx(NULL, whitespace, NULL, "'", nonstd_backslash, true, false, pset.encoding); if (token && pg_strcasecmp(token, "as") == 0) token = strtokx(NULL, whitespace, NULL, "'", nonstd_backslash, true, false, pset.encoding); if (token) result->null = pg_strdup(token); else goto error; } else if (pg_strcasecmp(token, "quote") == 0) { token = strtokx(NULL, whitespace, NULL, "'", nonstd_backslash, true, false, pset.encoding); if (token && pg_strcasecmp(token, "as") == 0) token = strtokx(NULL, whitespace, NULL, "'", nonstd_backslash, true, false, pset.encoding); if (token) result->quote = pg_strdup(token); else goto error; } else if (pg_strcasecmp(token, "escape") == 0) { token = strtokx(NULL, whitespace, NULL, "'", nonstd_backslash, true, false, pset.encoding); if (token && pg_strcasecmp(token, "as") == 0) token = strtokx(NULL, whitespace, NULL, "'", nonstd_backslash, true, false, pset.encoding); if (token) result->escape = pg_strdup(token); else goto error; } else if (pg_strcasecmp(token, "force") == 0) { token = strtokx(NULL, whitespace, ",", "\"", 0, false, false, pset.encoding); if (pg_strcasecmp(token, "quote") == 0) { /* handle column list */ fetch_next = false; for (;;) { token = strtokx(NULL, whitespace, ",", "\"", 0, false, false, pset.encoding); if (!token || strchr(",", token[0])) goto error; if (!result->force_quote_list) result->force_quote_list = pg_strdup(token); else xstrcat(&result->force_quote_list, token); token = strtokx(NULL, whitespace, ",", "\"", 0, false, false, pset.encoding); if (!token || token[0] != ',') break; xstrcat(&result->force_quote_list, token); } } else if (pg_strcasecmp(token, "not") == 0) { token = strtokx(NULL, whitespace, ",", "\"", 0, false, false, pset.encoding); if (pg_strcasecmp(token, "null") != 0) goto error; /* handle column list */ fetch_next = false; for (;;) { token = strtokx(NULL, whitespace, ",", "\"", 0, false, false, pset.encoding); if (!token || strchr(",", token[0])) goto error; if (!result->force_notnull_list) result->force_notnull_list = pg_strdup(token); else xstrcat(&result->force_notnull_list, token); token = strtokx(NULL, whitespace, ",", "\"", 0, false, false, pset.encoding); if (!token || token[0] != ',') break; xstrcat(&result->force_notnull_list, token); } } else goto error; } else goto error; if (fetch_next) token = strtokx(NULL, whitespace, NULL, NULL, 0, false, false, pset.encoding); } } free(line); return result; error: if (token) psql_error("\\copy: parse error at \"%s\"\n", token); else psql_error("\\copy: parse error at end of line\n"); free_copy_options(result); free(line); return NULL; }