diff options
author | Shigeru Hanada | 2011-07-07 00:28:08 +0000 |
---|---|---|
committer | Shigeru Hanada | 2011-07-07 00:28:08 +0000 |
commit | 25808fe6314d40a137b5b007b6b535c01d685eb0 (patch) | |
tree | 7285c46ef348043b299b140dfc042b99626e777a | |
parent | 9461d72639824d9e47b66c7aaeeb86c5f020cdde (diff) | |
parent | c895e775a57072b075b230d60381ac432520b1a8 (diff) |
Merge branch 'master' into per_column_optionper_column_option
-rw-r--r-- | doc/src/sgml/ref/psql-ref.sgml | 15 | ||||
-rw-r--r-- | src/backend/optimizer/util/predtest.c | 191 | ||||
-rw-r--r-- | src/backend/parser/parse_expr.c | 26 | ||||
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 97 | ||||
-rw-r--r-- | src/bin/psql/command.c | 37 | ||||
-rw-r--r-- | src/bin/psql/command.h | 2 | ||||
-rw-r--r-- | src/bin/psql/describe.c | 48 | ||||
-rw-r--r-- | src/bin/psql/help.c | 3 | ||||
-rw-r--r-- | src/bin/psql/settings.h | 2 | ||||
-rw-r--r-- | src/bin/psql/startup.c | 6 | ||||
-rw-r--r-- | src/bin/psql/tab-complete.c | 3 | ||||
-rw-r--r-- | src/include/port.h | 1 | ||||
-rw-r--r-- | src/include/utils/lsyscache.h | 12 | ||||
-rw-r--r-- | src/port/path.c | 11 | ||||
-rwxr-xr-x | src/tools/msvc/pgbison.bat | 54 | ||||
-rw-r--r-- | src/tools/msvc/pgbison.pl | 48 | ||||
-rwxr-xr-x | src/tools/msvc/pgflex.bat | 48 | ||||
-rw-r--r-- | src/tools/msvc/pgflex.pl | 76 |
18 files changed, 371 insertions, 309 deletions
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index 74b26b2486..1b4831179a 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -1633,6 +1633,21 @@ Tue Oct 26 21:40:57 CEST 1999 <varlistentry> + <term><literal>\ir <replaceable class="parameter">filename</replaceable></literal></term> + <listitem> + <para> + The <literal>\ir</> command is similar to <literal>\i</>, but resolves + relative pathnames differently. When executing in interactive mode, + the two commands behave identically. However, when invoked from a + script, <literal>\ir</literal> interprets pathnames relative to the + directory in which the script is located, rather than the current + working directory. + </para> + </listitem> + </varlistentry> + + + <varlistentry> <term><literal>\l</literal> (or <literal>\list</literal>)</term> <term><literal>\l+</literal> (or <literal>\list+</literal>)</term> <listitem> diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c index 6c3dfb7eb5..beabafb5a8 100644 --- a/src/backend/optimizer/util/predtest.c +++ b/src/backend/optimizer/util/predtest.c @@ -1250,6 +1250,7 @@ list_member_strip(List *list, Expr *datum) * and in addition we use (6) to represent <>. <> is not a btree-indexable * operator, but we assume here that if an equality operator of a btree * opfamily has a negator operator, the negator behaves as <> for the opfamily. + * (This convention is also known to get_op_btree_interpretation().) * * The interpretation of: * @@ -1286,7 +1287,7 @@ list_member_strip(List *list, Expr *datum) #define BTEQ BTEqualStrategyNumber #define BTGE BTGreaterEqualStrategyNumber #define BTGT BTGreaterStrategyNumber -#define BTNE 6 +#define BTNE ROWCOMPARE_NE static const StrategyNumber BT_implic_table[6][6] = { /* @@ -1557,18 +1558,12 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it) OprProofCacheKey key; OprProofCacheEntry *cache_entry; bool cfound; - bool pred_op_negated; - Oid pred_op_negator, - clause_op_negator, - test_op = InvalidOid; - Oid opfamily_id; + Oid test_op = InvalidOid; bool found = false; - StrategyNumber pred_strategy, - clause_strategy, - test_strategy; - Oid clause_righttype; - CatCList *catlist; - int i; + List *pred_op_infos, + *clause_op_infos; + ListCell *lcp, + *lcc; /* * Find or make a cache entry for this pair of operators. @@ -1629,135 +1624,71 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it) * corresponding test operator. This should work for any logically * consistent opfamilies. */ - catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(pred_op)); + clause_op_infos = get_op_btree_interpretation(clause_op); + if (clause_op_infos) + pred_op_infos = get_op_btree_interpretation(pred_op); + else /* no point in looking */ + pred_op_infos = NIL; - /* - * If we couldn't find any opfamily containing the pred_op, perhaps it is - * a <> operator. See if it has a negator that is in an opfamily. - */ - pred_op_negated = false; - if (catlist->n_members == 0) + foreach(lcp, pred_op_infos) { - pred_op_negator = get_negator(pred_op); - if (OidIsValid(pred_op_negator)) - { - pred_op_negated = true; - ReleaseSysCacheList(catlist); - catlist = SearchSysCacheList1(AMOPOPID, - ObjectIdGetDatum(pred_op_negator)); - } - } + OpBtreeInterpretation *pred_op_info = lfirst(lcp); + Oid opfamily_id = pred_op_info->opfamily_id; - /* Also may need the clause_op's negator */ - clause_op_negator = get_negator(clause_op); + foreach(lcc, clause_op_infos) + { + OpBtreeInterpretation *clause_op_info = lfirst(lcc); + StrategyNumber pred_strategy, + clause_strategy, + test_strategy; - /* Now search the opfamilies */ - for (i = 0; i < catlist->n_members; i++) - { - HeapTuple pred_tuple = &catlist->members[i]->tuple; - Form_pg_amop pred_form = (Form_pg_amop) GETSTRUCT(pred_tuple); - HeapTuple clause_tuple; + /* Must find them in same opfamily */ + if (opfamily_id != clause_op_info->opfamily_id) + continue; + /* Lefttypes should match */ + Assert(clause_op_info->oplefttype == pred_op_info->oplefttype); - /* Must be btree */ - if (pred_form->amopmethod != BTREE_AM_OID) - continue; + pred_strategy = pred_op_info->strategy; + clause_strategy = clause_op_info->strategy; - /* Get the predicate operator's btree strategy number */ - opfamily_id = pred_form->amopfamily; - pred_strategy = (StrategyNumber) pred_form->amopstrategy; - Assert(pred_strategy >= 1 && pred_strategy <= 5); + /* + * Look up the "test" strategy number in the implication table + */ + if (refute_it) + test_strategy = BT_refute_table[clause_strategy - 1][pred_strategy - 1]; + else + test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1]; - if (pred_op_negated) - { - /* Only consider negators that are = */ - if (pred_strategy != BTEqualStrategyNumber) + if (test_strategy == 0) + { + /* Can't determine implication using this interpretation */ continue; - pred_strategy = BTNE; - } + } - /* - * From the same opfamily, find a strategy number for the clause_op, - * if possible - */ - clause_tuple = SearchSysCache3(AMOPOPID, - ObjectIdGetDatum(clause_op), - CharGetDatum(AMOP_SEARCH), - ObjectIdGetDatum(opfamily_id)); - if (HeapTupleIsValid(clause_tuple)) - { - Form_pg_amop clause_form = (Form_pg_amop) GETSTRUCT(clause_tuple); - - /* Get the restriction clause operator's strategy/datatype */ - clause_strategy = (StrategyNumber) clause_form->amopstrategy; - Assert(clause_strategy >= 1 && clause_strategy <= 5); - Assert(clause_form->amoplefttype == pred_form->amoplefttype); - clause_righttype = clause_form->amoprighttype; - ReleaseSysCache(clause_tuple); - } - else if (OidIsValid(clause_op_negator)) - { - clause_tuple = SearchSysCache3(AMOPOPID, - ObjectIdGetDatum(clause_op_negator), - CharGetDatum(AMOP_SEARCH), - ObjectIdGetDatum(opfamily_id)); - if (HeapTupleIsValid(clause_tuple)) + /* + * See if opfamily has an operator for the test strategy and the + * datatypes. + */ + if (test_strategy == BTNE) { - Form_pg_amop clause_form = (Form_pg_amop) GETSTRUCT(clause_tuple); - - /* Get the restriction clause operator's strategy/datatype */ - clause_strategy = (StrategyNumber) clause_form->amopstrategy; - Assert(clause_strategy >= 1 && clause_strategy <= 5); - Assert(clause_form->amoplefttype == pred_form->amoplefttype); - clause_righttype = clause_form->amoprighttype; - ReleaseSysCache(clause_tuple); - - /* Only consider negators that are = */ - if (clause_strategy != BTEqualStrategyNumber) - continue; - clause_strategy = BTNE; + test_op = get_opfamily_member(opfamily_id, + pred_op_info->oprighttype, + clause_op_info->oprighttype, + BTEqualStrategyNumber); + if (OidIsValid(test_op)) + test_op = get_negator(test_op); } else - continue; - } - else - continue; - - /* - * Look up the "test" strategy number in the implication table - */ - if (refute_it) - test_strategy = BT_refute_table[clause_strategy - 1][pred_strategy - 1]; - else - test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1]; + { + test_op = get_opfamily_member(opfamily_id, + pred_op_info->oprighttype, + clause_op_info->oprighttype, + test_strategy); + } - if (test_strategy == 0) - { - /* Can't determine implication using this interpretation */ - continue; - } + if (!OidIsValid(test_op)) + continue; - /* - * See if opfamily has an operator for the test strategy and the - * datatypes. - */ - if (test_strategy == BTNE) - { - test_op = get_opfamily_member(opfamily_id, - pred_form->amoprighttype, - clause_righttype, - BTEqualStrategyNumber); - if (OidIsValid(test_op)) - test_op = get_negator(test_op); - } - else - { - test_op = get_opfamily_member(opfamily_id, - pred_form->amoprighttype, - clause_righttype, - test_strategy); - } - if (OidIsValid(test_op)) - { /* * Last check: test_op must be immutable. * @@ -1773,9 +1704,13 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it) break; } } + + if (found) + break; } - ReleaseSysCacheList(catlist); + list_free_deep(pred_op_infos); + list_free_deep(clause_op_infos); if (!found) { diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 08f0439e7e..65d03adc49 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -2170,8 +2170,7 @@ make_row_comparison_op(ParseState *pstate, List *opname, List *opfamilies; ListCell *l, *r; - List **opfamily_lists; - List **opstrat_lists; + List **opinfo_lists; Bitmapset *strats; int nopers; int i; @@ -2241,8 +2240,7 @@ make_row_comparison_op(ParseState *pstate, List *opname, * containing the operators, and see which interpretations (strategy * numbers) exist for each operator. */ - opfamily_lists = (List **) palloc(nopers * sizeof(List *)); - opstrat_lists = (List **) palloc(nopers * sizeof(List *)); + opinfo_lists = (List **) palloc(nopers * sizeof(List *)); strats = NULL; i = 0; foreach(l, opexprs) @@ -2251,17 +2249,18 @@ make_row_comparison_op(ParseState *pstate, List *opname, Bitmapset *this_strats; ListCell *j; - get_op_btree_interpretation(opno, - &opfamily_lists[i], &opstrat_lists[i]); + opinfo_lists[i] = get_op_btree_interpretation(opno); /* - * convert strategy number list to a Bitmapset to make the + * convert strategy numbers into a Bitmapset to make the * intersection calculation easy. */ this_strats = NULL; - foreach(j, opstrat_lists[i]) + foreach(j, opinfo_lists[i]) { - this_strats = bms_add_member(this_strats, lfirst_int(j)); + OpBtreeInterpretation *opinfo = lfirst(j); + + this_strats = bms_add_member(this_strats, opinfo->strategy); } if (i == 0) strats = this_strats; @@ -2309,14 +2308,15 @@ make_row_comparison_op(ParseState *pstate, List *opname, for (i = 0; i < nopers; i++) { Oid opfamily = InvalidOid; + ListCell *j; - forboth(l, opfamily_lists[i], r, opstrat_lists[i]) + foreach(j, opinfo_lists[i]) { - int opstrat = lfirst_int(r); + OpBtreeInterpretation *opinfo = lfirst(j); - if (opstrat == rctype) + if (opinfo->strategy == rctype) { - opfamily = lfirst_oid(l); + opfamily = opinfo->opfamily_id; break; } } diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 69ec513634..326f1eee92 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -623,52 +623,30 @@ get_op_hash_functions(Oid opno, /* * get_op_btree_interpretation * Given an operator's OID, find out which btree opfamilies it belongs to, - * and what strategy number it has within each one. The results are - * returned as an OID list and a parallel integer list. + * and what properties it has within each one. The results are returned + * as a palloc'd list of OpBtreeInterpretation structs. * * In addition to the normal btree operators, we consider a <> operator to be * a "member" of an opfamily if its negator is an equality operator of the * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case. */ -void -get_op_btree_interpretation(Oid opno, List **opfamilies, List **opstrats) +List * +get_op_btree_interpretation(Oid opno) { + List *result = NIL; + OpBtreeInterpretation *thisresult; CatCList *catlist; - bool op_negated; int i; - *opfamilies = NIL; - *opstrats = NIL; - /* * Find all the pg_amop entries containing the operator. */ catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno)); - /* - * If we can't find any opfamily containing the op, perhaps it is a <> - * operator. See if it has a negator that is in an opfamily. - */ - op_negated = false; - if (catlist->n_members == 0) - { - Oid op_negator = get_negator(opno); - - if (OidIsValid(op_negator)) - { - op_negated = true; - ReleaseSysCacheList(catlist); - catlist = SearchSysCacheList1(AMOPOPID, - ObjectIdGetDatum(op_negator)); - } - } - - /* Now search the opfamilies */ for (i = 0; i < catlist->n_members; i++) { HeapTuple op_tuple = &catlist->members[i]->tuple; Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple); - Oid opfamily_id; StrategyNumber op_strategy; /* must be btree */ @@ -676,23 +654,66 @@ get_op_btree_interpretation(Oid opno, List **opfamilies, List **opstrats) continue; /* Get the operator's btree strategy number */ - opfamily_id = op_form->amopfamily; op_strategy = (StrategyNumber) op_form->amopstrategy; Assert(op_strategy >= 1 && op_strategy <= 5); - if (op_negated) + thisresult = (OpBtreeInterpretation *) + palloc(sizeof(OpBtreeInterpretation)); + thisresult->opfamily_id = op_form->amopfamily; + thisresult->strategy = op_strategy; + thisresult->oplefttype = op_form->amoplefttype; + thisresult->oprighttype = op_form->amoprighttype; + result = lappend(result, thisresult); + } + + ReleaseSysCacheList(catlist); + + /* + * If we didn't find any btree opfamily containing the operator, perhaps + * it is a <> operator. See if it has a negator that is in an opfamily. + */ + if (result == NIL) + { + Oid op_negator = get_negator(opno); + + if (OidIsValid(op_negator)) { - /* Only consider negators that are = */ - if (op_strategy != BTEqualStrategyNumber) - continue; - op_strategy = ROWCOMPARE_NE; - } + catlist = SearchSysCacheList1(AMOPOPID, + ObjectIdGetDatum(op_negator)); - *opfamilies = lappend_oid(*opfamilies, opfamily_id); - *opstrats = lappend_int(*opstrats, op_strategy); + for (i = 0; i < catlist->n_members; i++) + { + HeapTuple op_tuple = &catlist->members[i]->tuple; + Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple); + StrategyNumber op_strategy; + + /* must be btree */ + if (op_form->amopmethod != BTREE_AM_OID) + continue; + + /* Get the operator's btree strategy number */ + op_strategy = (StrategyNumber) op_form->amopstrategy; + Assert(op_strategy >= 1 && op_strategy <= 5); + + /* Only consider negators that are = */ + if (op_strategy != BTEqualStrategyNumber) + continue; + + /* OK, report it with "strategy" ROWCOMPARE_NE */ + thisresult = (OpBtreeInterpretation *) + palloc(sizeof(OpBtreeInterpretation)); + thisresult->opfamily_id = op_form->amopfamily; + thisresult->strategy = ROWCOMPARE_NE; + thisresult->oplefttype = op_form->amoplefttype; + thisresult->oprighttype = op_form->amoprighttype; + result = lappend(result, thisresult); + } + + ReleaseSysCacheList(catlist); + } } - ReleaseSysCacheList(catlist); + return result; } /* diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 378330b96a..16ff9e91e5 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -784,8 +784,9 @@ exec_command(const char *cmd, } - /* \i is include file */ - else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0) + /* \i and \ir include files */ + else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0 + || strcmp(cmd, "ir") == 0 || strcmp(cmd, "include_relative") == 0) { char *fname = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); @@ -797,8 +798,12 @@ exec_command(const char *cmd, } else { + bool include_relative; + + include_relative = (strcmp(cmd, "ir") == 0 + || strcmp(cmd, "include_relative") == 0); expand_tilde(&fname); - success = (process_file(fname, false) == EXIT_SUCCESS); + success = (process_file(fname, false, include_relative) == EXIT_SUCCESS); free(fname); } } @@ -1969,15 +1974,19 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf, * 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 + * Handler for \i and \ir, but can be used for other things as well. Returns * MainLoop() error code. + * + * If use_relative_path is true and filename is not an absolute path, then open + * the file from where the currently processed file (if any) is located. */ int -process_file(char *filename, bool single_txn) +process_file(char *filename, bool single_txn, bool use_relative_path) { FILE *fd; int result; char *oldfilename; + char relpath[MAXPGPATH]; PGresult *res; if (!filename) @@ -1986,6 +1995,24 @@ process_file(char *filename, bool single_txn) if (strcmp(filename, "-") != 0) { canonicalize_path(filename); + + /* + * If we were asked to resolve the pathname relative to the location + * of the currently executing script, and there is one, and this is + * a relative pathname, then prepend all but the last pathname + * component of the current script to this pathname. + */ + if (use_relative_path && pset.inputfile && !is_absolute_path(filename) + && !has_drive_prefix(filename)) + { + snprintf(relpath, MAXPGPATH, "%s", pset.inputfile); + get_parent_directory(relpath); + join_path_components(relpath, relpath, filename); + canonicalize_path(relpath); + + filename = relpath; + } + fd = fopen(filename, PG_BINARY_R); } else diff --git a/src/bin/psql/command.h b/src/bin/psql/command.h index 852d645cfd..9d0c31c103 100644 --- a/src/bin/psql/command.h +++ b/src/bin/psql/command.h @@ -27,7 +27,7 @@ typedef enum _backslashResult extern backslashResult HandleSlashCmds(PsqlScanState scan_state, PQExpBuffer query_buf); -extern int process_file(char *filename, bool single_txn); +extern int process_file(char *filename, bool single_txn, bool use_relative_path); extern bool do_pset(const char *param, const char *value, diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 381150c75a..101d7a5a56 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -1159,7 +1159,7 @@ describeOneTableDetails(const char *schemaname, "c.relpersistence\n" "FROM pg_catalog.pg_class c\n " "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n" - "WHERE c.oid = '%s'\n", + "WHERE c.oid = '%s';", (verbose ? "pg_catalog.array_to_string(c.reloptions || " "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n" @@ -1175,7 +1175,7 @@ describeOneTableDetails(const char *schemaname, "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END\n" "FROM pg_catalog.pg_class c\n " "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n" - "WHERE c.oid = '%s'\n", + "WHERE c.oid = '%s';", (verbose ? "pg_catalog.array_to_string(c.reloptions || " "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n" @@ -1190,7 +1190,7 @@ describeOneTableDetails(const char *schemaname, "%s, c.reltablespace\n" "FROM pg_catalog.pg_class c\n " "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n" - "WHERE c.oid = '%s'\n", + "WHERE c.oid = '%s';", (verbose ? "pg_catalog.array_to_string(c.reloptions || " "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n" @@ -1203,7 +1203,7 @@ describeOneTableDetails(const char *schemaname, "SELECT relchecks, relkind, relhasindex, relhasrules, " "reltriggers <> 0, relhasoids, " "%s, reltablespace\n" - "FROM pg_catalog.pg_class WHERE oid = '%s'", + "FROM pg_catalog.pg_class WHERE oid = '%s';", (verbose ? "pg_catalog.array_to_string(reloptions, E', ')" : "''"), oid); @@ -1214,7 +1214,7 @@ describeOneTableDetails(const char *schemaname, "SELECT relchecks, relkind, relhasindex, relhasrules, " "reltriggers <> 0, relhasoids, " "'', reltablespace\n" - "FROM pg_catalog.pg_class WHERE oid = '%s'", + "FROM pg_catalog.pg_class WHERE oid = '%s';", oid); } else @@ -1223,7 +1223,7 @@ describeOneTableDetails(const char *schemaname, "SELECT relchecks, relkind, relhasindex, relhasrules, " "reltriggers <> 0, relhasoids, " "'', ''\n" - "FROM pg_catalog.pg_class WHERE oid = '%s'", + "FROM pg_catalog.pg_class WHERE oid = '%s';", oid); } @@ -1265,7 +1265,7 @@ describeOneTableDetails(const char *schemaname, { printfPQExpBuffer(&buf, "SELECT * FROM %s", fmtId(schemaname)); /* must be separate because fmtId isn't reentrant */ - appendPQExpBuffer(&buf, ".%s", fmtId(relationname)); + appendPQExpBuffer(&buf, ".%s;", fmtId(relationname)); res = PSQLexec(buf.data, false); if (!res) @@ -1310,7 +1310,7 @@ describeOneTableDetails(const char *schemaname, appendPQExpBuffer(&buf, ",\n a.attstorage, pg_catalog.col_description(a.attrelid, a.attnum)"); appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_attribute a"); appendPQExpBuffer(&buf, "\nWHERE a.attrelid = '%s' AND a.attnum > 0 AND NOT a.attisdropped", oid); - appendPQExpBuffer(&buf, "\nORDER BY a.attnum"); + appendPQExpBuffer(&buf, "\nORDER BY a.attnum;"); res = PSQLexec(buf.data, false); if (!res) @@ -1408,7 +1408,7 @@ describeOneTableDetails(const char *schemaname, PGresult *result; printfPQExpBuffer(&buf, - "SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid, true)", + "SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid, true);", oid); result = PSQLexec(buf.data, false); if (!result) @@ -1527,7 +1527,7 @@ describeOneTableDetails(const char *schemaname, "pg_catalog.pg_get_expr(i.indpred, i.indrelid, true)\n" "FROM pg_catalog.pg_index i, pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_am a\n" "WHERE i.indexrelid = c.oid AND c.oid = '%s' AND c.relam = a.oid\n" - "AND i.indrelid = c2.oid", + "AND i.indrelid = c2.oid;", oid); result = PSQLexec(buf.data, false); @@ -1598,7 +1598,7 @@ describeOneTableDetails(const char *schemaname, printfPQExpBuffer(&buf, "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true))\n" "FROM pg_catalog.pg_rewrite r\n" - "WHERE r.ev_class = '%s' AND r.rulename != '_RETURN' ORDER BY 1", + "WHERE r.ev_class = '%s' AND r.rulename != '_RETURN' ORDER BY 1;", oid); result = PSQLexec(buf.data, false); if (!result) @@ -1655,7 +1655,7 @@ describeOneTableDetails(const char *schemaname, " LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN ('p','u','x'))\n"); appendPQExpBuffer(&buf, "WHERE c.oid = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n" - "ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname", + "ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname;", oid); result = PSQLexec(buf.data, false); if (!result) @@ -1735,7 +1735,7 @@ describeOneTableDetails(const char *schemaname, "SELECT r.conname, " "pg_catalog.pg_get_constraintdef(r.oid, true)\n" "FROM pg_catalog.pg_constraint r\n" - "WHERE r.conrelid = '%s' AND r.contype = 'c'\nORDER BY 1", + "WHERE r.conrelid = '%s' AND r.contype = 'c'\nORDER BY 1;", oid); result = PSQLexec(buf.data, false); if (!result) @@ -1766,7 +1766,7 @@ describeOneTableDetails(const char *schemaname, "SELECT conname,\n" " pg_catalog.pg_get_constraintdef(r.oid, true) as condef\n" "FROM pg_catalog.pg_constraint r\n" - "WHERE r.conrelid = '%s' AND r.contype = 'f' ORDER BY 1", + "WHERE r.conrelid = '%s' AND r.contype = 'f' ORDER BY 1;", oid); result = PSQLexec(buf.data, false); if (!result) @@ -1797,7 +1797,7 @@ describeOneTableDetails(const char *schemaname, "SELECT conname, conrelid::pg_catalog.regclass,\n" " pg_catalog.pg_get_constraintdef(c.oid, true) as condef\n" "FROM pg_catalog.pg_constraint c\n" - "WHERE c.confrelid = '%s' AND c.contype = 'f' ORDER BY 1", + "WHERE c.confrelid = '%s' AND c.contype = 'f' ORDER BY 1;", oid); result = PSQLexec(buf.data, false); if (!result) @@ -1830,7 +1830,7 @@ describeOneTableDetails(const char *schemaname, "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), " "ev_enabled\n" "FROM pg_catalog.pg_rewrite r\n" - "WHERE r.ev_class = '%s' ORDER BY 1", + "WHERE r.ev_class = '%s' ORDER BY 1;", oid); } else @@ -1839,7 +1839,7 @@ describeOneTableDetails(const char *schemaname, "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), " "'O'::char AS ev_enabled\n" "FROM pg_catalog.pg_rewrite r\n" - "WHERE r.ev_class = '%s' ORDER BY 1", + "WHERE r.ev_class = '%s' ORDER BY 1;", oid); } result = PSQLexec(buf.data, false); @@ -1945,7 +1945,7 @@ describeOneTableDetails(const char *schemaname, " (SELECT 1 FROM pg_catalog.pg_depend d " " JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) " " WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))"); - appendPQExpBuffer(&buf, "\nORDER BY 1"); + appendPQExpBuffer(&buf, "\nORDER BY 1;"); result = PSQLexec(buf.data, false); if (!result) @@ -2053,7 +2053,7 @@ describeOneTableDetails(const char *schemaname, "SELECT s.srvname\n" "FROM pg_catalog.pg_foreign_table f,\n" " pg_catalog.pg_foreign_server s\n" - "WHERE f.ftrelid = %s AND s.oid = f.ftserver", + "WHERE f.ftrelid = %s AND s.oid = f.ftserver;", oid); result = PSQLexec(buf.data, false); if (!result) @@ -2071,7 +2071,7 @@ describeOneTableDetails(const char *schemaname, } /* print inherited tables */ - printfPQExpBuffer(&buf, "SELECT c.oid::pg_catalog.regclass FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i WHERE c.oid=i.inhparent AND i.inhrelid = '%s' ORDER BY inhseqno", oid); + printfPQExpBuffer(&buf, "SELECT c.oid::pg_catalog.regclass FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i WHERE c.oid=i.inhparent AND i.inhrelid = '%s' ORDER BY inhseqno;", oid); result = PSQLexec(buf.data, false); if (!result) @@ -2233,7 +2233,7 @@ add_tablespace_footer(printTableContent *const cont, char relkind, initPQExpBuffer(&buf); printfPQExpBuffer(&buf, "SELECT spcname FROM pg_catalog.pg_tablespace\n" - "WHERE oid = '%u'", tablespace); + "WHERE oid = '%u';", tablespace); result = PSQLexec(buf.data, false); if (!result) return; @@ -2442,7 +2442,7 @@ listDbRoleSettings(const char *pattern, const char *pattern2) NULL, "pg_roles.rolname", NULL, NULL); processSQLNamePattern(pset.db, &buf, pattern2, havewhere, false, NULL, "pg_database.datname", NULL, NULL); - appendPQExpBufferStr(&buf, "ORDER BY role, database"); + appendPQExpBufferStr(&buf, "ORDER BY role, database;"); } else { @@ -3188,7 +3188,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname) " p.prslextype::pg_catalog.regproc, \n" " pg_catalog.obj_description(p.prslextype, 'pg_proc') \n" " FROM pg_catalog.pg_ts_parser p \n" - " WHERE p.oid = '%s' \n", + " WHERE p.oid = '%s';", gettext_noop("Start parse"), gettext_noop("Method"), gettext_noop("Function"), @@ -3549,7 +3549,7 @@ describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname, "FROM pg_catalog.pg_ts_config AS c, pg_catalog.pg_ts_config_map AS m \n" "WHERE c.oid = '%s' AND m.mapcfg = c.oid \n" "GROUP BY m.mapcfg, m.maptokentype, c.cfgparser \n" - "ORDER BY 1", + "ORDER BY 1;", gettext_noop("Token"), gettext_noop("Dictionaries"), oid); diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index ac5edca65d..e56ab61ac6 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -158,7 +158,7 @@ slashUsage(unsigned short int pager) { FILE *output; - output = PageOutput(92, pager); + output = PageOutput(93, pager); /* if you add/remove a line here, change the row count above */ @@ -184,6 +184,7 @@ slashUsage(unsigned short int pager) fprintf(output, _(" \\copy ... perform SQL COPY with data stream to the client host\n")); fprintf(output, _(" \\echo [STRING] write string to standard output\n")); fprintf(output, _(" \\i FILE execute commands from file\n")); + fprintf(output, _(" \\ir FILE as \\i, but relative to location of current script\n")); fprintf(output, _(" \\o [FILE] send all query results to file or |pipe\n")); fprintf(output, _(" \\qecho [STRING] write string to query output stream (see \\o)\n")); fprintf(output, "\n"); diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h index 7228f9d0ee..3aebf53299 100644 --- a/src/bin/psql/settings.h +++ b/src/bin/psql/settings.h @@ -81,7 +81,7 @@ typedef struct _psqlSettings bool cur_cmd_interactive; int sversion; /* backend server version */ const char *progname; /* in case you renamed psql */ - char *inputfile; /* for error reporting */ + char *inputfile; /* file being currently processed, if any */ char *dirname; /* current directory for \s display */ uint64 lineno; /* also for error reporting */ diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c index 7b8078c21e..3c17eece7b 100644 --- a/src/bin/psql/startup.c +++ b/src/bin/psql/startup.c @@ -256,7 +256,7 @@ main(int argc, char *argv[]) if (!options.no_psqlrc) process_psqlrc(argv[0]); - successResult = process_file(options.action_string, options.single_txn); + successResult = process_file(options.action_string, options.single_txn, false); } /* @@ -604,9 +604,9 @@ process_psqlrc_file(char *filename) sprintf(psqlrc, "%s-%s", filename, PG_VERSION); if (access(psqlrc, R_OK) == 0) - (void) process_file(psqlrc, false); + (void) process_file(psqlrc, false, false); else if (access(filename, R_OK) == 0) - (void) process_file(filename, false); + (void) process_file(filename, false, false); free(psqlrc); } diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 32f418306c..4f7df367e5 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -735,7 +735,7 @@ psql_completion(char *text, int start, int end) "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL", "\\dn", "\\do", "\\dp", "\\drds", "\\ds", "\\dS", "\\dt", "\\dT", "\\dv", "\\du", "\\e", "\\echo", "\\ef", "\\encoding", - "\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l", + "\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\ir", "\\l", "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink", "\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r", "\\set", "\\sf", "\\t", "\\T", @@ -2874,6 +2874,7 @@ psql_completion(char *text, int start, int end) strcmp(prev_wd, "\\e") == 0 || strcmp(prev_wd, "\\edit") == 0 || strcmp(prev_wd, "\\g") == 0 || strcmp(prev_wd, "\\i") == 0 || strcmp(prev_wd, "\\include") == 0 || + strcmp(prev_wd, "\\ir") == 0 || strcmp(prev_wd, "\\include_relative") == 0 || strcmp(prev_wd, "\\o") == 0 || strcmp(prev_wd, "\\out") == 0 || strcmp(prev_wd, "\\s") == 0 || strcmp(prev_wd, "\\w") == 0 || strcmp(prev_wd, "\\write") == 0 diff --git a/src/include/port.h b/src/include/port.h index 4c7ed64317..2cab65fbde 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -34,6 +34,7 @@ extern bool pg_set_block(pgsocket sock); /* Portable path handling for Unix/Win32 (in path.c) */ +extern bool has_drive_prefix(const char *filename); extern char *first_dir_separator(const char *filename); extern char *last_dir_separator(const char *filename); extern char *first_path_var_separator(const char *pathlist); diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 0a419dcf65..f4490adc31 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -17,6 +17,15 @@ #include "access/htup.h" #include "nodes/pg_list.h" +/* Result list element for get_op_btree_interpretation */ +typedef struct OpBtreeInterpretation +{ + Oid opfamily_id; /* btree opfamily containing operator */ + int strategy; /* its strategy number */ + Oid oplefttype; /* declared left input datatype */ + Oid oprighttype; /* declared right input datatype */ +} OpBtreeInterpretation; + /* I/O function selector for get_type_io_data */ typedef enum IOFuncSelector { @@ -50,8 +59,7 @@ extern bool get_compatible_hash_operators(Oid opno, Oid *lhs_opno, Oid *rhs_opno); extern bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno); -extern void get_op_btree_interpretation(Oid opno, - List **opfamilies, List **opstrats); +extern List *get_op_btree_interpretation(Oid opno); extern bool equality_ops_are_compatible(Oid opno1, Oid opno2); extern Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum); diff --git a/src/port/path.c b/src/port/path.c index 6991bc7247..13ca4f3f1c 100644 --- a/src/port/path.c +++ b/src/port/path.c @@ -75,6 +75,17 @@ skip_drive(const char *path) #endif /* + * has_drive_prefix + * + * Return true if the given pathname has a drive prefix. + */ +bool +has_drive_prefix(const char *path) +{ + return skip_drive(path) != path; +} + +/* * first_dir_separator * * Find the location of the first directory separator, return diff --git a/src/tools/msvc/pgbison.bat b/src/tools/msvc/pgbison.bat index c5d355e5ab..27b5353a55 100755 --- a/src/tools/msvc/pgbison.bat +++ b/src/tools/msvc/pgbison.bat @@ -1,51 +1,7 @@ @echo off -REM src/tools/msvc/pgbison.bat - -IF NOT EXIST src\tools\msvc\buildenv.pl goto nobuildenv -perl -e "require 'src/tools/msvc/buildenv.pl'; while(($k,$v) = each %%ENV) { print qq[\@SET $k=$v\n]; }" > bldenv.bat -CALL bldenv.bat -del bldenv.bat -:nobuildenv - -SET BV= -for /F "tokens=4 usebackq" %%f in (`bison -V`) do if "!BV!"=="" SET BV=%%f -if "%BV%"=="" goto novarexp -if %BV% EQU 1.875 goto bisonok -if %BV% GEQ 2.2 goto bisonok -goto nobison -:bisonok - -if "%1" == "src\backend\parser\gram.y" call :generate %1 src\backend\parser\gram.c src\backend\parser\gram.h -if "%1" == "src\backend\bootstrap\bootparse.y" call :generate %1 src\backend\bootstrap\bootparse.c -if "%1" == "src\backend\replication\repl_gram.y" call :generate %1 src\backend\replication\repl_gram.c -if "%1" == "src\pl\plpgsql\src\gram.y" call :generate %1 src\pl\plpgsql\src\pl_gram.c src\pl\plpgsql\src\pl_gram.h -if "%1" == "src\test\isolation\specparse.y" call :generate %1 src\test\isolation\specparse.c -if "%1" == "src\interfaces\ecpg\preproc\preproc.y" call :generate %1 src\interfaces\ecpg\preproc\preproc.c src\interfaces\ecpg\preproc\preproc.h -if "%1" == "contrib\cube\cubeparse.y" call :generate %1 contrib\cube\cubeparse.c -if "%1" == "contrib\seg\segparse.y" call :generate %1 contrib\seg\segparse.c - -echo Unknown bison input: %1 -exit 1 -:generate -SET fn=%1 -SET cf=%2 -bison.exe -d %fn% -o %cf% -if errorlevel 1 exit 1 -SET hf=%cf:~0,-2%.h -if not "%hf%"=="%3" ( - copy /y %hf% %3 - if errorlevel 1 exit 1 - del %hf% -) -exit 0 - - -:novarexp -echo pgbison must be called with cmd /V:ON /C pgbison to work! -exit 1 - -:nobison -echo WARNING! Bison install not found, or unsupported Bison version. -echo Attempting to build without. -exit 0 +REM src/tools/msvc/pgbison.bat +REM all the logic for this now belongs in builddoc.pl. This file really +REM only exists so you don't have to type "perl src/tools/msvc/pgbison.pl" +REM Resist any temptation to add any logic here. +@perl src/tools/msvc/pgbison.pl %* diff --git a/src/tools/msvc/pgbison.pl b/src/tools/msvc/pgbison.pl new file mode 100644 index 0000000000..c48863aff6 --- /dev/null +++ b/src/tools/msvc/pgbison.pl @@ -0,0 +1,48 @@ +# -*-perl-*- hey - emacs - this is a perl file + +# src/tools/msvc/pgbison.pl + +use strict; +use File::Basename; + +# assume we are in the postgres source root + +require 'src/tools/msvc/buildenv.pl' if -e 'src/tools/msvc/buildenv.pl'; + +my ($bisonver) = `bison -V`; # grab first line +$bisonver=(split(/\s+/,$bisonver))[3]; # grab version number + +unless ($bisonver eq '1.875' || $bisonver ge '2.2') +{ + print "WARNING! Bison install not found, or unsupported Bison version.\n"; + print "echo Attempting to build without.\n"; + exit 0; +} + +my $input = shift; +if ($input !~ /\.y$/) +{ + print "Input must be a .y file\n"; + exit 1; +} +elsif (!-e $input) +{ + print "Input file $input not found\n"; + exit 1; +} + +(my $output = $input) =~ s/\.y$/.c/; + +# plpgsql just has to be different +$output =~ s/gram\.c$/pl_gram.c/ if $input =~ /src.pl.plpgsql.src.gram\.y$/; + +my $makefile = dirname($input) . "/Makefile"; +my ($mf, $make); +open($mf,$makefile); +local $/ = undef; +$make=<$mf>; +close($mf); +my $headerflag = ($make =~ /\$\(BISON\)\s+-d/ ? '-d' : ''); + +system("bison $headerflag $input -o $output"); +exit $? >> 8; diff --git a/src/tools/msvc/pgflex.bat b/src/tools/msvc/pgflex.bat index e26724cc5f..144422d313 100755 --- a/src/tools/msvc/pgflex.bat +++ b/src/tools/msvc/pgflex.bat @@ -1,45 +1,7 @@ @echo off -REM src/tools/msvc/pgflex.bat - -REM silence flex bleatings about file path style -SET CYGWIN=nodosfilewarning - -IF NOT EXIST src\tools\msvc\buildenv.pl goto nobuildenv -perl -e "require 'src/tools/msvc/buildenv.pl'; while(($k,$v) = each %%ENV) { print qq[\@SET $k=$v\n]; }" > bldenv.bat -CALL bldenv.bat -del bldenv.bat -:nobuildenv - -flex -V > NUL -if errorlevel 1 goto noflex -if "%1" == "src\backend\parser\scan.l" call :generate %1 src\backend\parser\scan.c -CF -if "%1" == "src\backend\bootstrap\bootscanner.l" call :generate %1 src\backend\bootstrap\bootscanner.c -if "%1" == "src\backend\utils\misc\guc-file.l" call :generate %1 src\backend\utils\misc\guc-file.c -if "%1" == "src\backend\replication\repl_scanner.l" call :generate %1 src\backend\replication\repl_scanner.c -if "%1" == "src\test\isolation\specscanner.l" call :generate %1 src\test\isolation\specscanner.c -if "%1" == "src\interfaces\ecpg\preproc\pgc.l" call :generate %1 src\interfaces\ecpg\preproc\pgc.c -if "%1" == "src\bin\psql\psqlscan.l" call :generate %1 src\bin\psql\psqlscan.c -if "%1" == "contrib\cube\cubescan.l" call :generate %1 contrib\cube\cubescan.c -if "%1" == "contrib\seg\segscan.l" call :generate %1 contrib\seg\segscan.c - -echo Unknown flex input: %1 -exit 1 - -REM For non-reentrant scanners we need to fix up the yywrap macro definition -REM to keep the MS compiler happy. -REM For reentrant scanners (like the core scanner) we do not -REM need to (and must not) change the yywrap definition. -:generate -flex %3 -o%2 %1 -if errorlevel 1 exit %errorlevel% -perl -n -e "exit 1 if /^\%%option\s+reentrant/;" %1 -if errorlevel 1 exit 0 -perl -pi.bak -e "s/yywrap\(n\)/yywrap()/;" %2 -if errorlevel 1 exit %errorlevel% -del %2.bak -exit 0 - -:noflex -echo WARNING! flex install not found, attempting to build without -exit 0 +REM src/tools/msvc/pgflex.bat +REM all the logic for this now belongs in builddoc.pl. This file really +REM only exists so you don't have to type "perl src/tools/msvc/pgflex.pl" +REM Resist any temptation to add any logic here. +@perl src/tools/msvc/pgflex.pl %* diff --git a/src/tools/msvc/pgflex.pl b/src/tools/msvc/pgflex.pl new file mode 100644 index 0000000000..332d422f64 --- /dev/null +++ b/src/tools/msvc/pgflex.pl @@ -0,0 +1,76 @@ +# -*-perl-*- hey - emacs - this is a perl file + +# src/tools/msvc/pgflex.pl + +# silence flex bleatings about file path style +$ENV{CYGWIN} = 'nodosfilewarning'; + +use strict; +use File::Basename; + +# assume we are in the postgres source root + +require 'src/tools/msvc/buildenv.pl' if -e 'src/tools/msvc/buildenv.pl'; + +system('flex -V > NUL'); +if ($? != 0) +{ + print "WARNING! flex install not found, attempting to build without\n"; + exit 0; +} + +my $input = shift; +if ($input !~ /\.l$/) +{ + print "Input must be a .l file\n"; + exit 1; +} +elsif (!-e $input) +{ + print "Input file $input not found\n"; + exit 1; +} + +(my $output = $input) =~ s/\.l$/.c/; + +# get flex flags from make file +my $makefile = dirname($input) . "/Makefile"; +my ($mf, $make); +open($mf,$makefile); +local $/ = undef; +$make=<$mf>; +close($mf); +my $flexflags = ($make =~ /^\s*FLEXFLAGS\s*=\s*(\S.*)/m ? $1 : ''); + +system("flex $flexflags -o$output $input"); +if ($? == 0) +{ + + # For non-reentrant scanners we need to fix up the yywrap macro definition + # to keep the MS compiler happy. + # For reentrant scanners (like the core scanner) we do not + # need to (and must not) change the yywrap definition. + my $lfile; + open($lfile,$input) || die "opening $input for reading: $!"; + my $lcode = <$lfile>; + close($lfile); + if ($lcode !~ /\%option\sreentrant/) + { + my $cfile; + open($cfile,$output) || die "opening $output for reading: $!"; + my $ccode = <$cfile>; + close($cfile); + $ccode =~ s/yywrap\(n\)/yywrap()/; + open($cfile,">$output") || die "opening $output for reading: $!"; + print $cfile $ccode; + close($cfile); + } + + exit 0; + +} +else +{ + exit $? >> 8; +} + |