diff options
| author | Bruce Momjian | 2003-09-07 04:37:13 +0000 |
|---|---|---|
| committer | Bruce Momjian | 2003-09-07 04:37:13 +0000 |
| commit | c40ed5131948495a30caac2efff7927b673cd2d0 (patch) | |
| tree | 4ee7a43fa571f53a370e60d0be421f4c6927c97f | |
| parent | 432ca9116bc51f6cfe6e88be33dbe6cb078cda9d (diff) | |
Update this branch to match CVS head, includes WIN32 improvements.
383 files changed, 80564 insertions, 83185 deletions
@@ -212,6 +212,7 @@ Add new DateStyle values MDY, DMY, and YMD, honor US and European for prepared statements) (Tom) Assume NaN value to be larger than any other value in MIN()/MAX() (Tom) Prevent interval from supressing ':00' seconds display +New pg_get_triggerdef(prettyprint) and pg_constraint_is_visible() functions _________________________________________________________________ @@ -259,6 +260,10 @@ Allow pqInternalNotice() to accept a format string and args instead of just a preformatted message (Tom, Sean Chittenden) Allow control SSL negotiation with sslmode values "disable", "allow", "Prefer", and "require" (Jon Jensen) +Allow new error codes and levels of text (Tom) +Allow access to the underlying table and column of a query result (Tom) +Allow access to the current transaction status (Tom) +Add ability to pass binary data directly to the backend (Tom) _________________________________________________________________ diff --git a/config/ac_func_accept_argtypes.m4 b/config/ac_func_accept_argtypes.m4 index f22d9056599..abe5b1e77ec 100644 --- a/config/ac_func_accept_argtypes.m4 +++ b/config/ac_func_accept_argtypes.m4 @@ -1,4 +1,4 @@ -# $Header: /cvsroot/pgsql/config/ac_func_accept_argtypes.m4,v 1.4 2002/03/29 17:32:53 petere Exp $ +# $Header: /cvsroot/pgsql/config/ac_func_accept_argtypes.m4,v 1.4.4.1 2003/09/07 04:36:39 momjian Exp $ # This comes from the official Autoconf macro archive at # <http://research.cys.de/autoconf-archive/> # (I removed the $ before the Id CVS keyword below.) @@ -7,9 +7,10 @@ dnl @synopsis AC_FUNC_ACCEPT_ARGTYPES dnl dnl Checks the data types of the three arguments to accept(). Results are -dnl placed into the symbols ACCEPT_TYPE_ARG[123], consistent with the -dnl following example: +dnl placed into the symbols ACCEPT_TYPE_RETURN and ACCEPT_TYPE_ARG[123], +dnl consistent with the following example: dnl +dnl #define ACCEPT_TYPE_RETURN int dnl #define ACCEPT_TYPE_ARG1 int dnl #define ACCEPT_TYPE_ARG2 struct sockaddr * dnl #define ACCEPT_TYPE_ARG3 socklen_t @@ -36,24 +37,29 @@ dnl # Solaris 7 and 8 have arg3 as 'void *' (disguised as 'Psocklen_t' # which is *not* 'socklen_t *'). If we detect that, then we assume # 'int' as the result, because that ought to work best. +# +# On Win32, accept() returns 'unsigned int PASCAL' AC_DEFUN([AC_FUNC_ACCEPT_ARGTYPES], [AC_MSG_CHECKING([types of arguments for accept()]) - AC_CACHE_VAL(ac_cv_func_accept_arg1,dnl - [AC_CACHE_VAL(ac_cv_func_accept_arg2,dnl - [AC_CACHE_VAL(ac_cv_func_accept_arg3,dnl - [for ac_cv_func_accept_arg1 in 'int' 'unsigned int'; do - for ac_cv_func_accept_arg2 in 'struct sockaddr *' 'const struct sockaddr *' 'void *'; do - for ac_cv_func_accept_arg3 in 'int' 'size_t' 'socklen_t' 'unsigned int' 'void'; do - AC_TRY_COMPILE( + AC_CACHE_VAL(ac_cv_func_accept_return,dnl + [AC_CACHE_VAL(ac_cv_func_accept_arg1,dnl + [AC_CACHE_VAL(ac_cv_func_accept_arg2,dnl + [AC_CACHE_VAL(ac_cv_func_accept_arg3,dnl + [for ac_cv_func_accept_return in 'int' 'unsigned int PASCAL'; do + for ac_cv_func_accept_arg1 in 'int' 'unsigned int'; do + for ac_cv_func_accept_arg2 in 'struct sockaddr *' 'const struct sockaddr *' 'void *'; do + for ac_cv_func_accept_arg3 in 'int' 'size_t' 'socklen_t' 'unsigned int' 'void'; do + AC_TRY_COMPILE( [#ifdef HAVE_SYS_TYPES_H #include <sys/types.h> #endif #ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> #endif -extern int accept ($ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *);], - [], [ac_not_found=no; break 3], [ac_not_found=yes]) +extern $ac_cv_func_accept_return accept ($ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *);], + [], [ac_not_found=no; break 4], [ac_not_found=yes]) + done done done done @@ -63,10 +69,13 @@ extern int accept ($ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func if test "$ac_cv_func_accept_arg3" = "void"; then ac_cv_func_accept_arg3=int fi + ])dnl AC_CACHE_VAL ])dnl AC_CACHE_VAL ])dnl AC_CACHE_VAL ])dnl AC_CACHE_VAL - AC_MSG_RESULT([$ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *]) + AC_MSG_RESULT([$ac_cv_func_accept_return, $ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *]) + AC_DEFINE_UNQUOTED(ACCEPT_TYPE_RETURN, $ac_cv_func_accept_return, + [Define to the return type of 'accept']) AC_DEFINE_UNQUOTED(ACCEPT_TYPE_ARG1, $ac_cv_func_accept_arg1, [Define to the type of arg 1 of 'accept']) AC_DEFINE_UNQUOTED(ACCEPT_TYPE_ARG2, $ac_cv_func_accept_arg2, diff --git a/config/python.m4 b/config/python.m4 index ce126419b77..d8bf77d2998 100644 --- a/config/python.m4 +++ b/config/python.m4 @@ -1,7 +1,7 @@ # # Autoconf macros for configuring the build of Python extension modules # -# $Header: /cvsroot/pgsql/config/python.m4,v 1.5 2002/09/04 22:54:18 petere Exp $ +# $Header: /cvsroot/pgsql/config/python.m4,v 1.5.4.1 2003/09/07 04:36:39 momjian Exp $ # # PGAC_PATH_PYTHON @@ -26,19 +26,14 @@ python_version=`${PYTHON} -c "import sys; print sys.version[[:3]]"` python_prefix=`${PYTHON} -c "import sys; print sys.prefix"` python_execprefix=`${PYTHON} -c "import sys; print sys.exec_prefix"` python_configdir="${python_execprefix}/lib/python${python_version}/config" -python_moduledir="${python_prefix}/lib/python${python_version}/site-packages" -python_moduleexecdir="${python_execprefix}/lib/python${python_version}/site-packages" python_includespec="-I${python_prefix}/include/python${python_version}" if test "$python_prefix" != "$python_execprefix"; then python_includespec="-I${python_execprefix}/include/python${python_version} $python_includespec" fi -AC_SUBST(python_version)[]dnl AC_SUBST(python_prefix)[]dnl AC_SUBST(python_execprefix)[]dnl AC_SUBST(python_configdir)[]dnl -AC_SUBST(python_moduledir)[]dnl -AC_SUBST(python_moduleexecdir)[]dnl AC_SUBST(python_includespec)[]dnl # This should be enough of a message. if test "$python_prefix" != "$python_execprefix"; then @@ -49,19 +44,6 @@ fi ])# _PGAC_CHECK_PYTHON_DIRS -# PGAC_CHECK_PYTHON_MODULE_SETUP -# ------------------------------ -# Finds things required to build a Python extension module. -# This used to do more, that's why it's separate. -# -# It would be nice if we could check whether the current setup allows -# the build of the shared module. Future project. -AC_DEFUN([PGAC_CHECK_PYTHON_MODULE_SETUP], -[ - AC_REQUIRE([_PGAC_CHECK_PYTHON_DIRS]) -])# PGAC_CHECK_PYTHON_MODULE_SETUP - - # PGAC_CHECK_PYTHON_EMBED_SETUP # ----------------------------- # Courtesy of the INN 2.3.1 package... diff --git a/configure b/configure index 2ba5879468f..be06d57d51d 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.53 for PostgreSQL 7.4beta1. +# Generated by GNU Autoconf 2.53 for PostgreSQL 7.4beta2. # # Report bugs to <pgsql-bugs@postgresql.org>. # @@ -258,8 +258,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='PostgreSQL' PACKAGE_TARNAME='postgresql' -PACKAGE_VERSION='7.4beta1' -PACKAGE_STRING='PostgreSQL 7.4beta1' +PACKAGE_VERSION='7.4beta2' +PACKAGE_STRING='PostgreSQL 7.4beta2' PACKAGE_BUGREPORT='pgsql-bugs@postgresql.org' ac_unique_file="src/backend/access/common/heaptuple.c" @@ -769,7 +769,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures PostgreSQL 7.4beta1 to adapt to many kinds of systems. +\`configure' configures PostgreSQL 7.4beta2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -830,7 +830,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of PostgreSQL 7.4beta1:";; + short | recursive ) echo "Configuration of PostgreSQL 7.4beta2:";; esac cat <<\_ACEOF @@ -860,7 +860,7 @@ Optional Packages: --with-tclconfig=DIR tclConfig.sh and tkConfig.sh are in DIR --with-tkconfig=DIR tkConfig.sh is in DIR --with-perl build Perl modules (PL/Perl) - --with-python build Python interface module + --with-python build Python modules (PL/Python) --with-java build JDBC interface and Java tools --with-krb4[=DIR] build with Kerberos 4 support [/usr/athena] --with-krb5[=DIR] build with Kerberos 5 support [/usr/athena] @@ -949,7 +949,7 @@ fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF -PostgreSQL configure 7.4beta1 +PostgreSQL configure 7.4beta2 generated by GNU Autoconf 2.53 Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 @@ -966,7 +966,7 @@ cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by PostgreSQL $as_me 7.4beta1, which was +It was created by PostgreSQL $as_me 7.4beta2, which was generated by GNU Autoconf 2.53. Invocation command line was $ $0 $@ @@ -2370,6 +2370,12 @@ fi { echo "$as_me:$LINENO: using CFLAGS=$CFLAGS" >&5 echo "$as_me: using CFLAGS=$CFLAGS" >&6;} +# We already have this in Makefile.win32, but configure needs it too +if test "$PORTNAME" = "win32" +then + CPPFLAGS="$CPPFLAGS -Isrc/include/port/win32" +fi + # Check if the compiler still works with the template settings echo "$as_me:$LINENO: checking whether the C compiler still works" >&5 echo $ECHO_N "checking whether the C compiler still works... $ECHO_C" >&6 @@ -2981,7 +2987,7 @@ echo "${ECHO_T}$with_perl" >&6 # -# Optionally build Python interface module +# Optionally build Python modules (PL/Python) # echo "$as_me:$LINENO: checking whether to build Python modules" >&5 echo $ECHO_N "checking whether to build Python modules... $ECHO_C" >&6 @@ -4294,8 +4300,6 @@ python_version=`${PYTHON} -c "import sys; print sys.version[:3]"` python_prefix=`${PYTHON} -c "import sys; print sys.prefix"` python_execprefix=`${PYTHON} -c "import sys; print sys.exec_prefix"` python_configdir="${python_execprefix}/lib/python${python_version}/config" -python_moduledir="${python_prefix}/lib/python${python_version}/site-packages" -python_moduleexecdir="${python_execprefix}/lib/python${python_version}/site-packages" python_includespec="-I${python_prefix}/include/python${python_version}" if test "$python_prefix" != "$python_execprefix"; then python_includespec="-I${python_execprefix}/include/python${python_version} $python_includespec" @@ -4311,9 +4315,6 @@ echo "${ECHO_T}$python_prefix/lib/python${python_version}" >&6 fi - - - echo "$as_me:$LINENO: checking how to link an embedded Python application" >&5 echo $ECHO_N "checking how to link an embedded Python application... $ECHO_C" >&6 @@ -10815,19 +10816,23 @@ _ACEOF fi echo "$as_me:$LINENO: checking types of arguments for accept()" >&5 echo $ECHO_N "checking types of arguments for accept()... $ECHO_C" >&6 - if test "${ac_cv_func_accept_arg1+set}" = set; then + if test "${ac_cv_func_accept_return+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - if test "${ac_cv_func_accept_arg2+set}" = set; then + if test "${ac_cv_func_accept_arg1+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - if test "${ac_cv_func_accept_arg3+set}" = set; then + if test "${ac_cv_func_accept_arg2+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - for ac_cv_func_accept_arg1 in 'int' 'unsigned int'; do - for ac_cv_func_accept_arg2 in 'struct sockaddr *' 'const struct sockaddr *' 'void *'; do - for ac_cv_func_accept_arg3 in 'int' 'size_t' 'socklen_t' 'unsigned int' 'void'; do - cat >conftest.$ac_ext <<_ACEOF + if test "${ac_cv_func_accept_arg3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + for ac_cv_func_accept_return in 'int' 'unsigned int PASCAL'; do + for ac_cv_func_accept_arg1 in 'int' 'unsigned int'; do + for ac_cv_func_accept_arg2 in 'struct sockaddr *' 'const struct sockaddr *' 'void *'; do + for ac_cv_func_accept_arg3 in 'int' 'size_t' 'socklen_t' 'unsigned int' 'void'; do + cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" #include "confdefs.h" #ifdef HAVE_SYS_TYPES_H @@ -10836,7 +10841,7 @@ else #ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> #endif -extern int accept ($ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *); +extern $ac_cv_func_accept_return accept ($ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" @@ -10863,13 +10868,14 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - ac_not_found=no; break 3 + ac_not_found=no; break 4 else echo "$as_me: failed program was:" >&5 cat conftest.$ac_ext >&5 ac_not_found=yes fi rm -f conftest.$ac_objext conftest.$ac_ext + done done done done @@ -10887,8 +10893,15 @@ fi fi fi - echo "$as_me:$LINENO: result: $ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *" >&5 -echo "${ECHO_T}$ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *" >&6 + +fi + echo "$as_me:$LINENO: result: $ac_cv_func_accept_return, $ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *" >&5 +echo "${ECHO_T}$ac_cv_func_accept_return, $ac_cv_func_accept_arg1, $ac_cv_func_accept_arg2, $ac_cv_func_accept_arg3 *" >&6 + +cat >>confdefs.h <<_ACEOF +#define ACCEPT_TYPE_RETURN $ac_cv_func_accept_return +_ACEOF + cat >>confdefs.h <<_ACEOF #define ACCEPT_TYPE_ARG1 $ac_cv_func_accept_arg1 @@ -11198,6 +11211,7 @@ fi +HAVE_IPV6=no echo "$as_me:$LINENO: checking for struct sockaddr_in6" >&5 echo $ECHO_N "checking for struct sockaddr_in6... $ECHO_C" >&6 if test "${ac_cv_type_struct_sockaddr_in6+set}" = set; then @@ -11319,11 +11333,13 @@ cat >>confdefs.h <<\_ACEOF #define HAVE_IPV6 1 _ACEOF + HAVE_IPV6=yes fi fi + echo "$as_me:$LINENO: checking for PS_STRINGS" >&5 echo $ECHO_N "checking for PS_STRINGS... $ECHO_C" >&6 if test "${pgac_cv_var_PS_STRINGS+set}" = set; then @@ -13102,6 +13118,7 @@ fi # # For each platform, we need to know about any special compile and link # libraries, and whether the normal C function names are thread-safe. +# See the comment at the top of src/port/thread.c for more information. # if test "$enable_thread_safety" = yes; then if test "${ac_cv_header_pthread_h+set}" = set; then @@ -13208,8 +13225,8 @@ fi if test $ac_cv_header_pthread_h = yes; then : else - { { echo "$as_me:$LINENO: error: pthread.h not found, required for --with-threads" >&5 -echo "$as_me: error: pthread.h not found, required for --with-threads" >&2;} + { { echo "$as_me:$LINENO: error: pthread.h not found, required for --enable-thread-safetys" >&5 +echo "$as_me: error: pthread.h not found, required for --enable-thread-safetys" >&2;} { (exit 1); exit 1; }; } fi @@ -13221,12 +13238,14 @@ Cannot enable threads on your platform. Please report your platform threading info to the PostgreSQL mailing lists so it can be added to the next release. Report all compile flags, link flags, functions, or libraries required for threading support. +See the comment at the top of src/port/thread.c for more information. " >&5 echo "$as_me: error: Cannot enable threads on your platform. Please report your platform threading info to the PostgreSQL mailing lists so it can be added to the next release. Report all compile flags, link flags, functions, or libraries required for threading support. +See the comment at the top of src/port/thread.c for more information. " >&2;} { (exit 1); exit 1; }; } fi @@ -13254,22 +13273,88 @@ _CFLAGS="$CFLAGS" _LIBS="$LIBS" CFLAGS="$CFLAGS $THREAD_CFLAGS" LIBS="$LIBS $THREAD_LIBS" +echo "$as_me:$LINENO: checking for strerror_r" >&5 +echo $ECHO_N "checking for strerror_r... $ECHO_C" >&6 +if test "${ac_cv_func_strerror_r+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strerror_r (); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strerror_r (); +char (*f) (); +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_strerror_r) || defined (__stub___strerror_r) +choke me +#else +f = strerror_r; +#endif + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_strerror_r=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_func_strerror_r=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_strerror_r" >&5 +echo "${ECHO_T}$ac_cv_func_strerror_r" >&6 +if test $ac_cv_func_strerror_r = yes; then + : +else + { { echo "$as_me:$LINENO: error: strerror_r not found, required on this platform for --enable-thread-safety" >&5 +echo "$as_me: error: strerror_r not found, required on this platform for --enable-thread-safety" >&2;} + { (exit 1); exit 1; }; } +fi -for ac_func in strerror_r getpwuid_r gethostbyname_r -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 -if eval "test \"\${$as_ac_var+set}\" = set"; then +echo "$as_me:$LINENO: checking for getpwuid_r" >&5 +echo $ECHO_N "checking for getpwuid_r... $ECHO_C" >&6 +if test "${ac_cv_func_getpwuid_r+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. */ + which can conflict with char getpwuid_r (); below. */ #include <assert.h> /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus @@ -13277,7 +13362,7 @@ extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ -char $ac_func (); +char getpwuid_r (); char (*f) (); #ifdef F77_DUMMY_MAIN @@ -13292,10 +13377,10 @@ main () /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ -#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +#if defined (__stub_getpwuid_r) || defined (__stub___getpwuid_r) choke me #else -f = $ac_func; +f = getpwuid_r; #endif ; @@ -13314,23 +13399,95 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - eval "$as_ac_var=yes" + ac_cv_func_getpwuid_r=yes else echo "$as_me: failed program was:" >&5 cat conftest.$ac_ext >&5 -eval "$as_ac_var=no" +ac_cv_func_getpwuid_r=no fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF +echo "$as_me:$LINENO: result: $ac_cv_func_getpwuid_r" >&5 +echo "${ECHO_T}$ac_cv_func_getpwuid_r" >&6 +if test $ac_cv_func_getpwuid_r = yes; then + : +else + { { echo "$as_me:$LINENO: error: getpwuid_r not found, required on this platform for --enable-thread-safety" >&5 +echo "$as_me: error: getpwuid_r not found, required on this platform for --enable-thread-safety" >&2;} + { (exit 1); exit 1; }; } +fi + +echo "$as_me:$LINENO: checking for gethostbyname_r" >&5 +echo $ECHO_N "checking for gethostbyname_r... $ECHO_C" >&6 +if test "${ac_cv_func_gethostbyname_r+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostbyname_r (); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname_r (); +char (*f) (); +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname_r) || defined (__stub___gethostbyname_r) +choke me +#else +f = gethostbyname_r; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_gethostbyname_r=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_func_gethostbyname_r=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname_r" >&5 +echo "${ECHO_T}$ac_cv_func_gethostbyname_r" >&6 +if test $ac_cv_func_gethostbyname_r = yes; then + : +else + { { echo "$as_me:$LINENO: error: gethostbyname_r not found, required on this platform for --enable-thread-safety" >&5 +echo "$as_me: error: gethostbyname_r not found, required on this platform for --enable-thread-safety" >&2;} + { (exit 1); exit 1; }; } fi -done CFLAGS="$_CFLAGS" LIBS="$_LIBS" @@ -17838,7 +17995,7 @@ _ASBOX } >&5 cat >&5 <<_CSEOF -This file was extended by PostgreSQL $as_me 7.4beta1, which was +This file was extended by PostgreSQL $as_me 7.4beta2, which was generated by GNU Autoconf 2.53. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -17900,7 +18057,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -PostgreSQL config.status 7.4beta1 +PostgreSQL config.status 7.4beta2 configured by $0, generated by GNU Autoconf 2.53, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" @@ -18144,15 +18301,13 @@ s,@perl_privlibexp@,$perl_privlibexp,;t t s,@perl_useshrplib@,$perl_useshrplib,;t t s,@perl_embed_ldflags@,$perl_embed_ldflags,;t t s,@PYTHON@,$PYTHON,;t t -s,@python_version@,$python_version,;t t s,@python_prefix@,$python_prefix,;t t s,@python_execprefix@,$python_execprefix,;t t s,@python_configdir@,$python_configdir,;t t -s,@python_moduledir@,$python_moduledir,;t t -s,@python_moduleexecdir@,$python_moduleexecdir,;t t s,@python_includespec@,$python_includespec,;t t s,@python_libspec@,$python_libspec,;t t s,@LIBOBJS@,$LIBOBJS,;t t +s,@HAVE_IPV6@,$HAVE_IPV6,;t t s,@THREAD_CFLAGS@,$THREAD_CFLAGS,;t t s,@THREAD_LIBS@,$THREAD_LIBS,;t t s,@HAVE_POSIX_SIGNALS@,$HAVE_POSIX_SIGNALS,;t t diff --git a/configure.in b/configure.in index fcd50520b3f..a4bcbbc8b27 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -dnl $Header: /cvsroot/pgsql/configure.in,v 1.280 2003/08/11 18:07:38 tgl Exp $ +dnl $Header: /cvsroot/pgsql/configure.in,v 1.280.2.1 2003/09/07 04:36:38 momjian Exp $ dnl dnl Developers, please strive to achieve this order: dnl @@ -21,7 +21,7 @@ dnl The GNU folks apparently haven't heard that some people don't use dnl Texinfo. Use this sorcery to use "docdir" instead of "infodir". m4_define([info], [doc]) m4_define([infodir], [docdir]) -AC_INIT([PostgreSQL], [7.4beta1], [pgsql-bugs@postgresql.org]) +AC_INIT([PostgreSQL], [7.4beta2], [pgsql-bugs@postgresql.org]) m4_undefine([infodir]) m4_undefine([info]) AC_SUBST(docdir) @@ -238,6 +238,12 @@ if test "$enable_debug" = yes && test "$ac_cv_prog_cc_g" = yes; then fi AC_MSG_NOTICE([using CFLAGS=$CFLAGS]) +# We already have this in Makefile.win32, but configure needs it too +if test "$PORTNAME" = "win32" +then + CPPFLAGS="$CPPFLAGS -Isrc/include/port/win32" +fi + # Check if the compiler still works with the template settings AC_MSG_CHECKING([whether the C compiler still works]) AC_TRY_LINK([], [return 0;], @@ -362,10 +368,10 @@ AC_MSG_RESULT([$with_perl]) AC_SUBST(with_perl) # -# Optionally build Python interface module +# Optionally build Python modules (PL/Python) # AC_MSG_CHECKING([whether to build Python modules]) -PGAC_ARG_BOOL(with, python, no, [ --with-python build Python interface module]) +PGAC_ARG_BOOL(with, python, no, [ --with-python build Python modules (PL/Python)]) AC_MSG_RESULT([$with_python]) AC_SUBST(with_python) @@ -608,7 +614,6 @@ fi if test "$with_python" = yes; then PGAC_PATH_PYTHON - PGAC_CHECK_PYTHON_MODULE_SETUP PGAC_CHECK_PYTHON_EMBED_SETUP fi @@ -833,12 +838,15 @@ AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getpeereid memmove poll pstat setproc AC_CHECK_DECLS(fdatasync, [], [], [#include <unistd.h>]) +HAVE_IPV6=no AC_CHECK_TYPE([struct sockaddr_in6], [AC_CHECK_FUNC(inet_ntop, - [AC_DEFINE(HAVE_IPV6, 1, [Define to 1 if you have support for IPv6.])])], + [AC_DEFINE(HAVE_IPV6, 1, [Define to 1 if you have support for IPv6.]) + HAVE_IPV6=yes])], [], [$ac_includes_default #include <netinet/in.h>]) +AC_SUBST(HAVE_IPV6) AC_CACHE_CHECK([for PS_STRINGS], [pgac_cv_var_PS_STRINGS], [AC_TRY_LINK( @@ -978,9 +986,10 @@ AC_FUNC_FSEEKO # # For each platform, we need to know about any special compile and link # libraries, and whether the normal C function names are thread-safe. +# See the comment at the top of src/port/thread.c for more information. # if test "$enable_thread_safety" = yes; then -AC_CHECK_HEADER(pthread.h, [], [AC_MSG_ERROR([pthread.h not found, required for --with-threads])]) +AC_CHECK_HEADER(pthread.h, [], [AC_MSG_ERROR([pthread.h not found, required for --enable-thread-safetys])]) if test "$SUPPORTS_THREADS" != yes; then AC_MSG_ERROR([ @@ -988,6 +997,7 @@ Cannot enable threads on your platform. Please report your platform threading info to the PostgreSQL mailing lists so it can be added to the next release. Report all compile flags, link flags, functions, or libraries required for threading support. +See the comment at the top of src/port/thread.c for more information. ]) fi else @@ -1014,7 +1024,12 @@ _CFLAGS="$CFLAGS" _LIBS="$LIBS" CFLAGS="$CFLAGS $THREAD_CFLAGS" LIBS="$LIBS $THREAD_LIBS" -AC_CHECK_FUNCS([strerror_r getpwuid_r gethostbyname_r]) +AC_CHECK_FUNC(strerror_r, + [], [AC_MSG_ERROR([strerror_r not found, required on this platform for --enable-thread-safety])]) +AC_CHECK_FUNC(getpwuid_r, + [], [AC_MSG_ERROR([getpwuid_r not found, required on this platform for --enable-thread-safety])]) +AC_CHECK_FUNC(gethostbyname_r, + [], [AC_MSG_ERROR([gethostbyname_r not found, required on this platform for --enable-thread-safety])]) CFLAGS="$_CFLAGS" LIBS="$_LIBS" fi diff --git a/contrib/contrib-global.mk b/contrib/contrib-global.mk index 3e4c19c0c90..649ffa79b8c 100644 --- a/contrib/contrib-global.mk +++ b/contrib/contrib-global.mk @@ -1,4 +1,4 @@ -# $Header: /cvsroot/pgsql/contrib/contrib-global.mk,v 1.5 2002/11/02 00:16:21 tgl Exp $ +# $Header: /cvsroot/pgsql/contrib/contrib-global.mk,v 1.5.4.1 2003/09/07 04:36:39 momjian Exp $ # This file contains generic rules to build many kinds of simple # contrib modules. You only need to set a few variables and include @@ -127,7 +127,7 @@ endif uninstall: ifneq (,$(DATA)$(DATA_built)) - rm -f $(addprefix $(DESTDIR)$(datadir)/contrib/, $(DATA) $(DATA_built)) + rm -f $(addprefix $(DESTDIR)$(datadir)/contrib/, $(notdir $(DATA) $(DATA_built))) endif ifdef MODULES rm -f $(addprefix $(DESTDIR)$(pkglibdir)/, $(addsuffix $(DLSUFFIX), $(MODULES))) diff --git a/contrib/tsearch/parser.h b/contrib/tsearch/parser.h index f3aa0b8c06b..469b9c043ff 100644 --- a/contrib/tsearch/parser.h +++ b/contrib/tsearch/parser.h @@ -5,7 +5,6 @@ char *token; int tokenlen; int tsearch_yylex(void); void start_parse_str(char *, int); -void start_parse_fh(FILE *, int); void end_parse(void); #endif diff --git a/contrib/tsearch/parser.l b/contrib/tsearch/parser.l index 4323bda7ef0..2bf3dcba076 100644 --- a/contrib/tsearch/parser.l +++ b/contrib/tsearch/parser.l @@ -22,36 +22,6 @@ char *s = NULL; /* to return WHOLE hyphenated-word */ YY_BUFFER_STATE buf = NULL; /* buffer to parse; it need for parse from string */ -int lrlimit = -1; /* for limiting read from filehandle ( -1 - unlimited read ) */ -int bytestoread = 0; /* for limiting read from filehandle */ - -/* redefine macro for read limited length */ -#define YY_INPUT(buf,result,max_size) \ - if ( yy_current_buffer->yy_is_interactive ) { \ - int c = '*', n; \ - for ( n = 0; n < max_size && \ - (c = getc( tsearch_yyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( tsearch_yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } else { \ - if ( lrlimit == 0 ) \ - result=YY_NULL; \ - else { \ - if ( lrlimit>0 ) { \ - bytestoread = ( lrlimit > max_size ) ? max_size : lrlimit; \ - lrlimit -= bytestoread; \ - } else \ - bytestoread = max_size; \ - if ( ((result = fread( buf, 1, bytestoread, tsearch_yyin )) == 0) \ - && ferror( tsearch_yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - } \ - } - %} %option 8bit @@ -327,13 +297,4 @@ void start_parse_str(char* str, int limit) { BEGIN INITIAL; } -/* start parse from filehandle */ -void start_parse_fh( FILE* fh, int limit ) { - if (buf) end_parse(); - lrlimit = ( limit ) ? limit : -1; - buf = tsearch_yy_create_buffer( fh, YY_BUF_SIZE ); - tsearch_yy_switch_to_buffer( buf ); - BEGIN INITIAL; -} - diff --git a/contrib/tsearch2/Makefile b/contrib/tsearch2/Makefile index 6df6bcf3ba5..9c42d7a9b43 100644 --- a/contrib/tsearch2/Makefile +++ b/contrib/tsearch2/Makefile @@ -1,10 +1,10 @@ +# $Header: /cvsroot/pgsql/contrib/tsearch2/Makefile,v 1.3.2.1 2003/09/07 04:36:39 momjian Exp $ + subdir = contrib/tsearch2 top_builddir = ../.. include $(top_builddir)/src/Makefile.global -override CPPFLAGS := -I$(srcdir) -I$(srcdir)/snowball -I$(srcdir)/ispell -I$(srcdir)/wordparser $(CPPFLAGS) - MODULE_big = tsearch2 OBJS = dict_ex.o dict.o snmap.o stopword.o common.o prs_dcfg.o \ dict_snowball.o dict_ispell.o dict_syn.o \ @@ -22,30 +22,26 @@ $(SUBDIROBJS): $(SUBDIRS:%=%-recursive) ; $(SUBDIRS:%=%-recursive): $(MAKE) -C $(subst -recursive,,$@) SUBSYS.o +PG_CPPFLAGS = -I$(srcdir)/snowball -I$(srcdir)/ispell -I$(srcdir)/wordparser + +DATA = stopword/english.stop stopword/russian.stop DATA_built = tsearch2.sql untsearch2.sql DOCS = README.tsearch2 REGRESS = tsearch2 -EXTRA_CLEAN = tsearch2.sql.in - SHLIB_LINK := -lm -include $(top_srcdir)/contrib/contrib-global.mk -# DO NOT DELETE -install: installstop - -installstop: - cp $(srcdir)/stopword/*.stop $(datadir) - - -tsearch2.sql.in: tsearch.sql._in - sed 's,DATA_PATH,$(datadir),g' < $< > $@ +tsearch2.sql: tsearch.sql.in + sed -e 's,MODULE_PATHNAME,$$libdir/$(MODULE_big),g' \ + -e 's,DATA_PATH,$(datadir)/contrib,g' $< >$@ untsearch2.sql: untsearch.sql.in cp $< $@ +.PHONY: subclean clean: subclean subclean: for dir in $(SUBDIRS); do $(MAKE) -C $$dir clean || exit; done +include $(top_srcdir)/contrib/contrib-global.mk diff --git a/contrib/tsearch2/docs/tsearch-V2-intro.html b/contrib/tsearch2/docs/tsearch-V2-intro.html index 8375d4ca773..ed2bc4179f0 100644 --- a/contrib/tsearch2/docs/tsearch-V2-intro.html +++ b/contrib/tsearch2/docs/tsearch-V2-intro.html @@ -1,17 +1,13 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>tsearch-v2-intro</title> + +<link type="text/css" rel="stylesheet" href="tsearch-V2-intro_files/tsearch.txt"></head> -<html> -<head> - <title>tsearch-v2-intro</title> -<link type="text/css" rel="stylesheet" href="/~megera/postgres/gist/tsearch/tsearch.css"> -</head> <body> <div class="content"> <h2>Tsearch2 - Introduction</h2> - <p><a href= - "http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/docs/tsearch-V2-intro.html"> + <p><a href="http://www.sai.msu.su/%7Emegera/postgres/gist/tsearch/V2/docs/tsearch-V2-intro.html"> [Online version]</a> of this document is available.</p> <p>The tsearch2 module is available to add as an extension to @@ -38,13 +34,11 @@ <p>The README.tsearch2 file included in the contrib/tsearch2 directory contains a brief overview and history behind tsearch. - This can also be found online <a href= - "http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/">[right + This can also be found online <a href="http://www.sai.msu.su/%7Emegera/postgres/gist/tsearch/V2/">[right here]</a>.</p> <p>Further in depth documentation such as a full function - reference, and user guide can be found online at the <a href= - "http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/docs/">[tsearch + reference, and user guide can be found online at the <a href="http://www.sai.msu.su/%7Emegera/postgres/gist/tsearch/V2/docs/">[tsearch documentation home]</a>.</p> <h3>ACKNOWLEDGEMENTS</h3> @@ -105,11 +99,9 @@ <p>Step one is to download the tsearch V2 module :</p> - <p><a href= - "http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/">[http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/]</a> + <p><a href="http://www.sai.msu.su/%7Emegera/postgres/gist/tsearch/V2/">[http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/]</a> (check Development History for latest stable version !)</p> - <pre> - tar -zxvf tsearch-v2.tar.gz + <pre> tar -zxvf tsearch-v2.tar.gz mv tsearch2 PGSQL_SRC/contrib/ cd PGSQL_SRC/contrib/tsearch2 </pre> @@ -121,18 +113,15 @@ <p>Then continue with the regular building and installation process</p> - <pre> - gmake + <pre> gmake gmake install gmake installcheck </pre> <p>That is pretty much all you have to do, unless of course you get errors. However if you get those, you better go check with - the mailing lists over at <a href= - "http://www.postgresql.org">http://www.postgresql.org</a> or - <a href= - "http://openfts.sourceforge.net/">http://openfts.sourceforge.net/</a> + the mailing lists over at <a href="http://www.postgresql.org/">http://www.postgresql.org</a> or + <a href="http://openfts.sourceforge.net/">http://openfts.sourceforge.net/</a> since its never failed for me.</p> <p>The directory in the contib/ and the directory from the @@ -151,15 +140,13 @@ <p>We should create a database to use as an example for the remainder of this file. We can call the database "ftstest". You can create it from the command line like this:</p> - <pre> - #createdb ftstest + <pre> #createdb ftstest </pre> <p>If you thought installation was easy, this next bit is even easier. Change to the PGSQL_SRC/contrib/tsearch2 directory and type:</p> - <pre> - psql ftstest < tsearch2.sql + <pre> psql ftstest < tsearch2.sql </pre> <p>The file "tsearch2.sql" holds all the wonderful little @@ -170,8 +157,7 @@ pg_ts_cfgmap are added.</p> <p>You can check out the tables if you like:</p> - <pre> - #psql ftstest + <pre> #psql ftstest ftstest=# \d List of relations Schema | Name | Type | Owner @@ -188,8 +174,7 @@ <p>The first thing we can do is try out some of the types that are provided for us. Lets look at the tsvector type provided for us:</p> - <pre> - SELECT 'Our first string used today'::tsvector; + <pre> SELECT 'Our first string used today'::tsvector; tsvector --------------------------------------- 'Our' 'used' 'first' 'today' 'string' @@ -199,8 +184,7 @@ <p>The results are the words used within our string. Notice they are not in any particular order. The tsvector type returns a string of space separated words.</p> - <pre> - SELECT 'Our first string used today first string'::tsvector; + <pre> SELECT 'Our first string used today first string'::tsvector; tsvector ----------------------------------------------- 'Our' 'used' 'again' 'first' 'today' 'string' @@ -217,8 +201,7 @@ by the tsearch2 module.</p> <p>The function to_tsvector has 3 possible signatures:</p> - <pre> - to_tsvector(oid, text); + <pre> to_tsvector(oid, text); to_tsvector(text, text); to_tsvector(text); </pre> @@ -228,8 +211,7 @@ the searchable text is broken up into words (Stemming process). Right now we will specify the 'default' configuration. See the section on TSEARCH2 CONFIGURATION to learn more about this.</p> - <pre> - SELECT to_tsvector('default', + <pre> SELECT to_tsvector('default', 'Our first string used today first string'); to_tsvector -------------------------------------------- @@ -259,8 +241,7 @@ <p>If you want to view the output of the tsvector fields without their positions, you can do so with the function "strip(tsvector)".</p> - <pre> - SELECT strip(to_tsvector('default', + <pre> SELECT strip(to_tsvector('default', 'Our first string used today first string')); strip -------------------------------- @@ -270,8 +251,7 @@ <p>If you wish to know the number of unique words returned in the tsvector you can do so by using the function "length(tsvector)"</p> - <pre> - SELECT length(to_tsvector('default', + <pre> SELECT length(to_tsvector('default', 'Our first string used today first string')); length -------- @@ -282,15 +262,13 @@ <p>Lets take a look at the function to_tsquery. It also has 3 signatures which follow the same rational as the to_tsvector function:</p> - <pre> - to_tsquery(oid, text); + <pre> to_tsquery(oid, text); to_tsquery(text, text); to_tsquery(text); </pre> <p>Lets try using the function with a single word :</p> - <pre> - SELECT to_tsquery('default', 'word'); + <pre> SELECT to_tsquery('default', 'word'); to_tsquery ----------- 'word' @@ -303,8 +281,7 @@ <p>Lets attempt to use the function with a string of multiple words:</p> - <pre> - SELECT to_tsquery('default', 'this is many words'); + <pre> SELECT to_tsquery('default', 'this is many words'); ERROR: Syntax error </pre> @@ -313,8 +290,7 @@ "tsquery" used for searching a tsvector field. What we need to do is search for one to many words with some kind of logic (for now simple boolean).</p> - <pre> - SELECT to_tsquery('default', 'searching|sentence'); + <pre> SELECT to_tsquery('default', 'searching|sentence'); to_tsquery ---------------------- 'search' | 'sentenc' @@ -328,8 +304,7 @@ <p>You can not use words defined as being a stop word in your configuration. The function will not fail ... you will just get no result, and a NOTICE like this:</p> - <pre> - SELECT to_tsquery('default', 'a|is&not|!the'); + <pre> SELECT to_tsquery('default', 'a|is&not|!the'); NOTICE: Query contains only stopword(s) or doesn't contain lexem(s), ignored to_tsquery @@ -348,8 +323,7 @@ <p>The next stage is to add a full text index to an existing table. In this example we already have a table defined as follows:</p> - <pre> - CREATE TABLE tblMessages + <pre> CREATE TABLE tblMessages ( intIndex int4, strTopic varchar(100), @@ -362,8 +336,7 @@ test strings for a topic, and a message. here is some test data I inserted. (yes I know it's completely useless stuff ;-) but it will serve our purpose right now).</p> - <pre> - INSERT INTO tblMessages + <pre> INSERT INTO tblMessages VALUES ('1', 'Testing Topic', 'Testing message data input'); INSERT INTO tblMessages VALUES ('2', 'Movie', 'Breakfast at Tiffany\'s'); @@ -400,8 +373,7 @@ <p>The next stage is to create a special text index which we will use for FTI, so we can search our table of messages for words or a phrase. We do this using the SQL command:</p> - <pre> - ALTER TABLE tblMessages ADD idxFTI tsvector; + <pre> ALTER TABLE tblMessages ADD COLUMN idxFTI tsvector; </pre> <p>Note that unlike traditional indexes, this is actually a new @@ -411,8 +383,7 @@ <p>The general rule for the initial insertion of data will follow four steps:</p> - <pre> - 1. update table + <pre> 1. update table 2. vacuum full analyze 3. create index 4. vacuum full analyze @@ -426,8 +397,7 @@ the index has been created on the table, vacuum full analyze is run again to update postgres's statistics (ie having the index take effect).</p> - <pre> - UPDATE tblMessages SET idxFTI=to_tsvector('default', strMessage); + <pre> UPDATE tblMessages SET idxFTI=to_tsvector('default', strMessage); VACUUM FULL ANALYZE; </pre> @@ -436,8 +406,7 @@ information stored, you should instead do the following, which effectively concatenates the two fields into one before being inserted into the table:</p> - <pre> - UPDATE tblMessages + <pre> UPDATE tblMessages SET idxFTI=to_tsvector('default',coalesce(strTopic,'') ||' '|| coalesce(strMessage,'')); VACUUM FULL ANALYZE; </pre> @@ -451,8 +420,7 @@ Full Text INDEXINGi ;-)), so don't worry about any indexing overhead. We will create an index based on the gist function. GiST is an index structure for Generalized Search Tree.</p> - <pre> - CREATE INDEX idxFTI_idx ON tblMessages USING gist(idxFTI); + <pre> CREATE INDEX idxFTI_idx ON tblMessages USING gist(idxFTI); VACUUM FULL ANALYZE; </pre> @@ -464,15 +432,13 @@ <p>The last thing to do is set up a trigger so every time a row in this table is changed, the text index is automatically updated. This is easily done using:</p> - <pre> - CREATE TRIGGER tsvectorupdate BEFORE UPDATE OR INSERT ON tblMessages + <pre> CREATE TRIGGER tsvectorupdate BEFORE UPDATE OR INSERT ON tblMessages FOR EACH ROW EXECUTE PROCEDURE tsearch2(idxFTI, strMessage); </pre> <p>Or if you are indexing both strMessage and strTopic you should instead do:</p> - <pre> - CREATE TRIGGER tsvectorupdate BEFORE UPDATE OR INSERT ON tblMessages + <pre> CREATE TRIGGER tsvectorupdate BEFORE UPDATE OR INSERT ON tblMessages FOR EACH ROW EXECUTE PROCEDURE tsearch2(idxFTI, strTopic, strMessage); </pre> @@ -490,15 +456,13 @@ the tsearch2 function. Lets say we want to create a function to remove certain characters (like the @ symbol from all text).</p> - <pre> - CREATE FUNCTION dropatsymbol(text) + <pre> CREATE FUNCTION dropatsymbol(text) RETURNS text AS 'select replace($1, \'@\', \' \');' LANGUAGE SQL; </pre> <p>Now we can use this function within the tsearch2 function on the trigger.</p> - <pre> - DROP TRIGGER tsvectorupdate ON tblmessages; + <pre> DROP TRIGGER tsvectorupdate ON tblmessages; CREATE TRIGGER tsvectorupdate BEFORE UPDATE OR INSERT ON tblMessages FOR EACH ROW EXECUTE PROCEDURE tsearch2(idxFTI, dropatsymbol, strMessage); INSERT INTO tblmessages VALUES (69, 'Attempt for dropatsymbol', 'Test@test.com'); @@ -513,8 +477,7 @@ locale of the server. All you have to do is change your default configuration, or add a new one for your specific locale. See the section on TSEARCH2 CONFIGURATION.</p> - <pre class="real"> - SELECT * FROM tblmessages WHERE intindex = 69; + <pre class="real"> SELECT * FROM tblmessages WHERE intindex = 69; intindex | strtopic | strmessage | idxfti ----------+--------------------------+---------------+----------------------- @@ -540,8 +503,7 @@ in the tsvector column. <p>Lets search the indexed data for the word "Test". I indexed based on the the concatenation of the strTopic, and the strMessage:</p> - <pre> - SELECT intindex, strtopic FROM tblmessages + <pre> SELECT intindex, strtopic FROM tblmessages WHERE idxfti @@ 'test'::tsquery; intindex | strtopic ----------+--------------- @@ -553,8 +515,7 @@ in the tsvector column. "Testing Topic". Notice that the word I search for was all lowercase. Let's see what happens when I query for uppercase "Test".</p> - <pre> - SELECT intindex, strtopic FROM tblmessages + <pre> SELECT intindex, strtopic FROM tblmessages WHERE idxfti @@ 'Test'::tsquery; intindex | strtopic ----------+---------- @@ -570,8 +531,7 @@ in the tsvector column. <p>Most likely the best way to query the field is to use the to_tsquery function on the right hand side of the @@ operator like this:</p> - <pre> - SELECT intindex, strtopic FROM tblmessages + <pre> SELECT intindex, strtopic FROM tblmessages WHERE idxfti @@ to_tsquery('default', 'Test | Zeppelin'); intindex | strtopic ----------+-------------------- @@ -592,8 +552,7 @@ in the tsvector column. a way around which doesn't appear to have a significant impact on query time, and that is to use a query such as the following:</p> - <pre> - SELECT intindex, strTopic FROM tblmessages + <pre> SELECT intindex, strTopic FROM tblmessages WHERE idxfti @@ to_tsquery('default', 'gettysburg & address') AND strMessage ~* '.*men are created equal.*'; intindex | strtopic @@ -626,8 +585,7 @@ in the tsvector column. english stemming. We could edit the file :'/usr/local/pgsql/share/english.stop' and add a word to the list. I edited mine to exclude my name from indexing:</p> - <pre> - - Edit /usr/local/pgsql/share/english.stop + <pre> - Edit /usr/local/pgsql/share/english.stop - Add 'andy' to the list - Save the file. </pre> @@ -638,16 +596,14 @@ in the tsvector column. connected to the DB while editing the stop words, you will need to end the current session and re-connect. When you re-connect to the database, 'andy' is no longer indexed:</p> - <pre> - SELECT to_tsvector('default', 'Andy'); + <pre> SELECT to_tsvector('default', 'Andy'); to_tsvector ------------ (1 row) </pre> <p>Originally I would get the result :</p> - <pre> - SELECT to_tsvector('default', 'Andy'); + <pre> SELECT to_tsvector('default', 'Andy'); to_tsvector ------------ 'andi':1 @@ -660,8 +616,7 @@ in the tsvector column. 'simple', the results would be different. There are no stop words for the simple dictionary. It will just convert to lower case, and index every unique word.</p> - <pre> - SELECT to_tsvector('simple', 'Andy andy The the in out'); + <pre> SELECT to_tsvector('simple', 'Andy andy The the in out'); to_tsvector ------------------------------------- 'in':5 'out':6 'the':3,4 'andy':1,2 @@ -672,8 +627,7 @@ in the tsvector column. into the actual configuration of tsearch2. In the examples in this document the configuration has always been specified when using the tsearch2 functions:</p> - <pre> - SELECT to_tsvector('default', 'Testing the default config'); + <pre> SELECT to_tsvector('default', 'Testing the default config'); SELECT to_tsvector('simple', 'Example of simple Config'); </pre> @@ -682,8 +636,7 @@ in the tsvector column. contains both the 'default' configurations based on the 'C' locale. And the 'simple' configuration which is not based on any locale.</p> - <pre> - SELECT * from pg_ts_cfg; + <pre> SELECT * from pg_ts_cfg; ts_name | prs_name | locale -----------------+----------+-------------- default | default | C @@ -706,8 +659,7 @@ in the tsvector column. configuration or just use one that already exists. If I do not specify which configuration to use in the to_tsvector function, I receive the following error.</p> - <pre> - SELECT to_tsvector('learning tsearch is like going to school'); + <pre> SELECT to_tsvector('learning tsearch is like going to school'); ERROR: Can't find tsearch config by locale </pre> @@ -716,8 +668,7 @@ in the tsvector column. into the pg_ts_cfg table. We will call the configuration 'default_english', with the default parser and use the locale 'en_US'.</p> - <pre> - INSERT INTO pg_ts_cfg (ts_name, prs_name, locale) + <pre> INSERT INTO pg_ts_cfg (ts_name, prs_name, locale) VALUES ('default_english', 'default', 'en_US'); </pre> @@ -732,15 +683,14 @@ in the tsvector column. tsearch2.sql</p> <p>Lets take a first look at the pg_ts_dict table</p> - <pre> - ftstest=# \d pg_ts_dict + <pre> ftstest=# \d pg_ts_dict Table "public.pg_ts_dict" Column | Type | Modifiers -----------------+---------+----------- dict_name | text | not null dict_init | oid | dict_initoption | text | - dict_lemmatize | oid | not null + dict_lexize | oid | not null dict_comment | text | Indexes: pg_ts_dict_idx unique btree (dict_name) </pre> @@ -763,28 +713,57 @@ in the tsvector column. ISpell. We will assume you have ISpell installed on you machine. (in /usr/local/lib)</p> - <p>First lets register the dictionary(ies) to use from ISpell. - We will use the english dictionary from ISpell. We insert the - paths to the relevant ISpell dictionary (*.hash) and affixes - (*.aff) files. There seems to be some question as to which - ISpell files are to be used. I installed ISpell from the latest - sources on my computer. The installation installed the - dictionary files with an extension of *.hash. Some - installations install with an extension of *.dict As far as I - know the two extensions are equivilant. So *.hash == - *.dict.</p> - - <p>We will also continue to use the english word stop file that + <p>There has been some confusion in the past as to which files + are used from ISpell. ISpell operates using a hash file. This + is a binary file created by the ISpell command line utility + "buildhash". This utility accepts a file containing the words + from the dictionary, and the affixes file and the output is the + hash file. The default installation of ISPell installs the + english hash file english.hash, which is the exact same file as + american.hash. ISpell uses this as the fallback dictionary to + use.</p> + + <p>This hash file is not what tsearch2 requires as the ISpell + interface. The file(s) needed are those used to create the + hash. Tsearch uses the dictionary words for morphology, so the + listing is needed not spellchecking. Regardless, these files + are included in the ISpell sources, and you can use them to + integrate into tsearch2. This is not complicated, but is not + very obvious to begin with. The tsearch2 ISpell interface needs + only the listing of dictionary words, it will parse and load + those words, and use the ISpell dictionary for lexem + processing.</p> + + <p>I found the ISPell make system to be very finicky. Their + documentation actually states this to be the case. So I just + did things the command line way. In the ISpell source tree + under langauges/english there are several files in this + directory. For a complete description, please read the ISpell + README. Basically for the english dictionary there is the + option to create the small, medium, large and extra large + dictionaries. The medium dictionary is recommended. If the make + system is configured correctly, it would build and install the + english.has file from the medium size dictionary. Since we are + only concerned with the dictionary word listing ... it can be + created from the /languages/english directory with the + following command:</p> + <pre> sort -u -t/ +0f -1 +0 -T /usr/tmp -o english.med english.0 english.1 +</pre> + + <p>This will create a file called english.med. You can copy + this file to whever you like. I place mine in /usr/local/lib so + it coincides with the ISpell hash files. You can now add the + tsearch2 configuration entry for the ISpell english dictionary. + We will also continue to use the english word stop file that was installed for the en_stem dictionary. You could use a different one if you like. The ISpell configuration is based on the "ispell_template" dictionary installed by default with tsearch2. We will use the OIDs to the stored procedures from the row where the dict_name = 'ispell_template'.</p> - <pre> - INSERT INTO pg_ts_dict + <pre> INSERT INTO pg_ts_dict (SELECT 'en_ispell', dict_init, - 'DictFile="/usr/local/lib/english.hash",' + 'DictFile="/usr/local/lib/english.med",' 'AffFile="/usr/local/lib/english.aff",' 'StopFile="/usr/local/pgsql/share/english.stop"', dict_lexize @@ -792,6 +771,50 @@ in the tsvector column. WHERE dict_name = 'ispell_template'); </pre> + <p>Now that we have a dictionary we can specify it's use in a + query to get a lexem. For this we will use the lexize function. + The lexize function takes the name of the dictionary to use as + an argument. Just as the other tsearch2 functions operate.</p> + <pre> SELECT lexize('en_ispell', 'program'); + lexize + ----------- + {program} + (1 row) +</pre> + + <p>If you wanted to always use the ISpell english dictionary + you have installed, you can configure tsearch2 to always use a + specific dictionary.</p> + <pre> SELCECT set_curdict('en_ispell'); +</pre> + + <p>Lexize is meant to turn a word into a lexem. It is possible + to receive more than one lexem returned for a single word.</p> + <pre> SELECT lexize('en_ispell', 'conditionally'); + lexize + ----------------------------- + {conditionally,conditional} + (1 row) +</pre> + + <p>The lexize function is not meant to take a full string as an + argument to return lexems for. If you passed in an entire + sentence, it attempts to find that entire sentence in the + dictionary. SInce the dictionary contains only words, you will + receive an empty result set back.</p> + <pre> SELECT lexize('en_ispell', 'This is a senctece to lexize'); + lexize + -------- + + (1 row) + +If you parse a lexem from a word not in the dictionary, then you will receive an empty result. This makes sense because the word "tsearch" is not int the english dictionary. You can create your own additions to the dictionary if you like. This may be useful for scientific or technical glossaries that need to be indexed. SELECT lexize('en_ispell', 'tsearch'); lexize -------- (1 row) +</pre> + + <p>This is not to say that tsearch will be ignored when adding + text information to the the tsvector index column. This will be + explained in greater detail with the table pg_ts_cfgmap.</p> + <p>Next we need to set up the configuration for mapping the dictionay use to the lexxem parsings. This will be done by altering the pg_ts_cfgmap table. We will insert several rows, @@ -799,8 +822,7 @@ in the tsvector column. configured for use within tsearch2. There are several type of lexims we would be concerned with forcing the use of the ISpell dictionary.</p> - <pre> - INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name) + <pre> INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name) VALUES ('default_english', 'lhword', '{en_ispell,en_stem}'); INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name) VALUES ('default_english', 'lpart_hword', '{en_ispell,en_stem}'); @@ -818,8 +840,7 @@ in the tsvector column. <p>There are several other lexem types used that we do not need to specify as using the ISpell dictionary. We can simply insert values using the 'simple' stemming process dictionary.</p> - <pre> - INSERT INTO pg_ts_cfgmap + <pre> INSERT INTO pg_ts_cfgmap VALUES ('default_english', 'url', '{simple}'); INSERT INTO pg_ts_cfgmap VALUES ('default_english', 'host', '{simple}'); @@ -857,8 +878,7 @@ in the tsvector column. complete. We have successfully created a new tsearch2 configuration. At the same time we have also set the new configuration to be our default for en_US locale.</p> - <pre> - SELECT to_tsvector('default_english', + <pre> SELECT to_tsvector('default_english', 'learning tsearch is like going to school'); to_tsvector -------------------------------------------------- @@ -870,12 +890,37 @@ in the tsvector column. (1 row) </pre> + <p>Notice here that words like "tsearch" are still parsed and + indexed in the tsvector column. There is a lexem returned for + the word becuase in the configuration mapping table, we specify + words to be used from the 'en_ispell' dictionary first, but as + a fallback to use the 'en_stem' dictionary. Therefore a lexem + is not returned from en_ispell, but is returned from en_stem, + and added to the tsvector.</p> + <pre> SELECT to_tsvector('learning tsearch is like going to computer school'); + to_tsvector + --------------------------------------------------------------------------- + 'go':5 'like':4 'learn':1 'school':8 'compute':7 'tsearch':2 'computer':7 + (1 row) +</pre> + + <p>Notice in this last example I added the word "computer" to + the text to be converted into a tsvector. Because we have setup + our default configuration to use the ISpell english dictionary, + the words are lexized, and computer returns 2 lexems at the + same position. 'compute':7 and 'computer':7 are now both + indexed for the word computer.</p> + + <p>You can create additional dictionarynlists, or use the extra + large dictionary from ISpell. You can read through the ISpell + documents, and source tree to make modifications as you see + fit.</p> + <p>In the case that you already have a configuration set for the locale, and you are changing it to your new dictionary configuration. You will have to set the old locale to NULL. If we are using the 'C' locale then we would do this:</p> - <pre> - UPDATE pg_ts_cfg SET locale=NULL WHERE locale = 'C'; + <pre> UPDATE pg_ts_cfg SET locale=NULL WHERE locale = 'C'; </pre> <p>That about wraps up the configuration of tsearch2. There is @@ -917,38 +962,32 @@ in the tsvector column. <p>1) Backup any global database objects such as users and groups (this step is usually only necessary when you will be restoring to a virgin system)</p> - <pre> - pg_dumpall -g > GLOBALobjects.sql + <pre> pg_dumpall -g > GLOBALobjects.sql </pre> <p>2) Backup the full database schema using pg_dump</p> - <pre> - pg_dump -s DATABASE > DATABASEschema.sql + <pre> pg_dump -s DATABASE > DATABASEschema.sql </pre> <p>3) Backup the full database using pg_dump</p> - <pre> - pg_dump -Fc DATABASE > DATABASEdata.tar + <pre> pg_dump -Fc DATABASE > DATABASEdata.tar </pre> <p>To Restore a PostgreSQL database that uses the tsearch2 module:</p> <p>1) Create the blank database</p> - <pre> - createdb DATABASE + <pre> createdb DATABASE </pre> <p>2) Restore any global database objects such as users and groups (this step is usually only necessary when you will be restoring to a virgin system)</p> - <pre> - psql DATABASE < GLOBALobjects.sql + <pre> psql DATABASE < GLOBALobjects.sql </pre> <p>3) Create the tsearch2 objects, functions and operators</p> - <pre> - psql DATABASE < tsearch2.sql + <pre> psql DATABASE < tsearch2.sql </pre> <p>4) Edit the backed up database schema and delete all SQL @@ -957,13 +996,11 @@ in the tsvector column. tsvector types. If your not sure what these are, they are the ones listed in tsearch2.sql. Then restore the edited schema to the database</p> - <pre> - psql DATABASE < DATABASEschema.sql + <pre> psql DATABASE < DATABASEschema.sql </pre> <p>5) Restore the data for the database</p> - <pre> - pg_restore -N -a -d DATABASE DATABASEdata.tar + <pre> pg_restore -N -a -d DATABASE DATABASEdata.tar </pre> <p>If you get any errors in step 4, it will most likely be @@ -971,5 +1008,4 @@ in the tsvector column. tsearch2.sql. Any errors in step 5 will mean the database schema was probably restored wrongly.</p> </div> -</body> -</html> +</body></html>
\ No newline at end of file diff --git a/contrib/tsearch2/expected/tsearch2.out b/contrib/tsearch2/expected/tsearch2.out index d0b91043539..8571e59bbb1 100644 --- a/contrib/tsearch2/expected/tsearch2.out +++ b/contrib/tsearch2/expected/tsearch2.out @@ -569,6 +569,30 @@ select to_tsquery('default', '\'the wether\':dc & \' sKies \':BC '); 'wether':CD & 'sky':BC (1 row) +select to_tsquery('asd&(and|fghj)'); + to_tsquery +---------------- + 'asd' & 'fghj' +(1 row) + +select to_tsquery('(asd&and)|fghj'); + to_tsquery +---------------- + 'asd' | 'fghj' +(1 row) + +select to_tsquery('(asd&!and)|fghj'); + to_tsquery +---------------- + 'asd' | 'fghj' +(1 row) + +select to_tsquery('(the|and&(i&1))&fghj'); + to_tsquery +-------------- + '1' & 'fghj' +(1 row) + select 'a b:89 ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca'; ?column? ---------- diff --git a/contrib/tsearch2/ispell/Makefile b/contrib/tsearch2/ispell/Makefile index 5532359b1cf..7cf3c6f8b6a 100644 --- a/contrib/tsearch2/ispell/Makefile +++ b/contrib/tsearch2/ispell/Makefile @@ -1,9 +1,11 @@ +# $Header: /cvsroot/pgsql/contrib/tsearch2/ispell/Attic/Makefile,v 1.3.2.1 2003/09/07 04:36:39 momjian Exp $ + subdir = contrib/tsearch2/ispell top_builddir = ../../.. include $(top_builddir)/src/Makefile.global -override CPPFLAGS := -I$(srcdir) -I$(srcdir)/.. $(CPPFLAGS) +PG_CPPFLAGS = -I$(srcdir)/.. $(CPPFLAGS) override CFLAGS += $(CFLAGS_SL) SUBOBJS = spell.o @@ -16,6 +18,3 @@ SUBSYS.o: $(SUBOBJS) EXTRA_CLEAN = SUBSYS.o $(SUBOBJS) include $(top_srcdir)/contrib/contrib-global.mk -# DO NOT DELETE - - diff --git a/contrib/tsearch2/query.c b/contrib/tsearch2/query.c index 0019b04f166..00537f4170e 100644 --- a/contrib/tsearch2/query.c +++ b/contrib/tsearch2/query.c @@ -52,15 +52,6 @@ Datum to_tsquery_name(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(to_tsquery_current); Datum to_tsquery_current(PG_FUNCTION_ARGS); -#define END 0 -#define ERR 1 -#define VAL 2 -#define OPR 3 -#define OPEN 4 -#define CLOSE 5 -#define VALTRUE 6 /* for stop words */ -#define VALFALSE 7 - /* parser's states */ #define WAITOPERAND 1 #define WAITOPERATOR 2 @@ -293,7 +284,7 @@ pushval_morph(QPRS_STATE * state, int typeval, char *strval, int lenval, int2 we /* XXX */ if (prs.curwords == 0) - pushval_asis(state, VALTRUE, 0, 0, 0); + pushval_asis(state, VALSTOP, 0, 0, 0); } #define STACKDEPTH 32 @@ -526,7 +517,7 @@ findoprnd(ITEM * ptr, int4 *pos) elog(DEBUG3, (ptr[*pos].type == OPR) ? "%d %c" : "%d %d", *pos, ptr[*pos].val); #endif - if (ptr[*pos].type == VAL || ptr[*pos].type == VALTRUE) + if (ptr[*pos].type == VAL || ptr[*pos].type == VALSTOP) { ptr[*pos].left = 0; (*pos)++; diff --git a/contrib/tsearch2/query.h b/contrib/tsearch2/query.h index 4a79efdc539..a65dbca762f 100644 --- a/contrib/tsearch2/query.h +++ b/contrib/tsearch2/query.h @@ -46,8 +46,7 @@ typedef struct #define OPR 3 #define OPEN 4 #define CLOSE 5 -#define VALTRUE 6 /* for stop words */ -#define VALFALSE 7 +#define VALSTOP 6 /* for stop words */ bool TS_execute(ITEM * curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, ITEM * val)); diff --git a/contrib/tsearch2/rewrite.c b/contrib/tsearch2/rewrite.c index ac42f2c9a94..4d7294cd74a 100644 --- a/contrib/tsearch2/rewrite.c +++ b/contrib/tsearch2/rewrite.c @@ -177,6 +177,7 @@ clean_NOT_v2(ITEM * ptr, int4 *len) #define V_UNKNOWN 0 #define V_TRUE 1 #define V_FALSE 2 +#define V_STOP 3 /* * Clean query tree from values which is always in @@ -190,10 +191,10 @@ clean_fakeval_intree(NODE * node, char *result) if (node->valnode->type == VAL) return node; - else if (node->valnode->type == VALTRUE) + else if (node->valnode->type == VALSTOP) { pfree(node); - *result = V_TRUE; + *result = V_STOP; return NULL; } @@ -203,65 +204,29 @@ clean_fakeval_intree(NODE * node, char *result) node->right = clean_fakeval_intree(node->right, &rresult); if (!node->right) { - *result = (rresult == V_TRUE) ? V_FALSE : V_TRUE; + *result = V_STOP; freetree(node); return NULL; } } - else if (node->valnode->val == (int4) '|') - { - NODE *res = node; - - node->left = clean_fakeval_intree(node->left, &lresult); - node->right = clean_fakeval_intree(node->right, &rresult); - if (lresult == V_TRUE || rresult == V_TRUE) - { - freetree(node); - *result = V_TRUE; - return NULL; - } - else if (lresult == V_FALSE && rresult == V_FALSE) - { - freetree(node); - *result = V_FALSE; - return NULL; - } - else if (lresult == V_FALSE) - { - res = node->right; - pfree(node); - } - else if (rresult == V_FALSE) - { - res = node->left; - pfree(node); - } - return res; - } else { NODE *res = node; node->left = clean_fakeval_intree(node->left, &lresult); node->right = clean_fakeval_intree(node->right, &rresult); - if (lresult == V_FALSE || rresult == V_FALSE) - { - freetree(node); - *result = V_FALSE; - return NULL; - } - else if (lresult == V_TRUE && rresult == V_TRUE) + if (lresult == V_STOP && rresult == V_STOP) { freetree(node); - *result = V_TRUE; + *result = V_STOP; return NULL; } - else if (lresult == V_TRUE) + else if (lresult == V_STOP) { res = node->right; pfree(node); } - else if (rresult == V_TRUE) + else if (rresult == V_STOP) { res = node->left; pfree(node); diff --git a/contrib/tsearch2/snowball/Makefile b/contrib/tsearch2/snowball/Makefile index 156b1b3d399..3ac0ff72540 100644 --- a/contrib/tsearch2/snowball/Makefile +++ b/contrib/tsearch2/snowball/Makefile @@ -1,9 +1,11 @@ +# $Header: /cvsroot/pgsql/contrib/tsearch2/snowball/Attic/Makefile,v 1.3.2.1 2003/09/07 04:36:39 momjian Exp $ + subdir = contrib/tsearch2/snowball top_builddir = ../../.. include $(top_builddir)/src/Makefile.global -override CPPFLAGS := -I$(srcdir) -I$(srcdir)/.. $(CPPFLAGS) +PG_CPPFLAGS = -I$(srcdir)/.. override CFLAGS += $(CFLAGS_SL) SUBOBJS = english_stem.o api.o russian_stem.o utilities.o @@ -16,6 +18,3 @@ SUBSYS.o: $(SUBOBJS) EXTRA_CLEAN = SUBSYS.o $(SUBOBJS) include $(top_srcdir)/contrib/contrib-global.mk -# DO NOT DELETE - - diff --git a/contrib/tsearch2/sql/tsearch2.sql b/contrib/tsearch2/sql/tsearch2.sql index 0c10edb6ec9..d4f1021d7d8 100644 --- a/contrib/tsearch2/sql/tsearch2.sql +++ b/contrib/tsearch2/sql/tsearch2.sql @@ -87,6 +87,10 @@ SELECT length(to_tsvector('default', '345 qwe@efd.r \' http://www.com/ http://ae select to_tsquery('default', 'qwe & sKies '); select to_tsquery('simple', 'qwe & sKies '); select to_tsquery('default', '\'the wether\':dc & \' sKies \':BC '); +select to_tsquery('asd&(and|fghj)'); +select to_tsquery('(asd&and)|fghj'); +select to_tsquery('(asd&!and)|fghj'); +select to_tsquery('(the|and&(i&1))&fghj'); select 'a b:89 ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca'; select 'a b:89 ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:B'; select 'a b:89 ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:A'; diff --git a/contrib/tsearch2/wordparser/Makefile b/contrib/tsearch2/wordparser/Makefile index 56d476525f5..fdf75eeaebb 100644 --- a/contrib/tsearch2/wordparser/Makefile +++ b/contrib/tsearch2/wordparser/Makefile @@ -1,9 +1,11 @@ +# $Header: /cvsroot/pgsql/contrib/tsearch2/wordparser/Attic/Makefile,v 1.3.2.1 2003/09/07 04:36:39 momjian Exp $ + subdir = contrib/tsearch2/wordparser top_builddir = ../../.. include $(top_builddir)/src/Makefile.global -override CPPFLAGS := -I$(srcdir) -I$(srcdir)/.. $(CPPFLAGS) +PG_CPPFLAGS = -I$(srcdir)/.. override CFLAGS += $(CFLAGS_SL) SUBOBJS = parser.o deflex.o @@ -23,6 +25,3 @@ SUBSYS.o: $(SUBOBJS) EXTRA_CLEAN = SUBSYS.o $(SUBOBJS) parser.c include $(top_srcdir)/contrib/contrib-global.mk -# DO NOT DELETE - - diff --git a/contrib/tsearch2/wordparser/parser.h b/contrib/tsearch2/wordparser/parser.h index 55cf0051ed0..1ce18741977 100644 --- a/contrib/tsearch2/wordparser/parser.h +++ b/contrib/tsearch2/wordparser/parser.h @@ -5,7 +5,6 @@ char *token; int tokenlen; int tsearch2_yylex(void); void start_parse_str(char *, int); -void start_parse_fh(FILE *, int); void end_parse(void); #endif diff --git a/contrib/tsearch2/wordparser/parser.l b/contrib/tsearch2/wordparser/parser.l index 49824f55259..23cfedaa201 100644 --- a/contrib/tsearch2/wordparser/parser.l +++ b/contrib/tsearch2/wordparser/parser.l @@ -23,36 +23,6 @@ char *s = NULL; /* to return WHOLE hyphenated-word */ YY_BUFFER_STATE buf = NULL; /* buffer to parse; it need for parse from string */ -int lrlimit = -1; /* for limiting read from filehandle ( -1 - unlimited read ) */ -int bytestoread = 0; /* for limiting read from filehandle */ - -/* redefine macro for read limited length */ -#define YY_INPUT(buf,result,max_size) \ - if ( yy_current_buffer->yy_is_interactive ) { \ - int c = '*', n; \ - for ( n = 0; n < max_size && \ - (c = getc( tsearch2_yyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( tsearch2_yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } else { \ - if ( lrlimit == 0 ) \ - result=YY_NULL; \ - else { \ - if ( lrlimit>0 ) { \ - bytestoread = ( lrlimit > max_size ) ? max_size : lrlimit; \ - lrlimit -= bytestoread; \ - } else \ - bytestoread = max_size; \ - if ( ((result = fread( buf, 1, bytestoread, tsearch2_yyin )) == 0) \ - && ferror( tsearch2_yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - } \ - } - %} %option 8bit @@ -334,13 +304,5 @@ void start_parse_str(char* str, int limit) { BEGIN INITIAL; } -/* start parse from filehandle */ -void start_parse_fh( FILE* fh, int limit ) { - if (buf) end_parse(); - lrlimit = ( limit ) ? limit : -1; - buf = tsearch2_yy_create_buffer( fh, YY_BUF_SIZE ); - tsearch2_yy_switch_to_buffer( buf ); - BEGIN INITIAL; -} @@ -1,7 +1,7 @@ Frequently Asked Questions (FAQ) for PostgreSQL - Last updated: Fri Jul 25 18:07:30 EDT 2003 + Last updated: Fri Sep 5 12:42:57 EDT 2003 Current maintainer: Bruce Momjian (pgman@candle.pha.pa.us) @@ -199,7 +199,8 @@ A native port to MS Win NT/2000/XP is currently being worked on. For more details on the current status of PostgreSQL on Windows see - http://techdocs.postgresql.org/guides/Windows. + http://techdocs.postgresql.org/guides/Windows and + http://candle.pha.pa.us/main/writings/pgsql/win32.html. There is also a Novell Netware 6 port at http://forge.novell.com. @@ -916,7 +917,8 @@ BYTEA bytea variable-length byte array (null-byte safe) Finally, you could use the OID returned from the INSERT statement to look up the default value, though this is probably the least portable - approach. In Perl, using DBI with Edmund Mergl's DBD::Pg module, the + approach, and the oid value will wrap around when it reaches 4 + billion. In Perl, using DBI with Edmund Mergl's DBD::Pg module, the oid value is made available via $sth->{pg_oid_status} after $sth->execute(). diff --git a/doc/FAQ_german b/doc/FAQ_german index 6d3aa8e75f6..32cb5464152 100644 --- a/doc/FAQ_german +++ b/doc/FAQ_german @@ -5,8 +5,8 @@ Deutsche эbersetzung von Ian Barwick (barwick@gmx.net). - Letzte Aktualisierung der deutschen эbersetzung: Di., den 22.07.2003, - 16:20 CET + Letzte Aktualisierung der deutschen эbersetzung: Di., den 02.09.2003, + 10:00 CET Die aktuellste Version dieses Dokuments liegt auf der PostgreSQL Website: @@ -1063,9 +1063,12 @@ BYTEA bytea Bytearray mit variabler LДnge Schlieъlich besteht noch die MЖglichkeit, den von einer INSERT-Anweisung zurЭckgelieferten OID-Wert als einmaligen Wert zu - verwenden. In Perl mit dem DBD::Pg-Modul von Edmund Mergl wird der - OID-Wert nach einem $sth->excute() Эber $sth->{pg_oid_status} - zurЭckgeliefert. + verwenden. Dieser Ansatz ist allerdings PostgreSQL-spezifisch; + auъerdem wird nach ca. 4 Milliarden EintrДgen der OID-Wert wieder auf + eine kleine Zahl gesetzt, ist also nicht garantiert einmalig. + + In Perl mit dem DBD::Pg-Modul wird der OID-Wert nach einem + $sth->excute() Эber $sth->{pg_oid_status} zurЭckgeliefert. 4.15.3) FЭhren currval() und nextval() zu einer Race-Condition mit anderen Nutzern? @@ -1278,15 +1281,21 @@ BYTEA bytea Bytearray mit variabler LДnge 4.28) Welche MЖglichkeiten zur VerschlЭsselung gibt es? * contrib/pgcrypto enthДlt diverse Funktionen fЭr die BenЭtzung mit - SQL-Abfragen; - * die einzige MЖglichkeit, Kommunikationen zwischen Client und - Server zu verschlЭsseln, ist durch die Anwendung von hostssl in - pg_hba.conf; + SQL-Abfragen. + * Um Verbindungen zwischen dem Server und Client-Anwendungen zu + verschlЭsseln, muss in der Server-Konfigurationsdatei + postgresql.conf die ssl-Option auf true (Voreinstellung: false) + gesetzt werden und ein passender host- bzw. hostssl-Eintrag muss + in pg_hba.conf vorhanden sein. Zudem muss die sslmode-Einstellung + beim Client nicht auf disable gesetzt werden. (Bitte beachten Sie + auch, daъ neben der eingebauten SSL-UnterstЭtzung verschlЭsselte + Verbindungen auch Эber externe Anwendungen wie stunnel oder ssh + aufgebaut werden kЖnnen). * Die PasswЖrter der Datenbanknutzer werden ab Version 7.3 automatisch verschlЭsselt (in frЭheren Versionen muъ der Parameter PASSWORD_ENCRYPTION in postgresql.conf explizit eingeschaltet - werden); - * der Server lДuft auf einem verschlЭsselten Dateisystem. + werden). + * Betrieb des Servers auf einem verschlЭsselten Dateisystem. _________________________________________________________________ PostgreSQL erweitern @@ -1326,10 +1335,15 @@ BYTEA bytea Bytearray mit variabler LДnge Die englische Vorlage dieser FAQ wird stДndig Эberarbeitet. Daher liegt die эbersetzung nicht immer auf dem aktuellsten Stand. + Die aktuellste Version der deutschen эbersetzung befindet sich immer + unter http://sql-info.de/postgresql/FAQ_german.html. Diese + "Arbeitsversion" enthДlt eventuell дnderungen, die noch nicht auf der + PostgreSQL-Website eingebunden worden sind. + эber Verbesserungshinweise und KorrekturvorschlДge sowie VerstДndnisfragen zum Inhalt der FAQ freue ich mich. Ich nehme auch - allgemeine Fragen zu PostgreSQL gerne entgegen, kann aber leider keine - zeitige Antwort garantieren. + allgemeine Fragen zu PostgreSQL gerne entgegen, verweise jedoch auf + die Mailing-Listen als schnelle und zuverlДssige Anlaufstellen. Diese эbersetzung basiert teilweise auf einer frЭheren эbersetzung von Karsten Schulz (schulz@linux-systemhaus.de). @@ -1,6 +1,6 @@ TODO list for PostgreSQL ======================== -Last updated: Tue Aug 12 18:04:15 EDT 2003 +Last updated: Fri Sep 5 15:52:01 EDT 2003 Current maintainer: Bruce Momjian (pgman@candle.pha.pa.us) @@ -52,7 +52,7 @@ Administration * Allow configuration files to be specified in a different directory * -Add start time to pg_stat_activity * Allow limits on per-db/user connections -* Have standalone backend read postgresql.conf +* -Have standalone backend read postgresql.conf (Tom) * Add group object ownership, so groups can rename/drop/grant on objects, so we can implement roles * Add the concept of dataspaces/tablespaces [tablespaces] @@ -62,6 +62,8 @@ Administration * Allow server log information to be output as INSERT statements * Prevent default re-use of sysids for dropped users and groups * Prevent dropping user that still owns objects, or auto-drop the objects +* Allow pooled connections to query prepared queries +* Allow pooled connections to close all open WITH HOLD cursors @@ -88,6 +90,10 @@ Data Types from making invalid dates valid * -Prevent month/day swapping of ISO dates to make invalid dates valid * Have initdb set DateStyle based on locale? +* Add pg_get_acldef(), pg_get_typedefault(), and pg_get_attrdef() +* Add ALTER DOMAIN, AGGREGATE, CONVERSION, SEQUENCE ... OWNER TO +* Allow to_char to print localized month names (Karel) + * ARRAYS o Allow nulls in arrays @@ -117,6 +123,8 @@ Multi-Language Support * Prevent mismatch of frontend/backend encodings from converting bytea data from being interpreted as encoded strings * -Remove Cyrillic recode support +* Fix upper()/lower() to work for multibyte encodings + Views / Rules @@ -142,7 +150,7 @@ Indexes INSERT INTO inherit_table (unique_index_col) VALUES (dup) should fail [inheritance] * Add UNIQUE capability to non-btree indexes -* Add btree index support for reltime, tinterval, regproc +* -Add btree index support for reltime, tinterval, regproc (Tom) * Add rtree index support for line, lseg, path, point * -Certain indexes will not shrink, e.g. indexes on ever-increasing columns and indexes with many duplicate keys @@ -160,7 +168,7 @@ Indexes float4, numeric/decimal too [optimizer] * Add FILLFACTOR to btree index creation * Add concurrency to GIST -* Improve concurrency of hash indexes (Neil) +* -Improve concurrency of hash indexes (Tom) * Allow a single index to index multiple tables (for inheritance and subtables) @@ -188,6 +196,8 @@ Commands * -Have SELECT '13 minutes'::interval display zero seconds in ISO datestyle * Prevent COMMENT ON DATABASE from using a database name * Add GUC variable to prevent waiting on locks +* Allow TRUNCATE ... CASCADE/RESTRICT +* Allow PREPARE of cursors * ALTER @@ -204,6 +214,7 @@ Commands o Allow ALTER TABLE to modify column lengths and change to binary compatible types o Add ALTER DATABASE ... OWNER TO newowner + o Allow ALTER TABLE ... ALTER CONSTRAINT ... RENAME * CLUSTER o Automatically maintain clustering on a table @@ -267,7 +278,7 @@ Clients * -Allow psql to show transaction status if backend protocol changes made * -Add schema, cast, and conversion backslash commands to psql (Christopher) * -Allow pg_dump to dump a specific schema (Neil Conway) -* Allow psql to do table completion for SELECT * FROM schema_part and +* -Allow psql to do table completion for SELECT * FROM schema_part and table completion for SELECT * FROM schema_name. * Add XML capability to pg_dump and COPY, when backend XML capability * -Allow SSL-enabled clients to turn off SSL transfers @@ -276,6 +287,7 @@ Clients * Allow psql \du to show groups, and add \dg for groups * Allow clients to query WITH HOLD cursors and prepared statements * Prevent unneeded quoting in psql \d output using fmtId() +* Add a libpq function to support Parse/DescribeStatement capability * JDBC @@ -326,7 +338,8 @@ Referential Integrity * Support triggers on columns (Neil) * Have AFTER triggers execute after the appropriate SQL statement in a function, not at the end of the function - +* Print table names with constraint names in error messages, or make constraint + names unique within a schema Dependency Checking =================== @@ -381,6 +394,8 @@ Vacuum * Provide automatic running of vacuum in the background in backend rather than in /contrib [vacuum] * Allow free space map to be auto-sized or warn when it is too small +* Maintain a map of recently-expired of pages so vacuum can reclaim + free space without a sequential scan Locking @@ -479,7 +494,7 @@ Source Code * Acquire lock on a relation before building a relcache entry for it * Research interaction of setitimer() and sleep() used by statement_timeout * Add checks for fclose() failure -* Change CVS $Id: TODO,v 1.1115 2003/08/13 03:12:04 momjian Exp $ to $PostgreSQL: pgsql/doc/TODO,v 1.1115 2003/08/13 03:12:04 momjian Exp $ +* Change CVS $Id: TODO,v 1.1115.2.1 2003/09/07 04:36:40 momjian Exp $ to $PostgreSQL: pgsql/doc/TODO,v 1.1115.2.1 2003/09/07 04:36:40 momjian Exp $ * Exit postmaster if postgresql.conf can not be opened * Rename /scripts directory because they are all C programs now * Allow the regression tests to start postmaster with -i so the tests diff --git a/doc/src/FAQ/FAQ.html b/doc/src/FAQ/FAQ.html index 641a3de6ea2..2983f0519d3 100644 --- a/doc/src/FAQ/FAQ.html +++ b/doc/src/FAQ/FAQ.html @@ -10,7 +10,7 @@ alink="#0000ff"> <H1>Frequently Asked Questions (FAQ) for PostgreSQL</H1> - <P>Last updated: Fri Jul 25 18:07:30 EDT 2003</P> + <P>Last updated: Fri Sep 5 12:42:57 EDT 2003</P> <P>Current maintainer: Bruce Momjian (<A href= "mailto:pgman@candle.pha.pa.us">pgman@candle.pha.pa.us</A>)<BR> @@ -251,7 +251,9 @@ <p>A native port to MS Win NT/2000/XP is currently being worked on. For more details on the current status of PostgreSQL on Windows see <a href="http://techdocs.postgresql.org/guides/Windows"> - http://techdocs.postgresql.org/guides/Windows</a>.</p> + http://techdocs.postgresql.org/guides/Windows</a> and + <a href="http://candle.pha.pa.us/main/writings/pgsql/win32.html"> + http://candle.pha.pa.us/main/writings/pgsql/win32.html</a>.</p> <p>There is also a Novell Netware 6 port at <a href="http://forge.novell.com">http://forge.novell.com</a>.</p> @@ -1152,7 +1154,8 @@ BYTEA bytea variable-length byte array (null-byte safe) Finally, you could use the <A href="#4.16"><SMALL>OID</SMALL></A> returned from the <SMALL>INSERT</SMALL> statement to look up the - default value, though this is probably the least portable approach. + default value, though this is probably the least portable approach, + and the oid value will wrap around when it reaches 4 billion. In Perl, using DBI with Edmund Mergl's DBD::Pg module, the oid value is made available via <I>$sth->{pg_oid_status}</I> after <I>$sth->execute()</I>. diff --git a/doc/src/FAQ/FAQ_german.html b/doc/src/FAQ/FAQ_german.html index 60752bcb5b2..5042cdfdca9 100644 --- a/doc/src/FAQ/FAQ_german.html +++ b/doc/src/FAQ/FAQ_german.html @@ -14,7 +14,7 @@ href="mailto:pgman@candle.pha.pa.us">pgman@candle.pha.pa.us</a>).</p> <p>Deutsche эbersetzung von Ian Barwick (<a href="mailto:barwick@gmx.net">barwick@gmx.net</a>).</p> - <p>Letzte Aktualisierung der deutschen эbersetzung: Di., den 22.07.2003, 16:20 CET</p> + <p>Letzte Aktualisierung der deutschen эbersetzung: Di., den 02.09.2003, 10:00 CET</p> <p>Die aktuellste Version dieses Dokuments liegt auf der PostgreSQL Website:</p> <ul> @@ -1060,8 +1060,12 @@ BYTEA bytea Bytearray mit variabler LДnge new_id = output of execute("SELECT currval('person_id_seq')"); </pre> <p>Schlieъlich besteht noch die MЖglichkeit, den von einer <small>INSERT</small>-Anweisung - zurЭckgelieferten <small>OID</small>-Wert als einmaligen Wert zu verwenden. - In Perl mit dem <em>DBD::Pg</em>-Modul von Edmund Mergl wird der OID-Wert nach einem + zurЭckgelieferten <a href="#4.16"><small>OID</small></a>-Wert als einmaligen Wert zu verwenden. + Dieser Ansatz ist allerdings PostgreSQL-spezifisch; auъerdem wird nach + ca. 4 Milliarden EintrДgen der <small>OID</small>-Wert wieder auf eine kleine Zahl + gesetzt, ist also nicht garantiert einmalig.</p> + + <p>In Perl mit dem <em>DBD::Pg</em>-Modul wird der OID-Wert nach einem <em>$sth->excute()</em> Эber <em>$sth->{pg_oid_status}</em> zurЭckgeliefert.</p> <h4><a name="4.15.3">4.15.3</a>) FЭhren <em>currval()</em> und <em>nextval()</em> zu einer Race-Condition mit anderen @@ -1285,13 +1289,21 @@ BYTEA bytea Bytearray mit variabler LДnge <ul> <li><em>contrib/pgcrypto</em> enthДlt diverse Funktionen fЭr die BenЭtzung mit - SQL-Abfragen;</li> - <li>die einzige MЖglichkeit, Kommunikationen zwischen Client und Server - zu verschlЭsseln, ist durch die Anwendung von <em>hostssl</em> in <em>pg_hba.conf</em>;</li> + SQL-Abfragen.</li> + + <li>Um Verbindungen zwischen dem Server und Client-Anwendungen zu + verschlЭsseln, muss in der Server-Konfigurationsdatei <em>postgresql.conf</em> + die <em>ssl</em>-Option auf <em>true</em> (Voreinstellung: <em>false</em>) gesetzt werden + und ein passender <em>host</em>- bzw. <em>hostssl</em>-Eintrag muss in + <em>pg_hba.conf</em> vorhanden sein. Zudem muss die <em>sslmode</em>-Einstellung + beim Client nicht auf <em>disable</em> gesetzt werden. (Bitte beachten Sie auch, + daъ neben der eingebauten SSL-UnterstЭtzung verschlЭsselte Verbindungen + auch Эber externe Anwendungen wie <em>stunnel</em> oder <em>ssh</em> aufgebaut werden kЖnnen).</li> + <li>Die PasswЖrter der Datenbanknutzer werden ab Version 7.3 automatisch verschlЭsselt (in frЭheren Versionen muъ der Parameter <em>PASSWORD_ENCRYPTION</em> - in <em>postgresql.conf</em> explizit eingeschaltet werden);</li> - <li>der Server lДuft auf einem verschlЭsselten Dateisystem.</li> + in <em>postgresql.conf</em> explizit eingeschaltet werden).</li> + <li>Betrieb des Servers auf einem verschlЭsselten Dateisystem.</li> </ul> <hr /> @@ -1333,9 +1345,15 @@ BYTEA bytea Bytearray mit variabler LДnge <p>Die englische Vorlage dieser FAQ wird stДndig Эberarbeitet. Daher liegt die эbersetzung nicht immer auf dem aktuellsten Stand.</p> + <p>Die aktuellste Version der deutschen эbersetzung befindet sich immer unter + <a href="http://sql-info.de/postgresql/FAQ_german.html">http://sql-info.de/postgresql/FAQ_german.html</a>. + Diese "Arbeitsversion" enthДlt eventuell дnderungen, die noch nicht auf der + PostgreSQL-Website eingebunden worden sind.</p> + <p>эber Verbesserungshinweise und KorrekturvorschlДge sowie VerstДndnisfragen zum Inhalt der FAQ freue ich mich. Ich nehme auch allgemeine Fragen zu PostgreSQL gerne - entgegen, kann aber leider keine zeitige Antwort garantieren.</p> + entgegen, verweise jedoch auf die Mailing-Listen als schnelle und zuverlДssige + Anlaufstellen.</p> <p>Diese эbersetzung basiert teilweise auf einer frЭheren эbersetzung von Karsten Schulz (<a href="mailto:schulz@linux-systemhaus.de">schulz@linux-systemhaus.de</a>).</p> diff --git a/doc/src/sgml/Makefile b/doc/src/sgml/Makefile index 42551d24074..22f8e427df2 100644 --- a/doc/src/sgml/Makefile +++ b/doc/src/sgml/Makefile @@ -2,7 +2,7 @@ # # PostgreSQL documentation makefile # -# $Header: /cvsroot/pgsql/doc/src/sgml/Makefile,v 1.57 2003/04/10 01:22:44 petere Exp $ +# $Header: /cvsroot/pgsql/doc/src/sgml/Makefile,v 1.57.2.1 2003/09/07 04:36:40 momjian Exp $ # #---------------------------------------------------------------------------- @@ -48,7 +48,7 @@ endif # Enable draft mode during development ifneq (,$(findstring devel, $(VERSION))) -JADEFLAGS += -V draft-mode +override JADEFLAGS += -V draft-mode endif @@ -82,7 +82,7 @@ html: postgres.sgml $(ALLSGML) stylesheet.dsl $(JADE) $(JADEFLAGS) $(SGMLINCLUDE) $(CATALOG) -d stylesheet.dsl -i output-html -t sgml $< -COLLATEINDEX := $(PERL) $(COLLATEINDEX) -f -g +COLLATEINDEX := LC_ALL=C $(PERL) $(COLLATEINDEX) -f -g ifeq (,$(wildcard HTML.index)) bookindex.sgml: diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml index d6d7881ef38..a0b4726a919 100644 --- a/doc/src/sgml/advanced.sgml +++ b/doc/src/sgml/advanced.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/advanced.sgml,v 1.34 2003/03/25 16:15:35 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/advanced.sgml,v 1.34.2.1 2003/09/07 04:36:40 momjian Exp $ --> <chapter id="tutorial-advanced"> @@ -142,7 +142,7 @@ ERROR: <unnamed> referential integrity violation - key referenced from we <title>Transactions</title> <indexterm zone="tutorial-transactions"> - <primary>transactions</primary> + <primary>transaction</primary> </indexterm> <para> diff --git a/doc/src/sgml/array.sgml b/doc/src/sgml/array.sgml index fabf2e732cd..a06c00cd348 100644 --- a/doc/src/sgml/array.sgml +++ b/doc/src/sgml/array.sgml @@ -1,10 +1,10 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/array.sgml,v 1.29 2003/08/09 22:50:21 tgl Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/array.sgml,v 1.29.2.1 2003/09/07 04:36:40 momjian Exp $ --> <sect1 id="arrays"> <title>Arrays</title> <indexterm> - <primary>arrays</primary> + <primary>array</primary> </indexterm> <para> @@ -162,7 +162,6 @@ ERROR: multidimensional arrays must have array expressions with matching dimens expression syntax is discussed in more detail in <xref linkend="sql-syntax-array-constructors">. </para> - </sect2> <sect2> @@ -326,9 +325,9 @@ UPDATE sal_emp SET pay_by_quarter[1:2] = '{27000,27000}' <literal>||</literal>. <programlisting> SELECT ARRAY[1,2] || ARRAY[3,4]; - ?column? ---------------- - {{1,2},{3,4}} + ?column? +----------- + {1,2,3,4} (1 row) SELECT ARRAY[5,6] || ARRAY[[1,2],[3,4]]; @@ -337,27 +336,68 @@ SELECT ARRAY[5,6] || ARRAY[[1,2],[3,4]]; {{5,6},{1,2},{3,4}} (1 row) </programlisting> + </para> + <para> The concatenation operator allows a single element to be pushed on to the beginning or end of a one-dimensional array. It also accepts two <replaceable>N</>-dimensional arrays, or an <replaceable>N</>-dimensional - and an <replaceable>N+1</>-dimensional array. In the former case, the two - <replaceable>N</>-dimension arrays become outer elements of an - <replaceable>N+1</>-dimensional array. In the latter, the - <replaceable>N</>-dimensional array is added as either the first or last - outer element of the <replaceable>N+1</>-dimensional array. - - When extending an array by concatenation, the subscripts of its existing - elements are preserved. For example, when pushing - onto the beginning of an array with one-based subscripts, the resulting - array has zero-based subscripts: + and an <replaceable>N+1</>-dimensional array. + </para> + <para> + When a single element is pushed on to the beginning of a one-dimensional + array, the result is an array with a lower bound subscript equal to + the righthand operand's lower bound subscript, minus one. When a single + element is pushed on to the end of a one-dimensional array, the result is + an array retaining the lower bound of the lefthand operand. For example: <programlisting> SELECT array_dims(1 || ARRAY[2,3]); array_dims ------------ [0:2] (1 row) + +SELECT array_dims(ARRAY[1,2] || 3); + array_dims +------------ + [1:3] +(1 row) +</programlisting> + </para> + + <para> + When two arrays with an equal number of dimensions are concatenated, the + result retains the lower bound subscript of the lefthand operand's outer + dimension. The result is an array comprising every element of the lefthand + operand followed by every element of the righthand operand. For example: +<programlisting> +SELECT array_dims(ARRAY[1,2] || ARRAY[3,4,5]); + array_dims +------------ + [1:5] +(1 row) + +SELECT array_dims(ARRAY[[1,2],[3,4]] || ARRAY[[5,6],[7,8],[9,0]]); + array_dims +------------ + [1:5][1:2] +(1 row) +</programlisting> + </para> + + <para> + When an <replaceable>N</>-dimensional array is pushed on to the beginning + or end of an <replaceable>N+1</>-dimensional array, the result is + analogous to the element-array case above. Each <replaceable>N</>-dimensional + sub-array is essentially an element of the <replaceable>N+1</>-dimensional + array's outer dimension. For example: +<programlisting> +SELECT array_dims(ARRAY[1,2] || ARRAY[[3,4],[5,6]]); + array_dims +------------ + [0:2][1:2] +(1 row) </programlisting> </para> @@ -386,9 +426,9 @@ SELECT array_append(ARRAY[1,2], 3); (1 row) SELECT array_cat(ARRAY[1,2], ARRAY[3,4]); - array_cat ---------------- - {{1,2},{3,4}} + array_cat +----------- + {1,2,3,4} (1 row) SELECT array_cat(ARRAY[[1,2],[3,4]], ARRAY[5,6]); diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml index 6e7e9cbf0be..204ffa5b838 100644 --- a/doc/src/sgml/backup.sgml +++ b/doc/src/sgml/backup.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/backup.sgml,v 2.27 2003/08/01 01:01:52 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/backup.sgml,v 2.27.2.1 2003/09/07 04:36:40 momjian Exp $ --> <chapter id="backup"> <title>Backup and Restore</title> @@ -153,6 +153,12 @@ pg_dump -h <replaceable>host1</> <replaceable>dbname</> | psql -h <replaceable>h </para> </important> + <tip> + <para> + Restore performance can be improved by increasing <literal>SORT_MEM</> + (see <xref linkend="runtime-config-resource-memory">). + </para> + </tip> </sect2> <sect2 id="backup-dump-all"> @@ -279,13 +285,15 @@ pg_dump -Fc <replaceable class="parameter">dbname</replaceable> > <replaceable c </para> <para> - For reasons of backward compatibility, <application>pg_dump</> does - not dump large objects by default. To dump large objects you must use - either the custom or the TAR output format, and use the <option>-b</> option in - <application>pg_dump</>. See the reference pages for details. - The directory <filename>contrib/pg_dumplo</> of the - <productname>PostgreSQL</> source tree also contains a program that can - dump large objects. + For reasons of backward compatibility, <application>pg_dump</> + does not dump large objects by default.<indexterm><primary>large + object</primary><secondary>backup</secondary></indexterm> To dump + large objects you must use either the custom or the TAR output + format, and use the <option>-b</> option in + <application>pg_dump</>. See the reference pages for details. The + directory <filename>contrib/pg_dumplo</> of the + <productname>PostgreSQL</> source tree also contains a program + that can dump large objects. </para> <para> @@ -365,7 +373,15 @@ tar -cf backup.tar /usr/local/pgsql/data <sect1 id="migration"> <title>Migration between releases</title> - <indexterm zone="migration"><primary>upgrading</></> + + <indexterm zone="migration"> + <primary>upgrading</primary> + </indexterm> + + <indexterm zone="migration"> + <primary>version</primary> + <secondary>compatibility</secondary> + </indexterm> <para> As a general rule, the internal data storage format is subject to diff --git a/doc/src/sgml/charset.sgml b/doc/src/sgml/charset.sgml index fb9db34019c..ec2ada9b488 100644 --- a/doc/src/sgml/charset.sgml +++ b/doc/src/sgml/charset.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/charset.sgml,v 2.37 2003/08/04 04:03:03 tgl Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/charset.sgml,v 2.37.2.1 2003/09/07 04:36:40 momjian Exp $ --> <chapter id="charset"> <title>Localization</> @@ -197,7 +197,7 @@ initdb --locale=sv_SE <listitem> <para> Sort order in queries using <command>ORDER BY</> - <indexterm><primary>ORDER BY</></> + <indexterm><primary>ORDER BY</><secondary>and locales</></indexterm> </para> </listitem> diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index e6180c762ee..0564779552a 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.53 2003/07/26 13:50:01 momjian Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.53.2.1 2003/09/07 04:36:40 momjian Exp $ --> <chapter id="client-authentication"> @@ -199,13 +199,17 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> <programlisting> (<replaceable>actual-IP-address</replaceable> xor <replaceable>IP-address-field</replaceable>) and <replaceable>IP-mask-field</replaceable> </programlisting> - must be zero for the record to match. (Of course IP addresses - can be spoofed but this consideration is beyond the scope of - <productname>PostgreSQL</productname>.) If you machine supports - IPv6, the default <filename>pg_hba.conf</> file will have an - IPv6 entry for <literal>localhost</>. You can add your own IPv6 - entries to the file. IPv6 entries are used only for IPv6 - connections. + must be zero for the record to match. + </para> + + <para> + An IP address given in IPv4 format will match IPv6 connections that + have the corresponding address, for example <literal>127.0.0.1</> + will match the IPv6 address <literal>::ffff:127.0.0.1</>. An entry + given in IPv6 format will match only IPv6 connections, even if the + represented address is in the IPv4-in-IPv6 range. Note that entries + in IPv6 format will be rejected if the system's C library does not have + support for IPv6 addresses. </para> <para> @@ -219,9 +223,10 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> <term><replaceable>CIDR-mask</replaceable></term> <listitem> <para> - This is an integer specifying the number of significant bits - to set in the mask, and is an alternative to using the - <replaceable>IP-mask</replaceable> notation. The number must + This field may be used as an alternative to the + <replaceable>IP-mask</replaceable> notation. It is an + integer specifying the number of high-order bits + to set in the mask. The number must be between 0 and 32 (in the case of an IPv4 address) or 128 (in the case of an IPv6 address) inclusive. 0 will match any address, while 32/128 will match only the exact host specified. @@ -451,6 +456,11 @@ local all all trust # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD host all all 127.0.0.1 255.255.255.255 trust +# The same as the last line but using a CIDR mask +# +# TYPE DATABASE USER IP-ADDRESS/CIDR-mask METHOD +host all all 127.0.0.1/32 trust + # Allow any user from any host with IP address 192.168.93.x to connect # to database "template1" as the same user name that ident reports for # the connection (typically the Unix user name). @@ -458,6 +468,11 @@ host all all 127.0.0.1 255.255.255.255 trust # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD host template1 all 192.168.93.0 255.255.255.0 ident sameuser +# The same as the last line but using a CIDR mask +# +# TYPE DATABASE USER IP-ADDRESS/CIDR-mask METHOD +host template1 all 192.168.93.0/24 ident sameuser + # Allow a user from host 192.168.12.10 to connect to database # "template1" if the user's password is correctly supplied. # @@ -566,6 +581,7 @@ local db1,db2,@demodbs all md5 </indexterm> <indexterm> <primary>password</primary> + <secondary>authentication</secondary> </indexterm> <para> @@ -610,16 +626,21 @@ local db1,db2,@demodbs all md5 <para> <productname>Kerberos</productname> is an industry-standard secure - authentication system suitable for distributed computing over a - public network. A description of the - <productname>Kerberos</productname> system is far beyond the scope - of this document; in all generality it can be quite complex (yet - powerful). The <ulink + authentication system suitable for distributed computing over a public + network. A description of the <productname>Kerberos</productname> system + is far beyond the scope of this document; in all generality it can be + quite complex (yet powerful). The <ulink url="http://www.nrl.navy.mil/CCS/people/kenh/kerberos-faq.html">Kerberos - <acronym>FAQ</></ulink> or <ulink - url="ftp://athena-dist.mit.edu">MIT Project Athena</ulink> can be - a good starting point for exploration. Several sources for - <productname>Kerberos</> distributions exist. + <acronym>FAQ</></ulink> or <ulink url="ftp://athena-dist.mit.edu">MIT + Project Athena</ulink> can be a good starting point for exploration. + Several sources for <productname>Kerberos</> distributions exist. + </para> + + <para> + While <productname>PostgreSQL</> supports both Kerberos 4 and + Kerberos 5, only Kerberos 5 is recommended. Kerberos 4 is + considered insecure and no longer recommended for general + use. </para> <para> @@ -850,6 +871,10 @@ omicron bryanh guest1 <sect2 id="auth-pam"> <title>PAM Authentication</title> + <indexterm zone="auth-pam"> + <primary>PAM</primary> + </indexterm> + <para> This authentication method operates similarly to <literal>password</literal> except that it uses PAM (Pluggable diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index b8053f94e55..295cbd779a0 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -1,17 +1,17 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.122 2003/08/09 22:50:21 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.122.2.1 2003/09/07 04:36:40 momjian Exp $ --> <chapter id="datatype"> <title id="datatype-title">Data Types</title> <indexterm zone="datatype"> - <primary>data types</primary> + <primary>data type</primary> </indexterm> <indexterm> - <primary>types</primary> - <see>data types</see> + <primary>type</primary> + <see>data type</see> </indexterm> <para> @@ -279,68 +279,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.122 2003/08/09 22:50:21 t <title>Numeric Types</title> <indexterm zone="datatype-numeric"> - <primary>data types</primary> + <primary>data type</primary> <secondary>numeric</secondary> </indexterm> - <indexterm zone="datatype-numeric"> - <primary>integer</primary> - </indexterm> - - <indexterm zone="datatype-numeric"> - <primary>smallint</primary> - </indexterm> - - <indexterm zone="datatype-numeric"> - <primary>bigint</primary> - </indexterm> - - <indexterm> - <primary>int4</primary> - <see>integer</see> - </indexterm> - - <indexterm> - <primary>int2</primary> - <see>smallint</see> - </indexterm> - - <indexterm> - <primary>int8</primary> - <see>bigint</see> - </indexterm> - - <indexterm zone="datatype-numeric"> - <primary>numeric (data type)</primary> - </indexterm> - - <indexterm> - <primary>decimal</primary> - <see>numeric</see> - </indexterm> - - <indexterm zone="datatype-numeric"> - <primary>real</primary> - </indexterm> - - <indexterm zone="datatype-numeric"> - <primary>double precision</primary> - </indexterm> - - <indexterm> - <primary>float4</primary> - <see>real</see> - </indexterm> - - <indexterm> - <primary>float8</primary> - <see>double precision</see> - </indexterm> - - <indexterm zone="datatype-numeric"> - <primary>floating point</primary> - </indexterm> - <para> Numeric types consist of two-, four-, and eight-byte integers, four- and eight-byte floating-point numbers, and fixed-precision @@ -434,6 +376,33 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.122 2003/08/09 22:50:21 t <sect2 id="datatype-int"> <title>Integer Types</title> + <indexterm zone="datatype-int"> + <primary>integer</primary> + </indexterm> + + <indexterm zone="datatype-int"> + <primary>smallint</primary> + </indexterm> + + <indexterm zone="datatype-int"> + <primary>bigint</primary> + </indexterm> + + <indexterm> + <primary>int4</primary> + <see>integer</see> + </indexterm> + + <indexterm> + <primary>int2</primary> + <see>smallint</see> + </indexterm> + + <indexterm> + <primary>int8</primary> + <see>bigint</see> + </indexterm> + <para> The types <type>smallint</type>, <type>integer</type>, and <type>bigint</type> store whole numbers, that is, numbers without @@ -495,6 +464,15 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.122 2003/08/09 22:50:21 t <sect2 id="datatype-numeric-decimal"> <title>Arbitrary Precision Numbers</title> + <indexterm zone="datatype-numeric-decimal"> + <primary>numeric (data type)</primary> + </indexterm> + + <indexterm> + <primary>decimal</primary> + <see>numeric</see> + </indexterm> + <para> The type <type>numeric</type> can store numbers with up to 1000 digits of precision and perform calculations exactly. It is @@ -562,6 +540,28 @@ NUMERIC <sect2 id="datatype-float"> <title>Floating-Point Types</title> + <indexterm zone="datatype-float"> + <primary>real</primary> + </indexterm> + + <indexterm zone="datatype-float"> + <primary>double precision</primary> + </indexterm> + + <indexterm> + <primary>float4</primary> + <see>real</see> + </indexterm> + + <indexterm> + <primary>float8</primary> + <see>double precision</see> + </indexterm> + + <indexterm zone="datatype-float"> + <primary>floating point</primary> + </indexterm> + <para> The data types <type>real</type> and <type>double precision</type> are inexact, variable-precision numeric types. @@ -675,7 +675,7 @@ NUMERIC </indexterm> <indexterm> - <primary>sequences</primary> + <primary>sequence</primary> <secondary>and serial type</secondary> </indexterm> @@ -807,18 +807,33 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> ( <title>Character Types</title> <indexterm zone="datatype-character"> - <primary>character strings</primary> + <primary>character string</primary> <secondary>data types</secondary> </indexterm> <indexterm> - <primary>strings</primary> - <see>character strings</see> + <primary>string</primary> + <see>character string</see> </indexterm> - <indexterm> + <indexterm zone="datatype-character"> + <primary>character</primary> + </indexterm> + + <indexterm zone="datatype-character"> + <primary>character varying</primary> + </indexterm> + + <indexterm zone="datatype-character"> <primary>text</primary> - <see>character strings</see> + </indexterm> + + <indexterm zone="datatype-character"> + <primary>char</primary> + </indexterm> + + <indexterm zone="datatype-character"> + <primary>varchar</primary> </indexterm> <table id="datatype-character-table"> @@ -1020,6 +1035,15 @@ SELECT b, char_length(b) FROM test2; <sect1 id="datatype-binary"> <title>Binary Data Types</title> + + <indexterm zone="datatype-binary"> + <primary>binary data</primary> + </indexterm> + + <indexterm zone="datatype-binary"> + <primary>bytea</primary> + </indexterm> + <para> The <type>bytea</type> data type allows storage of binary strings; see <xref linkend="datatype-binary-table">. @@ -1210,6 +1234,34 @@ SELECT b, char_length(b) FROM test2; <sect1 id="datatype-datetime"> <title>Date/Time Types</title> + <indexterm zone="datatype-datetime"> + <primary>date</primary> + </indexterm> + <indexterm zone="datatype-datetime"> + <primary>time</primary> + </indexterm> + <indexterm zone="datatype-datetime"> + <primary>time without time zone</primary> + </indexterm> + <indexterm zone="datatype-datetime"> + <primary>time with time zone</primary> + </indexterm> + <indexterm zone="datatype-datetime"> + <primary>timestamp</primary> + </indexterm> + <indexterm zone="datatype-datetime"> + <primary>timestamp with time zone</primary> + </indexterm> + <indexterm zone="datatype-datetime"> + <primary>timestamp without time zone</primary> + </indexterm> + <indexterm zone="datatype-datetime"> + <primary>interval</primary> + </indexterm> + <indexterm zone="datatype-datetime"> + <primary>time span</primary> + </indexterm> + <para> <productname>PostgreSQL</productname> supports the full set of <acronym>SQL</acronym> date and time types, shown in <xref @@ -1387,7 +1439,6 @@ SELECT b, char_length(b) FROM test2; <indexterm> <primary>date</primary> - <secondary>data type</secondary> </indexterm> <para> @@ -1461,15 +1512,12 @@ SELECT b, char_length(b) FROM test2; <indexterm> <primary>time</primary> - <secondary>data type</secondary> </indexterm> <indexterm> <primary>time without time zone</primary> - <secondary>time</secondary> </indexterm> <indexterm> <primary>time with time zone</primary> - <secondary>data type</secondary> </indexterm> <para> @@ -1587,17 +1635,14 @@ SELECT b, char_length(b) FROM test2; <indexterm> <primary>timestamp</primary> - <secondary>data type</secondary> </indexterm> <indexterm> <primary>timestamp with time zone</primary> - <secondary>data type</secondary> </indexterm> <indexterm> <primary>timestamp without time zone</primary> - <secondary>data type</secondary> </indexterm> <para> @@ -1797,13 +1842,13 @@ January 8 04:05:06 1999 PST <indexterm> <primary>date</primary> <secondary>output format</secondary> - <seealso>Formatting</seealso> + <seealso>formatting</seealso> </indexterm> <indexterm> <primary>time</primary> <secondary>output format</secondary> - <seealso>Formatting</seealso> + <seealso>formatting</seealso> </indexterm> <para> @@ -1924,7 +1969,7 @@ January 8 04:05:06 1999 PST <title>Time Zones</title> <indexterm zone="datatype-timezones"> - <primary>time zones</primary> + <primary>time zone</primary> </indexterm> <para> @@ -2265,7 +2310,11 @@ SELECT * FROM test1 WHERE a; <title>Line Segments</title> <indexterm> - <primary>line</primary> + <primary>lseg</primary> + </indexterm> + + <indexterm> + <primary>line segment</primary> </indexterm> <para> @@ -2293,6 +2342,10 @@ SELECT * FROM test1 WHERE a; <primary>box (data type)</primary> </indexterm> + <indexterm> + <primary>rectangle</primary> + </indexterm> + <para> Boxes are represented by pairs of points that are opposite corners of the box. @@ -2431,7 +2484,7 @@ SELECT * FROM test1 WHERE a; <indexterm zone="datatype-net-types"> <primary>network</primary> - <secondary>addresses</secondary> + <secondary>data types</secondary> </indexterm> <para> @@ -2708,7 +2761,7 @@ SELECT * FROM test1 WHERE a; <title>Bit String Types</title> <indexterm zone="datatype-bit"> - <primary>bit strings</primary> + <primary>bit string</primary> <secondary>data type</secondary> </indexterm> @@ -3046,11 +3099,6 @@ SELECT * FROM test; <tbody> <row> - <entry><type>record</></entry> - <entry>Identifies a function returning an unspecified row type.</entry> - </row> - - <row> <entry><type>any</></entry> <entry>Indicates that a function accepts any input data type whatever.</entry> </row> @@ -3058,23 +3106,24 @@ SELECT * FROM test; <row> <entry><type>anyarray</></entry> <entry>Indicates that a function accepts any array data type - (see <xref linkend="types-polymorphic">).</entry> + (see <xref linkend="extend-types-polymorphic">).</entry> </row> <row> <entry><type>anyelement</></entry> <entry>Indicates that a function accepts any data type - (see <xref linkend="types-polymorphic">).</entry> + (see <xref linkend="extend-types-polymorphic">).</entry> </row> <row> - <entry><type>void</></entry> - <entry>Indicates that a function returns no value.</entry> + <entry><type>cstring</></entry> + <entry>Indicates that a function accepts or returns a null-terminated C string.</entry> </row> <row> - <entry><type>trigger</></entry> - <entry>A trigger function is declared to return <type>trigger.</></entry> + <entry><type>internal</></entry> + <entry>Indicates that a function accepts or returns a server-internal + data type.</entry> </row> <row> @@ -3083,14 +3132,18 @@ SELECT * FROM test; </row> <row> - <entry><type>cstring</></entry> - <entry>Indicates that a function accepts or returns a null-terminated C string.</entry> + <entry><type>record</></entry> + <entry>Identifies a function returning an unspecified row type.</entry> </row> <row> - <entry><type>internal</></entry> - <entry>Indicates that a function accepts or returns a server-internal - data type.</entry> + <entry><type>trigger</></entry> + <entry>A trigger function is declared to return <type>trigger.</></entry> + </row> + + <row> + <entry><type>void</></entry> + <entry>Indicates that a function returns no value.</entry> </row> <row> diff --git a/doc/src/sgml/datetime.sgml b/doc/src/sgml/datetime.sgml index c205ee9c314..9c97f633898 100644 --- a/doc/src/sgml/datetime.sgml +++ b/doc/src/sgml/datetime.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.32 2003/07/29 00:03:17 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.32.2.1 2003/09/07 04:36:41 momjian Exp $ --> <appendix id="datetime-appendix"> @@ -364,7 +364,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.32 2003/07/29 00:03:17 tg </para> <indexterm> - <primary>time zones</primary> + <primary>time zone</primary> + <secondary>abbreviations</secondary> </indexterm> <para> @@ -536,18 +537,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.32 2003/07/29 00:03:17 tg <entry>+07:00</entry> <entry>Christmas (Island) Time</entry> </row> -<!-- - Conflicts with China Coastal Time - <row> - <entry>CCT</entry> - <entry>+06:30</entry> - <entry>Cocos Island Time</entry> - </row> ---> <row> <entry>MMT</entry> <entry>+06:30</entry> - <entry>Myannar Time</entry> + <entry>Myanmar Time</entry> </row> <row> <entry>ALMT</entry> @@ -760,6 +753,21 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.32 2003/07/29 00:03:17 tg <entry>West Africa Time</entry> </row> <row> + <entry>FNST</entry> + <entry>-01:00</entry> + <entry>Fernando de Noronha Summer Time</entry> + </row> + <row> + <entry>FNT</entry> + <entry>-02:00</entry> + <entry>Fernando de Noronha Time</entry> + </row> + <row> + <entry>BRST</entry> + <entry>-02:00</entry> + <entry>Brasilia Summer Time</entry> + </row> + <row> <entry>NDT</entry> <entry>-02:30</entry> <entry>Newfoundland Daylight-Saving Time</entry> @@ -775,6 +783,11 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.32 2003/07/29 00:03:17 tg <entry>(unknown)</entry> </row> <row> + <entry>BRT</entry> + <entry>-03:00</entry> + <entry>Brasilia Time</entry> + </row> + <row> <entry>NFT</entry> <entry>-03:30</entry> <entry>Newfoundland Standard Time</entry> @@ -795,11 +808,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.32 2003/07/29 00:03:17 tg <entry>Atlantic/Porto Acre Summer Time</entry> </row> <row> - <entry>ACT</entry> - <entry>-05:00</entry> - <entry>Atlantic/Porto Acre Standard Time</entry> - </row> - <row> <entry>EDT</entry> <entry>-04:00</entry> <entry>Eastern Daylight-Saving Time</entry> @@ -812,6 +820,11 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.32 2003/07/29 00:03:17 tg </row> --> <row> + <entry>ACT</entry> + <entry>-05:00</entry> + <entry>Atlantic/Porto Acre Standard Time</entry> + </row> + <row> <entry>CDT</entry> <entry>-05:00</entry> <entry>Central Daylight-Saving Time</entry> diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index fc6cdc331c2..183a8f790d3 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ddl.sgml,v 1.17 2003/08/14 23:13:27 tgl Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ddl.sgml,v 1.17.2.1 2003/09/07 04:36:41 momjian Exp $ --> <chapter id="ddl"> <title>Data Definition</title> @@ -19,6 +19,18 @@ <sect1 id="ddl-basics"> <title>Table Basics</title> + <indexterm zone="ddl-basics"> + <primary>table</primary> + </indexterm> + + <indexterm> + <primary>row</primary> + </indexterm> + + <indexterm> + <primary>column</primary> + </indexterm> + <para> A table in a relational database is much like a table on paper: It consists of rows and columns. The number and order of the columns @@ -60,6 +72,11 @@ containing both date and time. </para> + <indexterm> + <primary>table</primary> + <secondary>creating</secondary> + </indexterm> + <para> To create a table, you use the aptly named <literal>CREATE TABLE</literal> command. In this command you specify at least a @@ -114,6 +131,11 @@ CREATE TABLE products ( highly unusual and often a questionable design. </para> + <indexterm> + <primary>table</primary> + <secondary>removing</secondary> + </indexterm> + <para> If you no longer need a table, you can remove it using the <command>DROP TABLE</command> command. For example: @@ -156,8 +178,8 @@ DROP TABLE products; </para> <indexterm> - <primary>columns</primary> - <secondary>system columns</secondary> + <primary>column</primary> + <secondary>system column</secondary> </indexterm> <variablelist> @@ -167,6 +189,7 @@ DROP TABLE products; <para> <indexterm> <primary>OID</primary> + <secondary>column</secondary> </indexterm> The object identifier (object ID) of a row. This is a serial number that is automatically added by @@ -182,6 +205,10 @@ DROP TABLE products; <varlistentry> <term><structfield>tableoid</></term> <listitem> + <indexterm> + <primary>tableoid</primary> + </indexterm> + <para> The OID of the table containing this row. This column is particularly handy for queries that select from inheritance @@ -197,6 +224,10 @@ DROP TABLE products; <varlistentry> <term><structfield>xmin</></term> <listitem> + <indexterm> + <primary>xmin</primary> + </indexterm> + <para> The identity (transaction ID) of the inserting transaction for this tuple. (Note: In this context, a tuple is an individual @@ -209,6 +240,10 @@ DROP TABLE products; <varlistentry> <term><structfield>cmin</></term> <listitem> + <indexterm> + <primary>cmin</primary> + </indexterm> + <para> The command identifier (starting at zero) within the inserting transaction. @@ -219,6 +254,10 @@ DROP TABLE products; <varlistentry> <term><structfield>xmax</></term> <listitem> + <indexterm> + <primary>xmax</primary> + </indexterm> + <para> The identity (transaction ID) of the deleting transaction, or zero for an undeleted tuple. It is possible for this column to @@ -232,6 +271,10 @@ DROP TABLE products; <varlistentry> <term><structfield>cmax</></term> <listitem> + <indexterm> + <primary>cmax</primary> + </indexterm> + <para> The command identifier within the deleting transaction, or zero. </para> @@ -241,6 +284,10 @@ DROP TABLE products; <varlistentry> <term><structfield>ctid</></term> <listitem> + <indexterm> + <primary>ctid</primary> + </indexterm> + <para> The physical location of the tuple within its table. Note that although the <structfield>ctid</structfield> can be used to @@ -292,6 +339,10 @@ DROP TABLE products; <sect1 id="ddl-default"> <title>Default Values</title> + <indexterm zone="ddl-default"> + <primary>default value</primary> + </indexterm> + <para> A column can be assigned a default value. When a new row is created and no values are specified for some of the columns, the @@ -302,6 +353,7 @@ DROP TABLE products; </para> <para> + <indexterm><primary>null value</primary><secondary>default value</secondary></indexterm> If no default value is declared explicitly, the null value is the default value. This usually makes sense because a null value can be thought to represent unknown data. @@ -329,6 +381,10 @@ CREATE TABLE products ( <sect1 id="ddl-constraints"> <title>Constraints</title> + <indexterm zone="ddl-constraints"> + <primary>constraint</primary> + </indexterm> + <para> Data types are a way to limit the kind of data that can be stored in a table. For many applications, however, the constraint they @@ -351,6 +407,15 @@ CREATE TABLE products ( <sect2> <title>Check Constraints</title> + <indexterm> + <primary>check constraint</primary> + </indexterm> + + <indexterm> + <primary>constraint</primary> + <secondary>check</secondary> + </indexterm> + <para> A check constraint is the most generic constraint type. It allows you to specify that the value in a certain column must satisfy an @@ -375,6 +440,11 @@ CREATE TABLE products ( would not make too much sense. </para> + <indexterm> + <primary>constraint</primary> + <secondary>name</secondary> + </indexterm> + <para> You can also give the constraint a separate name. This clarifies error messages and allows you to refer to the constraint when you @@ -444,6 +514,11 @@ CREATE TABLE products ( It's a matter of taste. </para> + <indexterm> + <primary>null value</primary> + <secondary sortas="check constraints">with check constraints</secondary> + </indexterm> + <para> It should be noted that a check constraint is satisfied if the check expression evaluates to true or the null value. Since most @@ -457,6 +532,15 @@ CREATE TABLE products ( <sect2> <title>Not-Null Constraints</title> + <indexterm> + <primary>not-null constraint</primary> + </indexterm> + + <indexterm> + <primary>constraint</primary> + <secondary>NOT NULL</secondary> + </indexterm> + <para> A not-null constraint simply specifies that a column must not assume the null value. A syntax example: @@ -526,6 +610,15 @@ CREATE TABLE products ( <sect2> <title>Unique Constraints</title> + <indexterm> + <primary>unique constraint</primary> + </indexterm> + + <indexterm> + <primary>constraint</primary> + <secondary>unique</secondary> + </indexterm> + <para> Unique constraints ensure that the data contained in a column or a group of columns is unique with respect to all the rows in the @@ -573,6 +666,11 @@ CREATE TABLE products ( </programlisting> </para> + <indexterm> + <primary>null value</primary> + <secondary sortas="unique constraints">with unique constraints</secondary> + </indexterm> + <para> In general, a unique constraint is violated when there are (at least) two rows in the table where the values of each of the @@ -591,6 +689,15 @@ CREATE TABLE products ( <sect2> <title>Primary Keys</title> + <indexterm> + <primary>primary key</primary> + </indexterm> + + <indexterm> + <primary>constraint</primary> + <secondary>primary key</secondary> + </indexterm> + <para> Technically, a primary key constraint is simply a combination of a unique constraint and a not-null constraint. So, the following @@ -649,6 +756,19 @@ CREATE TABLE example ( <sect2 id="ddl-constraints-fk"> <title>Foreign Keys</title> + <indexterm> + <primary>foreign key</primary> + </indexterm> + + <indexterm> + <primary>constraint</primary> + <secondary>foreign key</secondary> + </indexterm> + + <indexterm> + <primary>referential integrity</primary> + </indexterm> + <para> A foreign key constraint specifies that the values in a column (or a group of columns) must match the values appearing in some row @@ -749,6 +869,16 @@ CREATE TABLE order_items ( the last table. </para> + <indexterm> + <primary>CASCADE</primary> + <secondary>foreign key action</secondary> + </indexterm> + + <indexterm> + <primary>RESTRICT</primary> + <secondary>foreign key action</secondary> + </indexterm> + <para> We know that the foreign keys disallow creation of orders that do not relate to any products. But what if a product is removed @@ -998,6 +1128,11 @@ SET SQL_Inheritance TO OFF; <sect1 id="ddl-alter"> <title>Modifying Tables</title> + <indexterm zone="ddl-alter"> + <primary>table</primary> + <secondary>modifying</secondary> + </indexterm> + <para> When you create a table and you realize that you made a mistake, or the requirements of the application changed, then you can drop the @@ -1042,6 +1177,11 @@ SET SQL_Inheritance TO OFF; <sect2> <title>Adding a Column</title> + <indexterm> + <primary>column</primary> + <secondary>adding</secondary> + </indexterm> + <para> To add a column, use this command: <programlisting> @@ -1070,6 +1210,11 @@ ALTER TABLE products ADD COLUMN description text CHECK (description <> '') <sect2> <title>Removing a Column</title> + <indexterm> + <primary>column</primary> + <secondary>removing</secondary> + </indexterm> + <para> To remove a column, use this command: <programlisting> @@ -1081,6 +1226,11 @@ ALTER TABLE products DROP COLUMN description; <sect2> <title>Adding a Constraint</title> + <indexterm> + <primary>constraint</primary> + <secondary>adding</secondary> + </indexterm> + <para> To add a constraint, the table constraint syntax is used. For example: <programlisting> @@ -1104,6 +1254,11 @@ ALTER TABLE products ALTER COLUMN product_no SET NOT NULL; <sect2> <title>Removing a Constraint</title> + <indexterm> + <primary>constraint</primary> + <secondary>removing</secondary> + </indexterm> + <para> To remove a constraint you need to know its name. If you gave it a name then that's easy. Otherwise the system assigned a @@ -1127,6 +1282,11 @@ ALTER TABLE products ALTER COLUMN product_no DROP NOT NULL; <sect2> <title>Changing the Default</title> + <indexterm> + <primary>default value</primary> + <secondary>changing</secondary> + </indexterm> + <para> To set a new default for a column, use a command like this: <programlisting> @@ -1146,6 +1306,11 @@ ALTER TABLE products ALTER COLUMN price DROP DEFAULT; <sect2> <title>Renaming a Column</title> + <indexterm> + <primary>column</primary> + <secondary>renaming</secondary> + </indexterm> + <para> To rename a column: <programlisting> @@ -1157,6 +1322,11 @@ ALTER TABLE products RENAME COLUMN product_no TO product_number; <sect2> <title>Renaming a Table</title> + <indexterm> + <primary>table</primary> + <secondary>renaming</secondary> + </indexterm> + <para> To rename a table: <programlisting> @@ -1169,6 +1339,15 @@ ALTER TABLE products RENAME TO items; <sect1 id="ddl-priv"> <title>Privileges</title> + <indexterm zone="ddl-priv"> + <primary>privilege</primary> + </indexterm> + + <indexterm> + <primary>permission</primary> + <see>privilege</see> + </indexterm> + <para> When you create a database object, you become its owner. By default, only the owner of an object can do anything with the @@ -1241,12 +1420,8 @@ REVOKE ALL ON accounts FROM PUBLIC; <sect1 id="ddl-schemas"> <title>Schemas</title> - <indexterm> - <primary>schemas</primary> - </indexterm> - - <indexterm> - <primary>namespaces</primary> + <indexterm zone="ddl-schemas"> + <primary>schema</primary> </indexterm> <para> @@ -1313,6 +1488,11 @@ REVOKE ALL ON accounts FROM PUBLIC; <sect2 id="ddl-schemas-create"> <title>Creating a Schema</title> + <indexterm zone="ddl-schemas-create"> + <primary>schema</primary> + <secondary>creating</secondary> + </indexterm> + <para> To create a separate schema, use the command <literal>CREATE SCHEMA</literal>. Give the schema a name of your choice. For @@ -1323,11 +1503,11 @@ CREATE SCHEMA myschema; </para> <indexterm> - <primary>qualified names</primary> + <primary>qualified name</primary> </indexterm> <indexterm> - <primary>names</primary> + <primary>name</primary> <secondary>qualified</secondary> </indexterm> @@ -1359,6 +1539,11 @@ CREATE TABLE myschema.mytable ( the following chapters. </para> + <indexterm> + <primary>schema</primary> + <secondary>removing</secondary> + </indexterm> + <para> To drop a schema if it's empty (all objects in it have been dropped), use @@ -1394,6 +1579,11 @@ CREATE SCHEMA <replaceable>schemaname</replaceable> AUTHORIZATION <replaceable>u <sect2 id="ddl-schemas-public"> <title>The Public Schema</title> + <indexterm zone="ddl-schemas-public"> + <primary>schema</primary> + <secondary>public</secondary> + </indexterm> + <para> In the previous sections we created tables without specifying any schema names. By default, such tables (and other objects) are @@ -1417,11 +1607,11 @@ CREATE TABLE public.products ( ... ); </indexterm> <indexterm> - <primary>unqualified names</primary> + <primary>unqualified name</primary> </indexterm> <indexterm> - <primary>names</primary> + <primary>name</primary> <secondary>unqualified</secondary> </indexterm> @@ -1437,6 +1627,11 @@ CREATE TABLE public.products ( ... ); in other schemas in the database. </para> + <indexterm> + <primary>schema</primary> + <secondary>current</secondary> + </indexterm> + <para> The first schema named in the search path is called the current schema. Aside from being the first schema searched, it is also the schema in @@ -1444,6 +1639,10 @@ CREATE TABLE public.products ( ... ); command does not specify a schema name. </para> + <indexterm> + <primary>search_path</primary> + </indexterm> + <para> To show the current search path, use the following command: <programlisting> @@ -1523,6 +1722,11 @@ SELECT 3 OPERATOR(pg_catalog.+) 4; <sect2 id="ddl-schemas-priv"> <title>Schemas and Privileges</title> + <indexterm zone="ddl-schemas-priv"> + <primary>privilege</primary> + <secondary sortas="schemas">for schemas</secondary> + </indexterm> + <para> By default, users cannot see the objects in schemas they do not own. To allow that, the owner of the schema needs to grant the @@ -1550,9 +1754,14 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC; </para> </sect2> - <sect2> + <sect2 id="ddl-schemas-catalog"> <title>The System Catalog Schema</title> + <indexterm zone="ddl-schemas-catalog"> + <primary>system catalog</primary> + <secondary>schema</secondary> + </indexterm> + <para> In addition to <literal>public</> and user-created schemas, each database contains a <literal>pg_catalog</> schema, which contains @@ -1701,6 +1910,16 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC; <sect1 id="ddl-depend"> <title>Dependency Tracking</title> + <indexterm zone="ddl-depend"> + <primary>CASCADE</primary> + <secondary sortas="DROP">with DROP</secondary> + </indexterm> + + <indexterm zone="ddl-depend"> + <primary>RESTRICT</primary> + <secondary sortas="DROP">with DROP</secondary> + </indexterm> + <para> When you create complex database structures involving many tables with foreign key constraints, views, triggers, functions, etc. you diff --git a/doc/src/sgml/dfunc.sgml b/doc/src/sgml/dfunc.sgml index 3898a2bc176..57fb6f208f3 100644 --- a/doc/src/sgml/dfunc.sgml +++ b/doc/src/sgml/dfunc.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.25 2003/04/10 01:22:44 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.25.2.1 2003/09/07 04:36:41 momjian Exp $ --> <sect2 id="dfunc"> @@ -8,9 +8,11 @@ $Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.25 2003/04/10 01:22:44 peter <para> Before you are able to use your <productname>PostgreSQL</productname> extension functions written in - C, they must be compiled and linked in a special way to produce a file - that can be dynamically loaded by the server. To be - precise, a <firstterm>shared library</firstterm> needs to be created. + C, they must be compiled and linked in a special way to produce a + file that can be dynamically loaded by the server. To be precise, a + <firstterm>shared library</firstterm> needs to be + created.<indexterm><primary>shared library</></indexterm> + </para> <para> @@ -26,17 +28,18 @@ $Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.25 2003/04/10 01:22:44 peter </para> <para> - <indexterm><primary>PIC</></> - Creating shared libraries is generally analogous to linking - executables: first the source files are compiled into object files, - then the object files are linked together. The object files need to - be created as <firstterm>position-independent code</firstterm> - (<acronym>PIC</acronym>), which conceptually means that they can be - placed at an arbitrary location in memory when they are loaded by the - executable. (Object files intended for executables are usually not compiled - that way.) The command to link a shared library contains special - flags to distinguish it from linking an executable. --- At least - this is the theory. On some systems the practice is much uglier. + <indexterm><primary>PIC</></> Creating shared libraries is generally + analogous to linking executables: first the source files are + compiled into object files, then the object files are linked + together. The object files need to be created as + <firstterm>position-independent code</firstterm> + (<acronym>PIC</acronym>),<indexterm><primary>PIC</></> which + conceptually means that they can be placed at an arbitrary location + in memory when they are loaded by the executable. (Object files + intended for executables are usually not compiled that way.) The + command to link a shared library contains special flags to + distinguish it from linking an executable. --- At least this is the + theory. On some systems the practice is much uglier. </para> <para> @@ -57,7 +60,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.25 2003/04/10 01:22:44 peter <variablelist> <varlistentry> <term><systemitem class="osname">BSD/OS</></term> - <indexterm><primary>BSD/OS</></> + <indexterm><primary>BSD/OS</><secondary>shared library</></> <listitem> <para> The compiler flag to create <acronym>PIC</acronym> is @@ -75,7 +78,7 @@ ld -shared -o foo.so foo.o <varlistentry> <term><systemitem class="osname">FreeBSD</></term> - <indexterm><primary>FreeBSD</></> + <indexterm><primary>FreeBSD</><secondary>shared library</></> <listitem> <para> The compiler flag to create <acronym>PIC</acronym> is @@ -93,7 +96,7 @@ gcc -shared -o foo.so foo.o <varlistentry> <term><systemitem class="osname">HP-UX</></term> - <indexterm><primary>HP-UX</></> + <indexterm><primary>HP-UX</><secondary>shared library</></> <listitem> <para> The compiler flag of the system compiler to create @@ -120,7 +123,7 @@ ld -b -o foo.sl foo.o <varlistentry> <term><systemitem class="osname">IRIX</></term> - <indexterm><primary>IRIX</></> + <indexterm><primary>IRIX</><secondary>shared library</></> <listitem> <para> <acronym>PIC</acronym> is the default, no special compiler @@ -136,7 +139,7 @@ ld -shared -o foo.so foo.o <varlistentry> <term><systemitem class="osname">Linux</></term> - <indexterm><primary>Linux</></> + <indexterm><primary>Linux</><secondary>shared library</></> <listitem> <para> The compiler flag to create <acronym>PIC</acronym> is @@ -155,7 +158,7 @@ cc -shared -o foo.so foo.o <varlistentry> <term><systemitem class="osname">MacOS X</></term> - <indexterm><primary>MacOS X</></> + <indexterm><primary>MacOS X</><secondary>shared library</></> <listitem> <para> Here is an example. It assumes the developer tools are installed. @@ -169,7 +172,7 @@ cc -bundle -flat_namespace -undefined suppress -o foo.so foo.o <varlistentry> <term><systemitem class="osname">NetBSD</></term> - <indexterm><primary>NetBSD</></> + <indexterm><primary>NetBSD</><secondary>shared library</></> <listitem> <para> The compiler flag to create <acronym>PIC</acronym> is @@ -187,7 +190,7 @@ gcc -shared -o foo.so foo.o <varlistentry> <term><systemitem class="osname">OpenBSD</></term> - <indexterm><primary>OpenBSD</></> + <indexterm><primary>OpenBSD</><secondary>shared library</></> <listitem> <para> The compiler flag to create <acronym>PIC</acronym> is @@ -203,7 +206,7 @@ ld -Bshareable -o foo.so foo.o <varlistentry> <term><systemitem class="osname">Solaris</></term> - <indexterm><primary>Solaris</></> + <indexterm><primary>Solaris</><secondary>shared library</></> <listitem> <para> The compiler flag to create <acronym>PIC</acronym> is @@ -227,7 +230,7 @@ gcc -G -o foo.so foo.o <varlistentry> <term><systemitem class="osname">Tru64 UNIX</></term> - <indexterm><primary>Tru64 UNIX</></> + <indexterm><primary>Tru64 UNIX</><secondary>shared library</></> <indexterm><primary>Digital UNIX</><see>Tru64 UNIX</></> <listitem> <para> @@ -246,7 +249,7 @@ ld -shared -expect_unresolved '*' -o foo.so foo.o <varlistentry> <term><systemitem class="osname">UnixWare</></term> - <indexterm><primary>UnixWare</></> + <indexterm><primary>UnixWare</><secondary>shared library</></> <listitem> <para> The compiler flag to create <acronym>PIC</acronym> is <option>-K diff --git a/doc/src/sgml/dml.sgml b/doc/src/sgml/dml.sgml index 6476fcf14ab..4f9343cce98 100644 --- a/doc/src/sgml/dml.sgml +++ b/doc/src/sgml/dml.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/dml.sgml,v 1.5 2003/08/10 01:20:34 tgl Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/dml.sgml,v 1.5.2.1 2003/09/07 04:36:41 momjian Exp $ --> <chapter id="dml"> <title>Data Manipulation</title> @@ -20,6 +20,14 @@ <sect1 id="dml-insert"> <title>Inserting Data</title> + <indexterm zone="dml-insert"> + <primary>inserting</primary> + </indexterm> + + <indexterm zone="dml-insert"> + <primary>INSERT</primary> + </indexterm> + <para> When a table is created, it contains no data. The first thing to do before a database can be of much use is to insert data. Data is @@ -98,6 +106,14 @@ INSERT INTO products DEFAULT VALUES; <sect1 id="dml-update"> <title>Updating Data</title> + <indexterm zone="dml-update"> + <primary>updating</primary> + </indexterm> + + <indexterm zone="dml-update"> + <primary>UPDATE</primary> + </indexterm> + <para> The modification of data that is already in the database is referred to as updating. You can update individual rows, all the @@ -182,6 +198,14 @@ UPDATE mytable SET a = 5, b = 3, c = 1 WHERE a > 0; <sect1 id="dml-delete"> <title>Deleting Data</title> + <indexterm zone="dml-delete"> + <primary>deleting</primary> + </indexterm> + + <indexterm zone="dml-delete"> + <primary>DELETE</primary> + </indexterm> + <para> So far we have explained how to add data to tables and how to change data. What remains is to discuss how to remove data that is diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml index c26b10ab0e3..4c9fb206290 100644 --- a/doc/src/sgml/ecpg.sgml +++ b/doc/src/sgml/ecpg.sgml @@ -1,11 +1,13 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ecpg.sgml,v 1.48 2003/08/07 04:17:21 momjian Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ecpg.sgml,v 1.48.2.1 2003/09/07 04:36:41 momjian Exp $ --> <chapter id="ecpg"> <title><application>ECPG</application> - Embedded <acronym>SQL</acronym> in C</title> <indexterm zone="ecpg"><primary>embedded SQL</primary><secondary>in C</secondary></indexterm> + <indexterm zone="ecpg"><primary>C</primary></indexterm> + <indexterm zone="ecpg"><primary>ECPG</primary></indexterm> <para> This chapter describes the embedded <acronym>SQL</acronym> package diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml index 7d0f65f0679..f8e0ec08ac3 100644 --- a/doc/src/sgml/extend.sgml +++ b/doc/src/sgml/extend.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.23 2003/08/09 22:50:21 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.23.2.1 2003/09/07 04:36:41 momjian Exp $ --> <chapter id="extend"> @@ -80,16 +80,25 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.23 2003/08/09 22:50:21 tgl </para> </sect1> - <sect1 id="type-system"> + <sect1 id="extend-type-system"> <title>The <productname>PostgreSQL</productname> Type System</title> - <indexterm zone="type-system"> - <primary>extending SQL</primary> - <secondary>types</secondary> + <indexterm zone="extend-type-system"> + <primary>base type</primary> + </indexterm> + + <indexterm zone="extend-type-system"> + <primary>data type</primary> + <secondary>base</secondary> + </indexterm> + + <indexterm zone="extend-type-system"> + <primary>composite type</primary> </indexterm> - <indexterm zone="type-system"> - <primary>data types</primary> + <indexterm zone="extend-type-system"> + <primary>data type</primary> + <secondary>composite</secondary> </indexterm> <para> @@ -138,15 +147,25 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.23 2003/08/09 22:50:21 tgl pseudo-types. </para> - <sect2 id="types-polymorphic"> + <sect2 id="extend-types-polymorphic"> <title>Polymorphic Types and Functions</title> - <indexterm> - <primary>polymorphic types</primary> + <indexterm zone="extend-types-polymorphic"> + <primary>polymorphic type</primary> + </indexterm> + + <indexterm zone="extend-types-polymorphic"> + <primary>polymorphic function</primary> + </indexterm> + + <indexterm zone="extend-types-polymorphic"> + <primary>type</primary> + <secondary>polymorphic</secondary> </indexterm> - <indexterm> - <primary>polymorphic functions</primary> + <indexterm zone="extend-types-polymorphic"> + <primary>function</primary> + <secondary>polymorphic</secondary> </indexterm> <para> diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index 4ba2bd9e51a..888220d8df1 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/filelist.sgml,v 1.29 2003/05/18 20:55:56 petere Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/filelist.sgml,v 1.29.2.1 2003/09/07 04:36:41 momjian Exp $ --> <!entity history SYSTEM "history.sgml"> <!entity info SYSTEM "info.sgml"> @@ -68,7 +68,6 @@ <!entity libpgeasy SYSTEM "libpgeasy.sgml"> <!entity libpq SYSTEM "libpq.sgml"> <!entity libpgtcl SYSTEM "libpgtcl.sgml"> -<!entity pygresql SYSTEM "pygresql.sgml"> <!entity lobj SYSTEM "lobj.sgml"> <!entity odbc SYSTEM "odbc.sgml"> <!entity rules SYSTEM "rules.sgml"> diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 6729dc677e8..59dd23c2efa 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.166 2003/08/10 01:20:34 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.166.2.1 2003/09/07 04:36:41 momjian Exp $ PostgreSQL documentation --> @@ -7,11 +7,11 @@ PostgreSQL documentation <title>Functions and Operators</title> <indexterm zone="functions"> - <primary>functions</primary> + <primary>function</primary> </indexterm> <indexterm zone="functions"> - <primary>operators</primary> + <primary>operator</primary> </indexterm> <para> @@ -40,7 +40,7 @@ PostgreSQL documentation <title>Logical Operators</title> <indexterm zone="functions-logical"> - <primary>operators</primary> + <primary>operator</primary> <secondary>logical</secondary> </indexterm> @@ -54,18 +54,27 @@ PostgreSQL documentation The usual logical operators are available: <indexterm> - <primary>and</primary> - <secondary>operator</secondary> + <primary>AND (operator)</primary> </indexterm> <indexterm> - <primary>or</primary> - <secondary>operator</secondary> + <primary>OR (operator)</primary> </indexterm> <indexterm> - <primary>not</primary> - <secondary>operator</secondary> + <primary>NOT (operator)</primary> + </indexterm> + + <indexterm> + <primary>conjunction</primary> + </indexterm> + + <indexterm> + <primary>disjunction</primary> + </indexterm> + + <indexterm> + <primary>negation</primary> </indexterm> <simplelist> @@ -252,7 +261,7 @@ PostgreSQL documentation <primary>between</primary> </indexterm> In addition to the comparison operators, the special - <token>BETWEEN</token> construct is available. + <token>BETWEEN</token> construct is available.<indexterm><primary>BETWEEN</primary></indexterm> <synopsis> <replaceable>a</replaceable> BETWEEN <replaceable>x</replaceable> AND <replaceable>y</replaceable> </synopsis> @@ -284,6 +293,7 @@ PostgreSQL documentation <replaceable>expression</replaceable> ISNULL <replaceable>expression</replaceable> NOTNULL </synopsis> + <indexterm><primary>null value</primary><secondary>comparing</secondary></indexterm> </para> <para> @@ -847,7 +857,7 @@ PostgreSQL documentation <entry> String concatenation <indexterm> - <primary>character strings</primary> + <primary>character string</primary> <secondary>concatenation</secondary> </indexterm> </entry> @@ -869,12 +879,12 @@ PostgreSQL documentation <entry> Number of characters in string <indexterm> - <primary>character strings</primary> + <primary>character string</primary> <secondary>length</secondary> </indexterm> <indexterm> <primary>length</primary> - <secondary>character strings</secondary> + <secondary sortas="character string">of a character string</secondary> <see>character strings, length</see> </indexterm> </entry> @@ -1110,12 +1120,12 @@ PostgreSQL documentation <entry> Number of characters in string <indexterm> - <primary>character strings</primary> + <primary>character string</primary> <secondary>length</secondary> </indexterm> <indexterm> <primary>length</primary> - <secondary>character strings</secondary> + <secondary sortas="character string">of a character string</secondary> <see>character strings, length</see> </indexterm> </entry> @@ -1174,7 +1184,7 @@ PostgreSQL documentation </row> <row> - <entry><literal><function>quote_ident</function>(<parameter>string</parameter> text)</literal></entry> + <entry><literal><function>quote_ident</function>(<parameter>string</parameter> text)</literal><indexterm><primary>quote_ident</></></entry> <entry><type>text</type></entry> <entry> Return the given string suitably quoted to be used as an identifier @@ -1188,7 +1198,7 @@ PostgreSQL documentation </row> <row> - <entry><literal><function>quote_literal</function>(<parameter>string</parameter> text)</literal></entry> + <entry><literal><function>quote_literal</function>(<parameter>string</parameter> text)</literal><indexterm><primary>quote_literal</></></entry> <entry><type>text</type></entry> <entry> Return the given string suitably quoted to be used as a string literal @@ -2055,6 +2065,11 @@ PostgreSQL documentation <sect1 id="functions-binarystring"> <title>Binary String Functions and Operators</title> + <indexterm zone="functions-binarystring"> + <primary>binary data</primary> + <secondary>functions</secondary> + </indexterm> + <para> This section describes functions and operators for examining and manipulating values of type <type>bytea</type>. @@ -2092,7 +2107,7 @@ PostgreSQL documentation <entry> String concatenation <indexterm> - <primary>binary strings</primary> + <primary>binary string</primary> <secondary>concatenation</secondary> </indexterm> </entry> @@ -2243,12 +2258,12 @@ PostgreSQL documentation <entry> Length of binary string <indexterm> - <primary>binary strings</primary> + <primary>binary string</primary> <secondary>length</secondary> </indexterm> <indexterm> <primary>length</primary> - <secondary>binary strings</secondary> + <secondary sortas="binary string">of a binary string</secondary> <see>binary strings, length</see> </indexterm> </entry> @@ -2321,8 +2336,8 @@ PostgreSQL documentation <sect2 id="functions-like"> <title><function>LIKE</function></title> - <indexterm> - <primary>like</primary> + <indexterm zone="functions-like"> + <primary>LIKE</primary> </indexterm> <synopsis> @@ -2420,12 +2435,12 @@ PostgreSQL documentation Regular Expressions</title> <indexterm zone="functions-sql99-regexp"> - <primary>regular expressions</primary> + <primary>regular expression</primary> <!-- <seealso>pattern matching</seealso> breaks index build --> </indexterm> <indexterm> - <primary>similar to</primary> + <primary>SIMILAR TO</primary> </indexterm> <indexterm> @@ -2547,7 +2562,7 @@ substring('foobar' from '#"o_b#"%' for '#') <lineannotation>NULL</lineannotat <title><acronym>POSIX</acronym> Regular Expressions</title> <indexterm zone="functions-posix-regexp"> - <primary>regular expressions</primary> + <primary>regular expression</primary> <seealso>pattern matching</seealso> </indexterm> @@ -3794,6 +3809,10 @@ substring('foobar' from 'o(.)b') <lineannotation>o</lineannotation> <primary>formatting</primary> </indexterm> + <indexterm zone="functions-formatting"> + <primary>to_char</primary> + </indexterm> + <para> The <productname>PostgreSQL</productname> formatting functions provide a powerful set of tools for converting various data types @@ -3871,6 +3890,11 @@ substring('foobar' from 'o(.)b') <lineannotation>o</lineannotation> </table> <para> + Warning. <literal><function>to_char</function>(<type>interval</type>, <type>text</type>)</literal> + is deprecated and should not be used in newly-written code. Will be removed in the next version. + </para> + + <para> In an output template string (for <function>to_char</>), there are certain patterns that are recognized and replaced with appropriately-formatted data from the value to be formatted. Any text that is not a template pattern is simply @@ -5999,7 +6023,7 @@ SELECT TIMESTAMP 'now'; <title>Sequence-Manipulation Functions</title> <indexterm> - <primary>sequences</primary> + <primary>sequence</primary> </indexterm> <indexterm> <primary>nextval</primary> @@ -6162,11 +6186,11 @@ SELECT setval('foo', 42, false); <lineannotation>Next <function>nextval</> wi <title>Conditional Expressions</title> <indexterm> - <primary>case</primary> + <primary>CASE</primary> </indexterm> <indexterm> - <primary>conditionals</primary> + <primary>conditional expression</primary> </indexterm> <para> @@ -6287,8 +6311,12 @@ SELECT a, <sect2> <title><literal>COALESCE</></title> + <indexterm> + <primary>COALESCE</primary> + </indexterm> + <synopsis> -<function>COALESCE</function>(<replaceable>value</replaceable> <optional>, ...</optional>) +<function>coalesce</function>(<replaceable>value</replaceable> <optional>, ...</optional>) </synopsis> <para> @@ -6497,7 +6525,8 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, .. <indexterm zone="functions-misc"> <primary>configuration</primary> - <secondary>server</secondary> + <secondary sortas="server">of the server</secondary> + <tertiary>functions</tertiary> </indexterm> <para> @@ -6534,6 +6563,11 @@ SELECT set_config('show_statement_stats', 'off', false); </programlisting> </para> + <indexterm> + <primary>privilege</primary> + <secondary>querying</secondary> + </indexterm> + <para> <xref linkend="functions-misc-access-table"> lists functions that allow the user to query object access privileges programmatically. @@ -6966,6 +7000,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); <primary>col_description</primary> </indexterm> + <indexterm zone="functions-misc"> + <primary>comment</primary> + <secondary sortas="database objects">about database objects</secondary> + </indexterm> + <para> The function shown in <xref linkend="functions-misc-comment-table"> extract comments @@ -7027,7 +7066,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); <para> <xref linkend="array-operators-table"> shows the operators - available for the <type>array</type> types. + available for <type>array</type> types. </para> <table id="array-operators-table"> @@ -7088,7 +7127,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); <entry> <literal>||</literal> </entry> <entry>array-to-array concatenation</entry> <entry><literal>ARRAY[1,2,3] || ARRAY[4,5,6]</literal></entry> - <entry><literal>{{1,2,3},{4,5,6}}</literal></entry> + <entry><literal>{1,2,3,4,5,6}</literal></entry> </row> <row> @@ -7116,6 +7155,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); </table> <para> + See <xref linkend="arrays"> for more details about array operator + behavior. + </para> + + <para> <xref linkend="array-functions-table"> shows the functions available for use with array types. See <xref linkend="arrays"> for more discussion and examples for the use of these functions. @@ -7162,7 +7206,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); for <literal>NULL</literal> inputs </entry> <entry><literal>array_cat(ARRAY[1,2,3], ARRAY[4,5,6])</literal></entry> - <entry><literal>{{1,2,3},{4,5,6}}</literal></entry> + <entry><literal>{1,2,3,4,5,6}</literal></entry> </row> <row> <entry> @@ -7262,6 +7306,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); <sect1 id="functions-aggregate"> <title>Aggregate Functions</title> + <indexterm zone="functions-aggregate"> + <primary>aggregate function</primary> + <secondary>built-in</secondary> + </indexterm> + <para> <firstterm>Aggregate functions</firstterm> compute a single result value from a set of input values. <xref @@ -7290,7 +7339,6 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); <entry> <indexterm> <primary>average</primary> - <secondary>function</secondary> </indexterm> <function>avg(<replaceable class="parameter">expression</replaceable>)</function> </entry> @@ -7472,31 +7520,31 @@ SELECT col FROM sometable ORDER BY col ASC LIMIT 1; <title>Subquery Expressions</title> <indexterm> - <primary>exists</primary> + <primary>EXISTS</primary> </indexterm> <indexterm> - <primary>in</primary> + <primary>IN</primary> </indexterm> <indexterm> - <primary>not in</primary> + <primary>NOT IN</primary> </indexterm> <indexterm> - <primary>any</primary> + <primary>ANY</primary> </indexterm> <indexterm> - <primary>all</primary> + <primary>ALL</primary> </indexterm> <indexterm> - <primary>some</primary> + <primary>SOME</primary> </indexterm> <indexterm> - <primary>subqueries</primary> + <primary>subquery</primary> </indexterm> <para> @@ -7798,6 +7846,11 @@ SELECT col1 FROM tab1 <sect2> <title>Row-wise Comparison</title> + <indexterm> + <primary>comparison</primary> + <secondary>of rows</secondary> + </indexterm> + <synopsis> (<replaceable>expression</replaceable> <optional>, <replaceable>expression</replaceable> ...</optional>) <replaceable>operator</replaceable> (<replaceable>subquery</replaceable>) </synopsis> diff --git a/doc/src/sgml/indices.sgml b/doc/src/sgml/indices.sgml index 4e79084e7ec..45166fcdea0 100644 --- a/doc/src/sgml/indices.sgml +++ b/doc/src/sgml/indices.sgml @@ -1,10 +1,10 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/indices.sgml,v 1.42 2003/05/28 16:03:55 tgl Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/indices.sgml,v 1.42.2.1 2003/09/07 04:36:41 momjian Exp $ --> <chapter id="indexes"> <title id="indexes-title">Indexes</title> <indexterm zone="indexes"> - <primary>indexes</primary> + <primary>index</primary> </indexterm> <para> @@ -109,12 +109,12 @@ CREATE INDEX test1_id_index ON test1 (id); B-tree, R-tree, GiST, and Hash. Each index type is more appropriate for a particular query type because of the algorithm it uses. <indexterm> - <primary>indexes</primary> + <primary>index</primary> <secondary>B-tree</secondary> </indexterm> <indexterm> <primary>B-tree</primary> - <see>indexes</see> + <see>index</see> </indexterm> By default, the <command>CREATE INDEX</command> command will create a @@ -147,12 +147,12 @@ CREATE INDEX test1_id_index ON test1 (id); <para> <indexterm> - <primary>indexes</primary> + <primary>index</primary> <secondary>R-tree</secondary> </indexterm> <indexterm> <primary>R-tree</primary> - <see>indexes</see> + <see>index</see> </indexterm> R-tree indexes are especially suited for spatial data. To create an R-tree index, use a command of the form @@ -178,12 +178,12 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> <para> <indexterm> - <primary>indexes</primary> + <primary>index</primary> <secondary>hash</secondary> </indexterm> <indexterm> <primary>hash</primary> - <see>indexes</see> + <see>index</see> </indexterm> The query planner will consider using a hash index whenever an indexed column is involved in a comparison using the @@ -219,7 +219,7 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> <title>Multicolumn Indexes</title> <indexterm zone="indexes-multicolumn"> - <primary>indexes</primary> + <primary>index</primary> <secondary>multicolumn</secondary> </indexterm> @@ -294,7 +294,7 @@ SELECT name FROM test2 WHERE major = <replaceable>constant</replaceable> OR mino <title>Unique Indexes</title> <indexterm zone="indexes-unique"> - <primary>indexes</primary> + <primary>index</primary> <secondary>unique</secondary> </indexterm> @@ -337,8 +337,8 @@ CREATE UNIQUE INDEX <replaceable>name</replaceable> ON <replaceable>table</repla <title>Indexes on Expressions</title> <indexterm zone="indexes-expressional"> - <primary>indexes</primary> - <secondary>on expressions</secondary> + <primary>index</primary> + <secondary sortas="expressions">on expressions</secondary> </indexterm> <para> @@ -392,6 +392,10 @@ CREATE INDEX people_names ON people ((first_name || ' ' || last_name)); <sect1 id="indexes-opclass"> <title>Operator Classes</title> + <indexterm zone="indexes-opclass"> + <primary>operator class</primary> + </indexterm> + <para> An index definition may specify an <firstterm>operator class</firstterm> for each column of an index. @@ -492,7 +496,7 @@ SELECT am.amname AS index_method, <title>Partial Indexes</title> <indexterm zone="indexes-partial"> - <primary>indexes</primary> + <primary>index</primary> <secondary>partial</secondary> </indexterm> @@ -709,6 +713,11 @@ CREATE UNIQUE INDEX tests_success_constraint ON tests (subject, target) <sect1 id="indexes-examine"> <title>Examining Index Usage</title> + <indexterm zone="indexes-examine"> + <primary>index</primary> + <secondary>examining usage</secondary> + </indexterm> + <para> Although indexes in <productname>PostgreSQL</> do not need maintenance and tuning, it is still important to check diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index 6f4f8486023..ac24dc76720 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/installation.sgml,v 1.138 2003/08/04 04:03:03 tgl Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/installation.sgml,v 1.138.2.1 2003/09/07 04:36:41 momjian Exp $ --> <chapter id="installation"> <title><![%standalone-include[<productname>PostgreSQL</>]]> @@ -169,10 +169,9 @@ su - postgres <listitem> <para> - To build the Python interface module or the PL/Python server - programming language, you need a Python installation, including - the header files. - Since PL/Python will be a shared library, the + To build the PL/Python server programming language, you need a + Python installation, including the header files. Since + PL/Python will be a shared library, the <indexterm><primary>libpython</primary></indexterm> <filename>libpython</filename> library must be a shared library also on most platforms. This is not the case in a default @@ -383,6 +382,7 @@ JAVACMD=$JAVA_HOME/bin/java <para> <indexterm> <primary>pg_dumpall</primary> + <secondary>use during upgrade</secondary> </indexterm> To back up your database installation, type: @@ -750,10 +750,7 @@ JAVACMD=$JAVA_HOME/bin/java <term><option>--with-python</option></term> <listitem> <para> - Build the Python interface module and the PL/Python - server-side language. You need to have root access to be able - to install the Python module at its default place - (<filename>/usr/lib/python<replaceable>x</>.<replaceable>y</></>). + Build the PL/Python server-side language. </para> </listitem> </varlistentry> @@ -875,8 +872,8 @@ JAVACMD=$JAVA_HOME/bin/java <term><option>--with-pam</option></term> <listitem> <para> - Build with <acronym>PAM</> (Pluggable Authentication Modules) - support. + Build with <acronym>PAM</><indexterm><primary>PAM</></> + (Pluggable Authentication Modules) support. </para> </listitem> </varlistentry> @@ -1079,20 +1076,6 @@ All of PostgreSQL is successfully made. Ready to install. </para> <para> - If you built the Python interfaces and you were not the - root user when you executed the above command then that part of - the installation probably failed. In that case you should become - the root user and then do -<screen> -<userinput>gmake -C src/interfaces/python install</userinput> -</screen> - If you do not have root access you are on your own: - you can still take the required files and place them in - other directories where Python can find them, but how to - do that is left as an exercise. - </para> - - <para> The standard installation provides only the header files needed for client application development. If you plan to do any server-side program development (such as custom functions or data types written in C), @@ -1163,7 +1146,7 @@ All of PostgreSQL is successfully made. Ready to install. <title>Shared Libraries</title> <indexterm> - <primary>shared libraries</primary> + <primary>shared library</primary> </indexterm> <para> @@ -1284,7 +1267,6 @@ set path = ( /usr/local/pgsql/bin $path ) <para> <indexterm> <primary><envar>MANPATH</envar></primary> - <seealso>man pages</seealso> </indexterm> To enable your system to find the <application>man</> documentation, you need to add lines like the following to a diff --git a/doc/src/sgml/jdbc.sgml b/doc/src/sgml/jdbc.sgml index a577398bbb4..b524f9dec8c 100644 --- a/doc/src/sgml/jdbc.sgml +++ b/doc/src/sgml/jdbc.sgml @@ -1,10 +1,18 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/Attic/jdbc.sgml,v 1.47 2003/08/07 05:06:40 barry Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/Attic/jdbc.sgml,v 1.47.2.1 2003/09/07 04:36:42 momjian Exp $ --> <chapter id="jdbc"> <title><acronym>JDBC</acronym> Interface</title> + <indexterm zone="jdbc"> + <primary>JDBC</primary> + </indexterm> + + <indexterm zone="jdbc"> + <primary>Java</primary> + </indexterm> + <para> <acronym>JDBC</acronym> is a core <acronym>API</acronym> of Java 1.1 and later. It provides a standard set of @@ -66,6 +74,14 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/jdbc.sgml,v 1.47 2003/08/07 05:06:40 <sect2 id="jdbc-classpath"> <title>Setting up the Class Path</title> + <indexterm zone="jdbc-classpath"> + <primary>class path</primary> + </indexterm> + + <indexterm zone="jdbc-classpath"> + <primary>CLASSPATH</primary> + </indexterm> + <para> To use the driver, the JAR archive (named <filename>postgresql.jar</filename> if you built from source, otherwise @@ -316,6 +332,18 @@ db.close(); <sect1 id="jdbc-query"> <title>Issuing a Query and Processing the Result</title> + <indexterm zone="jdbc-query"> + <primary>Statement</primary> + </indexterm> + + <indexterm zone="jdbc-query"> + <primary>PreparedStatement</primary> + </indexterm> + + <indexterm zone="jdbc-query"> + <primary>ResultSet</primary> + </indexterm> + <para> Any time you want to issue <acronym>SQL</acronym> statements to the database, you require a <classname>Statement</classname> or @@ -681,6 +709,16 @@ st.close(); <sect1 id="jdbc-binary-data"> <title>Storing Binary Data</title> + <indexterm zone="jdbc-binary-data"> + <primary>bytea</primary> + <secondary sortas="JDBC">in JDBC</secondary> + </indexterm> + + <indexterm zone="jdbc-binary-data"> + <primary>large object</primary> + <secondary sortas="JDBC">in JDBC</secondary> + </indexterm> + <para> <application>PostgreSQL</application> provides two distinct ways to store binary data. Binary data can be stored in a table using @@ -2597,6 +2635,11 @@ public void unlink(int oid) throws SQLException <sect1 id="jdbc-thread"> <title>Using the Driver in a Multithreaded or a Servlet Environment</title> + <indexterm zone="jdbc-thread"> + <primary>threads</primary> + <secondary sortas="JDBC">with JDBC</secondary> + </indexterm> + <para> A problem with many <acronym>JDBC</acronym> drivers is that only one thread can use a <classname>Connection</classname> at any one @@ -2645,6 +2688,15 @@ public void unlink(int oid) throws SQLException <sect1 id="jdbc-datasource"> <title>Connection Pools and Data Sources</title> + <indexterm zone="jdbc-datasource"> + <primary>connection pool</primary> + <secondary sortas="JDBC">in JDBC</secondary> + </indexterm> + + <indexterm zone="jdbc-datasource"> + <primary>DataSource</primary> + </indexterm> + <para> <acronym>JDBC</> 2 introduced standard connection pooling features in an add-on <acronym>API</> known as the <acronym>JDBC</acronym> 2.0 Optional @@ -3029,7 +3081,11 @@ try { </sect2> <sect2 id="jdbc-jndi"> - <title>Data Sources and <acronym>JNDI</acronym></title> + <title>Data Sources and <acronym>JNDI</acronym></title> + + <indexterm zone="jdbc-jndi"> + <primary>JNDI</primary> + </indexterm> <para> All the <literal>ConnectionPoolDataSource</literal> and diff --git a/doc/src/sgml/keywords.sgml b/doc/src/sgml/keywords.sgml index 26764553f87..b6d129354a2 100644 --- a/doc/src/sgml/keywords.sgml +++ b/doc/src/sgml/keywords.sgml @@ -1,10 +1,10 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/keywords.sgml,v 2.9 2003/06/12 07:49:43 momjian Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/keywords.sgml,v 2.9.2.1 2003/09/07 04:36:42 momjian Exp $ --> <appendix id="sql-keywords-appendix"> <title><acronym>SQL</acronym> Key Words</title> <indexterm zone="sql-keywords-appendix"> - <primary>key words</primary> + <primary>key word</primary> <secondary>list of</secondary> </indexterm> diff --git a/doc/src/sgml/libpgtcl.sgml b/doc/src/sgml/libpgtcl.sgml index 220a7d42be2..afcc7061ede 100644 --- a/doc/src/sgml/libpgtcl.sgml +++ b/doc/src/sgml/libpgtcl.sgml @@ -125,8 +125,8 @@ <para> The <function>pg_lo_*</function> commands are interfaces to the large object features of - <ProductName>PostgreSQL</ProductName>.<indexterm><primary>Large - Object</></> The functions are designed to mimic the analogous file + <ProductName>PostgreSQL</ProductName>.<indexterm><primary>large + object</><secondary>in pgctl</></> The functions are designed to mimic the analogous file system functions in the standard Unix file system interface. The <function>pg_lo_*</function> commands should be used within a <command>BEGIN</command>/<command>COMMIT</command> transaction @@ -1043,12 +1043,12 @@ pg_listen <parameter>conn</parameter> <parameter>notifyName</parameter> <optiona message bearing the given name arrives from the server. This occurs when any <productname>PostgreSQL</productname> client application issues a - <command>NOTIFY</command><indexterm><primary>NOTIFY</><secondary>in - pgtcl</></> command referencing that name. The command string is - executed from the Tcl idle loop. That is the normal idle state of - an application written with Tk. In non-Tk Tcl shells, you can - execute <function>update</function> or <function>vwait</function> - to cause the idle loop to be entered. + <command>NOTIFY</command><indexterm><primary>NOTIFY</><secondary + sortas="pgtcl">in pgtcl</></> command referencing that name. The + command string is executed from the Tcl idle loop. That is the + normal idle state of an application written with Tk. In non-Tk Tcl + shells, you can execute <function>update</function> or + <function>vwait</function> to cause the idle loop to be entered. </para> <para> diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 8284d4b5f8d..935b1c1186d 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.131 2003/08/13 16:29:03 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.131.2.1 2003/09/07 04:36:42 momjian Exp $ --> <chapter id="libpq"> @@ -9,6 +9,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.131 2003/08/13 16:29:03 tgl <primary>libpq</primary> </indexterm> + <indexterm zone="libpq"> + <primary>C</primary> + </indexterm> + <para> <application>libpq</application> is the <acronym>C</acronym> application programmer's interface to @@ -31,9 +35,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.131 2003/08/13 16:29:03 tgl </para> <para> - Client programs that use <application>libpq</application> must include the - header file <filename>libpq-fe.h</filename> and must link with the - <application>libpq</application> library. + Client programs that use <application>libpq</application> must + include the header file + <filename>libpq-fe.h</filename><indexterm><primary>libpq-fe.h</></> + and must link with the <application>libpq</application> library. </para> <sect1 id="libpq-connect"> @@ -45,17 +50,18 @@ $Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.131 2003/08/13 16:29:03 tgl application program can have several backend connections open at one time. (One reason to do that is to access more than one database.) Each connection is represented by a - <structname>PGconn</> object which is obtained from the function - <function>PQconnectdb</> or <function>PQsetdbLogin</>. Note that - these functions will always return a non-null object pointer, - unless perhaps there is too little memory even to allocate the - <structname>PGconn</> object. The <function>PQstatus</> function - should be called to check whether a connection was successfully - made before queries are sent via the connection object. + <structname>PGconn</><indexterm><primary>PGconn</></> object which + is obtained from the function <function>PQconnectdb</> or + <function>PQsetdbLogin</>. Note that these functions will always + return a non-null object pointer, unless perhaps there is too + little memory even to allocate the <structname>PGconn</> object. + The <function>PQstatus</> function should be called to check + whether a connection was successfully made before queries are sent + via the connection object. <variablelist> <varlistentry> - <term><function>PQconnectdb</function></term> + <term><function>PQconnectdb</function><indexterm><primary>PQconnectdb</></></term> <listitem> <para> Makes a new connection to the database server. @@ -93,12 +99,13 @@ PGconn *PQconnectdb(const char *conninfo); <term><literal>host</literal></term> <listitem> <para> - Name of host to connect to. - If this begins with a slash, it specifies Unix-domain communication - rather than TCP/IP communication; the value is the name of the - directory in which the socket file is stored. - The default is to connect to a Unix-domain socket in - <filename>/tmp</filename>. + Name of host to connect to.<indexterm><primary>host name</></> + If this begins with a slash, it specifies Unix-domain + communication rather than TCP/IP communication; the value is the + name of the directory in which the socket file is stored. The + default is to connect to a Unix-domain socket in + <filename>/tmp</filename>.<indexterm><primary>Unix domain + socket</></> </para> </listitem> </varlistentry> @@ -144,8 +151,9 @@ PGconn *PQconnectdb(const char *conninfo); <term><literal>port</literal></term> <listitem> <para> - Port number to connect to at the server host, - or socket file name extension for Unix-domain connections. + Port number to connect to at the server host, or socket file + name extension for Unix-domain + connections.<indexterm><primary>port</></> </para> </listitem> </varlistentry> @@ -209,44 +217,51 @@ PGconn *PQconnectdb(const char *conninfo); <varlistentry> <term><literal>sslmode</literal></term> <listitem> - <para> - This option determines whether or with what priority an <acronym>SSL</> - connection will be negotiated with the server. There are four - modes: <literal>disable</> will attempt only an unencrypted - <acronym>SSL</> connection; <literal>allow</> will negotiate, - trying first a non-<acronym>SSL</> connection, then if that fails, - trying an <acronym>SSL</> connection; <literal>prefer</> - (the default) will negotiate, trying first an <acronym>SSL</> connection, - then if that fails, trying a regular non-<acronym>SSL</> connection; - <literal>require</> will try only an <acronym>SSL</> connection. - </para> - <para> - If <productname>PostgreSQL</> is compiled without SSL support, - using option <literal>require</> will cause an error, and options - <literal>allow</> and <literal>prefer</> will be tolerated but - <application>libpq</> will be unable to negotiate an <acronym>SSL</> - connection. - </para> + <para> + This option determines whether or with what priority an + <acronym>SSL</> connection will be negotiated with the + server. There are four modes: <literal>disable</> will attempt + only an unencrypted <acronym>SSL</> connection; + <literal>allow</> will negotiate, trying first a + non-<acronym>SSL</> connection, then if that fails, trying an + <acronym>SSL</> connection; <literal>prefer</> (the default) + will negotiate, trying first an <acronym>SSL</> connection, + then if that fails, trying a regular non-<acronym>SSL</> + connection; <literal>require</> will try only an + <acronym>SSL</> connection. + </para> + + <para> + If <productname>PostgreSQL</> is compiled without SSL support, + using option <literal>require</> will cause an error, and + options <literal>allow</> and <literal>prefer</> will be + tolerated but <application>libpq</> will be unable to negotiate + an <acronym>SSL</> + connection.<indexterm><primary>SSL</><secondary + sortas="libpq">with libpq</></indexterm> + </para> </listitem> </varlistentry> <varlistentry> <term><literal>requiressl</literal></term> <listitem> - <para> - This option is deprecated in favor of the <literal>sslmode</> - setting. - </para> - <para> - If set to 1, an <acronym>SSL</acronym> connection to the server is required - (this is equivalent to <literal>sslmode</> <literal>require</>). - <application>libpq</> will then refuse to connect if the server does not - accept an <acronym>SSL</acronym> connection. - If set to 0 (default), <application>libpq</> will negotiate the connection - type with the server (equivalent to <literal>sslmode</> <literal>prefer</>). - This option is only available if - <productname>PostgreSQL</> is compiled with SSL support. - </para> + <para> + This option is deprecated in favor of the <literal>sslmode</> + setting. + </para> + + <para> + If set to 1, an <acronym>SSL</acronym> connection to the server + is required (this is equivalent to <literal>sslmode</> + <literal>require</>). <application>libpq</> will then refuse + to connect if the server does not accept an + <acronym>SSL</acronym> connection. If set to 0 (default), + <application>libpq</> will negotiate the connection type with + the server (equivalent to <literal>sslmode</> + <literal>prefer</>). This option is only available if + <productname>PostgreSQL</> is compiled with SSL support. + </para> </listitem> </varlistentry> @@ -274,7 +289,7 @@ PGconn *PQconnectdb(const char *conninfo); </varlistentry> <varlistentry> - <term><function>PQsetdbLogin</function></term> + <term><function>PQsetdbLogin</function><indexterm><primary>PQsetdbLogin</></></term> <listitem> <para> Makes a new connection to the database server. @@ -299,7 +314,7 @@ PGconn *PQsetdbLogin(const char *pghost, </varlistentry> <varlistentry> - <term><function>PQsetdb</function></term> + <term><function>PQsetdb</function><indexterm><primary>PQsetdb</></></term> <listitem> <para> Makes a new connection to the database server. @@ -321,8 +336,8 @@ PGconn *PQsetdb(char *pghost, </varlistentry> <varlistentry> - <term><function>PQconnectStart</function></term> - <term><function>PQconnectPoll</function></term> + <term><function>PQconnectStart</function><indexterm><primary>PQconnectStart</></></term> + <term><function>PQconnectPoll</function><indexterm><primary>PQconnectPoll</></></term> <listitem> <para> <indexterm><primary>nonblocking connection</primary></indexterm> @@ -515,7 +530,7 @@ switch(PQstatus(conn)) </varlistentry> <varlistentry> - <term><function>PQconndefaults</function></term> + <term><function>PQconndefaults</function><indexterm><primary>PQconndefaults</></></term> <listitem> <para> Returns the default connection options. @@ -560,7 +575,7 @@ typedef struct </varlistentry> <varlistentry> - <term><function>PQfinish</function></term> + <term><function>PQfinish</function><indexterm><primary>PQfinish</></></term> <listitem> <para> Closes the connection to the server. Also frees @@ -581,7 +596,7 @@ void PQfinish(PGconn *conn); </varlistentry> <varlistentry> - <term><function>PQreset</function></term> + <term><function>PQreset</function><indexterm><primary>PQreset</></></term> <listitem> <para> Resets the communication channel to the server. @@ -601,8 +616,8 @@ void PQreset(PGconn *conn); </varlistentry> <varlistentry> - <term><function>PQresetStart</function></term> - <term><function>PQresetPoll</function></term> + <term><function>PQresetStart</function><indexterm><primary>PQresetStart</></></term> + <term><function>PQresetPoll</function><indexterm><primary>PQresetPoll</></></term> <listitem> <para> Reset the communication channel to the server, in a nonblocking manner. @@ -665,7 +680,7 @@ These values are fixed for the life of the <structname>PGconn</> object. <variablelist> <varlistentry> -<term><function>PQdb</function></term> +<term><function>PQdb</function><indexterm><primary>PQdb</></></term> <listitem> <para> Returns the database name of the connection. @@ -677,7 +692,7 @@ char *PQdb(const PGconn *conn); </varlistentry> <varlistentry> -<term><function>PQuser</function></term> +<term><function>PQuser</function><indexterm><primary>PQuser</></></term> <listitem> <para> Returns the user name of the connection. @@ -689,7 +704,7 @@ char *PQuser(const PGconn *conn); </varlistentry> <varlistentry> -<term><function>PQpass</function></term> +<term><function>PQpass</function><indexterm><primary>PQpass</></></term> <listitem> <para> Returns the password of the connection. @@ -701,7 +716,7 @@ char *PQpass(const PGconn *conn); </varlistentry> <varlistentry> -<term><function>PQhost</function></term> +<term><function>PQhost</function><indexterm><primary>PQhost</></></term> <listitem> <para> Returns the server host name of the connection. @@ -713,7 +728,7 @@ char *PQhost(const PGconn *conn); </varlistentry> <varlistentry> -<term><function>PQport</function></term> +<term><function>PQport</function><indexterm><primary>PQport</></></term> <listitem> <para> Returns the port of the connection. @@ -725,13 +740,13 @@ char *PQport(const PGconn *conn); </varlistentry> <varlistentry> -<term><function>PQtty</function></term> +<term><function>PQtty</function><indexterm><primary>PQtty</></></term> <listitem> <para> Returns the debug <acronym>TTY</acronym> of the connection. - (This is obsolete, since the server no longer pays attention - to the <acronym>TTY</acronym> setting, but the function remains - for backwards compatibility.) + (This is obsolete, since the server no longer pays attention + to the <acronym>TTY</acronym> setting, but the function remains + for backwards compatibility.) <synopsis> char *PQtty(const PGconn *conn); </synopsis> @@ -740,7 +755,7 @@ char *PQtty(const PGconn *conn); </varlistentry> <varlistentry> -<term><function>PQoptions</function></term> +<term><function>PQoptions</function><indexterm><primary>PQoptions</></></term> <listitem> <para> Returns the command-line options passed in the connection request. @@ -759,7 +774,7 @@ are executed on the <structname>PGconn</> object. <variablelist> <varlistentry> -<term><function>PQstatus</function></term> +<term><function>PQstatus</function><indexterm><primary>PQstatus</></></term> <listitem> <para> Returns the status of the connection. @@ -795,7 +810,7 @@ ConnStatusType PQstatus(const PGconn *conn); </varlistentry> <varlistentry> -<term><function>PQtransactionStatus</function></term> +<term><function>PQtransactionStatus</function><indexterm><primary>PQtransactionStatus</></></term> <listitem> <para> Returns the current in-transaction status of the server. @@ -823,7 +838,7 @@ deprecated and does not exist in later server versions. </varlistentry> <varlistentry> -<term><function>PQparameterStatus</function></term> +<term><function>PQparameterStatus</function><indexterm><primary>PQparameterStatus</></></term> <listitem> <para> Looks up a current parameter setting of the server. @@ -841,27 +856,27 @@ is not known. <para> Parameters reported as of the current release include <literal>server_version</> (cannot change after startup); -<literal>server_encoding</> (also not presently changeable after start); <literal>client_encoding</>, -<literal>is_superuser</>, and +<literal>is_superuser</>, +<literal>session_authorization</literal>, and <literal>DateStyle</>. </para> <para> -Pre-3.0-protocol servers do not report parameter settings, -but <application>libpq</> includes logic to obtain values for -<literal>server_version</>, <literal>server_encoding</>, and -<literal>client_encoding</>. Applications are encouraged to use -<function>PQparameterStatus</> rather than ad-hoc code to determine these -values. (Beware however that on a pre-3.0 connection, changing -<literal>client_encoding</> via <command>SET</> after connection startup -will not be reflected by <function>PQparameterStatus</>.) +Pre-3.0-protocol servers do not report parameter settings, but +<application>libpq</> includes logic to obtain values for +<literal>server_version</>, and <literal>client_encoding</>. +Applications are encouraged to use <function>PQparameterStatus</> +rather than ad-hoc code to determine these values. (Beware however +that on a pre-3.0 connection, changing <literal>client_encoding</> via +<command>SET</> after connection startup will not be reflected by +<function>PQparameterStatus</>.) </para> </listitem> </varlistentry> <varlistentry> -<term><function>PQprotocolVersion</function></term> +<term><function>PQprotocolVersion</function><indexterm><primary>PQprotocolVersion</></></term> <listitem> <para> Interrogates the frontend/backend protocol being used. @@ -881,7 +896,7 @@ only protocol 2.0. (Protocol 1.0 is obsolete and not supported by libpq.) </varlistentry> <varlistentry> - <term><function>PQerrorMessage</function></term> + <term><function>PQerrorMessage</function><indexterm><primary>PQerrorMessage</></></term> <listitem> <para> <indexterm><primary>error message</></> @@ -903,7 +918,7 @@ char *PQerrorMessage(const PGconn* conn); </varlistentry> <varlistentry> - <term><function>PQsocket</function></term> + <term><function>PQsocket</function><indexterm><primary>PQsocket</></></term> <listitem> <para> Obtains the file descriptor number of the connection socket to @@ -919,11 +934,13 @@ int PQsocket(const PGconn *conn); </varlistentry> <varlistentry> - <term><function>PQbackendPID</function></term> + <term><function>PQbackendPID</function><indexterm><primary>PQbackendPID</></></term> <listitem> <para> - Returns the process <acronym>ID</acronym> of the backend server process - handling this connection. + Returns the process <acronym>ID</acronym> + (PID)<indexterm><primary>PID</><secondary>determining PID of + server process</><tertiary>in libpq</></> of the backend server + process handling this connection. <synopsis> int PQbackendPID(const PGconn *conn); </synopsis> @@ -941,10 +958,10 @@ int PQbackendPID(const PGconn *conn); </varlistentry> <varlistentry> - <term><function>PQgetssl</function></term> + <term><function>PQgetssl</function><indexterm><primary>PQgetssl</></></term> <listitem> <para> - <indexterm><primary>SSL</></> + <indexterm><primary>SSL</><secondary sortas="libpq">in libpq</secondary></indexterm> Returns the SSL structure used in the connection, or null if SSL is not in use. <synopsis> @@ -985,7 +1002,7 @@ SQL queries and commands. <para> <variablelist> <varlistentry> -<term><function>PQexec</function></term> +<term><function>PQexec</function><indexterm><primary>PQexec</></></term> <listitem> <para> Submits a command to the server @@ -1001,8 +1018,8 @@ PGresult *PQexec(PGconn *conn, const char *command); out-of-memory conditions or serious errors such as inability to send the command to the server. If a null pointer is returned, it - should be treated like a <symbol>PGRES_FATAL_ERROR</symbol> result. Use - <function>PQerrorMessage</function> to get more information about the error. + should be treated like a <symbol>PGRES_FATAL_ERROR</symbol> result. Use + <function>PQerrorMessage</function> to get more information about the error. </para> </listitem> </varlistentry> @@ -1022,12 +1039,12 @@ condition. <para> <variablelist> <varlistentry> -<term><function>PQexecParams</function></term> +<term><function>PQexecParams</function><indexterm><primary>PQexecParams</></></term> <listitem> <para> Submits a command to the server and waits for the result, - with the ability to pass parameters separately from the SQL - command text. + with the ability to pass parameters separately from the SQL + command text. <synopsis> PGresult *PQexecParams(PGconn *conn, const char *command, @@ -1093,11 +1110,11 @@ but has some usefulness as an extra defense against SQL-injection attacks. <para> <variablelist> <varlistentry> -<term><function>PQexecPrepared</function></term> +<term><function>PQexecPrepared</function><indexterm><primary>PQexecPrepared</></></term> <listitem> <para> Sends a request to execute a prepared statement with given - parameters, and waits for the result. + parameters, and waits for the result. <synopsis> PGresult *PQexecPrepared(PGconn *conn, const char *stmtName, @@ -1138,16 +1155,19 @@ future release. </para> <para> -The <structname>PGresult</structname> structure encapsulates the result -returned by the server. -<application>libpq</application> application programmers should be careful to -maintain the <structname>PGresult</structname> abstraction. Use the accessor functions below to get -at the contents of <structname>PGresult</structname>. Avoid directly referencing the fields of the -<structname>PGresult</structname> structure because they are subject to change in the future. +The +<structname>PGresult</structname><indexterm><primary>PGresult</></> +structure encapsulates the result returned by the server. +<application>libpq</application> application programmers should be +careful to maintain the <structname>PGresult</structname> abstraction. +Use the accessor functions below to get at the contents of +<structname>PGresult</structname>. Avoid directly referencing the +fields of the <structname>PGresult</structname> structure because they +are subject to change in the future. <variablelist> <varlistentry> -<term><function>PQresultStatus</function></term> +<term><function>PQresultStatus</function><indexterm><primary>PQresultStatus</></></term> <listitem> <para> Returns the result status of the command. @@ -1238,11 +1258,11 @@ processor (see <xref linkend="libpq-notice-processing">). </varlistentry> <varlistentry> -<term><function>PQresStatus</function></term> +<term><function>PQresStatus</function><indexterm><primary>PQresStatus</></></term> <listitem> <para> - Converts the enumerated type returned by <function>PQresultStatus</> into - a string constant describing the status code. + Converts the enumerated type returned by <function>PQresultStatus</> into + a string constant describing the status code. <synopsis> char *PQresStatus(ExecStatusType status); </synopsis> @@ -1251,7 +1271,7 @@ char *PQresStatus(ExecStatusType status); </varlistentry> <varlistentry> -<term><function>PQresultErrorMessage</function></term> +<term><function>PQresultErrorMessage</function><indexterm><primary>PQresultErrorMessage</></></term> <listitem> <para> Returns the error message associated with the command, or an empty string @@ -1276,27 +1296,145 @@ when you want to know the status from the latest operation on the connection. </varlistentry> <varlistentry> -<term><function>PQresultErrorField</function></term> +<term><function>PQresultErrorField</function><indexterm><primary>PQresultErrorField</></></term> <listitem> <para> Returns an individual field of an error report. <synopsis> char *PQresultErrorField(const PGresult *res, int fieldcode); </synopsis> -<parameter>fieldcode</> is an error field identifier defined by the -<productname>PostgreSQL</> protocol (see <xref -linkend="protocol-error-fields">), for example <literal>'C'</> for -the SQLSTATE error code. NULL is returned if the +<parameter>fieldcode</> is an error field identifier; see the symbols +listed below. <symbol>NULL</symbol> is returned if the <structname>PGresult</structname> is not an error or warning result, or does not include the specified field. Field values will normally not include a trailing newline. </para> <para> -Errors generated internally by libpq will have severity and primary message, -but typically no other fields. Errors returned by a pre-3.0-protocol server -will include severity and primary message, and sometimes a detail message, -but no other fields. +The following field codes are available: +<variablelist> + +<varlistentry> +<term><symbol>PG_DIAG_SEVERITY</></term> +<listitem> +<para> +The severity; the field contents are <literal>ERROR</>, +<literal>FATAL</>, or <literal>PANIC</> (in an error message), or +<literal>WARNING</>, <literal>NOTICE</>, <literal>DEBUG</>, +<literal>INFO</>, or <literal>LOG</> (in a notice message), or a +localized translation of one of these. Always present. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><symbol>PG_DIAG_SQLSTATE</> +</term> +<listitem> +<para> +The SQLSTATE code for the error (a 5-character string following SQL +spec conventions). Not localizable. Always present. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><symbol>PG_DIAG_MESSAGE_PRIMARY</></term> +<listitem> +<para> +The primary human-readable error message (typically one line). Always +present. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><symbol>PG_DIAG_MESSAGE_DETAIL</></term> +<listitem> +<para> +Detail: an optional secondary error message carrying more detail about +the problem. May run to multiple lines. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><symbol>PG_DIAG_MESSAGE_HINT</></term> +<listitem> +<para> +Hint: an optional suggestion what to do about the problem. This is +intended to differ from detail in that it offers advice (potentially +inappropriate) rather than hard facts. May run to multiple lines. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><symbol>PG_DIAG_STATEMENT_POSITION</></term> +<listitem> +<para> +A string containing a decimal integer indicating an error cursor +position as an index into the original statement string. The first +character has index 1, and positions are measured in characters not +bytes. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><symbol>PG_DIAG_CONTEXT</></term> +<listitem> +<para> +An indication of the context in which the error occurred. Presently +this includes a call stack traceback of active PL functions. The +trace is one entry per line, most recent first. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><symbol>PG_DIAG_SOURCE_FILE</></term> +<listitem> +<para> +The file name of the source-code location where the error was +reported. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><symbol>PG_DIAG_SOURCE_LINE</></term> +<listitem> +<para> +The line number of the source-code location where the error was +reported. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><symbol>PG_DIAG_SOURCE_FUNCTION</></term> +<listitem> +<para> +The name of the source-code function reporting the error. +</para> +</listitem> +</varlistentry> +</variablelist> +</para> + +<para> +The client is responsible for formatting displayed information to meet +its needs; in particular it should break long lines as needed. +Newline characters appearing in the error message fields should be +treated as paragraph breaks, not line breaks. +</para> + +<para> +Errors generated internally by <application>libpq</application> will +have severity and primary message, but typically no other fields. +Errors returned by a pre-3.0-protocol server will include severity and +primary message, and sometimes a detail message, but no other fields. </para> <para> @@ -1309,7 +1447,7 @@ Note that error fields are only available from </varlistentry> <varlistentry> -<term><function>PQclear</function></term> +<term><function>PQclear</function><indexterm><primary>PQclear</></></term> <listitem> <para> Frees the storage associated with a <structname>PGresult</structname>. @@ -1331,7 +1469,7 @@ void PQclear(PQresult *res); </varlistentry> <varlistentry> -<term><function>PQmakeEmptyPGresult</function></term> +<term><function>PQmakeEmptyPGresult</function><indexterm><primary>PQmakeEmptyPGresult</></></term> <listitem> <para> Constructs an empty <structname>PGresult</structname> object with the given status. @@ -1368,7 +1506,7 @@ values they will act as though the result has zero rows and zero columns. <variablelist> <varlistentry> -<term><function>PQntuples</function></term> +<term><function>PQntuples</function><indexterm><primary>PQntuples</></></term> <listitem> <para> Returns the number of rows (tuples) @@ -1381,7 +1519,7 @@ int PQntuples(const PGresult *res); </varlistentry> <varlistentry> -<term><function>PQnfields</function></term> +<term><function>PQnfields</function><indexterm><primary>PQnfields</></></term> <listitem> <para> Returns the number of columns (fields) @@ -1394,7 +1532,7 @@ int PQnfields(const PGresult *res); </varlistentry> <varlistentry> -<term><function>PQfname</function></term> +<term><function>PQfname</function><indexterm><primary>PQfname</></></term> <listitem> <para> Returns the column name associated with the given column number. @@ -1412,7 +1550,7 @@ NULL is returned if the column number is out of range. </varlistentry> <varlistentry> -<term><function>PQfnumber</function></term> +<term><function>PQfnumber</function><indexterm><primary>PQfnumber</></></term> <listitem> <para> Returns the column number @@ -1430,7 +1568,7 @@ int PQfnumber(const PGresult *res, </varlistentry> <varlistentry> -<term><function>PQftable</function></term> +<term><function>PQftable</function><indexterm><primary>PQftable</></></term> <listitem> <para> Returns the OID of the table from which the given column was fetched. @@ -1459,7 +1597,7 @@ exactly which table is referenced. </varlistentry> <varlistentry> -<term><function>PQftablecol</function></term> +<term><function>PQftablecol</function><indexterm><primary>PQftablecol</></></term> <listitem> <para> Returns the column number (within its table) of the column making up @@ -1480,7 +1618,7 @@ or when using pre-3.0 protocol. </varlistentry> <varlistentry> -<term><function>PQfformat</function></term> +<term><function>PQfformat</function><indexterm><primary>PQfformat</></></term> <listitem> <para> Returns the format code indicating the format of the given column. @@ -1500,7 +1638,7 @@ for future definition.) </varlistentry> <varlistentry> -<term><function>PQftype</function></term> +<term><function>PQftype</function><indexterm><primary>PQftype</></></term> <listitem> <para> Returns the data type associated with the @@ -1523,7 +1661,7 @@ in the source tree. </varlistentry> <varlistentry> -<term><function>PQfmod</function></term> +<term><function>PQfmod</function><indexterm><primary>PQfmod</></></term> <listitem> <para> Returns the type modifier of the column @@ -1545,7 +1683,7 @@ in which case the value is always -1. </varlistentry> <varlistentry> -<term><function>PQfsize</function></term> +<term><function>PQfsize</function><indexterm><primary>PQfsize</></></term> <listitem> <para> Returns the size in bytes of the column @@ -1567,7 +1705,7 @@ A negative value indicates the data type is variable-length. </varlistentry> <varlistentry> -<term><function>PQbinaryTuples</function></term> +<term><function>PQbinaryTuples</function><indexterm><primary>PQbinaryTuples</></></term> <listitem> <para> Returns 1 if the <structname>PGresult</> contains binary data @@ -1589,11 +1727,11 @@ returns 1 only if all columns of the result are binary (format 1). </varlistentry> <varlistentry> -<term><function>PQgetvalue</function></term> +<term><function>PQgetvalue</function><indexterm><primary>PQgetvalue</></></term> <listitem> <para> Returns a single field value of one row - of a <structname>PGresult</structname>. + of a <structname>PGresult</structname>. Row and column numbers start at 0. <synopsis> char* PQgetvalue(const PGresult *res, @@ -1629,8 +1767,8 @@ be used past the lifetime of the <structname>PGresult</structname> structure i </varlistentry> <varlistentry> -<term><function>PQgetisnull</function></term> -<listitem> +<term><function>PQgetisnull</function><indexterm><primary>PQgetisnull</></></term> +<indexterm><primary>null value</><secondary sortas="libpq">in libpq</></indexterm><listitem> <para> Tests a field for a null value. Row and column numbers start at 0. @@ -1650,7 +1788,7 @@ will return an empty string, not a null pointer, for a null field.) </varlistentry> <varlistentry> -<term><function>PQgetlength</function></term> +<term><function>PQgetlength</function><indexterm><primary>PQgetlength</></></term> <listitem> <para> Returns the actual length of a field value in bytes. @@ -1673,7 +1811,7 @@ on <function>PQfsize</function> to obtain the actual data length. </varlistentry> <varlistentry> -<term><function>PQprint</function></term> +<term><function>PQprint</function><indexterm><primary>PQprint</></></term> <listitem> <para> Prints out all the rows and, optionally, the @@ -1719,11 +1857,11 @@ results. <variablelist> <varlistentry> -<term><function>PQcmdStatus</function></term> +<term><function>PQcmdStatus</function><indexterm><primary>PQcmdStatus</></></term> <listitem> <para> Returns the command status tag from the SQL command that - generated the <structname>PGresult</structname>. + generated the <structname>PGresult</structname>. <synopsis> char * PQcmdStatus(PGresult *res); </synopsis> @@ -1736,10 +1874,10 @@ data such as the number of rows processed. </varlistentry> <varlistentry> -<term><function>PQcmdTuples</function></term> +<term><function>PQcmdTuples</function><indexterm><primary>PQcmdTuples</></></term> <listitem> <para> - Returns the number of rows affected by the SQL command. + Returns the number of rows affected by the SQL command. <synopsis> char * PQcmdTuples(PGresult *res); </synopsis> @@ -1747,23 +1885,25 @@ char * PQcmdTuples(PGresult *res); <para> If the <acronym>SQL</acronym> command that generated the - <structname>PGresult</structname> was <command>INSERT</>, - <command>UPDATE</>, <command>DELETE</command>, <command>MOVE</>, - or <command>FETCH</>, this returns a - string containing the number of rows affected. If the + <structname>PGresult</structname> was <command>INSERT</>, + <command>UPDATE</>, <command>DELETE</command>, <command>MOVE</>, + or <command>FETCH</>, this returns a + string containing the number of rows affected. If the command was anything else, it returns the empty string. </para> </listitem> </varlistentry> <varlistentry> -<term><function>PQoidValue</function></term> +<term><function>PQoidValue</function><indexterm><primary>PQoidValue</></></term> <listitem> <para> - Returns the OID of the inserted row, if the - <acronym>SQL</acronym> command was an <command>INSERT</command> - that inserted exactly one row into a table that has OIDs. - Otherwise, returns <literal>InvalidOid</literal>. + Returns the OID<indexterm><primary>OID</><secondary>in + libpq</></> of the inserted row, if the + <acronym>SQL</acronym> command was an + <command>INSERT</command> that inserted exactly one row into + a table that has OIDs. Otherwise, returns + <literal>InvalidOid</literal>. <synopsis> Oid PQoidValue(const PGresult *res); </synopsis> @@ -1772,7 +1912,7 @@ Oid PQoidValue(const PGresult *res); </varlistentry> <varlistentry> -<term><function>PQoidStatus</function></term> +<term><function>PQoidStatus</function><indexterm><primary>PQoidStatus</></></term> <listitem> <para> Returns a string with the OID of the inserted row, if the @@ -1800,6 +1940,7 @@ It is not thread-safe. <sect2 id="libpq-exec-escape-string"> <title>Escaping Strings for Inclusion in SQL Commands</title> + <indexterm zone="libpq-exec-escape-string"><primary>PQescapeString</></> <indexterm zone="libpq-exec-escape-string"><primary>escaping strings</></> <para> @@ -1858,13 +1999,15 @@ strings overlap. <sect2 id="libpq-exec-escape-bytea"> <title>Escaping Binary Strings for Inclusion in SQL Commands</title> + <indexterm zone="libpq-exec-escape-bytea"> - <primary>escaping binary strings</primary> + <primary>bytea</> + <secondary sortas="libpq">in libpq</> </indexterm> <variablelist> <varlistentry> - <term><function>PQescapeBytea</function></term> + <term><function>PQescapeBytea</function><indexterm><primary>PQescapeBytea</></></term> <listitem> <para> Escapes binary data for use within an SQL command with the type @@ -1916,7 +2059,7 @@ unsigned char *PQescapeBytea(const unsigned char *from, </varlistentry> <varlistentry> - <term><function>PQunescapeBytea</function></term> + <term><function>PQunescapeBytea</function><indexterm><primary>PQunescapeBytea</></></term> <listitem> <para> Converts an escaped string representation of binary data into binary @@ -1943,7 +2086,7 @@ unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length); </varlistentry> <varlistentry> - <term><function>PQfreemem</function></term> + <term><function>PQfreemem</function><indexterm><primary>PQfreemem</></></term> <listitem> <para> Frees memory allocated by <application>libpq</>. @@ -2016,32 +2159,32 @@ respectively. <variablelist> <varlistentry> -<term><function>PQsendQuery</function></term> +<term><function>PQsendQuery</function><indexterm><primary>PQsendQuery</></></term> <listitem> <para> Submits a command to the server without - waiting for the result(s). 1 is returned if the command was - successfully dispatched and 0 if not (in which case, use - <function>PQerrorMessage</> to get more information about the failure). + waiting for the result(s). 1 is returned if the command was + successfully dispatched and 0 if not (in which case, use + <function>PQerrorMessage</> to get more information about the failure). <synopsis> int PQsendQuery(PGconn *conn, const char *command); </synopsis> - After successfully calling <function>PQsendQuery</function>, call + After successfully calling <function>PQsendQuery</function>, call <function>PQgetResult</function> one or more - times to obtain the results. <function>PQsendQuery</function> may not be called - again (on the same connection) until <function>PQgetResult</function> has returned a null pointer, - indicating that the command is done. + times to obtain the results. <function>PQsendQuery</function> may not be called + again (on the same connection) until <function>PQgetResult</function> has returned a null pointer, + indicating that the command is done. </para> </listitem> </varlistentry> <varlistentry> -<term><function>PQsendQueryParams</function></term> +<term><function>PQsendQueryParams</function><indexterm><primary>PQsendQueryParams</></></term> <listitem> <para> Submits a command and separate parameters to the server without - waiting for the result(s). + waiting for the result(s). <synopsis> int PQsendQueryParams(PGconn *conn, const char *command, @@ -2053,22 +2196,22 @@ int PQsendQueryParams(PGconn *conn, int resultFormat); </synopsis> - This is equivalent to <function>PQsendQuery</function> except that - query parameters can be specified separately from the query string. - The function's parameters are handled identically to - <function>PQexecParams</function>. Like - <function>PQexecParams</function>, it will not work on 2.0-protocol - connections, and it allows only one command in the query string. + This is equivalent to <function>PQsendQuery</function> except that + query parameters can be specified separately from the query string. + The function's parameters are handled identically to + <function>PQexecParams</function>. Like + <function>PQexecParams</function>, it will not work on 2.0-protocol + connections, and it allows only one command in the query string. </para> </listitem> </varlistentry> <varlistentry> -<term><function>PQsendQueryPrepared</function></term> +<term><function>PQsendQueryPrepared</function><indexterm><primary>PQsendQueryPrepared</></></term> <listitem> <para> Sends a request to execute a prepared statement with given - parameters, without waiting for the result(s). + parameters, without waiting for the result(s). <synopsis> int PQsendQueryPrepared(PGconn *conn, const char *stmtName, @@ -2079,41 +2222,41 @@ int PQsendQueryPrepared(PGconn *conn, int resultFormat); </synopsis> - This is similar to <function>PQsendQueryParams</function>, but the - command to be executed is specified by naming a previously-prepared - statement, instead of giving a query string. - The function's parameters are handled identically to - <function>PQexecPrepared</function>. Like - <function>PQexecPrepared</function>, it will not work on 2.0-protocol - connections. + This is similar to <function>PQsendQueryParams</function>, but the + command to be executed is specified by naming a previously-prepared + statement, instead of giving a query string. + The function's parameters are handled identically to + <function>PQexecPrepared</function>. Like + <function>PQexecPrepared</function>, it will not work on 2.0-protocol + connections. </para> </listitem> </varlistentry> <varlistentry> -<term><function>PQgetResult</function></term> +<term><function>PQgetResult</function><indexterm><primary>PQgetResult</></></term> <listitem> <para> Waits for the next result from a prior - <function>PQsendQuery</function>, - <function>PQsendQueryParams</function>, or - <function>PQsendQueryPrepared</function> call, - and returns it. A null pointer is returned when the command is complete - and there will be no more results. + <function>PQsendQuery</function>, + <function>PQsendQueryParams</function>, or + <function>PQsendQueryPrepared</function> call, + and returns it. A null pointer is returned when the command is complete + and there will be no more results. <synopsis> PGresult *PQgetResult(PGconn *conn); </synopsis> </para> <para> - <function>PQgetResult</function> must be called repeatedly until it returns a null pointer, - indicating that the command is done. (If called when no command is - active, <function>PQgetResult</function> will just return a null pointer at once.) - Each non-null result from <function>PQgetResult</function> should be processed using - the same <structname>PGresult</> accessor functions previously described. - Don't forget to free each result object with <function>PQclear</function> when done with it. - Note that <function>PQgetResult</function> will block only if a command is active and the - necessary response data has not yet been read by <function>PQconsumeInput</function>. + <function>PQgetResult</function> must be called repeatedly until it returns a null pointer, + indicating that the command is done. (If called when no command is + active, <function>PQgetResult</function> will just return a null pointer at once.) + Each non-null result from <function>PQgetResult</function> should be processed using + the same <structname>PGresult</> accessor functions previously described. + Don't forget to free each result object with <function>PQclear</function> when done with it. + Note that <function>PQgetResult</function> will block only if a command is active and the + necessary response data has not yet been read by <function>PQconsumeInput</function>. </para> </listitem> </varlistentry> @@ -2134,10 +2277,10 @@ more functions: <variablelist> <varlistentry> -<term><function>PQconsumeInput</function></term> +<term><function>PQconsumeInput</function><indexterm><primary>PQconsumeInput</></></term> <listitem> <para> - If input is available from the server, consume it. + If input is available from the server, consume it. <synopsis> int PQconsumeInput(PGconn *conn); </synopsis> @@ -2165,7 +2308,7 @@ application can thus use <function>PQconsumeInput</function> to clear the </varlistentry> <varlistentry> -<term><function>PQisBusy</function></term> +<term><function>PQisBusy</function><indexterm><primary>PQisBusy</></></term> <listitem> <para> Returns 1 if a command is busy, that is, <function>PQgetResult</function> would block @@ -2201,16 +2344,18 @@ if <function>PQisBusy</function> returns false (0). It can also call </para> <para> -A client that uses <function>PQsendQuery</function>/<function>PQgetResult</function> -can also attempt to cancel a command that is still being processed by the server. +A client that uses +<function>PQsendQuery</function>/<function>PQgetResult</function> can +also attempt to cancel a command that is still being processed by the +server.<indexterm><primary>canceling</><secondary>SQL command</></> <variablelist> <varlistentry> -<term><function>PQrequestCancel</function></term> +<term><function>PQrequestCancel</function><indexterm><primary>PQrequestCancel</></></term> <listitem> <para> - Requests that the server abandon - processing of the current command. + Requests that the server abandon + processing of the current command. <synopsis> int PQrequestCancel(PGconn *conn); </synopsis> @@ -2259,7 +2404,7 @@ functions may be used. <variablelist> <varlistentry> - <term><function>PQsetnonblocking</function></term> + <term><function>PQsetnonblocking</function><indexterm><primary>PQsetnonblocking</></></term> <listitem> <para> Sets the nonblocking status of the connection. @@ -2289,7 +2434,7 @@ int PQsetnonblocking(PGconn *conn, int arg); </varlistentry> <varlistentry> -<term><function>PQisnonblocking</function></term> +<term><function>PQisnonblocking</function><indexterm><primary>PQisnonblocking</></></term> <listitem> <para> Returns the blocking status of the database connection. @@ -2306,7 +2451,7 @@ int PQisnonblocking(const PGconn *conn); </varlistentry> <varlistentry> -<term><function>PQflush</function></term> +<term><function>PQflush</function><indexterm><primary>PQflush</></></term> <listitem> <para> Attempts to flush any queued output data to the server. @@ -2335,6 +2480,8 @@ and then read the response as described above. <sect1 id="libpq-fastpath"> <title>The Fast-Path Interface</title> +<indexterm zone="libpq-fastpath"><primary>fast path</></> + <para> <productname>PostgreSQL</productname> provides a fast-path interface to send simple function calls to the server. @@ -2350,8 +2497,8 @@ parameters and results substitutes for a fast-path function call. </tip> <para> -The function <function>PQfn</function> requests execution of a server -function via the fast-path interface: +The function <function>PQfn</function><indexterm><primary>PQfn</></> +requests execution of a server function via the fast-path interface: <synopsis> PGresult* PQfn(PGconn* conn, int fnid, @@ -2417,7 +2564,10 @@ set-valued results when using this interface. <sect1 id="libpq-notify"> <title>Asynchronous Notification</title> - <indexterm zone="libpq-notify"><primary>NOTIFY</primary></indexterm> + <indexterm zone="libpq-notify"> + <primary>NOTIFY</primary> + <secondary>in libpq</secondary> + </indexterm> <para> <productname>PostgreSQL</productname> offers asynchronous notification via the @@ -2433,9 +2583,11 @@ not necessary for there to be any associated table. </para> <para> -<application>libpq</application> applications submit <command>LISTEN</command> and <command>UNLISTEN</command> -commands as ordinary SQL commands. The arrival of <command>NOTIFY</command> -messages can subsequently be detected by calling <function>PQnotifies</function>. +<application>libpq</application> applications submit +<command>LISTEN</command> and <command>UNLISTEN</command> commands as +ordinary SQL commands. The arrival of <command>NOTIFY</command> +messages can subsequently be detected by calling +<function>PQnotifies</function>.<indexterm><primary>PQnotifies</></> </para> <para> @@ -2443,8 +2595,8 @@ The function <function>PQnotifies</function> returns the next notification from a list of unhandled notification messages received from the server. It returns a null pointer if there are no pending notifications. Once a notification is - returned from <function>PQnotifies</>, it is considered handled and will be - removed from the list of notifications. + returned from <function>PQnotifies</>, it is considered handled and will be + removed from the list of notifications. <synopsis> PGnotify* PQnotifies(PGconn *conn); @@ -2570,7 +2722,7 @@ if any notifications came in during the processing of the command. <variablelist> <varlistentry> -<term><function>PQnfields</function></term> +<term><function>PQnfields</function><indexterm><primary>PQnfields</><secondary>with COPY</></></term> <listitem> <para> Returns the number of columns (fields) to be copied. @@ -2579,30 +2731,30 @@ if any notifications came in during the processing of the command. </varlistentry> <varlistentry> -<term><function>PQbinaryTuples</function></term> +<term><function>PQbinaryTuples</function><indexterm><primary>PQbinaryTuples</><secondary>with COPY</></></term> <listitem> <para> 0 indicates the overall copy format is textual (rows - separated by newlines, columns separated by separator - characters, etc). - 1 indicates the overall copy format is binary. - See <xref linkend="sql-copy" endterm="sql-copy-title"> - for more information. + separated by newlines, columns separated by separator + characters, etc). + 1 indicates the overall copy format is binary. + See <xref linkend="sql-copy" endterm="sql-copy-title"> + for more information. </para> </listitem> </varlistentry> <varlistentry> -<term><function>PQfformat</function></term> +<term><function>PQfformat</function><indexterm><primary>PQfformat</><secondary>with COPY</></></term> <listitem> <para> Returns the format code (0 for text, 1 for binary) associated - with each column of the copy operation. The per-column format - codes will always be zero when the overall copy format is textual, - but the binary format can support both text and binary columns. - (However, as of the current implementation of <command>COPY</>, - only binary columns appear in a binary copy; so the per-column - formats always match the overall format at present.) + with each column of the copy operation. The per-column format + codes will always be zero when the overall copy format is textual, + but the binary format can support both text and binary columns. + (However, as of the current implementation of <command>COPY</>, + only binary columns appear in a binary copy; so the per-column + formats always match the overall format at present.) </para> </listitem> </varlistentry> @@ -2627,7 +2779,7 @@ When using protocol 2.0, all these functions will return 0. <variablelist> <varlistentry> -<term><function>PQputCopyData</function></term> +<term><function>PQputCopyData</function><indexterm><primary>PQputCopyData</></></term> <listitem> <para> Sends data to the server during <literal>COPY_IN</> state. @@ -2658,7 +2810,7 @@ by the <command>COPY</> command; see </varlistentry> <varlistentry> -<term><function>PQputCopyEnd</function></term> +<term><function>PQputCopyEnd</function><indexterm><primary>PQputCopyEnd</></></term> <listitem> <para> Sends end-of-data indication to the server during <literal>COPY_IN</> state. @@ -2710,7 +2862,7 @@ operation. <variablelist> <varlistentry> -<term><function>PQgetCopyData</function></term> +<term><function>PQgetCopyData</function><indexterm><primary>PQgetCopyData</></></term> <listitem> <para> Receives data from the server during <literal>COPY_OUT</> state. @@ -2779,7 +2931,7 @@ operation. <variablelist> <varlistentry> -<term><function>PQgetline</function></term> +<term><function>PQgetline</function><indexterm><primary>PQgetline</></></term> <listitem> <para> Reads a newline-terminated line of characters @@ -2815,7 +2967,7 @@ for a terminator line). </varlistentry> <varlistentry> -<term><function>PQgetlineAsync</function></term> +<term><function>PQgetlineAsync</function><indexterm><primary>PQgetlineAsync</></></term> <listitem> <para> Reads a row of COPY data @@ -2867,7 +3019,7 @@ than the room actually available.) </varlistentry> <varlistentry> -<term><function>PQputline</function></term> +<term><function>PQputline</function><indexterm><primary>PQputline</></></term> <listitem> <para> Sends a null-terminated string to the server. @@ -2901,7 +3053,7 @@ having sent the actual data. </varlistentry> <varlistentry> -<term><function>PQputnbytes</function></term> +<term><function>PQputnbytes</function><indexterm><primary>PQputnbytes</></></term> <listitem> <para> Sends a non-null-terminated string to the server. @@ -2922,7 +3074,7 @@ specified directly. Use this procedure when sending binary data. </varlistentry> <varlistentry> -<term><function>PQendcopy</function></term> +<term><function>PQendcopy</function><indexterm><primary>PQendcopy</></></term> <listitem> <para> Synchronizes with the server. @@ -2981,7 +3133,7 @@ These functions control miscellaneous details of <variablelist> <varlistentry> -<term><function>PQsetErrorVerbosity</function></term> +<term><function>PQsetErrorVerbosity</function><indexterm><primary>PQsetErrorVerbosity</></></term> <listitem> <para> Determines the verbosity of messages returned by @@ -3007,7 +3159,7 @@ ones. </varlistentry> <varlistentry> -<term><function>PQtrace</function></term> +<term><function>PQtrace</function><indexterm><primary>PQtrace</></></term> <listitem> <para> Enables tracing of the client/server communication to a debugging file stream. @@ -3019,7 +3171,7 @@ void PQtrace(PGconn *conn, FILE *stream); </varlistentry> <varlistentry> -<term><function>PQuntrace</function></term> +<term><function>PQuntrace</function><indexterm><primary>PQuntrace</></></term> <listitem> <para> Disables tracing started by <function>PQtrace</function>. @@ -3036,6 +3188,11 @@ void PQuntrace(PGconn *conn); <sect1 id="libpq-notice-processing"> <title>Notice Processing</title> +<indexterm zone="libpq-notice-processing"> + <primary>notice processing</primary> + <secondary>in libpq</secondary> +</indexterm> + <para> Notice and warning messages generated by the server are not returned by the query execution functions, since they do not imply failure of the query. @@ -3056,10 +3213,10 @@ work in the notice receiver. <para> The function <function>PQsetNoticeReceiver</function> -<indexterm><primary>notice receiver</></> +<indexterm><primary>notice receiver</></><indexterm><primary>PQsetNoticeReceiver</></> sets or examines the current notice receiver for a connection object. Similarly, <function>PQsetNoticeProcessor</function> -<indexterm><primary>notice processor</></> +<indexterm><primary>notice processor</></><indexterm><primary>PQsetNoticeProcessor</></> sets or examines the current notice processor. <synopsis> @@ -3137,7 +3294,7 @@ functions like <function>PQgetvalue</function>. <title>Environment Variables</title> <indexterm zone="libpq-envars"> - <primary>environment variables</primary> + <primary>environment variable</primary> </indexterm> <para> @@ -3426,11 +3583,12 @@ call <function>fe_setauthsvc</function> at all. </para> <para> -<application>libpq</application> applications that use the <literal>crypt</literal> -authentication method rely on the <literal>crypt()</literal> operating -system function, which is often not thread-safe. It is better to use the -<literal>md5</literal> method, which is thread-safe on all -platforms. +<application>libpq</application> applications that use the +<literal>crypt</literal> authentication method rely on the +<literal>crypt()</literal> operating system function, which is often +not thread-safe.<indexterm><primary>crypt</><secondary>thread +safety</></> It is better to use the <literal>md5</literal> method, +which is thread-safe on all platforms. </para> </sect1> @@ -3438,6 +3596,11 @@ platforms. <sect1 id="libpq-build"> <title>Building <application>libpq</application> Programs</title> + <indexterm zone="libpq-build"> + <primary>compiling</primary> + <secondary>libpq applications</secondary> + </indexterm> + <para> To build (i.e., compile and link) your <application>libpq</application> programs you need to do all of the following things: @@ -3482,12 +3645,12 @@ CPPFLAGS += -I/usr/local/pgsql/include </para> <para> - <indexterm><primary>pg_config</></> If there is any chance that your program might be compiled by other users then you should not hardcode the directory location like that. Instead, you can run the utility - <command>pg_config</command> to find out where the header files - are on the local system: + <command>pg_config</command><indexterm><primary>pg_config</><secondary + sortas="libpq">with libpq</></> to find out where the header + files are on the local system: <screen> <prompt>$</prompt> pg_config --includedir <computeroutput>/usr/local/include</computeroutput> @@ -3576,7 +3739,7 @@ testlibpq.o(.text+0xa4): undefined reference to `PQerrorMessage' /* * testlibpq.c * - * Test the C version of LIBPQ, the POSTGRES frontend library. + * Test the C version of LIBPQ, the POSTGRES frontend library. */ #include <stdio.h> #include <stdlib.h> @@ -3585,112 +3748,112 @@ testlibpq.o(.text+0xa4): undefined reference to `PQerrorMessage' static void exit_nicely(PGconn *conn) { - PQfinish(conn); - exit(1); + PQfinish(conn); + exit(1); } int main(int argc, char **argv) { - const char *conninfo; - PGconn *conn; - PGresult *res; - int nFields; - int i, - j; - - /* - * If the user supplies a parameter on the command line, use it as - * the conninfo string; otherwise default to setting dbname=template1 - * and using environment variables or defaults for all other connection - * parameters. - */ - if (argc > 1) - conninfo = argv[1]; - else - conninfo = "dbname = template1"; - - /* Make a connection to the database */ - conn = PQconnectdb(conninfo); - - /* Check to see that the backend connection was successfully made */ - if (PQstatus(conn) != CONNECTION_OK) - { - fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn)); - fprintf(stderr, "%s", PQerrorMessage(conn)); - exit_nicely(conn); - } - - /* - * Our test case here involves using a cursor, for which we must be - * inside a transaction block. We could do the whole thing with a - * single PQexec() of "select * from pg_database", but that's too - * trivial to make a good example. - */ - - /* Start a transaction block */ - res = PQexec(conn, "BEGIN"); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn)); - PQclear(res); - exit_nicely(conn); - } - - /* - * Should PQclear PGresult whenever it is no longer needed to avoid - * memory leaks - */ - PQclear(res); - - /* - * Fetch rows from pg_database, the system catalog of databases - */ - res = PQexec(conn, "DECLARE myportal CURSOR FOR select * from pg_database"); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "DECLARE CURSOR failed: %s", PQerrorMessage(conn)); - PQclear(res); - exit_nicely(conn); - } - PQclear(res); - - res = PQexec(conn, "FETCH ALL in myportal"); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - fprintf(stderr, "FETCH ALL failed: %s", PQerrorMessage(conn)); - PQclear(res); - exit_nicely(conn); - } - - /* first, print out the attribute names */ - nFields = PQnfields(res); - for (i = 0; i < nFields; i++) - printf("%-15s", PQfname(res, i)); - printf("\n\n"); - - /* next, print out the rows */ - for (i = 0; i < PQntuples(res); i++) - { - for (j = 0; j < nFields; j++) - printf("%-15s", PQgetvalue(res, i, j)); - printf("\n"); - } - - PQclear(res); - - /* close the portal ... we don't bother to check for errors ... */ - res = PQexec(conn, "CLOSE myportal"); - PQclear(res); - - /* end the transaction */ - res = PQexec(conn, "END"); - PQclear(res); - - /* close the connection to the database and cleanup */ - PQfinish(conn); - - return 0; + const char *conninfo; + PGconn *conn; + PGresult *res; + int nFields; + int i, + j; + + /* + * If the user supplies a parameter on the command line, use it as + * the conninfo string; otherwise default to setting dbname=template1 + * and using environment variables or defaults for all other connection + * parameters. + */ + if (argc > 1) + conninfo = argv[1]; + else + conninfo = "dbname = template1"; + + /* Make a connection to the database */ + conn = PQconnectdb(conninfo); + + /* Check to see that the backend connection was successfully made */ + if (PQstatus(conn) != CONNECTION_OK) + { + fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn)); + fprintf(stderr, "%s", PQerrorMessage(conn)); + exit_nicely(conn); + } + + /* + * Our test case here involves using a cursor, for which we must be + * inside a transaction block. We could do the whole thing with a + * single PQexec() of "select * from pg_database", but that's too + * trivial to make a good example. + */ + + /* Start a transaction block */ + res = PQexec(conn, "BEGIN"); + if (PQresultStatus(res) != PGRES_COMMAND_OK) + { + fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn)); + PQclear(res); + exit_nicely(conn); + } + + /* + * Should PQclear PGresult whenever it is no longer needed to avoid + * memory leaks + */ + PQclear(res); + + /* + * Fetch rows from pg_database, the system catalog of databases + */ + res = PQexec(conn, "DECLARE myportal CURSOR FOR select * from pg_database"); + if (PQresultStatus(res) != PGRES_COMMAND_OK) + { + fprintf(stderr, "DECLARE CURSOR failed: %s", PQerrorMessage(conn)); + PQclear(res); + exit_nicely(conn); + } + PQclear(res); + + res = PQexec(conn, "FETCH ALL in myportal"); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + fprintf(stderr, "FETCH ALL failed: %s", PQerrorMessage(conn)); + PQclear(res); + exit_nicely(conn); + } + + /* first, print out the attribute names */ + nFields = PQnfields(res); + for (i = 0; i < nFields; i++) + printf("%-15s", PQfname(res, i)); + printf("\n\n"); + + /* next, print out the rows */ + for (i = 0; i < PQntuples(res); i++) + { + for (j = 0; j < nFields; j++) + printf("%-15s", PQgetvalue(res, i, j)); + printf("\n"); + } + + PQclear(res); + + /* close the portal ... we don't bother to check for errors ... */ + res = PQexec(conn, "CLOSE myportal"); + PQclear(res); + + /* end the transaction */ + res = PQexec(conn, "END"); + PQclear(res); + + /* close the connection to the database and cleanup */ + PQfinish(conn); + + return 0; } </programlisting> </example> @@ -3701,7 +3864,7 @@ main(int argc, char **argv) <programlisting> /* * testlibpq2.c - * Test of the asynchronous notification interface + * Test of the asynchronous notification interface * * Start this program, then from psql in another window do * NOTIFY TBL2; @@ -3732,102 +3895,102 @@ main(int argc, char **argv) static void exit_nicely(PGconn *conn) { - PQfinish(conn); - exit(1); + PQfinish(conn); + exit(1); } int main(int argc, char **argv) { - const char *conninfo; - PGconn *conn; - PGresult *res; - PGnotify *notify; - int nnotifies; - - /* - * If the user supplies a parameter on the command line, use it as - * the conninfo string; otherwise default to setting dbname=template1 - * and using environment variables or defaults for all other connection - * parameters. - */ - if (argc > 1) - conninfo = argv[1]; - else - conninfo = "dbname = template1"; - - /* Make a connection to the database */ - conn = PQconnectdb(conninfo); - - /* Check to see that the backend connection was successfully made */ - if (PQstatus(conn) != CONNECTION_OK) - { - fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn)); - fprintf(stderr, "%s", PQerrorMessage(conn)); - exit_nicely(conn); - } - - /* - * Issue LISTEN command to enable notifications from the rule's NOTIFY. - */ - res = PQexec(conn, "LISTEN TBL2"); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - { - fprintf(stderr, "LISTEN command failed: %s", PQerrorMessage(conn)); - PQclear(res); - exit_nicely(conn); - } - - /* - * should PQclear PGresult whenever it is no longer needed to avoid - * memory leaks - */ - PQclear(res); - - /* Quit after four notifies are received. */ - nnotifies = 0; - while (nnotifies < 4) - { - /* - * Sleep until something happens on the connection. We use select(2) - * to wait for input, but you could also use poll() or similar - * facilities. - */ - int sock; - fd_set input_mask; - - sock = PQsocket(conn); - - if (sock < 0) - break; /* shouldn't happen */ - - FD_ZERO(&input_mask); - FD_SET(sock, &input_mask); - - if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0) - { - fprintf(stderr, "select() failed: %s\n", strerror(errno)); - exit_nicely(conn); - } - - /* Now check for input */ - PQconsumeInput(conn); - while ((notify = PQnotifies(conn)) != NULL) - { - fprintf(stderr, - "ASYNC NOTIFY of '%s' received from backend pid %d\n", - notify->relname, notify->be_pid); - PQfreemem(notify); - nnotifies++; - } - } - - fprintf(stderr, "Done.\n"); - - /* close the connection to the database and cleanup */ - PQfinish(conn); - - return 0; + const char *conninfo; + PGconn *conn; + PGresult *res; + PGnotify *notify; + int nnotifies; + + /* + * If the user supplies a parameter on the command line, use it as + * the conninfo string; otherwise default to setting dbname=template1 + * and using environment variables or defaults for all other connection + * parameters. + */ + if (argc > 1) + conninfo = argv[1]; + else + conninfo = "dbname = template1"; + + /* Make a connection to the database */ + conn = PQconnectdb(conninfo); + + /* Check to see that the backend connection was successfully made */ + if (PQstatus(conn) != CONNECTION_OK) + { + fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn)); + fprintf(stderr, "%s", PQerrorMessage(conn)); + exit_nicely(conn); + } + + /* + * Issue LISTEN command to enable notifications from the rule's NOTIFY. + */ + res = PQexec(conn, "LISTEN TBL2"); + if (PQresultStatus(res) != PGRES_COMMAND_OK) + { + fprintf(stderr, "LISTEN command failed: %s", PQerrorMessage(conn)); + PQclear(res); + exit_nicely(conn); + } + + /* + * should PQclear PGresult whenever it is no longer needed to avoid + * memory leaks + */ + PQclear(res); + + /* Quit after four notifies are received. */ + nnotifies = 0; + while (nnotifies < 4) + { + /* + * Sleep until something happens on the connection. We use select(2) + * to wait for input, but you could also use poll() or similar + * facilities. + */ + int sock; + fd_set input_mask; + + sock = PQsocket(conn); + + if (sock < 0) + break; /* shouldn't happen */ + + FD_ZERO(&input_mask); + FD_SET(sock, &input_mask); + + if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0) + { + fprintf(stderr, "select() failed: %s\n", strerror(errno)); + exit_nicely(conn); + } + + /* Now check for input */ + PQconsumeInput(conn); + while ((notify = PQnotifies(conn)) != NULL) + { + fprintf(stderr, + "ASYNC NOTIFY of '%s' received from backend pid %d\n", + notify->relname, notify->be_pid); + PQfreemem(notify); + nnotifies++; + } + } + + fprintf(stderr, "Done.\n"); + + /* close the connection to the database and cleanup */ + PQfinish(conn); + + return 0; } </programlisting> </example> @@ -3838,7 +4001,7 @@ main(int argc, char **argv) <programlisting> /* * testlibpq3.c - * Test out-of-line parameters and binary I/O. + * Test out-of-line parameters and binary I/O. * * Before running this, populate a database with the following commands * (provided in src/test/examples/testlibpq3.sql): @@ -3870,125 +4033,125 @@ main(int argc, char **argv) static void exit_nicely(PGconn *conn) { - PQfinish(conn); - exit(1); + PQfinish(conn); + exit(1); } int main(int argc, char **argv) { - const char *conninfo; - PGconn *conn; - PGresult *res; - const char *paramValues[1]; - int i, - j; - int i_fnum, - t_fnum, - b_fnum; - - /* - * If the user supplies a parameter on the command line, use it as - * the conninfo string; otherwise default to setting dbname=template1 - * and using environment variables or defaults for all other connection - * parameters. - */ - if (argc > 1) - conninfo = argv[1]; - else - conninfo = "dbname = template1"; - - /* Make a connection to the database */ - conn = PQconnectdb(conninfo); - - /* Check to see that the backend connection was successfully made */ - if (PQstatus(conn) != CONNECTION_OK) - { - fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn)); - fprintf(stderr, "%s", PQerrorMessage(conn)); - exit_nicely(conn); - } - - /* - * The point of this program is to illustrate use of PQexecParams() - * with out-of-line parameters, as well as binary transmission of - * results. By using out-of-line parameters we can avoid a lot of - * tedious mucking about with quoting and escaping. Notice how we - * don't have to do anything special with the quote mark in the - * parameter value. - */ - - /* Here is our out-of-line parameter value */ - paramValues[0] = "joe's place"; - - res = PQexecParams(conn, - "SELECT * FROM test1 WHERE t = $1", - 1, /* one param */ - NULL, /* let the backend deduce param type */ - paramValues, - NULL, /* don't need param lengths since text */ - NULL, /* default to all text params */ - 1); /* ask for binary results */ - - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn)); - PQclear(res); - exit_nicely(conn); - } - - /* Use PQfnumber to avoid assumptions about field order in result */ - i_fnum = PQfnumber(res, "i"); - t_fnum = PQfnumber(res, "t"); - b_fnum = PQfnumber(res, "b"); - - for (i = 0; i < PQntuples(res); i++) - { - char *iptr; - char *tptr; - char *bptr; - int blen; - int ival; - - /* Get the field values (we ignore possibility they are null!) */ - iptr = PQgetvalue(res, i, i_fnum); - tptr = PQgetvalue(res, i, t_fnum); - bptr = PQgetvalue(res, i, b_fnum); - - /* - * The binary representation of INT4 is in network byte order, - * which we'd better coerce to the local byte order. - */ - ival = ntohl(*((uint32_t *) iptr)); - - /* - * The binary representation of TEXT is, well, text, and since - * libpq was nice enough to append a zero byte to it, it'll work - * just fine as a C string. - * - * The binary representation of BYTEA is a bunch of bytes, which - * could include embedded nulls so we have to pay attention to - * field length. - */ - blen = PQgetlength(res, i, b_fnum); - - printf("tuple %d: got\n", i); - printf(" i = (%d bytes) %d\n", - PQgetlength(res, i, i_fnum), ival); - printf(" t = (%d bytes) '%s'\n", - PQgetlength(res, i, t_fnum), tptr); - printf(" b = (%d bytes) ", blen); - for (j = 0; j < blen; j++) - printf("\\%03o", bptr[j]); - printf("\n\n"); - } - - PQclear(res); - - /* close the connection to the database and cleanup */ - PQfinish(conn); - - return 0; + const char *conninfo; + PGconn *conn; + PGresult *res; + const char *paramValues[1]; + int i, + j; + int i_fnum, + t_fnum, + b_fnum; + + /* + * If the user supplies a parameter on the command line, use it as + * the conninfo string; otherwise default to setting dbname=template1 + * and using environment variables or defaults for all other connection + * parameters. + */ + if (argc > 1) + conninfo = argv[1]; + else + conninfo = "dbname = template1"; + + /* Make a connection to the database */ + conn = PQconnectdb(conninfo); + + /* Check to see that the backend connection was successfully made */ + if (PQstatus(conn) != CONNECTION_OK) + { + fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn)); + fprintf(stderr, "%s", PQerrorMessage(conn)); + exit_nicely(conn); + } + + /* + * The point of this program is to illustrate use of PQexecParams() + * with out-of-line parameters, as well as binary transmission of + * results. By using out-of-line parameters we can avoid a lot of + * tedious mucking about with quoting and escaping. Notice how we + * don't have to do anything special with the quote mark in the + * parameter value. + */ + + /* Here is our out-of-line parameter value */ + paramValues[0] = "joe's place"; + + res = PQexecParams(conn, + "SELECT * FROM test1 WHERE t = $1", + 1, /* one param */ + NULL, /* let the backend deduce param type */ + paramValues, + NULL, /* don't need param lengths since text */ + NULL, /* default to all text params */ + 1); /* ask for binary results */ + + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn)); + PQclear(res); + exit_nicely(conn); + } + + /* Use PQfnumber to avoid assumptions about field order in result */ + i_fnum = PQfnumber(res, "i"); + t_fnum = PQfnumber(res, "t"); + b_fnum = PQfnumber(res, "b"); + + for (i = 0; i < PQntuples(res); i++) + { + char *iptr; + char *tptr; + char *bptr; + int blen; + int ival; + + /* Get the field values (we ignore possibility they are null!) */ + iptr = PQgetvalue(res, i, i_fnum); + tptr = PQgetvalue(res, i, t_fnum); + bptr = PQgetvalue(res, i, b_fnum); + + /* + * The binary representation of INT4 is in network byte order, + * which we'd better coerce to the local byte order. + */ + ival = ntohl(*((uint32_t *) iptr)); + + /* + * The binary representation of TEXT is, well, text, and since + * libpq was nice enough to append a zero byte to it, it'll work + * just fine as a C string. + * + * The binary representation of BYTEA is a bunch of bytes, which + * could include embedded nulls so we have to pay attention to + * field length. + */ + blen = PQgetlength(res, i, b_fnum); + + printf("tuple %d: got\n", i); + printf(" i = (%d bytes) %d\n", + PQgetlength(res, i, i_fnum), ival); + printf(" t = (%d bytes) '%s'\n", + PQgetlength(res, i, t_fnum), tptr); + printf(" b = (%d bytes) ", blen); + for (j = 0; j < blen; j++) + printf("\\%03o", bptr[j]); + printf("\n\n"); + } + + PQclear(res); + + /* close the connection to the database and cleanup */ + PQfinish(conn); + + return 0; } </programlisting> </example> diff --git a/doc/src/sgml/lobj.sgml b/doc/src/sgml/lobj.sgml index 019c715c25f..c41c7571a61 100644 --- a/doc/src/sgml/lobj.sgml +++ b/doc/src/sgml/lobj.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.29 2003/06/21 21:51:33 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.29.2.1 2003/09/07 04:36:42 momjian Exp $ --> <chapter id="largeObjects"> @@ -113,6 +113,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.29 2003/06/21 21:51:33 tgl Ex <synopsis> Oid lo_creat(PGconn *conn, int mode); </synopsis> + <indexterm><primary>lo_creat</></> creates a new large object. <replaceable class="parameter">mode</replaceable> is a bit mask describing several different attributes of the new @@ -143,7 +144,8 @@ inv_oid = lo_creat(INV_READ|INV_WRITE); <synopsis> Oid lo_import(PGconn *conn, const char *filename); </synopsis> - <replaceable class="parameter">filename</replaceable> + <indexterm><primary>lo_import</></> + <replaceable class="parameter">filename</replaceable> specifies the operating system name of the file to be imported as a large object. The return value is the OID that was assigned to the new large object. @@ -159,6 +161,7 @@ Oid lo_import(PGconn *conn, const char *filename); <synopsis> int lo_export(PGconn *conn, Oid lobjId, const char *filename); </synopsis> + <indexterm><primary>lo_export</></> The <parameter>lobjId</parameter> argument specifies the OID of the large object to export and the <parameter>filename</parameter> argument specifies the operating system name name of the file. @@ -173,6 +176,7 @@ int lo_export(PGconn *conn, Oid lobjId, const char *filename); <synopsis> int lo_open(PGconn *conn, Oid lobjId, int mode); </synopsis> + <indexterm><primary>lo_open</></> The <parameter>lobjId</parameter> argument specifies the OID of the large object to open. The <parameter>mode</parameter> bits control whether the object is opened for reading (<symbol>INV_READ</>), writing (<symbol>INV_WRITE</symbol>), or @@ -194,10 +198,13 @@ int lo_open(PGconn *conn, Oid lobjId, int mode); <synopsis> int lo_write(PGconn *conn, int fd, const char *buf, size_t len); </synopsis> - writes <parameter>len</parameter> bytes from <parameter>buf</parameter> to large object <parameter>fd</>. The <parameter>fd</parameter> - argument must have been returned by a previous <function>lo_open</function>. - The number of bytes actually written is returned. In - the event of an error, the return value is negative. + <indexterm><primary>lo_write</></> writes + <parameter>len</parameter> bytes from <parameter>buf</parameter> + to large object <parameter>fd</>. The <parameter>fd</parameter> + argument must have been returned by a previous + <function>lo_open</function>. The number of bytes actually + written is returned. In the event of an error, the return value + is negative. </para> </sect2> @@ -209,10 +216,13 @@ int lo_write(PGconn *conn, int fd, const char *buf, size_t len); <synopsis> int lo_read(PGconn *conn, int fd, char *buf, size_t len); </synopsis> - reads <parameter>len</parameter> bytes from large object <parameter>fd</parameter> into <parameter>buf</parameter>. The <parameter>fd</parameter> - argument must have been returned by a previous <function>lo_open</function>. - The number of bytes actually read is returned. In - the event of an error, the return value is negative. + <indexterm><primary>lo_read</></> reads + <parameter>len</parameter> bytes from large object + <parameter>fd</parameter> into <parameter>buf</parameter>. The + <parameter>fd</parameter> argument must have been returned by a + previous <function>lo_open</function>. The number of bytes + actually read is returned. In the event of an error, the return + value is negative. </para> </sect2> @@ -225,10 +235,14 @@ int lo_read(PGconn *conn, int fd, char *buf, size_t len); <synopsis> int lo_lseek(PGconn *conn, int fd, int offset, int whence); </synopsis> - This function moves the current location pointer for the - large object described by <parameter>fd</> to the new location specified - by <parameter>offset</>. The valid values for <parameter>whence</> are - <symbol>SEEK_SET</> (seek from object start), <symbol>SEEK_CUR</> (seek from current position), and <symbol>SEEK_END</> (seek from object end). The return value is the new location pointer. + <indexterm><primary>lo_lseek</></> This function moves the + current location pointer for the large object described by + <parameter>fd</> to the new location specified by + <parameter>offset</>. The valid values for <parameter>whence</> + are <symbol>SEEK_SET</> (seek from object start), + <symbol>SEEK_CUR</> (seek from current position), and + <symbol>SEEK_END</> (seek from object end). The return value is + the new location pointer. </para> </sect2> @@ -241,7 +255,8 @@ int lo_lseek(PGconn *conn, int fd, int offset, int whence); <synopsis> int lo_tell(PGconn *conn, int fd); </synopsis> - If there is an error, the return value is negative. + <indexterm><primary>lo_tell</></> If there is an error, the + return value is negative. </para> </sect2> @@ -253,9 +268,10 @@ int lo_tell(PGconn *conn, int fd); <synopsis> int lo_close(PGconn *conn, int fd); </synopsis> - where <parameter>fd</> is a large object descriptor returned by - <function>lo_open</function>. On success, <function>lo_close</function> - returns zero. On error, the return value is negative. + <indexterm><primary>lo_close</></> where <parameter>fd</> is a + large object descriptor returned by <function>lo_open</function>. + On success, <function>lo_close</function> returns zero. On + error, the return value is negative. </para> <para> @@ -272,8 +288,10 @@ int lo_close(PGconn *conn, int fd); <synopsis> int lo_unlink(PGconn *conn, Oid lobjId); </synopsis> - The <parameter>lobjId</parameter> argument specifies the OID of the large - object to remove. In the event of an error, the return value is negative. + <indexterm><primary>lo_unlink</></> The + <parameter>lobjId</parameter> argument specifies the OID of the + large object to remove. In the event of an error, the return + value is negative. </para> </sect2> @@ -284,11 +302,13 @@ int lo_unlink(PGconn *conn, Oid lobjId); <title>Server-side Functions</title> <para> - There are two built-in server-side functions, <function>lo_import</function> - and <function>lo_export</function>, for large object access, which are available for use - in <acronym>SQL</acronym> - commands. - Here is an example of their use: + There are two built-in server-side functions, + <function>lo_import</function><indexterm><primary>lo_import</></> + and + <function>lo_export</function>,<indexterm><primary>lo_export</></> + for large object access, which are available for use in + <acronym>SQL</acronym> commands. Here is an example of their + use: <programlisting> CREATE TABLE image ( name text, diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml index 122137ad2b9..4404c5e929e 100644 --- a/doc/src/sgml/maintenance.sgml +++ b/doc/src/sgml/maintenance.sgml @@ -1,10 +1,14 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/maintenance.sgml,v 1.23 2003/06/18 12:19:11 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/maintenance.sgml,v 1.23.2.1 2003/09/07 04:36:42 momjian Exp $ --> <chapter id="maintenance"> <title>Routine Database Maintenance Tasks</title> + <indexterm zone="maintenance"> + <primary>maintenance</primary> + </indexterm> + <para> There are a few routine maintenance chores that must be performed on a regular basis to keep a <productname>PostgreSQL</productname> @@ -158,6 +162,15 @@ $Header: /cvsroot/pgsql/doc/src/sgml/maintenance.sgml,v 1.23 2003/06/18 12:19:11 <sect2 id="vacuum-for-statistics"> <title>Updating planner statistics</title> + <indexterm zone="vacuum-for-statistics"> + <primary>statistics</primary> + <secondary>of the planner</secondary> + </indexterm> + + <indexterm zone="vacuum-for-statistics"> + <primary>ANALYZE</primary> + </indexterm> + <para> The <productname>PostgreSQL</productname> query planner relies on statistical information about the contents of tables in order to @@ -396,7 +409,8 @@ VACUUM <title>Log File Maintenance</title> <indexterm zone="logfile-maintenance"> - <primary>log files</primary> + <primary>server log</primary> + <secondary>log file maintenance</secondary> </indexterm> <para> diff --git a/doc/src/sgml/manage-ag.sgml b/doc/src/sgml/manage-ag.sgml index dd0b390230c..c55f78f5cb7 100644 --- a/doc/src/sgml/manage-ag.sgml +++ b/doc/src/sgml/manage-ag.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/manage-ag.sgml,v 2.27 2003/03/25 16:15:37 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/manage-ag.sgml,v 2.27.2.1 2003/09/07 04:36:42 momjian Exp $ --> <chapter id="managing-databases"> @@ -19,6 +19,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/manage-ag.sgml,v 2.27 2003/03/25 16:15:37 p <sect1 id="manage-ag-overview"> <title>Overview</title> + <indexterm zone="manage-ag-overview"> + <primary>schema</primary> + </indexterm> + <para> A database is a named collection of <acronym>SQL</acronym> objects (<quote>database objects</quote>). Generally, every database @@ -70,8 +74,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/manage-ag.sgml,v 2.27 2003/03/25 16:15:37 p </para> <para> - Databases are created with the SQL command - <command>CREATE DATABASE</command>: + Databases are created with the SQL command <command>CREATE + DATABASE</command>:<indexterm><primary>CREATE DATABASE</></> <synopsis> CREATE DATABASE <replaceable>name</>; </synopsis> @@ -93,9 +97,10 @@ CREATE DATABASE <replaceable>name</>; question remains how the <emphasis>first</> database at any given site can be created. The first database is always created by the <command>initdb</> command when the data storage area is - initialized. (See <xref linkend="creating-cluster">.) - This database is called <literal>template1</>. So to create the - first <quote>real</> database you can connect to + initialized. (See <xref linkend="creating-cluster">.) This + database is called + <literal>template1</>.<indexterm><primary>template1</></> So to + create the first <quote>real</> database you can connect to <literal>template1</>. </para> @@ -112,7 +117,7 @@ CREATE DATABASE <replaceable>name</>; <para> As an extra convenience, there is also a program that you can execute from the shell to create new databases, - <command>createdb</>. + <command>createdb</>.<indexterm><primary>createdb</></> <synopsis> createdb <replaceable class="parameter">dbname</replaceable> @@ -157,31 +162,33 @@ createdb -O <replaceable>username</> <replaceable>dbname</> <para> <command>CREATE DATABASE</> actually works by copying an existing database. By default, it copies the standard system database named - <literal>template1</>. Thus that database is the <quote>template</> - from which new databases are made. If you add objects to - <literal>template1</>, these objects + <literal>template1</>.<indexterm><primary>template1</></> Thus that + database is the <quote>template</> from which new databases are + made. If you add objects to <literal>template1</>, these objects will be copied into subsequently created user databases. This behavior allows site-local modifications to the standard set of objects in databases. For example, if you install the procedural language <application>PL/pgSQL</> in <literal>template1</>, it will - automatically be available in user databases without any extra action - being taken when those databases are made. + automatically be available in user databases without any extra + action being taken when those databases are made. </para> <para> - There is a second standard system database named <literal>template0</>. - This database contains the same data as the initial contents of - <literal>template1</>, that is, only the standard objects predefined by - your version of <productname>PostgreSQL</productname>. - <literal>template0</> should never be changed - after <command>initdb</>. By instructing <command>CREATE DATABASE</> to - copy <literal>template0</> instead of <literal>template1</>, you can - create a <quote>virgin</> user database that contains none of the - site-local additions in <literal>template1</>. This is particularly - handy when restoring a <literal>pg_dump</> dump: the dump script should - be restored in a virgin database to ensure that one recreates the - correct contents of the dumped database, without any conflicts with - additions that may now be present in <literal>template1</>. + There is a second standard system database named + <literal>template0</>.<indexterm><primary>template0</></> This + database contains the same data as the initial contents of + <literal>template1</>, that is, only the standard objects + predefined by your version of + <productname>PostgreSQL</productname>. <literal>template0</> + should never be changed after <command>initdb</>. By instructing + <command>CREATE DATABASE</> to copy <literal>template0</> instead + of <literal>template1</>, you can create a <quote>virgin</> user + database that contains none of the site-local additions in + <literal>template1</>. This is particularly handy when restoring a + <literal>pg_dump</> dump: the dump script should be restored in a + virgin database to ensure that one recreates the correct contents + of the dumped database, without any conflicts with additions that + may now be present in <literal>template1</>. </para> <para> @@ -214,7 +221,7 @@ createdb -T template0 <replaceable>dbname</> </para> <para> - Two useful flags exist in <literal>pg_database</literal> for each + Two useful flags exist in <literal>pg_database</literal><indexterm><primary>pg_database</></> for each database: the columns <literal>datistemplate</literal> and <literal>datallowconn</literal>. <literal>datistemplate</literal> may be set to indicate that a database is intended as a template for @@ -382,7 +389,8 @@ gmake CPPFLAGS=-DALLOW_ABSOLUTE_DBPATHS all <title>Destroying a Database</title> <para> - Databases are destroyed with the command <command>DROP DATABASE</command>: + Databases are destroyed with the command <command>DROP + DATABASE</command>:<indexterm><primary>DROP DATABASE</></> <synopsis> DROP DATABASE <replaceable>name</>; </synopsis> @@ -403,7 +411,8 @@ DROP DATABASE <replaceable>name</>; </para> <para> - For convenience, there is also a shell program to drop databases: + For convenience, there is also a shell program to drop + databases:<indexterm><primary>dropdb</></> <synopsis> dropdb <replaceable class="parameter">dbname</replaceable> </synopsis> diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 90a77d0a2c8..03ca970c768 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -1,10 +1,20 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/monitoring.sgml,v 1.20 2003/04/04 03:03:53 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/monitoring.sgml,v 1.20.2.1 2003/09/07 04:36:42 momjian Exp $ --> <chapter id="monitoring"> <title>Monitoring Database Activity</title> + <indexterm zone="monitoring"> + <primary>monitoring</primary> + <secondary>database activity</secondary> + </indexterm> + + <indexterm zone="monitoring"> + <primary>database activity</primary> + <secondary>monitoring</secondary> + </indexterm> + <para> A database administrator frequently wonders, <quote>What is the system doing right now?</quote> @@ -589,6 +599,11 @@ SELECT pg_stat_get_backend_pid(s.backendid) AS procpid, <sect1 id="monitoring-locks"> <title>Viewing Locks</title> + <indexterm zone="monitoring-locks"> + <primary>lock</primary> + <secondary>monitoring</secondary> + </indexterm> + <para> Another useful tool for monitoring database activity is the <literal>pg_locks</literal> system table. It allows the diff --git a/doc/src/sgml/mvcc.sgml b/doc/src/sgml/mvcc.sgml index b5cda133ef2..077b0c3219c 100644 --- a/doc/src/sgml/mvcc.sgml +++ b/doc/src/sgml/mvcc.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.35 2003/03/25 16:15:37 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.35.2.1 2003/09/07 04:36:42 momjian Exp $ --> <chapter id="mvcc"> @@ -22,6 +22,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.35 2003/03/25 16:15:37 petere <sect1 id="mvcc-intro"> <title>Introduction</title> + <indexterm> + <primary>MVCC</primary> + </indexterm> + <para> Unlike traditional database systems which use locks for concurrency control, <productname>PostgreSQL</productname> @@ -57,6 +61,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.35 2003/03/25 16:15:37 petere <sect1 id="transaction-iso"> <title>Transaction Isolation</title> + <indexterm> + <primary>transaction isolation</primary> + </indexterm> + <para> The <acronym>SQL</acronym> standard defines four levels of transaction isolation in terms of three phenomena that must be @@ -108,7 +116,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.35 2003/03/25 16:15:37 petere <para> <indexterm> - <primary>isolation levels</primary> + <primary>transaction isolation level</primary> </indexterm> The four transaction isolation levels and the corresponding behaviors are described in <xref linkend="mvcc-isolevel-table">. @@ -206,7 +214,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.35 2003/03/25 16:15:37 petere <title>Read Committed Isolation Level</title> <indexterm> - <primary>isolation levels</primary> + <primary>transaction isolation level</primary> <secondary>read committed</secondary> </indexterm> @@ -292,7 +300,7 @@ COMMIT; <title>Serializable Isolation Level</title> <indexterm> - <primary>isolation levels</primary> + <primary>transaction isolation level</primary> <secondary>serializable</secondary> </indexterm> @@ -376,7 +384,7 @@ ERROR: Can't serialize access due to concurrent update <title>Explicit Locking</title> <indexterm> - <primary>locking</primary> + <primary>lock</primary> </indexterm> <para> @@ -394,6 +402,10 @@ ERROR: Can't serialize access due to concurrent update <sect2 id="locking-tables"> <title>Table-Level Locks</title> + <indexterm zone="locking-tables"> + <primary>LOCK</primary> + </indexterm> + <para> The list below shows the available lock modes and the contexts in which they are used automatically by @@ -644,6 +656,10 @@ ERROR: Can't serialize access due to concurrent update <sect2 id="locking-deadlocks"> <title>Deadlocks</title> + <indexterm zone="locking-deadlocks"> + <primary>deadlock</primary> + </indexterm> + <para> The use of explicit locking can increase the likelyhood of <firstterm>deadlocks</>, wherein two (or more) transactions each @@ -813,6 +829,11 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222; <sect1 id="locking-indexes"> <title>Locking and Indexes</title> + <indexterm zone="locking-indexes"> + <primary>index</primary> + <secondary>locks</secondary> + </indexterm> + <para> Though <productname>PostgreSQL</productname> provides nonblocking read/write access to table diff --git a/doc/src/sgml/perform.sgml b/doc/src/sgml/perform.sgml index 0de183a01e0..fa887a406e4 100644 --- a/doc/src/sgml/perform.sgml +++ b/doc/src/sgml/perform.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.30 2003/06/25 02:07:33 momjian Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.30.2.1 2003/09/07 04:36:42 momjian Exp $ --> <chapter id="performance-tips"> @@ -15,6 +15,14 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.30 2003/06/25 02:07:33 mom <sect1 id="using-explain"> <title>Using <command>EXPLAIN</command></title> + <indexterm zone="using-explain"> + <primary>EXPLAIN</primary> + </indexterm> + + <indexterm zone="using-explain"> + <primary>query plan</primary> + </indexterm> + <para> <productname>PostgreSQL</productname> devises a <firstterm>query plan</firstterm> for each query it is given. Choosing the right @@ -336,6 +344,11 @@ EXPLAIN ANALYZE SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 50 AND t1 <sect1 id="planner-stats"> <title>Statistics Used by the Planner</title> + <indexterm zone="planner-stats"> + <primary>statistics</primary> + <secondary>of the planner</secondary> + </indexterm> + <para> As we saw in the previous section, the query planner needs to estimate the number of rows retrieved by a query in order to make good choices @@ -381,6 +394,10 @@ SELECT relname, relkind, reltuples, relpages FROM pg_class WHERE relname LIKE 't since it does not read every row of the table. </para> + <indexterm> + <primary>pg_statistic</primary> + </indexterm> + <para> Most queries retrieve only a fraction of the rows in a table, due to having <literal>WHERE</> clauses that restrict the rows to be examined. @@ -393,6 +410,10 @@ SELECT relname, relkind, reltuples, relpages FROM pg_class WHERE relname LIKE 't and are always approximate even when freshly updated. </para> + <indexterm> + <primary>pg_stats</primary> + </indexterm> + <para> Rather than look at <structname>pg_statistic</structname> directly, it's better to look at its view <structname>pg_stats</structname> @@ -538,6 +559,11 @@ SELECT attname, n_distinct, most_common_vals FROM pg_stats WHERE tablename = 'ro <sect1 id="explicit-joins"> <title>Controlling the Planner with Explicit <literal>JOIN</> Clauses</title> + <indexterm zone="explicit-joins"> + <primary>join</primary> + <secondary>controlling the order</secondary> + </indexterm> + <para> It is possible to control the query planner to some extent by using the explicit <literal>JOIN</> @@ -700,6 +726,10 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse; <sect2 id="disable-autocommit"> <title>Disable Autocommit</title> + <indexterm zone="disable-autocommit"> + <primary>autocommit</primary> + </indexterm> + <para> Turn off autocommit and just do one commit at the end. (In plain SQL, this means issuing <command>BEGIN</command> diff --git a/doc/src/sgml/plperl.sgml b/doc/src/sgml/plperl.sgml index 02d38bc5340..55eb99a439a 100644 --- a/doc/src/sgml/plperl.sgml +++ b/doc/src/sgml/plperl.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/plperl.sgml,v 2.19 2003/04/07 01:29:25 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/plperl.sgml,v 2.19.2.1 2003/09/07 04:36:42 momjian Exp $ --> <chapter id="plperl"> @@ -73,11 +73,12 @@ CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS ' </para> <para> - If an SQL null value is passed to a function, the argument value - will appear as <quote>undefined</> in Perl. The above function - definition will not behave very nicely with null inputs (in fact, - it will act as though they are zeroes). We could add - <literal>STRICT</> to the function definition to make + If an SQL null value<indexterm><primary>null value</><secondary + sortas="PL/Perl">in PL/Perl</></indexterm> is passed to a function, + the argument value will appear as <quote>undefined</> in Perl. The + above function definition will not behave very nicely with null + inputs (in fact, it will act as though they are zeroes). We could + add <literal>STRICT</> to the function definition to make <productname>PostgreSQL</productname> do something more reasonable: if a null value is passed, the function will not be called at all, but will just return a null result automatically. Alternatively, @@ -170,7 +171,7 @@ SELECT name, empcomp(employee) FROM employee; mirror sites</ulink>). This module makes available a <acronym>DBI</>-compliant database-handle named <varname>$pg_dbh</varname> that can be used to perform queries - with normal <acronym>DBI</> syntax. + with normal <acronym>DBI</> syntax.<indexterm><primary>DBI</></indexterm> </para> <para> @@ -180,7 +181,7 @@ SELECT name, empcomp(employee) FROM employee; <varlistentry> <indexterm> <primary>elog</primary> - <secondary>PL/Perl</secondary> + <secondary>in PL/Perl</secondary> </indexterm> <term><function>elog</> <replaceable>level</replaceable>, <replaceable>msg</replaceable></term> @@ -202,6 +203,11 @@ SELECT name, empcomp(employee) FROM employee; <sect1 id="plperl-trusted"> <title>Trusted and Untrusted PL/Perl</title> + <indexterm zone="plperl-trusted"> + <primary>trusted</primary> + <secondary>PL/Perl</secondary> + </indexterm> + <para> Normally, PL/Perl is installed as a <quote>trusted</> programming language named <literal>plperl</>. In this setup, certain Perl @@ -231,13 +237,14 @@ CREATE FUNCTION badfunc() RETURNS integer AS ' <para> Sometimes it is desirable to write Perl functions that are not - restricted. For example, one might want a Perl function that - sends mail. To handle these cases, PL/Perl can also be installed - as an <quote>untrusted</> language (usually called - <application>PL/PerlU</application>). In this case the full Perl language is - available. If the <command>createlang</command> program is used to - install the language, the language name <literal>plperlu</literal> - will select the untrusted PL/Perl variant. + restricted. For example, one might want a Perl function that sends + mail. To handle these cases, PL/Perl can also be installed as an + <quote>untrusted</> language (usually called + <application>PL/PerlU</application><indexterm><primary>PL/PerlU</></indexterm>). + In this case the full Perl language is available. If the + <command>createlang</command> program is used to install the + language, the language name <literal>plperlu</literal> will select + the untrusted PL/Perl variant. </para> <para> @@ -272,7 +279,9 @@ CREATE FUNCTION badfunc() RETURNS integer AS ' <listitem> <para> - PL/Perl cannot be used to write trigger functions. + PL/Perl cannot be used to write trigger + functions.<indexterm><primary>trigger</><secondary>in + PL/Perl</></indexterm> </para> </listitem> diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index b313860ea0c..c616cec5cdc 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.20 2003/08/09 22:50:22 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.20.2.1 2003/09/07 04:36:42 momjian Exp $ --> <chapter id="plpgsql"> @@ -63,20 +63,22 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.20 2003/08/09 22:50:22 tgl </para> <para> - As each expression and <acronym>SQL</acronym> command is first used - in the function, the <application>PL/pgSQL</> interpreter creates - a prepared execution plan (using the <acronym>SPI</acronym> - manager's <function>SPI_prepare</function> and - <function>SPI_saveplan</function> functions). Subsequent visits - to that expression or command reuse the prepared plan. Thus, a - function with conditional code that contains many statements for - which execution plans might be required will only prepare and save - those plans that are really used during the lifetime of the - database connection. This can substantially reduce the total - amount of time required to parse, and generate execution plans for the - statements in a <application>PL/pgSQL</> function. A disadvantage is - that errors in a specific expression or command may not be detected - until that part of the function is reached in execution. + As each expression and <acronym>SQL</acronym> command is first + used in the function, the <application>PL/pgSQL</> interpreter + creates a prepared execution plan (using the + <acronym>SPI</acronym> manager's <function>SPI_prepare</function> + and <function>SPI_saveplan</function> + functions).<indexterm><primary>preparing a query</><secondary>in + PL/pgSQL</></> Subsequent visits to that expression or command + reuse the prepared plan. Thus, a function with conditional code + that contains many statements for which execution plans might be + required will only prepare and save those plans that are really + used during the lifetime of the database connection. This can + substantially reduce the total amount of time required to parse, + and generate execution plans for the statements in a + <application>PL/pgSQL</> function. A disadvantage is that errors + in a specific expression or command may not be detected until that + part of the function is reached in execution. </para> <para> @@ -196,7 +198,7 @@ END; and return the <quote>polymorphic</> types <type>anyelement</type> and <type>anyarray</type>. The actual datatypes handled by a polymorphic function can vary from call to - call, as discussed in <xref linkend="types-polymorphic">. + call, as discussed in <xref linkend="extend-types-polymorphic">. An example is shown in <xref linkend="plpgsql-declaration-aliases">. </para> @@ -563,7 +565,7 @@ END; or <type>anyarray</type>), a special parameter <literal>$0</literal> is created. Its datatype is the actual return type of the function, as deduced from the actual input types (see <xref - linkend="types-polymorphic">). + linkend="extend-types-polymorphic">). This allows the function to access its actual return type as shown in <xref linkend="plpgsql-declaration-type">. <literal>$0</literal> is initialized to NULL and can be modified by @@ -903,6 +905,11 @@ tax := subtotal * 0.06; <sect2 id="plpgsql-select-into"> <title><command>SELECT INTO</command></title> + <indexterm zone="plpgsql-select-into"> + <primary>SELECT INTO</primary> + <secondary>in PL/pgSQL</secondary> + </indexterm> + <para> The result of a <command>SELECT</command> command yielding multiple columns (but only one row) can be assigned to a record variable, row-type @@ -1097,14 +1104,16 @@ EXECUTE ''UPDATE tbl SET '' <para> This example shows use of the functions <function>quote_ident(<type>text</type>)</function> and - <function>quote_literal(<type>text</type>)</function>. - Variables containing column and table identifiers should be - passed to function <function>quote_ident</function>. - Variables containing values that should be literal strings in the - constructed command should be passed to - <function>quote_literal</function>. Both take the - appropriate steps to return the input text enclosed in double - or single quotes respectively, with any embedded special characters + <function>quote_literal(<type>text</type>)</function>.<indexterm><primary>quote_ident</><secondary>use + in + PL/pgSQL</></indexterm><indexterm><primary>quote_literal</><secondary>use + in PL/pgSQL</></indexterm> Variables containing column and table + identifiers should be passed to function + <function>quote_ident</function>. Variables containing values + that should be literal strings in the constructed command should + be passed to <function>quote_literal</function>. Both take the + appropriate steps to return the input text enclosed in double or + single quotes respectively, with any embedded special characters properly escaped. </para> @@ -1517,6 +1526,11 @@ END IF; <sect2 id="plpgsql-control-structures-loops"> <title>Simple Loops</title> + <indexterm zone="plpgsql-control-structures-loops"> + <primary>loop</primary> + <secondary>in PL/pgSQL</secondary> + </indexterm> + <para> With the <literal>LOOP</>, <literal>EXIT</>, <literal>WHILE</>, and <literal>FOR</> statements, you can arrange for your @@ -1655,6 +1669,11 @@ FOR i IN REVERSE 10..1 LOOP END LOOP; </programlisting> </para> + + <para> + If the lower bound is greater than the upper bound, the loop body is not + executed at all, but no error is raised. + </para> </sect3> </sect2> @@ -1734,6 +1753,11 @@ END LOOP; <sect1 id="plpgsql-cursors"> <title>Cursors</title> + <indexterm zone="plpgsql-cursors"> + <primary>cursor</primary> + <secondary>in PL/pgSQL</secondary> + </indexterm> + <para> Rather than executing a whole query at once, it is possible to set up a <firstterm>cursor</> that encapsulates the query, and then read @@ -2096,6 +2120,11 @@ RAISE EXCEPTION ''Inexistent ID --> %'', user_id; <sect1 id="plpgsql-trigger"> <title>Trigger Procedures</title> + <indexterm zone="plpgsql-trigger"> + <primary>trigger</primary> + <secondary>in PL/pgSQL</secondary> + </indexterm> + <para> <application>PL/pgSQL</application> can be used to define trigger procedures. A trigger procedure is created with the @@ -2302,10 +2331,12 @@ CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp <indexterm zone="plpgsql-porting"> <primary>Oracle</primary> + <secondary>porting from PL/SQL to PL/pgSQL</secondary> </indexterm> <indexterm zone="plpgsql-porting"> - <primary>PL/SQL</primary> + <primary>PL/SQL (Oracle)</primary> + <secondary>porting to PL/pgSQL</secondary> </indexterm> <para> @@ -2546,7 +2577,8 @@ END; with <literal>OUT</> parameters and string manipulation. <productname>PostgreSQL</> does not have an <function>instr</function> function, but you can work around it - using a combination of other functions. In <xref + using a combination of other + functions.<indexterm><primary>instr</></indexterm> In <xref linkend="plpgsql-porting-appendix"> there is a <application>PL/pgSQL</application> implementation of <function>instr</function> that you can use to make your porting diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml index 0a101384ee7..8d476a7a43a 100644 --- a/doc/src/sgml/plpython.sgml +++ b/doc/src/sgml/plpython.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/plpython.sgml,v 1.18 2003/07/01 13:52:29 tgl Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/plpython.sgml,v 1.18.2.1 2003/09/07 04:36:43 momjian Exp $ --> <chapter id="plpython"> <title>PL/Python - Python Procedural Language</title> @@ -68,9 +68,10 @@ def __plpython_procedure_myfunc_23456(): <para> If you do not provide a return value, Python returns the default - <symbol>None</symbol>. The - language module translates Python's <symbol>None</symbol> into the - SQL null value. + <symbol>None</symbol>. The language module translates Python's + <symbol>None</symbol> into the SQL null + value.<indexterm><primary>null value</><secondary + sortas="PL/Python">in PL/Python</></indexterm> </para> <para> @@ -87,7 +88,9 @@ def __plpython_procedure_myfunc_23456(): The global dictionary <varname>SD</varname> is available to store data between function calls. This variable is private static data. The global dictionary <varname>GD</varname> is public data, - available to all Python functions within a session. Use with care. + available to all Python functions within a session. Use with + care.<indexterm><primary>global data</><secondary>in + PL/Python</></indexterm> </para> <para> @@ -102,6 +105,11 @@ def __plpython_procedure_myfunc_23456(): <sect1 id="plpython-trigger"> <title>Trigger Functions</title> + <indexterm zone="plpython-trigger"> + <primary>trigger</primary> + <secondary>in PL/Python</secondary> + </indexterm> + <para> When a function is used in a trigger, the dictionary <literal>TD</literal> contains trigger-related values. The trigger @@ -146,7 +154,8 @@ def __plpython_procedure_myfunc_23456(): <literal>plpy.error("msg")</literal>, and <literal>plpy.fatal("msg")</literal>. They are mostly equivalent to calling <literal>elog(<replaceable>LEVEL</>, "msg")</literal> - from C code. <function>plpy.error</function> and + from C code.<indexterm><primary>elog</><secondary>in + PL/Python</></indexterm> <function>plpy.error</function> and <function>plpy.fatal</function> actually raise a Python exception which, if uncaught, causes the PL/Python module to call <literal>elog(ERROR, msg)</literal> when the function handler @@ -187,10 +196,11 @@ foo = rv[i]["my_column"] </para> <para> - The second function, <function>plpy.prepare</function>, prepares the - execution plan for a query. It is called with a query string and a - list of parameter types, if you have parameter references in the - query. For example: + <indexterm><primary>preparing a query</><secondary>in PL/Python</></indexterm> + The second function, <function>plpy.prepare</function>, prepares + the execution plan for a query. It is called with a query string + and a list of parameter types, if you have parameter references in + the query. For example: <programlisting> plan = plpy.prepare("SELECT last_name FROM my_users WHERE first_name = $1", [ "text" ]) </programlisting> @@ -235,7 +245,8 @@ CREATE FUNCTION usesavedplan() RETURNS trigger AS ' </para> </sect1> -<!-- NOT CURRENTLY SUPPORTED +<![IGNORE[ + <!-- NOT CURRENTLY SUPPORTED --> <sect1 id="plpython-trusted"> <title>Restricted Environment</title> @@ -259,6 +270,6 @@ CREATE FUNCTION usesavedplan() RETURNS trigger AS ' </para> </sect1> ---> +]]> </chapter> diff --git a/doc/src/sgml/pltcl.sgml b/doc/src/sgml/pltcl.sgml index d93f7f6517f..ebcf8bdfb8f 100644 --- a/doc/src/sgml/pltcl.sgml +++ b/doc/src/sgml/pltcl.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/pltcl.sgml,v 2.24 2003/06/22 16:17:00 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/pltcl.sgml,v 2.24.2.1 2003/09/07 04:36:43 momjian Exp $ --> <chapter id="pltcl"> @@ -190,6 +190,11 @@ CREATE FUNCTION overpaid(employee) RETURNS boolean AS ' <sect1 id="pltcl-global"> <title>Global Data in PL/Tcl</title> + <indexterm zone="pltcl-global"> + <primary>global data</primary> + <secondary>in PL/Tcl</secondary> + </indexterm> + <para> Sometimes it is useful to have some global data that is held between two @@ -298,8 +303,10 @@ spi_exec -array C "SELECT * FROM pg_class" { <term><function>spi_prepare</function> <replaceable>query</replaceable> <replaceable>typelist</replaceable></term> <listitem> <para> - Prepares and saves a query plan for later execution. The saved plan - will be retained for the life of the current session. + Prepares and saves a query plan for later execution. The + saved plan will be retained for the life of the current + session.<indexterm><primary>preparing a query</><secondary>in + PL/Tcl</></> </para> <para> The query may use parameters, that is, placeholders for @@ -437,7 +444,7 @@ SELECT 'doesn''t' AS ret <varlistentry> <indexterm> <primary>elog</primary> - <secondary>PL/Tcl</secondary> + <secondary>in PL/Tcl</secondary> </indexterm> <term><function>elog</> <replaceable>level</replaceable> <replaceable>msg</replaceable></term> <listitem> @@ -466,7 +473,7 @@ SELECT 'doesn''t' AS ret <title>Trigger Procedures in PL/Tcl</title> <indexterm> - <primary>triggers</primary> + <primary>trigger</primary> <secondary>in PL/Tcl</secondary> </indexterm> diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml index cca78b63977..2642b356214 100644 --- a/doc/src/sgml/postgres.sgml +++ b/doc/src/sgml/postgres.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.53 2003/06/22 16:16:44 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.53.2.1 2003/09/07 04:36:43 momjian Exp $ --> <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN" [ @@ -188,7 +188,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.53 2003/06/22 16:16:44 tg &libpgtcl; &ecpg; &jdbc; - &pygresql; &infoschema; </part> diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml index 1de14ddeb61..d949a57df56 100644 --- a/doc/src/sgml/protocol.sgml +++ b/doc/src/sgml/protocol.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.41 2003/08/14 20:09:31 tgl Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.41.2.1 2003/09/07 04:36:43 momjian Exp $ --> <chapter id="protocol"> <title>Frontend/Backend Protocol</title> @@ -1005,9 +1005,9 @@ ParameterStatus will be generated: they are <literal>server_version</> (a pseudo-parameter that cannot change after startup); - <literal>server_encoding</> (also not presently changeable after start); <literal>client_encoding</>, - <literal>is_superuser</>, and + <literal>is_superuser</>, + <literal>session_authorization</literal>, and <literal>DateStyle</>. This set might change in the future, or even become configurable. Accordingly, a frontend should simply ignore ParameterStatus for diff --git a/doc/src/sgml/queries.sgml b/doc/src/sgml/queries.sgml index d3ec786ac27..6ca1e023081 100644 --- a/doc/src/sgml/queries.sgml +++ b/doc/src/sgml/queries.sgml @@ -1,8 +1,16 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/queries.sgml,v 1.22 2003/08/14 23:13:27 tgl Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/queries.sgml,v 1.22.2.1 2003/09/07 04:36:43 momjian Exp $ --> <chapter id="queries"> <title>Queries</title> + <indexterm zone="queries"> + <primary>query</primary> + </indexterm> + + <indexterm zone="queries"> + <primary>SELECT</primary> + </indexterm> + <para> The previous chapters explained how to create tables, how to fill them with data, and how to manipulate that data. Now we finally @@ -73,6 +81,10 @@ SELECT random(); <sect1 id="queries-table-expressions"> <title>Table Expressions</title> + <indexterm zone="queries-table-expressions"> + <primary>table expression</primary> + </indexterm> + <para> A <firstterm>table expression</firstterm> computes a table. The table expression contains a <literal>FROM</> clause that is @@ -112,6 +124,10 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r overall table expression. </para> + <indexterm> + <primary>ONLY</primary> + </indexterm> + <para> When a table reference names a table that is the supertable of a table inheritance hierarchy, the table reference produces rows of @@ -125,7 +141,7 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r <title>Joined Tables</title> <indexterm zone="queries-join"> - <primary>joins</primary> + <primary>join</primary> </indexterm> <para> @@ -141,10 +157,14 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r <term>Cross join</term> <indexterm> - <primary>joins</primary> + <primary>join</primary> <secondary>cross</secondary> </indexterm> + <indexterm> + <primary>cross join</primary> + </indexterm> + <listitem> <synopsis> <replaceable>T1</replaceable> CROSS JOIN <replaceable>T2</replaceable> @@ -175,10 +195,14 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r <term>Qualified joins</term> <indexterm> - <primary>joins</primary> + <primary>join</primary> <secondary>outer</secondary> </indexterm> + <indexterm> + <primary>outer join</primary> + </indexterm> + <listitem> <synopsis> <replaceable>T1</replaceable> { <optional>INNER</optional> | { LEFT | RIGHT | FULL } <optional>OUTER</optional> } JOIN <replaceable>T2</replaceable> ON <replaceable>boolean_expression</replaceable> @@ -227,9 +251,12 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r <para> <indexterm> - <primary>joins</primary> + <primary>join</primary> <secondary>natural</secondary> </indexterm> + <indexterm> + <primary>natural join</primary> + </indexterm> Finally, <literal>NATURAL</> is a shorthand form of <literal>USING</>: it forms a <literal>USING</> list consisting of exactly those column names that appear in both @@ -256,10 +283,14 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r <term><literal>LEFT OUTER JOIN</></term> <indexterm> - <primary>joins</primary> + <primary>join</primary> <secondary>left</secondary> </indexterm> + <indexterm> + <primary>left join</primary> + </indexterm> + <listitem> <para> First, an inner join is performed. Then, for each row in @@ -274,6 +305,15 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r <varlistentry> <term><literal>RIGHT OUTER JOIN</></term> + <indexterm> + <primary>join</primary> + <secondary>right</secondary> + </indexterm> + + <indexterm> + <primary>right join</primary> + </indexterm> + <listitem> <para> First, an inner join is performed. Then, for each row in @@ -424,13 +464,13 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r <title>Table and Column Aliases</title> <indexterm zone="queries-table-aliases"> - <primary>label</primary> - <secondary>table</secondary> + <primary>alias</primary> + <secondary>in the FROM clause</secondary> </indexterm> <indexterm> - <primary>alias</primary> - <see>label</see> + <primary>label</primary> + <see>alias</see> </indexterm> <para> @@ -530,7 +570,7 @@ SELECT a.* FROM (my_table AS a JOIN your_table AS b ON ...) AS c <title>Subqueries</title> <indexterm zone="queries-subqueries"> - <primary>subqueries</primary> + <primary>subquery</primary> </indexterm> <para> @@ -556,6 +596,11 @@ FROM (SELECT * FROM table1) AS alias_name <indexterm zone="queries-tablefunctions"><primary>table function</></> + <indexterm zone="queries-tablefunctions"> + <primary>function</> + <secondary>in the FROM clause</> + </indexterm> + <para> Table functions are functions that produce a set of rows, made up of either base data types (scalar types) or composite data types @@ -628,7 +673,7 @@ SELECT * <title>The WHERE Clause</title> <indexterm zone="queries-where"> - <primary>where</primary> + <primary>WHERE</primary> </indexterm> <para> @@ -716,7 +761,11 @@ SELECT ... FROM fdt WHERE EXISTS (SELECT c1 FROM t2 WHERE c2 > fdt.c1) <title>The GROUP BY and HAVING Clauses</title> <indexterm zone="queries-group"> - <primary>group</primary> + <primary>GROUP BY</primary> + </indexterm> + + <indexterm zone="queries-group"> + <primary>grouping</primary> </indexterm> <para> @@ -827,6 +876,10 @@ SELECT product_id, p.name, (sum(s.units) * p.price) AS sales column names is also allowed. </para> + <indexterm> + <primary>HAVING</primary> + </indexterm> + <para> If a table has been grouped using a <literal>GROUP BY</literal> clause, but then only certain groups are of interest, the @@ -884,7 +937,7 @@ SELECT product_id, p.name, (sum(s.units) * (p.price - p.cost)) AS profit <title>Select Lists</title> <indexterm> - <primary>select</primary> + <primary>SELECT</primary> <secondary>select list</secondary> </indexterm> @@ -901,6 +954,10 @@ SELECT product_id, p.name, (sum(s.units) * (p.price - p.cost)) AS profit <sect2 id="queries-select-list-items"> <title>Select-List Items</title> + <indexterm> + <primary>*</primary> + </indexterm> + <para> The simplest kind of select list is <literal>*</literal> which emits all columns that the table expression produces. Otherwise, @@ -944,8 +1001,8 @@ SELECT tbl1.a, tbl2.a, tbl1.b FROM ... <title>Column Labels</title> <indexterm zone="queries-column-labels"> - <primary>label</primary> - <secondary>column</secondary> + <primary>alias</primary> + <secondary>in the select list</secondary> </indexterm> <para> @@ -981,7 +1038,11 @@ SELECT a AS value, b + c AS sum FROM ... <title>DISTINCT</title> <indexterm zone="queries-distinct"> - <primary>distinct</primary> + <primary>DISTINCT</primary> + </indexterm> + + <indexterm zone="queries-distinct"> + <primary>duplicates</primary> </indexterm> <para> @@ -997,6 +1058,8 @@ SELECT DISTINCT <replaceable>select_list</replaceable> ... </para> <para> + <indexterm><primary>null value</><secondary sortas="DISTINCT">in + DISTINCT</></indexterm> Obviously, two rows are considered distinct if they differ in at least one column value. Null values are considered equal in this comparison. @@ -1035,13 +1098,25 @@ SELECT DISTINCT ON (<replaceable>expression</replaceable> <optional>, <replaceab <title>Combining Queries</title> <indexterm zone="queries-union"> - <primary>union</primary> + <primary>UNION</primary> + </indexterm> + <indexterm zone="queries-union"> + <primary>INTERSECT</primary> + </indexterm> + <indexterm zone="queries-union"> + <primary>EXCEPT</primary> + </indexterm> + <indexterm zone="queries-union"> + <primary>set union</primary> + </indexterm> + <indexterm zone="queries-union"> + <primary>set intersection</primary> </indexterm> <indexterm zone="queries-union"> - <primary>intersection</primary> + <primary>set difference</primary> </indexterm> <indexterm zone="queries-union"> - <primary>except</primary> + <primary>set operation</primary> </indexterm> <para> @@ -1104,7 +1179,10 @@ SELECT DISTINCT ON (<replaceable>expression</replaceable> <optional>, <replaceab <indexterm zone="queries-order"> <primary>sorting</primary> - <secondary>query results</secondary> + </indexterm> + + <indexterm zone="queries-order"> + <primary>ORDER BY</primary> </indexterm> <para> @@ -1173,12 +1251,11 @@ SELECT a AS b FROM table1 ORDER BY a; <title>LIMIT and OFFSET</title> <indexterm zone="queries-limit"> - <primary>limit</primary> + <primary>LIMIT</primary> </indexterm> <indexterm zone="queries-limit"> - <primary>offset</primary> - <secondary>with query results</secondary> + <primary>OFFSET</primary> </indexterm> <para> diff --git a/doc/src/sgml/query.sgml b/doc/src/sgml/query.sgml index 5a7a7f4e62e..de464785a4f 100644 --- a/doc/src/sgml/query.sgml +++ b/doc/src/sgml/query.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/query.sgml,v 1.32 2003/06/24 23:27:24 momjian Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/query.sgml,v 1.32.2.1 2003/09/07 04:36:43 momjian Exp $ --> <chapter id="tutorial-sql"> @@ -87,7 +87,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/query.sgml,v 1.32 2003/06/24 23:27:24 momji </para> <para> - <indexterm><primary>cluster</primary></indexterm> + <indexterm><primary>database cluster</primary></indexterm> + <indexterm><primary>cluster</primary><secondary>of databases</secondary><see>database cluster</see></indexterm> Tables are grouped into databases, and a collection of databases managed by a single <productname>PostgreSQL</productname> server @@ -562,7 +563,7 @@ SELECT * <title>Aggregate Functions</title> <indexterm zone="tutorial-agg"> - <primary>aggregate</primary> + <primary>aggregate function</primary> </indexterm> <para> diff --git a/doc/src/sgml/ref/abort.sgml b/doc/src/sgml/ref/abort.sgml index 5d1d4472d01..87b27265f16 100644 --- a/doc/src/sgml/ref/abort.sgml +++ b/doc/src/sgml/ref/abort.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/abort.sgml,v 1.13 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/abort.sgml,v 1.13.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>abort the current transaction</refpurpose> </refnamediv> + <indexterm zone="sql-abort"> + <primary>ABORT</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ABORT [ WORK | TRANSACTION ] diff --git a/doc/src/sgml/ref/alter_aggregate.sgml b/doc/src/sgml/ref/alter_aggregate.sgml index 972accd7565..f1c85849b3f 100644 --- a/doc/src/sgml/ref/alter_aggregate.sgml +++ b/doc/src/sgml/ref/alter_aggregate.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_aggregate.sgml,v 1.1 2003/06/27 14:45:25 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_aggregate.sgml,v 1.1.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>change the definition of an aggregate function</refpurpose> </refnamediv> + <indexterm zone="sql-alteraggregate"> + <primary>ALTER AGGREGATE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ALTER AGGREGATE <replaceable>name</replaceable> ( <replaceable>type</replaceable> ) RENAME TO <replaceable>newname</replaceable> diff --git a/doc/src/sgml/ref/alter_conversion.sgml b/doc/src/sgml/ref/alter_conversion.sgml index b2767405ca8..469b7e5ec5f 100644 --- a/doc/src/sgml/ref/alter_conversion.sgml +++ b/doc/src/sgml/ref/alter_conversion.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_conversion.sgml,v 1.1 2003/06/27 14:45:25 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_conversion.sgml,v 1.1.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>change the definition of a conversion</refpurpose> </refnamediv> + <indexterm zone="sql-alterconversion"> + <primary>ALTER CONVERSION</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ALTER CONVERSION <replaceable>name</replaceable> RENAME TO <replaceable>newname</replaceable> diff --git a/doc/src/sgml/ref/alter_database.sgml b/doc/src/sgml/ref/alter_database.sgml index 12447d6b0a7..bb895328c93 100644 --- a/doc/src/sgml/ref/alter_database.sgml +++ b/doc/src/sgml/ref/alter_database.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_database.sgml,v 1.7 2003/06/27 14:45:25 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_database.sgml,v 1.7.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>change a database</refpurpose> </refnamediv> + <indexterm zone="sql-alterdatabase"> + <primary>ALTER DATABASE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> SET <replaceable>variable</replaceable> { TO | = } { <replaceable>value</replaceable> | DEFAULT } diff --git a/doc/src/sgml/ref/alter_domain.sgml b/doc/src/sgml/ref/alter_domain.sgml index fdbf08e6d48..3980a6f4298 100644 --- a/doc/src/sgml/ref/alter_domain.sgml +++ b/doc/src/sgml/ref/alter_domain.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_domain.sgml,v 1.7 2003/01/06 00:31:44 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_domain.sgml,v 1.7.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -8,6 +8,7 @@ PostgreSQL documentation <refentrytitle id="sql-alterdomain-title">ALTER DOMAIN</refentrytitle> <refmiscinfo>SQL - Language Statements</refmiscinfo> </refmeta> + <refnamediv> <refname> ALTER DOMAIN @@ -16,6 +17,11 @@ PostgreSQL documentation change the definition of a domain </refpurpose> </refnamediv> + + <indexterm zone="sql-alterdomain"> + <primary>ALTER DOMAIN</primary> + </indexterm> + <refsynopsisdiv> <refsynopsisdivinfo> <date>2002-11-27</date> diff --git a/doc/src/sgml/ref/alter_function.sgml b/doc/src/sgml/ref/alter_function.sgml index 621350980b8..c54974788d8 100644 --- a/doc/src/sgml/ref/alter_function.sgml +++ b/doc/src/sgml/ref/alter_function.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_function.sgml,v 1.1 2003/06/27 14:45:25 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_function.sgml,v 1.1.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>change the definition of a function</refpurpose> </refnamediv> + <indexterm zone="sql-alterfunction"> + <primary>ALTER FUNCTION</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ALTER FUNCTION <replaceable>name</replaceable> ( [ <replaceable class="parameter">type</replaceable> [, ...] ] ) RENAME TO <replaceable>newname</replaceable> diff --git a/doc/src/sgml/ref/alter_group.sgml b/doc/src/sgml/ref/alter_group.sgml index 6d0695b9384..588eeec2232 100644 --- a/doc/src/sgml/ref/alter_group.sgml +++ b/doc/src/sgml/ref/alter_group.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_group.sgml,v 1.10 2003/06/27 14:45:25 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_group.sgml,v 1.10.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>change a user group</refpurpose> </refnamediv> + <indexterm zone="sql-altergroup"> + <primary>ALTER GROUP</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ALTER GROUP <replaceable class="PARAMETER">groupname</replaceable> ADD USER <replaceable class="PARAMETER">username</replaceable> [, ... ] diff --git a/doc/src/sgml/ref/alter_language.sgml b/doc/src/sgml/ref/alter_language.sgml index 2c922d58830..51545e308f4 100644 --- a/doc/src/sgml/ref/alter_language.sgml +++ b/doc/src/sgml/ref/alter_language.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_language.sgml,v 1.1 2003/06/27 14:45:25 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_language.sgml,v 1.1.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>change the definition of a procedural language</refpurpose> </refnamediv> + <indexterm zone="sql-alterlanguage"> + <primary>ALTER LANGUAGE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ALTER LANGUAGE <replaceable>name</replaceable> RENAME TO <replaceable>newname</replaceable> diff --git a/doc/src/sgml/ref/alter_opclass.sgml b/doc/src/sgml/ref/alter_opclass.sgml index 5a9694c73a8..186b42bcc93 100644 --- a/doc/src/sgml/ref/alter_opclass.sgml +++ b/doc/src/sgml/ref/alter_opclass.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_opclass.sgml,v 1.1 2003/06/27 14:45:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_opclass.sgml,v 1.1.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>change the definition of an operator class</refpurpose> </refnamediv> + <indexterm zone="sql-alteropclass"> + <primary>ALTER OPERATOR CLASS</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> RENAME TO <replaceable>newname</replaceable> diff --git a/doc/src/sgml/ref/alter_schema.sgml b/doc/src/sgml/ref/alter_schema.sgml index 6e3c78c9c7c..6247993e13c 100644 --- a/doc/src/sgml/ref/alter_schema.sgml +++ b/doc/src/sgml/ref/alter_schema.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_schema.sgml,v 1.1 2003/06/27 14:45:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_schema.sgml,v 1.1.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>change the definition of a schema</refpurpose> </refnamediv> + <indexterm zone="sql-alterschema"> + <primary>ALTER SCHEMA</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ALTER SCHEMA <replaceable>name</replaceable> RENAME TO <replaceable>newname</replaceable> diff --git a/doc/src/sgml/ref/alter_sequence.sgml b/doc/src/sgml/ref/alter_sequence.sgml index 28a81022aab..b7ad7ea245a 100644 --- a/doc/src/sgml/ref/alter_sequence.sgml +++ b/doc/src/sgml/ref/alter_sequence.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_sequence.sgml,v 1.2 2003/06/12 07:49:43 momjian Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_sequence.sgml,v 1.2.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -8,6 +8,7 @@ PostgreSQL documentation <refentrytitle id="SQL-ALTERSEQUENCE-TITLE">ALTER SEQUENCE</refentrytitle> <refmiscinfo>SQL - Language Statements</refmiscinfo> </refmeta> + <refnamediv> <refname> ALTER SEQUENCE @@ -16,6 +17,11 @@ PostgreSQL documentation alter the definition of a sequence generator </refpurpose> </refnamediv> + + <indexterm zone="sql-altersequence"> + <primary>ALTER SEQUENCE</primary> + </indexterm> + <refsynopsisdiv> <refsynopsisdivinfo> <date>1999-07-20</date> diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index 7f5456c2772..7a208787734 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.59 2003/04/15 13:25:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.59.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>change the definition of a table</refpurpose> </refnamediv> + <indexterm zone="sql-altertable"> + <primary>ALTER TABLE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ALTER TABLE [ ONLY ] <replaceable class="PARAMETER">table</replaceable> [ * ] diff --git a/doc/src/sgml/ref/alter_trigger.sgml b/doc/src/sgml/ref/alter_trigger.sgml index b335434eaf8..90ebe0ce063 100644 --- a/doc/src/sgml/ref/alter_trigger.sgml +++ b/doc/src/sgml/ref/alter_trigger.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_trigger.sgml,v 1.4 2003/04/15 13:25:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_trigger.sgml,v 1.4.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>change the definition of a trigger</refpurpose> </refnamediv> + <indexterm zone="sql-altertrigger"> + <primary>ALTER TRIGGER</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ALTER TRIGGER <replaceable class="PARAMETER">trigger</replaceable> ON <replaceable class="PARAMETER">table</replaceable> diff --git a/doc/src/sgml/ref/alter_user.sgml b/doc/src/sgml/ref/alter_user.sgml index 95de7a592d5..a46a6aa029e 100644 --- a/doc/src/sgml/ref/alter_user.sgml +++ b/doc/src/sgml/ref/alter_user.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_user.sgml,v 1.28 2003/06/27 14:45:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_user.sgml,v 1.28.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>change a database user account</refpurpose> </refnamediv> + <indexterm zone="sql-alteruser"> + <primary>ALTER USER</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ALTER USER <replaceable class="PARAMETER">username</replaceable> [ [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ] ] diff --git a/doc/src/sgml/ref/analyze.sgml b/doc/src/sgml/ref/analyze.sgml index 4977964f4e7..12fd1e63be2 100644 --- a/doc/src/sgml/ref/analyze.sgml +++ b/doc/src/sgml/ref/analyze.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/analyze.sgml,v 1.12 2003/04/15 13:25:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/analyze.sgml,v 1.12.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>collect statistics about a database</refpurpose> </refnamediv> + <indexterm zone="sql-analyze"> + <primary>ANALYZE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ANALYZE [ VERBOSE ] [ <replaceable class="PARAMETER">table</replaceable> [ (<replaceable class="PARAMETER">column</replaceable> [, ...] ) ] ] diff --git a/doc/src/sgml/ref/begin.sgml b/doc/src/sgml/ref/begin.sgml index 7bd1309d289..30c78be8bcd 100644 --- a/doc/src/sgml/ref/begin.sgml +++ b/doc/src/sgml/ref/begin.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/begin.sgml,v 1.24 2003/05/14 03:26:00 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/begin.sgml,v 1.24.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>start a transaction block</refpurpose> </refnamediv> + <indexterm zone="sql-begin"> + <primary>BEGIN</primary> + </indexterm> + <refsynopsisdiv> <synopsis> BEGIN [ WORK | TRANSACTION ] diff --git a/doc/src/sgml/ref/checkpoint.sgml b/doc/src/sgml/ref/checkpoint.sgml index 71d075d542e..2ceacfad1a0 100644 --- a/doc/src/sgml/ref/checkpoint.sgml +++ b/doc/src/sgml/ref/checkpoint.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/checkpoint.sgml,v 1.9 2003/04/15 13:25:08 petere Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/checkpoint.sgml,v 1.9.2.1 2003/09/07 04:36:44 momjian Exp $ --> <refentry id="sql-checkpoint"> <refmeta> @@ -11,6 +11,10 @@ <refpurpose>force a transaction log checkpoint</refpurpose> </refnamediv> + <indexterm zone="sql-checkpoint"> + <primary>CHECKPOINT</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CHECKPOINT diff --git a/doc/src/sgml/ref/close.sgml b/doc/src/sgml/ref/close.sgml index 9ae487c3f78..5b8df9cfe07 100644 --- a/doc/src/sgml/ref/close.sgml +++ b/doc/src/sgml/ref/close.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/close.sgml,v 1.14 2003/04/15 13:25:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/close.sgml,v 1.14.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>close a cursor</refpurpose> </refnamediv> + <indexterm zone="sql-close"> + <primary>CLOSE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CLOSE <replaceable class="PARAMETER">cursor</replaceable> @@ -31,9 +35,13 @@ CLOSE <replaceable class="PARAMETER">cursor</replaceable> </para> <para> - Every open cursor is implicitly closed when a transaction is - terminated by <command>COMMIT</command> or - <command>ROLLBACK</command>. + Every non-holdable open cursor is implicitly closed when a + transaction is terminated by <command>COMMIT</command> or + <command>ROLLBACK</command>. Holdable cursors are implicitely + closed if the transaction that created them aborts via + <command>ROLLBACK</command>; if this does not happen, the holdable + cursor remains open until an explicit <command>CLOSE</command> is + executed, or the client disconnects. </para> </refsect1> @@ -66,10 +74,10 @@ CLOSE <replaceable class="PARAMETER">cursor</replaceable> </varlistentry> <varlistentry> - <term><computeroutput>WARNING: PerformPortalClose: portal "<replaceable class="PARAMETER">cursor</replaceable>" not found</computeroutput></term> + <term><computeroutput>ERROR: cursor "<replaceable class="PARAMETER">cursor</replaceable>" does not exist</computeroutput></term> <listitem> <para> - This warning is given if <replaceable + Message returned if <replaceable class="PARAMETER">cursor</replaceable> is not declared or has already been closed. </para> diff --git a/doc/src/sgml/ref/cluster.sgml b/doc/src/sgml/ref/cluster.sgml index 90c56551a33..c57f361cfdb 100644 --- a/doc/src/sgml/ref/cluster.sgml +++ b/doc/src/sgml/ref/cluster.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/cluster.sgml,v 1.26 2003/04/15 13:25:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/cluster.sgml,v 1.26.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>cluster a table according to an index</refpurpose> </refnamediv> + <indexterm zone="sql-cluster"> + <primary>CLUSTER</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CLUSTER <replaceable class="PARAMETER">indexname</replaceable> ON <replaceable class="PARAMETER">tablename</replaceable> diff --git a/doc/src/sgml/ref/clusterdb.sgml b/doc/src/sgml/ref/clusterdb.sgml index eb814261876..69aed65428c 100644 --- a/doc/src/sgml/ref/clusterdb.sgml +++ b/doc/src/sgml/ref/clusterdb.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/clusterdb.sgml,v 1.10 2003/06/18 12:19:11 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/clusterdb.sgml,v 1.10.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>cluster a <productname>PostgreSQL</productname> database</refpurpose> </refnamediv> + <indexterm zone="app-clusterdb"> + <primary>clusterdb</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>clusterdb</command> @@ -129,10 +133,9 @@ PostgreSQL documentation <term><option>--host <replaceable class="parameter">host</replaceable></></term> <listitem> <para> - Specifies the host name of the machine on which the - server - is running. If the value begins with a slash, it is used - as the directory for the Unix domain socket. + Specifies the host name of the machine on which the server is + running. If the value begins with a slash, it is used as the + directory for the Unix domain socket. </para> </listitem> </varlistentry> @@ -182,7 +185,7 @@ PostgreSQL documentation <term><computeroutput>CLUSTER</computeroutput></term> <listitem> <para> - Everything went well. + The database was successfully clustered. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/comment.sgml b/doc/src/sgml/ref/comment.sgml index 2eaf4ada45d..7e37ed29957 100644 --- a/doc/src/sgml/ref/comment.sgml +++ b/doc/src/sgml/ref/comment.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v 1.21 2003/04/15 13:25:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v 1.21.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define or change the comment of an object</refpurpose> </refnamediv> + <indexterm zone="sql-comment"> + <primary>COMMENT</primary> + </indexterm> + <refsynopsisdiv> <synopsis> COMMENT ON diff --git a/doc/src/sgml/ref/commit.sgml b/doc/src/sgml/ref/commit.sgml index a84c61a9011..724f6102e0e 100644 --- a/doc/src/sgml/ref/commit.sgml +++ b/doc/src/sgml/ref/commit.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/commit.sgml,v 1.15 2003/04/15 13:25:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/commit.sgml,v 1.15.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>commit the current transaction</refpurpose> </refnamediv> + <indexterm zone="sql-commit"> + <primary>COMMIT</primary> + </indexterm> + <refsynopsisdiv> <synopsis> COMMIT [ WORK | TRANSACTION ] diff --git a/doc/src/sgml/ref/copy.sgml b/doc/src/sgml/ref/copy.sgml index 0e24f8b3eec..ddd819eecb5 100644 --- a/doc/src/sgml/ref/copy.sgml +++ b/doc/src/sgml/ref/copy.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/copy.sgml,v 1.46 2003/05/09 21:19:48 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/copy.sgml,v 1.46.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>copy data between files and tables</refpurpose> </refnamediv> + <indexterm zone="sql-copy"> + <primary>COPY</primary> + </indexterm> + <refsynopsisdiv> <synopsis> COPY <replaceable class="parameter">table</replaceable> [ ( <replaceable class="parameter">column</replaceable> [, ...] ) ] @@ -380,7 +384,7 @@ COPY <replaceable class="parameter">table</replaceable> [ ( <replaceable class=" The file format used for <command>COPY BINARY</command> changed in <application>PostgreSQL</application> 7.4. The new format consists of a file header, zero or more tuples containing the row data, and - a file trailer. + a file trailer. Headers and data are now in network byte order. </para> <refsect3> @@ -484,6 +488,15 @@ to be specified. </para> <para> +To determine the appropriate binary format for the actual tuple data you +should consult the <application>PostgreSQL</application> source, in +particular the <function>*send</> and <function>*recv</> functions for +the data type (typically found in the <filename>src/backend/utils/adt</filename> +directory). The <application>contrib/binarycopy</application> module +can also be used to create an appropriate format file. + </para> + + <para> If OIDs are included in the file, the OID field immediately follows the field-count word. It is a normal field except that it's not included in the field-count. In particular it has a length word --- this will allow diff --git a/doc/src/sgml/ref/create_aggregate.sgml b/doc/src/sgml/ref/create_aggregate.sgml index 2aff0636713..81578b30b97 100644 --- a/doc/src/sgml/ref/create_aggregate.sgml +++ b/doc/src/sgml/ref/create_aggregate.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_aggregate.sgml,v 1.26 2003/06/27 14:45:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_aggregate.sgml,v 1.26.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new aggregate function</refpurpose> </refnamediv> + <indexterm zone="sql-createaggregate"> + <primary>CREATE AGGREGATE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> ( diff --git a/doc/src/sgml/ref/create_cast.sgml b/doc/src/sgml/ref/create_cast.sgml index b97135c9538..02002e3bdde 100644 --- a/doc/src/sgml/ref/create_cast.sgml +++ b/doc/src/sgml/ref/create_cast.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.11 2003/04/22 10:08:08 petere Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.11.2.1 2003/09/07 04:36:44 momjian Exp $ --> <refentry id="SQL-CREATECAST"> <refmeta> @@ -11,6 +11,10 @@ <refpurpose>define a user-defined cast</refpurpose> </refnamediv> + <indexterm zone="sql-createcast"> + <primary>CREATE CAST</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>) diff --git a/doc/src/sgml/ref/create_constraint.sgml b/doc/src/sgml/ref/create_constraint.sgml index b61cd5d911f..eaa93ba78ee 100644 --- a/doc/src/sgml/ref/create_constraint.sgml +++ b/doc/src/sgml/ref/create_constraint.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_constraint.sgml,v 1.9 2003/04/22 10:08:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_constraint.sgml,v 1.9.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new constraint trigger</refpurpose> </refnamediv> + <indexterm zone="sql-createconstraint"> + <primary>CREATE CONSTRAINT</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE CONSTRAINT TRIGGER <replaceable class="parameter">name</replaceable> diff --git a/doc/src/sgml/ref/create_conversion.sgml b/doc/src/sgml/ref/create_conversion.sgml index 382c5089832..1ced8820b87 100644 --- a/doc/src/sgml/ref/create_conversion.sgml +++ b/doc/src/sgml/ref/create_conversion.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_conversion.sgml,v 1.10 2003/06/27 14:45:26 petere Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_conversion.sgml,v 1.10.2.1 2003/09/07 04:36:44 momjian Exp $ --> <refentry id="SQL-CREATECONVERSION"> <refmeta> @@ -11,6 +11,10 @@ <refpurpose>define a user-defined conversion</refpurpose> </refnamediv> + <indexterm zone="sql-createconversion"> + <primary>CREATE CONVERSION</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE [DEFAULT] CONVERSION <replaceable>name</replaceable> diff --git a/doc/src/sgml/ref/create_database.sgml b/doc/src/sgml/ref/create_database.sgml index ad0008de403..398b70386ee 100644 --- a/doc/src/sgml/ref/create_database.sgml +++ b/doc/src/sgml/ref/create_database.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_database.sgml,v 1.34 2003/04/22 10:08:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_database.sgml,v 1.34.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>create a new database</refpurpose> </refnamediv> + <indexterm zone="sql-createdatabase"> + <primary>CREATE DATABASE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE DATABASE <replaceable class="PARAMETER">name</replaceable> diff --git a/doc/src/sgml/ref/create_domain.sgml b/doc/src/sgml/ref/create_domain.sgml index 0d6fe6ef50a..3ff05d603a5 100644 --- a/doc/src/sgml/ref/create_domain.sgml +++ b/doc/src/sgml/ref/create_domain.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_domain.sgml,v 1.13 2003/04/22 10:08:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_domain.sgml,v 1.13.2.1 2003/09/07 04:36:44 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new domain</refpurpose> </refnamediv> + <indexterm zone="sql-createdomain"> + <primary>CREATE DOMAIN</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE DOMAIN <replaceable class="parameter">domainname</replaceable> [AS] <replaceable class="parameter">data_type</replaceable> diff --git a/doc/src/sgml/ref/create_function.sgml b/doc/src/sgml/ref/create_function.sgml index 4e1978c6eec..a6467d774d6 100644 --- a/doc/src/sgml/ref/create_function.sgml +++ b/doc/src/sgml/ref/create_function.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.48 2003/06/27 14:45:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.48.2.1 2003/09/07 04:36:45 momjian Exp $ --> <refentry id="SQL-CREATEFUNCTION"> @@ -13,6 +13,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.48 2003/06/27 <refpurpose>define a new function</refpurpose> </refnamediv> + <indexterm zone="sql-createfunction"> + <primary>CREATE FUNCTION</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceable class="parameter">argtype</replaceable> [, ...] ] ) diff --git a/doc/src/sgml/ref/create_group.sgml b/doc/src/sgml/ref/create_group.sgml index d90dd31086a..7758de6d47e 100644 --- a/doc/src/sgml/ref/create_group.sgml +++ b/doc/src/sgml/ref/create_group.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_group.sgml,v 1.11 2003/04/22 10:08:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_group.sgml,v 1.11.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new user group</refpurpose> </refnamediv> + <indexterm zone="sql-creategroup"> + <primary>CREATE GROUP</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE GROUP <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ] ] diff --git a/doc/src/sgml/ref/create_index.sgml b/doc/src/sgml/ref/create_index.sgml index ff60aaa3b01..05293b25d5f 100644 --- a/doc/src/sgml/ref/create_index.sgml +++ b/doc/src/sgml/ref/create_index.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_index.sgml,v 1.39 2003/05/28 16:03:55 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_index.sgml,v 1.39.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new index</refpurpose> </refnamediv> + <indexterm zone="sql-createindex"> + <primary>CREATE INDEX</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE [ UNIQUE ] INDEX <replaceable class="parameter">index_name</replaceable> ON <replaceable class="parameter">table</replaceable> [ USING <replaceable class="parameter">method</replaceable> ] diff --git a/doc/src/sgml/ref/create_language.sgml b/doc/src/sgml/ref/create_language.sgml index d26eb48911d..a6884abee1d 100644 --- a/doc/src/sgml/ref/create_language.sgml +++ b/doc/src/sgml/ref/create_language.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.33 2003/06/27 14:45:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.33.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new procedural language</refpurpose> </refnamediv> + <indexterm zone="sql-createlanguage"> + <primary>CREATE LANGUAGE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">langname</replaceable> diff --git a/doc/src/sgml/ref/create_opclass.sgml b/doc/src/sgml/ref/create_opclass.sgml index eddb8e71287..6696a9eb343 100644 --- a/doc/src/sgml/ref/create_opclass.sgml +++ b/doc/src/sgml/ref/create_opclass.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_opclass.sgml,v 1.8 2003/06/27 14:45:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_opclass.sgml,v 1.8.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new operator class for indexes</refpurpose> </refnamediv> + <indexterm zone="sql-createopclass"> + <primary>CREATE OPERATOR CLASS</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE OPERATOR CLASS <replaceable class="parameter">name</replaceable> [ DEFAULT ] FOR TYPE <replaceable class="parameter">data_type</replaceable> USING <replaceable class="parameter">index_method</replaceable> AS diff --git a/doc/src/sgml/ref/create_operator.sgml b/doc/src/sgml/ref/create_operator.sgml index 2ac9d3f2edd..d64bc28f2d9 100644 --- a/doc/src/sgml/ref/create_operator.sgml +++ b/doc/src/sgml/ref/create_operator.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.35 2003/04/22 10:08:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.35.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new operator</refpurpose> </refnamediv> + <indexterm zone="sql-createoperator"> + <primary>CREATE OPERATOR</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE OPERATOR <replaceable>name</replaceable> ( @@ -43,19 +47,13 @@ CREATE OPERATOR <replaceable>name</replaceable> ( The operator name is a sequence of up to <symbol>NAMEDATALEN</>-1 (63 by default) characters from the following list: <literallayout> -+ - * / < > = ~ ! @ # % ^ & | ` ? $ ++ - * / < > = ~ ! @ # % ^ & | ` ? </literallayout> There are a few restrictions on your choice of name: <itemizedlist> <listitem> <para> - <literal>$</literal> cannot be defined as a single-character operator, - although it can be part of a multicharacter operator name. - </para> - </listitem> - <listitem> - <para> <literal>--</literal> and <literal>/*</literal> cannot appear anywhere in an operator name, since they will be taken as the start of a comment. </para> @@ -66,7 +64,7 @@ CREATE OPERATOR <replaceable>name</replaceable> ( <literal>-</literal>, unless the name also contains at least one of these characters: <literallayout> -~ ! @ # % ^ & | ` ? $ +~ ! @ # % ^ & | ` ? </literallayout> For example, <literal>@-</literal> is an allowed operator name, but <literal>*-</literal> is not. diff --git a/doc/src/sgml/ref/create_rule.sgml b/doc/src/sgml/ref/create_rule.sgml index ff7f2bfb134..566f8bddfb8 100644 --- a/doc/src/sgml/ref/create_rule.sgml +++ b/doc/src/sgml/ref/create_rule.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_rule.sgml,v 1.39 2003/04/22 10:08:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_rule.sgml,v 1.39.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new rewrite rule</refpurpose> </refnamediv> + <indexterm zone="sql-createrule"> + <primary>CREATE RULE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE [ OR REPLACE ] RULE <replaceable class="parameter">name</replaceable> AS ON <replaceable class="parameter">event</replaceable> diff --git a/doc/src/sgml/ref/create_schema.sgml b/doc/src/sgml/ref/create_schema.sgml index e70d29a37b8..4a40160caf3 100644 --- a/doc/src/sgml/ref/create_schema.sgml +++ b/doc/src/sgml/ref/create_schema.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_schema.sgml,v 1.6 2003/06/27 14:45:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_schema.sgml,v 1.6.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new schema</refpurpose> </refnamediv> + <indexterm zone="sql-createschema"> + <primary>CREATE SCHEMA</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE SCHEMA <replaceable class="parameter">schemaname</replaceable> [ AUTHORIZATION <replaceable class="parameter">username</replaceable> ] [ <replaceable class="parameter">schema_element</replaceable> [ ... ] ] diff --git a/doc/src/sgml/ref/create_sequence.sgml b/doc/src/sgml/ref/create_sequence.sgml index 374f34cb0a8..93b6fc7d50c 100644 --- a/doc/src/sgml/ref/create_sequence.sgml +++ b/doc/src/sgml/ref/create_sequence.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_sequence.sgml,v 1.33 2003/04/22 10:08:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_sequence.sgml,v 1.33.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new sequence generator</refpurpose> </refnamediv> + <indexterm zone="sql-createsequence"> + <primary>CREATE SEQUENCE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE [ TEMPORARY | TEMP ] SEQUENCE <replaceable class="parameter">seqname</replaceable> [ INCREMENT [ BY ] <replaceable class="parameter">increment</replaceable> ] diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index 2d55997e708..ea35353d314 100644 --- a/doc/src/sgml/ref/create_table.sgml +++ b/doc/src/sgml/ref/create_table.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table.sgml,v 1.70 2003/06/12 18:34:06 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table.sgml,v 1.70.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new table</refpurpose> </refnamediv> + <indexterm zone="sql-createtable"> + <primary>CREATE TABLE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PARAMETER">table_name</replaceable> ( diff --git a/doc/src/sgml/ref/create_table_as.sgml b/doc/src/sgml/ref/create_table_as.sgml index 0f648d56b3a..4e9a54a9e42 100644 --- a/doc/src/sgml/ref/create_table_as.sgml +++ b/doc/src/sgml/ref/create_table_as.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table_as.sgml,v 1.14 2003/07/01 00:04:31 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table_as.sgml,v 1.14.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>create a new table from the results of a query</refpurpose> </refnamediv> + <indexterm zone="sql-createtableas"> + <primary>CREATE TABLE AS</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name</replaceable> [ (<replaceable>column_name</replaceable> [, ...] ) ] diff --git a/doc/src/sgml/ref/create_trigger.sgml b/doc/src/sgml/ref/create_trigger.sgml index 1856264954c..9ceea50c503 100644 --- a/doc/src/sgml/ref/create_trigger.sgml +++ b/doc/src/sgml/ref/create_trigger.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_trigger.sgml,v 1.34 2003/04/22 10:08:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_trigger.sgml,v 1.34.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new trigger</refpurpose> </refnamediv> + <indexterm zone="sql-createtrigger"> + <primary>CREATE TRIGGER</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFORE | AFTER } { <replaceable class="PARAMETER">event</replaceable> [ OR ... ] } diff --git a/doc/src/sgml/ref/create_type.sgml b/doc/src/sgml/ref/create_type.sgml index 2d2b92a85aa..f72d5344ccf 100644 --- a/doc/src/sgml/ref/create_type.sgml +++ b/doc/src/sgml/ref/create_type.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_type.sgml,v 1.43 2003/05/09 23:01:44 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_type.sgml,v 1.43.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new data type</refpurpose> </refnamediv> + <indexterm zone="sql-createtype"> + <primary>CREATE TYPE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE TYPE <replaceable class="parameter">typename</replaceable> AS diff --git a/doc/src/sgml/ref/create_user.sgml b/doc/src/sgml/ref/create_user.sgml index 23d64bd2c54..382f1a246ce 100644 --- a/doc/src/sgml/ref/create_user.sgml +++ b/doc/src/sgml/ref/create_user.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_user.sgml,v 1.26 2003/04/22 10:08:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_user.sgml,v 1.26.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new database user account</refpurpose> </refnamediv> + <indexterm zone="sql-createuser"> + <primary>CREATE USER</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE USER <replaceable class="PARAMETER">username</replaceable> [ [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ] ] diff --git a/doc/src/sgml/ref/create_view.sgml b/doc/src/sgml/ref/create_view.sgml index 8bfb4f16636..42a69f5fcc2 100644 --- a/doc/src/sgml/ref/create_view.sgml +++ b/doc/src/sgml/ref/create_view.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_view.sgml,v 1.22 2003/04/22 10:08:08 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_view.sgml,v 1.22.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a new view</refpurpose> </refnamediv> + <indexterm zone="sql-createview"> + <primary>CREATE VIEW</primary> + </indexterm> + <refsynopsisdiv> <synopsis> CREATE [ OR REPLACE ] VIEW <replaceable class="PARAMETER">name</replaceable> [ ( <replaceable diff --git a/doc/src/sgml/ref/createdb.sgml b/doc/src/sgml/ref/createdb.sgml index 0ad159842a3..4f432a8dd91 100644 --- a/doc/src/sgml/ref/createdb.sgml +++ b/doc/src/sgml/ref/createdb.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/createdb.sgml,v 1.33 2003/05/26 17:50:09 momjian Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/createdb.sgml,v 1.33.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>create a new <productname>PostgreSQL</productname> database</refpurpose> </refnamediv> + <indexterm zone="app-createdb"> + <primary>createdb</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>createdb</command> diff --git a/doc/src/sgml/ref/createlang.sgml b/doc/src/sgml/ref/createlang.sgml index be86e7c1c79..e2fcee63e08 100644 --- a/doc/src/sgml/ref/createlang.sgml +++ b/doc/src/sgml/ref/createlang.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/createlang.sgml,v 1.31 2003/03/24 14:32:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/createlang.sgml,v 1.31.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>define a new <productname>PostgreSQL</productname> procedural language</refpurpose> </refnamediv> + <indexterm zone="app-createlang"> + <primary>createlang</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>createlang</command> diff --git a/doc/src/sgml/ref/createuser.sgml b/doc/src/sgml/ref/createuser.sgml index ba882776878..0b07662819b 100644 --- a/doc/src/sgml/ref/createuser.sgml +++ b/doc/src/sgml/ref/createuser.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/createuser.sgml,v 1.34 2003/06/06 15:31:46 momjian Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/createuser.sgml,v 1.34.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>define a new <productname>PostgreSQL</productname> user account</refpurpose> </refnamediv> + <indexterm zone="app-createuser"> + <primary>createuser</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>createuser</command> @@ -276,7 +280,7 @@ PostgreSQL documentation <term><computeroutput>CREATE USER</computeroutput></term> <listitem> <para> - All is well. + The user was successfully created. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/deallocate.sgml b/doc/src/sgml/ref/deallocate.sgml index 008a6262e12..91355ce61a6 100644 --- a/doc/src/sgml/ref/deallocate.sgml +++ b/doc/src/sgml/ref/deallocate.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/deallocate.sgml,v 1.2 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/deallocate.sgml,v 1.2.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>deallocate a prepared statement</refpurpose> </refnamediv> + <indexterm zone="sql-deallocate"> + <primary>DEALLOCATE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DEALLOCATE [ PREPARE ] <replaceable class="parameter">plan_name</replaceable> diff --git a/doc/src/sgml/ref/declare.sgml b/doc/src/sgml/ref/declare.sgml index 0aaf0dde43d..3585a71f79f 100644 --- a/doc/src/sgml/ref/declare.sgml +++ b/doc/src/sgml/ref/declare.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/declare.sgml,v 1.24 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/declare.sgml,v 1.24.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define a cursor</refpurpose> </refnamediv> + <indexterm zone="sql-declare"> + <primary>DECLARE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DECLARE <replaceable class="parameter">cursorname</replaceable> [ BINARY ] [ INSENSITIVE ] [ [ NO ] SCROLL ] @@ -202,11 +206,10 @@ DECLARE <replaceable class="parameter">cursorname</replaceable> [ BINARY ] [ INS </varlistentry> <varlistentry> - <term><computeroutput>WARNING: Closing pre-existing portal "<replaceable class="parameter">cursorname</replaceable>"</computeroutput></term> + <term><computeroutput>ERROR: cursor "<replaceable class="parameter">cursorname</replaceable>" already exists</computeroutput></term> <listitem> <para> - This message is reported if a cursor with the same name already - exists. The previous definition is discarded. + This error occurs if a cursor with the same name already exists. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/delete.sgml b/doc/src/sgml/ref/delete.sgml index b04b86c8887..c5c75459860 100644 --- a/doc/src/sgml/ref/delete.sgml +++ b/doc/src/sgml/ref/delete.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/delete.sgml,v 1.17 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/delete.sgml,v 1.17.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>delete rows of a table</refpurpose> </refnamediv> + <indexterm zone="sql-delete"> + <primary>DELETE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DELETE FROM [ ONLY ] <replaceable class="PARAMETER">table</replaceable> [ WHERE <replaceable class="PARAMETER">condition</replaceable> ] diff --git a/doc/src/sgml/ref/drop_aggregate.sgml b/doc/src/sgml/ref/drop_aggregate.sgml index 49915626a5c..4dcb29eee61 100644 --- a/doc/src/sgml/ref/drop_aggregate.sgml +++ b/doc/src/sgml/ref/drop_aggregate.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_aggregate.sgml,v 1.23 2003/06/27 14:45:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_aggregate.sgml,v 1.23.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a user-defined aggregate function</refpurpose> </refnamediv> + <indexterm zone="sql-dropaggregate"> + <primary>DROP AGGREGATE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP AGGREGATE <replaceable class="PARAMETER">name</replaceable> ( <replaceable class="PARAMETER">type</replaceable> ) [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_cast.sgml b/doc/src/sgml/ref/drop_cast.sgml index 427796e56bf..c25e2ab1db5 100644 --- a/doc/src/sgml/ref/drop_cast.sgml +++ b/doc/src/sgml/ref/drop_cast.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_cast.sgml,v 1.3 2003/05/04 02:23:16 petere Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_cast.sgml,v 1.3.2.1 2003/09/07 04:36:45 momjian Exp $ --> <refentry id="SQL-DROPCAST"> <refmeta> @@ -11,6 +11,10 @@ <refpurpose>remove a user-defined cast</refpurpose> </refnamediv> + <indexterm zone="sql-dropcast"> + <primary>DROP CAST</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>) [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_conversion.sgml b/doc/src/sgml/ref/drop_conversion.sgml index d9c795c445a..b225e2b1cea 100644 --- a/doc/src/sgml/ref/drop_conversion.sgml +++ b/doc/src/sgml/ref/drop_conversion.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_conversion.sgml,v 1.5 2003/06/27 14:45:26 petere Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_conversion.sgml,v 1.5.2.1 2003/09/07 04:36:45 momjian Exp $ --> <refentry id="SQL-DROPCONVERSION"> <refmeta> @@ -11,6 +11,10 @@ <refpurpose>remove a user-defined conversion</refpurpose> </refnamediv> + <indexterm zone="sql-dropconversion"> + <primary>DROP CONVERSION</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP CONVERSION <replaceable>conversion_name</replaceable> [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_database.sgml b/doc/src/sgml/ref/drop_database.sgml index fb77f53c67c..4c71b3cf680 100644 --- a/doc/src/sgml/ref/drop_database.sgml +++ b/doc/src/sgml/ref/drop_database.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_database.sgml,v 1.16 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_database.sgml,v 1.16.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a database</refpurpose> </refnamediv> + <indexterm zone="sql-dropdatabase"> + <primary>DROP DATABASE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP DATABASE <replaceable class="PARAMETER">name</replaceable> diff --git a/doc/src/sgml/ref/drop_domain.sgml b/doc/src/sgml/ref/drop_domain.sgml index 99c8ec7d44e..81271c88bf1 100644 --- a/doc/src/sgml/ref/drop_domain.sgml +++ b/doc/src/sgml/ref/drop_domain.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_domain.sgml,v 1.10 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_domain.sgml,v 1.10.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a domain</refpurpose> </refnamediv> + <indexterm zone="sql-dropdomain"> + <primary>DROP DOMAIN</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP DOMAIN <replaceable class="PARAMETER">domainname</replaceable> [, ...] [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_function.sgml b/doc/src/sgml/ref/drop_function.sgml index 1a62a00f482..005c8a1567b 100644 --- a/doc/src/sgml/ref/drop_function.sgml +++ b/doc/src/sgml/ref/drop_function.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_function.sgml,v 1.25 2003/06/27 14:45:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_function.sgml,v 1.25.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a user-defined function</refpurpose> </refnamediv> + <indexterm zone="sql-dropfunction"> + <primary>DROP FUNCTION</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceable class="parameter">type</replaceable> [, ...] ] ) [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_group.sgml b/doc/src/sgml/ref/drop_group.sgml index c6c6907e751..bf83d1e0221 100644 --- a/doc/src/sgml/ref/drop_group.sgml +++ b/doc/src/sgml/ref/drop_group.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_group.sgml,v 1.5 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_group.sgml,v 1.5.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a user group</refpurpose> </refnamediv> + <indexterm zone="sql-dropgroup"> + <primary>DROP GROUP</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP GROUP <replaceable class="PARAMETER">name</replaceable> diff --git a/doc/src/sgml/ref/drop_index.sgml b/doc/src/sgml/ref/drop_index.sgml index 4185a4158c2..5b33121c468 100644 --- a/doc/src/sgml/ref/drop_index.sgml +++ b/doc/src/sgml/ref/drop_index.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_index.sgml,v 1.18 2003/06/24 23:29:25 momjian Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_index.sgml,v 1.18.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove an index</refpurpose> </refnamediv> + <indexterm zone="sql-dropindex"> + <primary>DROP INDEX</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP INDEX <replaceable class="PARAMETER">name</replaceable> [, ...] [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_language.sgml b/doc/src/sgml/ref/drop_language.sgml index ad67a95d442..f1f50a1772e 100644 --- a/doc/src/sgml/ref/drop_language.sgml +++ b/doc/src/sgml/ref/drop_language.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_language.sgml,v 1.17 2003/06/27 14:45:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_language.sgml,v 1.17.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a user-defined procedural language</refpurpose> </refnamediv> + <indexterm zone="sql-droplanguage"> + <primary>DROP LANGUAGE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP [ PROCEDURAL ] LANGUAGE <replaceable class="PARAMETER">name</replaceable> [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_opclass.sgml b/doc/src/sgml/ref/drop_opclass.sgml index cb0aebd7103..0c5413c8e63 100644 --- a/doc/src/sgml/ref/drop_opclass.sgml +++ b/doc/src/sgml/ref/drop_opclass.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_opclass.sgml,v 1.4 2003/06/27 14:45:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_opclass.sgml,v 1.4.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a user-defined operator class</refpurpose> </refnamediv> + <indexterm zone="sql-dropopclass"> + <primary>DROP OPERATOR CLASS</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP OPERATOR CLASS <replaceable class="PARAMETER">name</replaceable> USING <replaceable class="PARAMETER">index_method</replaceable> [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_operator.sgml b/doc/src/sgml/ref/drop_operator.sgml index 8f3b1e069c6..feae97f5f0d 100644 --- a/doc/src/sgml/ref/drop_operator.sgml +++ b/doc/src/sgml/ref/drop_operator.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_operator.sgml,v 1.19 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_operator.sgml,v 1.19.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a user-defined operator</refpurpose> </refnamediv> + <indexterm zone="sql-dropoperator"> + <primary>DROP OPERATOR</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP OPERATOR <replaceable class="PARAMETER">name</replaceable> ( <replaceable class="PARAMETER">lefttype</replaceable> | NONE , <replaceable class="PARAMETER">righttype</replaceable> | NONE ) [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_rule.sgml b/doc/src/sgml/ref/drop_rule.sgml index 0276621c575..6824cd268b8 100644 --- a/doc/src/sgml/ref/drop_rule.sgml +++ b/doc/src/sgml/ref/drop_rule.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_rule.sgml,v 1.17 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_rule.sgml,v 1.17.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a rewrite rule</refpurpose> </refnamediv> + <indexterm zone="sql-droprule"> + <primary>DROP RULE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP RULE <replaceable class="PARAMETER">name</replaceable> ON <replaceable class="PARAMETER">relation</replaceable> [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_schema.sgml b/doc/src/sgml/ref/drop_schema.sgml index b8f706b0c77..61c8fbc9421 100644 --- a/doc/src/sgml/ref/drop_schema.sgml +++ b/doc/src/sgml/ref/drop_schema.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_schema.sgml,v 1.3 2003/06/27 14:45:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_schema.sgml,v 1.3.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a schema</refpurpose> </refnamediv> + <indexterm zone="sql-dropschema"> + <primary>DROP SCHEMA</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP SCHEMA <replaceable class="PARAMETER">name</replaceable> [, ...] [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_sequence.sgml b/doc/src/sgml/ref/drop_sequence.sgml index fe77e2a3d69..8aeeb80fd70 100644 --- a/doc/src/sgml/ref/drop_sequence.sgml +++ b/doc/src/sgml/ref/drop_sequence.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_sequence.sgml,v 1.17 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_sequence.sgml,v 1.17.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a sequence</refpurpose> </refnamediv> + <indexterm zone="sql-dropsequence"> + <primary>DROP SEQUENCE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP SEQUENCE <replaceable class="PARAMETER">name</replaceable> [, ...] [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_table.sgml b/doc/src/sgml/ref/drop_table.sgml index 4ebda8787e6..7671f9dbf03 100644 --- a/doc/src/sgml/ref/drop_table.sgml +++ b/doc/src/sgml/ref/drop_table.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_table.sgml,v 1.18 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_table.sgml,v 1.18.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a table</refpurpose> </refnamediv> + <indexterm zone="sql-droptable"> + <primary>DROP TABLE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP TABLE <replaceable class="PARAMETER">name</replaceable> [, ...] [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_trigger.sgml b/doc/src/sgml/ref/drop_trigger.sgml index 5a33d033c24..92307dc7459 100644 --- a/doc/src/sgml/ref/drop_trigger.sgml +++ b/doc/src/sgml/ref/drop_trigger.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_trigger.sgml,v 1.15 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_trigger.sgml,v 1.15.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a trigger</refpurpose> </refnamediv> + <indexterm zone="sql-droptrigger"> + <primary>DROP TRIGGER</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP TRIGGER <replaceable class="PARAMETER">name</replaceable> ON <replaceable class="PARAMETER">table</replaceable> [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_type.sgml b/doc/src/sgml/ref/drop_type.sgml index 4267efcb0bd..ccbdea350de 100644 --- a/doc/src/sgml/ref/drop_type.sgml +++ b/doc/src/sgml/ref/drop_type.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_type.sgml,v 1.21 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_type.sgml,v 1.21.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a user-defined data type</refpurpose> </refnamediv> + <indexterm zone="sql-droptype"> + <primary>DROP TYPE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP TYPE <replaceable class="PARAMETER">typename</replaceable> [, ...] [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/drop_user.sgml b/doc/src/sgml/ref/drop_user.sgml index 7d094b993d3..41040fe7a35 100644 --- a/doc/src/sgml/ref/drop_user.sgml +++ b/doc/src/sgml/ref/drop_user.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_user.sgml,v 1.16 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_user.sgml,v 1.16.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a database user account</refpurpose> </refnamediv> + <indexterm zone="sql-dropuser"> + <primary>DROP USER</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP USER <replaceable class="PARAMETER">name</replaceable> diff --git a/doc/src/sgml/ref/drop_view.sgml b/doc/src/sgml/ref/drop_view.sgml index fd32f92f8ac..4238a61cc83 100644 --- a/doc/src/sgml/ref/drop_view.sgml +++ b/doc/src/sgml/ref/drop_view.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_view.sgml,v 1.17 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_view.sgml,v 1.17.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove a view</refpurpose> </refnamediv> + <indexterm zone="sql-dropview"> + <primary>DROP VIEW</primary> + </indexterm> + <refsynopsisdiv> <synopsis> DROP VIEW <replaceable class="PARAMETER">name</replaceable> [, ...] [ CASCADE | RESTRICT ] diff --git a/doc/src/sgml/ref/dropdb.sgml b/doc/src/sgml/ref/dropdb.sgml index e029b1a6a36..b21ad29a91b 100644 --- a/doc/src/sgml/ref/dropdb.sgml +++ b/doc/src/sgml/ref/dropdb.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/dropdb.sgml,v 1.22 2003/05/26 17:50:09 momjian Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/dropdb.sgml,v 1.22.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>remove a <productname>PostgreSQL</productname> database</refpurpose> </refnamediv> + <indexterm zone="app-dropdb"> + <primary>dropdb</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>dropdb</command> diff --git a/doc/src/sgml/ref/droplang.sgml b/doc/src/sgml/ref/droplang.sgml index 6bddf1a5ba5..6d4f181feeb 100644 --- a/doc/src/sgml/ref/droplang.sgml +++ b/doc/src/sgml/ref/droplang.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/droplang.sgml,v 1.23 2003/03/24 14:32:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/droplang.sgml,v 1.23.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>remove a <productname>PostgreSQL</productname> procedural language</refpurpose> </refnamediv> + <indexterm zone="app-droplang"> + <primary>droplang</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>droplang</command> diff --git a/doc/src/sgml/ref/dropuser.sgml b/doc/src/sgml/ref/dropuser.sgml index 24e8d8ecf45..d1d8d10289d 100644 --- a/doc/src/sgml/ref/dropuser.sgml +++ b/doc/src/sgml/ref/dropuser.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/dropuser.sgml,v 1.26 2003/06/18 12:19:11 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/dropuser.sgml,v 1.26.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>remove a <productname>PostgreSQL</productname> user account</refpurpose> </refnamediv> + <indexterm zone="app-dropuser"> + <primary>dropuser</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>dropuser</command> @@ -180,7 +184,7 @@ PostgreSQL documentation <term><computeroutput>DROP USER</computeroutput></term> <listitem> <para> - All is well. + The user was successfully removed. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/ecpg-ref.sgml b/doc/src/sgml/ref/ecpg-ref.sgml index ffb5ed41945..4fb4d72c5ad 100644 --- a/doc/src/sgml/ref/ecpg-ref.sgml +++ b/doc/src/sgml/ref/ecpg-ref.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/ecpg-ref.sgml,v 1.26 2003/03/25 16:15:39 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/ecpg-ref.sgml,v 1.26.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>embedded SQL C preprocessor</refpurpose> </refnamediv> + <indexterm zone="app-ecpg"> + <primary>ecpg</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>ecpg</command> diff --git a/doc/src/sgml/ref/end.sgml b/doc/src/sgml/ref/end.sgml index b672319479e..82274be3e5c 100644 --- a/doc/src/sgml/ref/end.sgml +++ b/doc/src/sgml/ref/end.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/end.sgml,v 1.9 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/end.sgml,v 1.9.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>commit the current transaction</refpurpose> </refnamediv> + <indexterm zone="sql-end"> + <primary>END</primary> + </indexterm> + <refsynopsisdiv> <synopsis> END [ WORK | TRANSACTION ] diff --git a/doc/src/sgml/ref/execute.sgml b/doc/src/sgml/ref/execute.sgml index 7704b8ce27b..d5e29a07a1e 100644 --- a/doc/src/sgml/ref/execute.sgml +++ b/doc/src/sgml/ref/execute.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/execute.sgml,v 1.5 2003/07/01 00:04:31 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/execute.sgml,v 1.5.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>execute a prepared statement</refpurpose> </refnamediv> + <indexterm zone="sql-execute"> + <primary>EXECUTE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> EXECUTE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable class="PARAMETER">parameter</replaceable> [, ...] ) ] diff --git a/doc/src/sgml/ref/explain.sgml b/doc/src/sgml/ref/explain.sgml index 2ac74e8a383..5078d8fcc84 100644 --- a/doc/src/sgml/ref/explain.sgml +++ b/doc/src/sgml/ref/explain.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/explain.sgml,v 1.26 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/explain.sgml,v 1.26.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>show the execution plan of a statement</refpurpose> </refnamediv> + <indexterm zone="sql-explain"> + <primary>EXPLAIN</primary> + </indexterm> + <refsynopsisdiv> <synopsis> EXPLAIN [ ANALYZE ] [ VERBOSE ] <replaceable class="parameter">statement</replaceable> diff --git a/doc/src/sgml/ref/fetch.sgml b/doc/src/sgml/ref/fetch.sgml index 305e5fc02cc..682a4a68378 100644 --- a/doc/src/sgml/ref/fetch.sgml +++ b/doc/src/sgml/ref/fetch.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/fetch.sgml,v 1.29 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/fetch.sgml,v 1.29.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>retrieve rows from a query using a cursor</refpurpose> </refnamediv> + <indexterm zone="sql-fetch"> + <primary>FETCH</primary> + </indexterm> + <refsynopsisdiv> <synopsis> FETCH [ <replaceable class="PARAMETER">direction</replaceable> { FROM | IN } ] <replaceable class="PARAMETER">cursor</replaceable> @@ -281,7 +285,7 @@ where <replaceable class="PARAMETER">direction</replaceable> can be empty or one <variablelist> <varlistentry> - <term><computeroutput>WARNING: PerformPortalFetch: portal "<replaceable class="PARAMETER">cursor</replaceable>" not found</computeroutput></term> + <term><computeroutput>ERROR: cursor "<replaceable class="PARAMETER">cursor</replaceable>" does not exist</computeroutput></term> <listitem> <para> There is no cursor with the specified name. diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml index 7ba370d6598..10ec3ca1027 100644 --- a/doc/src/sgml/ref/grant.sgml +++ b/doc/src/sgml/ref/grant.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v 1.33 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v 1.33.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>define access privileges</refpurpose> </refnamediv> + <indexterm zone="sql-grant"> + <primary>GRANT</primary> + </indexterm> + <refsynopsisdiv> <synopsis> GRANT { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER } diff --git a/doc/src/sgml/ref/initdb.sgml b/doc/src/sgml/ref/initdb.sgml index ccab2e94422..1ab6d7f48d3 100644 --- a/doc/src/sgml/ref/initdb.sgml +++ b/doc/src/sgml/ref/initdb.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/initdb.sgml,v 1.26 2003/03/25 16:15:41 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/initdb.sgml,v 1.26.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>create a new <productname>PostgreSQL</productname> database cluster</refpurpose> </refnamediv> + <indexterm zone="app-initdb"> + <primary>initdb</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>initdb</command> diff --git a/doc/src/sgml/ref/initlocation.sgml b/doc/src/sgml/ref/initlocation.sgml index 8211e635cd2..938994e6953 100644 --- a/doc/src/sgml/ref/initlocation.sgml +++ b/doc/src/sgml/ref/initlocation.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/Attic/initlocation.sgml,v 1.20 2003/03/25 16:15:42 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/Attic/initlocation.sgml,v 1.20.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>create a secondary <productname>PostgreSQL</productname> database storage area</refpurpose> </refnamediv> + <indexterm zone="app-initlocation"> + <primary>initlocation</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>initlocation</command> diff --git a/doc/src/sgml/ref/insert.sgml b/doc/src/sgml/ref/insert.sgml index cbb0d279bd2..12f6d70384e 100644 --- a/doc/src/sgml/ref/insert.sgml +++ b/doc/src/sgml/ref/insert.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/insert.sgml,v 1.23 2003/07/03 16:32:03 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/insert.sgml,v 1.23.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>create new rows in a table</refpurpose> </refnamediv> + <indexterm zone="sql-insert"> + <primary>INSERT</primary> + </indexterm> + <refsynopsisdiv> <synopsis> INSERT INTO <replaceable class="PARAMETER">table</replaceable> [ ( <replaceable class="PARAMETER">column</replaceable> [, ...] ) ] diff --git a/doc/src/sgml/ref/ipcclean.sgml b/doc/src/sgml/ref/ipcclean.sgml index 85ca334c178..48efbd67590 100644 --- a/doc/src/sgml/ref/ipcclean.sgml +++ b/doc/src/sgml/ref/ipcclean.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/Attic/ipcclean.sgml,v 1.8 2003/03/24 14:32:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/Attic/ipcclean.sgml,v 1.8.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>remove shared memory and semaphores from an aborted <productname>PostgreSQL</productname> server</refpurpose> </refnamediv> + <indexterm zone="app-ipcclean"> + <primary>ipcclean</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>ipcclean</command> diff --git a/doc/src/sgml/ref/listen.sgml b/doc/src/sgml/ref/listen.sgml index 154224d0d20..733d34bda58 100644 --- a/doc/src/sgml/ref/listen.sgml +++ b/doc/src/sgml/ref/listen.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/listen.sgml,v 1.16 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/listen.sgml,v 1.16.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>listen for a notification</refpurpose> </refnamediv> + <indexterm zone="sql-listen"> + <primary>LISTEN</primary> + </indexterm> + <refsynopsisdiv> <synopsis> LISTEN <replaceable class="PARAMETER">name</replaceable> diff --git a/doc/src/sgml/ref/load.sgml b/doc/src/sgml/ref/load.sgml index 056322f58ed..ee0bf007d6a 100644 --- a/doc/src/sgml/ref/load.sgml +++ b/doc/src/sgml/ref/load.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/load.sgml,v 1.17 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/load.sgml,v 1.17.2.1 2003/09/07 04:36:45 momjian Exp $ --> <refentry id="SQL-LOAD"> @@ -13,6 +13,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/ref/load.sgml,v 1.17 2003/04/26 23:56:51 pe <refpurpose>load or reload a shared library file</refpurpose> </refnamediv> + <indexterm zone="sql-load"> + <primary>LOAD</primary> + </indexterm> + <refsynopsisdiv> <synopsis> LOAD '<replaceable class="PARAMETER">filename</replaceable>' diff --git a/doc/src/sgml/ref/lock.sgml b/doc/src/sgml/ref/lock.sgml index c39cb154b8e..8dfb661ba80 100644 --- a/doc/src/sgml/ref/lock.sgml +++ b/doc/src/sgml/ref/lock.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/lock.sgml,v 1.35 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/lock.sgml,v 1.35.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>lock a table</refpurpose> </refnamediv> + <indexterm zone="sql-lock"> + <primary>LOCK</primary> + </indexterm> + <refsynopsisdiv> <synopsis> LOCK [ TABLE ] <replaceable class="PARAMETER">name</replaceable> [, ...] [ IN <replaceable class="PARAMETER">lockmode</replaceable> MODE ] diff --git a/doc/src/sgml/ref/move.sgml b/doc/src/sgml/ref/move.sgml index d60ec29c3b5..b21f0244a70 100644 --- a/doc/src/sgml/ref/move.sgml +++ b/doc/src/sgml/ref/move.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/move.sgml,v 1.22 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/move.sgml,v 1.22.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>reposition a cursor</refpurpose> </refnamediv> + <indexterm zone="sql-move"> + <primary>MOVE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> MOVE [ <replaceable class="PARAMETER">direction</replaceable> { FROM | IN } ] <replaceable class="PARAMETER">cursor</replaceable> diff --git a/doc/src/sgml/ref/notify.sgml b/doc/src/sgml/ref/notify.sgml index 82cd1531790..37e6f8babc2 100644 --- a/doc/src/sgml/ref/notify.sgml +++ b/doc/src/sgml/ref/notify.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/notify.sgml,v 1.20 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/notify.sgml,v 1.20.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>generate a notification</refpurpose> </refnamediv> + <indexterm zone="sql-notify"> + <primary>NOTIFY</primary> + </indexterm> + <refsynopsisdiv> <synopsis> NOTIFY <replaceable class="PARAMETER">name</replaceable> diff --git a/doc/src/sgml/ref/pg_config-ref.sgml b/doc/src/sgml/ref/pg_config-ref.sgml index 084d78b95d0..cb27d5c902a 100644 --- a/doc/src/sgml/ref/pg_config-ref.sgml +++ b/doc/src/sgml/ref/pg_config-ref.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_config-ref.sgml,v 1.15 2003/03/25 16:15:42 petere Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_config-ref.sgml,v 1.15.2.1 2003/09/07 04:36:45 momjian Exp $ --> <refentry id="app-pgconfig"> <refmeta> @@ -12,6 +12,10 @@ <refpurpose>retrieve information about the installed version of <productname>PostgreSQL</></refpurpose> </refnamediv> + <indexterm zone="app-pgconfig"> + <primary>pg_config</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>pg_config</command> diff --git a/doc/src/sgml/ref/pg_controldata.sgml b/doc/src/sgml/ref/pg_controldata.sgml index 314022eb925..42d767846e2 100644 --- a/doc/src/sgml/ref/pg_controldata.sgml +++ b/doc/src/sgml/ref/pg_controldata.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_controldata.sgml,v 1.5 2003/03/24 14:32:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_controldata.sgml,v 1.5.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>display control information of a <productname>PostgreSQL</productname> database cluster</refpurpose> </refnamediv> + <indexterm zone="app-pgcontroldata"> + <primary>pg_controldata</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>pg_controldata</command> diff --git a/doc/src/sgml/ref/pg_ctl-ref.sgml b/doc/src/sgml/ref/pg_ctl-ref.sgml index 8aabb33934f..812e76e650e 100644 --- a/doc/src/sgml/ref/pg_ctl-ref.sgml +++ b/doc/src/sgml/ref/pg_ctl-ref.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_ctl-ref.sgml,v 1.22 2003/03/25 16:15:42 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_ctl-ref.sgml,v 1.22.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>start, stop, or restart a <productname>PostgreSQL</productname> server</refpurpose> </refnamediv> + <indexterm zone="app-pg-ctl"> + <primary>pg_ctl</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>pg_ctl</command> diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml index 5b9e2d4c40e..23ef56858f9 100644 --- a/doc/src/sgml/ref/pg_dump.sgml +++ b/doc/src/sgml/ref/pg_dump.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.62 2003/06/11 16:29:42 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.62.2.1 2003/09/07 04:36:45 momjian Exp $ PostgreSQL documentation --> @@ -18,6 +18,10 @@ PostgreSQL documentation </refpurpose> </refnamediv> + <indexterm zone="app-pgdump"> + <primary>pg_dump</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>pg_dump</command> diff --git a/doc/src/sgml/ref/pg_dumpall.sgml b/doc/src/sgml/ref/pg_dumpall.sgml index 500336e9196..e0ac946472a 100644 --- a/doc/src/sgml/ref/pg_dumpall.sgml +++ b/doc/src/sgml/ref/pg_dumpall.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dumpall.sgml,v 1.39 2003/05/30 23:55:10 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dumpall.sgml,v 1.39.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>extract a <productname>PostgreSQL</productname> database cluster into a script file</refpurpose> </refnamediv> + <indexterm zone="app-pg-dumpall"> + <primary>pg_dumpall</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>pg_dumpall</command> diff --git a/doc/src/sgml/ref/pg_restore.sgml b/doc/src/sgml/ref/pg_restore.sgml index cf028b93e59..a04427a7cbd 100644 --- a/doc/src/sgml/ref/pg_restore.sgml +++ b/doc/src/sgml/ref/pg_restore.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_restore.sgml,v 1.39 2003/06/11 16:29:42 tgl Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_restore.sgml,v 1.39.2.1 2003/09/07 04:36:46 momjian Exp $ --> <refentry id="APP-PGRESTORE"> <refmeta> @@ -15,6 +15,10 @@ </refpurpose> </refnamediv> + <indexterm zone="app-pgrestore"> + <primary>pg_restore</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>pg_restore</command> @@ -42,8 +46,8 @@ <para> <application>pg_restore</application> can operate in two modes: If a database name is specified, the archive is restored directly into - the database. Large objects can only be restored by using a direct - database connection. Otherwise, a script containing the SQL + the database. (Large objects can only be restored by using such a direct + database connection.) Otherwise, a script containing the SQL commands necessary to rebuild the database is created (and written to a file or standard output), similar to the ones created by the <application>pg_dump</application> plain text format. Some of the @@ -228,11 +232,13 @@ <term><option>--orig-order</option></term> <listitem> <para> - Restore items in the original dump order. By default - <application>pg_dump</application> will dump items in an order - convenient to <application>pg_dump</application>, then save the - archive in a modified OID order. This option overrides the OID - ordering. + Restore items in the order they were originally generated within + <application>pg_dump</application>. This option has no known + practical use, since <application>pg_dump</application> generates + the items in an order convenient to it, which is unlikely to be a + safe order for restoring them. (This is <emphasis>not</> the order + in which the items are ultimately listed in the archive's table of + contents.) See also <option>-r</>. </para> </listitem> </varlistentry> @@ -242,11 +248,10 @@ <term><option>--oid-order</option></term> <listitem> <para> - Restore items in the OID order. By default - <application>pg_dump</application> will dump items in an order - convenient to <application>pg_dump</application>, then save the - archive in a modified OID order. This option enforces strict - OID ordering. + Restore items in order by OID. This option is of limited usefulness, + since OID is only an approximate indication of original creation + order. This option overrides <option>-N</> if both are specified. + See also <option>-r</>. </para> </listitem> </varlistentry> @@ -281,13 +286,22 @@ <term><option>--rearrange</option></term> <listitem> <para> - Restore items in modified OID order. By default - <application>pg_dump</application> will dump items in an order - convenient to <application>pg_dump</application>, then save the - archive in a modified OID order. Most objects will be restored - in OID order, but some things (e.g., rules and indexes) will - be restored at the end of the process irrespective of their - OIDs. This option is the default. + Rearrange items by object type (this occurs after the sorting + specified by <option>-N</option> or <option>-o</option>, if + given). The rearrangement is intended to give the best possible + restore performance. + </para> + + <para> + When none of <option>-N</option>, <option>-o</option>, and + <option>-r</> appear, <application>pg_restore</application> restores + items in the order they appear in the dump's table of contents, + or in the order they appear in the <REPLACEABLE + CLASS="PARAMETER">list-file</REPLACEABLE> if <option>-L</> is + given. The combination of <option>-o</> and <option>-r</> + duplicates the sorting done by <application>pg_dump</application> + before creating the dump's table of contents, + and so it is normally unnecessary to specify it. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/pgtclsh.sgml b/doc/src/sgml/ref/pgtclsh.sgml index 2a32d6305e0..f7b52a7cc08 100644 --- a/doc/src/sgml/ref/pgtclsh.sgml +++ b/doc/src/sgml/ref/pgtclsh.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/Attic/pgtclsh.sgml,v 1.8 2003/03/25 16:15:43 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/Attic/pgtclsh.sgml,v 1.8.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -17,6 +17,10 @@ PostgreSQL documentation </refpurpose> </refnamediv> + <indexterm zone="app-pgtclsh"> + <primary>pgtclsh</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>pgtclsh</command> diff --git a/doc/src/sgml/ref/pgtksh.sgml b/doc/src/sgml/ref/pgtksh.sgml index bcc052bfdbf..c04f219c3f8 100644 --- a/doc/src/sgml/ref/pgtksh.sgml +++ b/doc/src/sgml/ref/pgtksh.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/Attic/pgtksh.sgml,v 1.8 2003/03/25 16:15:43 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/Attic/pgtksh.sgml,v 1.8.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -17,6 +17,10 @@ PostgreSQL documentation </refpurpose> </refnamediv> + <indexterm zone="app-pgtksh"> + <primary>pgtksh</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>pgtksh</command> diff --git a/doc/src/sgml/ref/postgres-ref.sgml b/doc/src/sgml/ref/postgres-ref.sgml index 073b83fd7d9..66e5e02502b 100644 --- a/doc/src/sgml/ref/postgres-ref.sgml +++ b/doc/src/sgml/ref/postgres-ref.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/postgres-ref.sgml,v 1.34 2003/07/29 00:03:17 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/postgres-ref.sgml,v 1.34.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>run a <productname>PostgreSQL</productname> server in single-user mode</refpurpose> </refnamediv> + <indexterm zone="app-postgres"> + <primary>postgres (the program)</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <!-- standalone call --> diff --git a/doc/src/sgml/ref/postmaster.sgml b/doc/src/sgml/ref/postmaster.sgml index ed431c6b54b..d68827c6e1e 100644 --- a/doc/src/sgml/ref/postmaster.sgml +++ b/doc/src/sgml/ref/postmaster.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/postmaster.sgml,v 1.36 2003/03/25 16:15:43 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/postmaster.sgml,v 1.36.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose><productname>PostgreSQL</productname> multiuser database server</refpurpose> </refnamediv> + <indexterm zone="app-postmaster"> + <primary>postmaster</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>postmaster</command> diff --git a/doc/src/sgml/ref/prepare.sgml b/doc/src/sgml/ref/prepare.sgml index 9f58b7a5ce8..22f9067dd0d 100644 --- a/doc/src/sgml/ref/prepare.sgml +++ b/doc/src/sgml/ref/prepare.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/prepare.sgml,v 1.4 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/prepare.sgml,v 1.4.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>prepare a statement for execution</refpurpose> </refnamediv> + <indexterm zone="sql-prepare"> + <primary>PREPARE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> PREPARE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable class="PARAMETER">datatype</replaceable> [, ...] ) ] AS <replaceable class="PARAMETER">statement</replaceable> @@ -130,7 +134,7 @@ PREPARE <replaceable class="PARAMETER">plan_name</replaceable> [ (<replaceable c In some situations, the query plan produced by for a prepared statement may be inferior to the plan produced if the statement were submitted and executed normally. This is because when the - statement is planned and the planer attempts to determine the + statement is planned and the planner attempts to determine the optimal query plan, the actual values of any parameters specified in the statement are unavailable. <productname>PostgreSQL</productname> collects diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index 3969a1ad641..251f67fa5cd 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.94 2003/08/02 02:44:38 momjian Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.94.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -17,6 +17,10 @@ PostgreSQL documentation </refpurpose> </refnamediv> + <indexterm zone="app-psql"> + <primary>psql</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>psql</command> @@ -2210,8 +2214,14 @@ testdb=> <userinput>\set content '\'' `sed -e "s/'/\\\\\\'/g" < my_file.txt` '\' <varlistentry> <term><literal>%n</literal></term> - <listitem><para>The user name you are connected as (not your local system - user name).</para></listitem> + <listitem> + <para> + The database session user name. (The expansion of this + value might change during a database session as the result + of the command <command>SET SESSION + AUTHORIZATION</command>.) + </para> + </listitem> </varlistentry> <varlistentry> @@ -2227,8 +2237,15 @@ testdb=> <userinput>\set content '\'' `sed -e "s/'/\\\\\\'/g" < my_file.txt` '\' <varlistentry> <term><literal>%#</literal></term> - <listitem><para>If the current user is a database superuser, then a - <literal>#</literal>, otherwise a <literal>></literal>.</para></listitem> + <listitem> + <para> + If the session user is a database superuser, then a + <literal>#</literal>, otherwise a <literal>></literal>. + (The expansion of this value might change during a database + session as the result of the command <command>SET SESSION + AUTHORIZATION</command>.) + </para> + </listitem> </varlistentry> <varlistentry> diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml index 591542ac1e0..c18950d0d29 100644 --- a/doc/src/sgml/ref/reindex.sgml +++ b/doc/src/sgml/ref/reindex.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/reindex.sgml,v 1.17 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/reindex.sgml,v 1.17.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>rebuild indexes</refpurpose> </refnamediv> + <indexterm zone="sql-reindex"> + <primary>REINDEX</primary> + </indexterm> + <refsynopsisdiv> <synopsis> REINDEX { DATABASE | TABLE | INDEX } <replaceable class="PARAMETER">name</replaceable> [ FORCE ] diff --git a/doc/src/sgml/ref/reset.sgml b/doc/src/sgml/ref/reset.sgml index 87d9de30974..71a2bf01b68 100644 --- a/doc/src/sgml/ref/reset.sgml +++ b/doc/src/sgml/ref/reset.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/reset.sgml,v 1.20 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/reset.sgml,v 1.20.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>restore the value of a run-time parameter to the default value</refpurpose> </refnamediv> + <indexterm zone="sql-reset"> + <primary>RESET</primary> + </indexterm> + <refsynopsisdiv> <synopsis> RESET <replaceable class="PARAMETER">parameter</replaceable> diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml index 22cb395a75d..6f7eb06deb2 100644 --- a/doc/src/sgml/ref/revoke.sgml +++ b/doc/src/sgml/ref/revoke.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/revoke.sgml,v 1.26 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/revoke.sgml,v 1.26.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>remove access privileges</refpurpose> </refnamediv> + <indexterm zone="sql-revoke"> + <primary>REVOKE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> REVOKE [ GRANT OPTION FOR ] diff --git a/doc/src/sgml/ref/rollback.sgml b/doc/src/sgml/ref/rollback.sgml index dc5b063c495..3a6026fee2a 100644 --- a/doc/src/sgml/ref/rollback.sgml +++ b/doc/src/sgml/ref/rollback.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/rollback.sgml,v 1.14 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/rollback.sgml,v 1.14.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>abort the current transaction</refpurpose> </refnamediv> + <indexterm zone="sql-rollback"> + <primary>ROLLBACK</primary> + </indexterm> + <refsynopsisdiv> <synopsis> ROLLBACK [ WORK | TRANSACTION ] diff --git a/doc/src/sgml/ref/select.sgml b/doc/src/sgml/ref/select.sgml index f983b2a8213..2353bb540cd 100644 --- a/doc/src/sgml/ref/select.sgml +++ b/doc/src/sgml/ref/select.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/select.sgml,v 1.67 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/select.sgml,v 1.67.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>retrieve rows from a table or view</refpurpose> </refnamediv> + <indexterm zone="sql-select"> + <primary>SELECT</primary> + </indexterm> + <refsynopsisdiv> <synopsis> SELECT [ ALL | DISTINCT [ ON ( <replaceable class="parameter">expression</replaceable> [, ...] ) ] ] @@ -660,8 +664,11 @@ SELECT name FROM distributors ORDER BY code; <literal>ORDER BY</> clause. If not specified, <literal>ASC</> is assumed by default. Alternatively, a specific ordering operator name may be specified in the <literal>USING</> clause. - <literal>ASC</> is equivalent to <literal>USING <</> and - <literal>DESC</> is equivalent to <literal>USING ></>. + <literal>ASC</> is usually equivalent to <literal>USING <</> and + <literal>DESC</> is usually equivalent to <literal>USING ></>. + (But the creator of a user-defined datatype can define exactly what the + default sort ordering is, and it might correspond to operators with other + names.) </para> <para> @@ -671,7 +678,7 @@ SELECT name FROM distributors ORDER BY code; </para> <para> - Data of character types is sorted according to the locale-specific + Character-string data is sorted according to the locale-specific collation order that was established when the database cluster was initialized. </para> @@ -1003,7 +1010,9 @@ SELECT distributors.* FROM distributors d, distributors distributors; that he will actually get. To help detect this sort of mistake, PostgreSQL will warn if the implicit-<literal>FROM</literal> feature is used in a <command>SELECT</command> statement that also - contains an explicit <literal>FROM</literal> clause. + contains an explicit <literal>FROM</literal> clause. Also, it is + possible to disable the implicit-<literal>FROM</literal> feature + by setting the <varname>ADD_MISSING_FROM</> parameter to false. </para> </refsect2> @@ -1015,7 +1024,7 @@ SELECT distributors.* FROM distributors d, distributors distributors; noise and can be omitted without affecting the meaning. The <productname>PostgreSQL</productname> parser requires this key word when renaming output columns because the type extensibility - features lead to parsing ambiguities in this context. + features lead to parsing ambiguities without it. <literal>AS</literal> is optional in <literal>FROM</literal> items, however. </para> @@ -1025,7 +1034,7 @@ SELECT distributors.* FROM distributors d, distributors distributors; <title>Namespace Available to <literal>GROUP BY</literal> and <literal>ORDER BY</literal></title> <para> - In the SQL standard, an <literal>ORDER BY</literal> clause may + In the SQL92 standard, an <literal>ORDER BY</literal> clause may only use result column names or numbers, while a <literal>GROUP BY</literal> clause may only use expressions based on input column names. <productname>PostgreSQL</productname> extends each of @@ -1036,6 +1045,13 @@ SELECT distributors.* FROM distributors d, distributors distributors; expression will always be taken as input-column names, not as result-column names. </para> + + <para> + SQL99 uses a slightly different definition which is not upward compatible + with SQL92. In most cases, however, <productname>PostgreSQL</productname> + will interpret an <literal>ORDER BY</literal> or <literal>GROUP + BY</literal> expression the same way SQL99 does. + </para> </refsect2> <refsect2> diff --git a/doc/src/sgml/ref/select_into.sgml b/doc/src/sgml/ref/select_into.sgml index 131bb6e1a2f..b7263025170 100644 --- a/doc/src/sgml/ref/select_into.sgml +++ b/doc/src/sgml/ref/select_into.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/select_into.sgml,v 1.22 2003/05/04 02:23:16 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/select_into.sgml,v 1.22.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>create a new table from the results of a query</refpurpose> </refnamediv> + <indexterm zone="sql-selectinto"> + <primary>SELECT INTO</primary> + </indexterm> + <refsynopsisdiv> <synopsis> SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replaceable> [, ...] ) ] ] diff --git a/doc/src/sgml/ref/set.sgml b/doc/src/sgml/ref/set.sgml index bb1ddd22759..57c491d6df5 100644 --- a/doc/src/sgml/ref/set.sgml +++ b/doc/src/sgml/ref/set.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/set.sgml,v 1.80 2003/07/29 00:03:17 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/set.sgml,v 1.80.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>change a run-time parameter</refpurpose> </refnamediv> + <indexterm zone="sql-set"> + <primary>SET</primary> + </indexterm> + <refsynopsisdiv> <synopsis> SET [ SESSION | LOCAL ] <replaceable class="PARAMETER">variable</replaceable> { TO | = } { <replaceable class="PARAMETER">value</replaceable> | '<replaceable class="PARAMETER">value</replaceable>' | DEFAULT } diff --git a/doc/src/sgml/ref/set_constraints.sgml b/doc/src/sgml/ref/set_constraints.sgml index 3d5b58bee2e..3e89f60769d 100644 --- a/doc/src/sgml/ref/set_constraints.sgml +++ b/doc/src/sgml/ref/set_constraints.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/set_constraints.sgml,v 1.6 2003/05/04 02:23:16 petere Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/set_constraints.sgml,v 1.6.2.1 2003/09/07 04:36:46 momjian Exp $ --> <refentry id="SQL-SET-CONSTRAINTS"> <refmeta> <refentrytitle id="SQL-SET-CONSTRAINTS-title">SET CONSTRAINTS</refentrytitle> @@ -10,6 +10,10 @@ <refpurpose>set the constraint mode of the current transaction</refpurpose> </refnamediv> + <indexterm zone="sql-set-constraints"> + <primary>SET CONSTRAINTS</primary> + </indexterm> + <refsynopsisdiv> <synopsis> SET CONSTRAINTS { ALL | <replaceable class="parameter">constraint</replaceable> [, ...] } { DEFERRED | IMMEDIATE } diff --git a/doc/src/sgml/ref/set_session_auth.sgml b/doc/src/sgml/ref/set_session_auth.sgml index f8c0297adad..ba2c27acbe9 100644 --- a/doc/src/sgml/ref/set_session_auth.sgml +++ b/doc/src/sgml/ref/set_session_auth.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/set_session_auth.sgml,v 1.9 2003/05/04 02:23:16 petere Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/set_session_auth.sgml,v 1.9.2.1 2003/09/07 04:36:46 momjian Exp $ --> <refentry id="SQL-SET-SESSION-AUTHORIZATION"> <refmeta> <refentrytitle id="sql-set-session-authorization-title">SET SESSION AUTHORIZATION</refentrytitle> @@ -10,6 +10,10 @@ <refpurpose>set the session user identifier and the current user identifier of the current session</refpurpose> </refnamediv> + <indexterm zone="sql-set-session-authorization"> + <primary>SET SESSION AUTHORIZATION</primary> + </indexterm> + <refsynopsisdiv> <synopsis> SET [ SESSION | LOCAL ] SESSION AUTHORIZATION <replaceable class="parameter">username</replaceable> diff --git a/doc/src/sgml/ref/set_transaction.sgml b/doc/src/sgml/ref/set_transaction.sgml index 2ff29bc3d5f..d531d8f43af 100644 --- a/doc/src/sgml/ref/set_transaction.sgml +++ b/doc/src/sgml/ref/set_transaction.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/set_transaction.sgml,v 1.14 2003/05/04 02:23:16 petere Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/set_transaction.sgml,v 1.14.2.1 2003/09/07 04:36:46 momjian Exp $ --> <refentry id="SQL-SET-TRANSACTION"> <refmeta> <refentrytitle id="SQL-SET-TRANSACTION-TITLE">SET TRANSACTION</refentrytitle> @@ -10,6 +10,10 @@ <refpurpose>set the characteristics of the current transaction</refpurpose> </refnamediv> + <indexterm zone="sql-set-transaction"> + <primary>SET TRANSACTION</primary> + </indexterm> + <refsynopsisdiv> <synopsis> SET TRANSACTION diff --git a/doc/src/sgml/ref/show.sgml b/doc/src/sgml/ref/show.sgml index 1f0f52735a0..3bb52cce54b 100644 --- a/doc/src/sgml/ref/show.sgml +++ b/doc/src/sgml/ref/show.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/show.sgml,v 1.30 2003/07/29 00:03:17 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/show.sgml,v 1.30.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>show the value of a run-time parameter</refpurpose> </refnamediv> + <indexterm zone="sql-show"> + <primary>SHOW</primary> + </indexterm> + <refsynopsisdiv> <synopsis> SHOW <replaceable class="PARAMETER">name</replaceable> diff --git a/doc/src/sgml/ref/start_transaction.sgml b/doc/src/sgml/ref/start_transaction.sgml index 5b9abefddd8..8b8690c0f29 100644 --- a/doc/src/sgml/ref/start_transaction.sgml +++ b/doc/src/sgml/ref/start_transaction.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/start_transaction.sgml,v 1.5 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/start_transaction.sgml,v 1.5.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>start a transaction block</refpurpose> </refnamediv> + <indexterm zone="sql-start-transaction"> + <primary>START TRANSACTION</primary> + </indexterm> + <refsynopsisdiv> <synopsis> START TRANSACTION [ ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE } ] [ READ WRITE | READ ONLY ] diff --git a/doc/src/sgml/ref/truncate.sgml b/doc/src/sgml/ref/truncate.sgml index b5b9d84ddc8..f10d0a4456c 100644 --- a/doc/src/sgml/ref/truncate.sgml +++ b/doc/src/sgml/ref/truncate.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/truncate.sgml,v 1.10 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/truncate.sgml,v 1.10.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>empty a table</refpurpose> </refnamediv> + <indexterm zone="sql-truncate"> + <primary>TRUNCATE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> TRUNCATE [ TABLE ] <replaceable class="PARAMETER">name</replaceable> diff --git a/doc/src/sgml/ref/unlisten.sgml b/doc/src/sgml/ref/unlisten.sgml index 4c3799177b2..54e857b3c9b 100644 --- a/doc/src/sgml/ref/unlisten.sgml +++ b/doc/src/sgml/ref/unlisten.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/unlisten.sgml,v 1.21 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/unlisten.sgml,v 1.21.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>stop listening for a notification</refpurpose> </refnamediv> + <indexterm zone="sql-unlisten"> + <primary>UNLISTEN</primary> + </indexterm> + <refsynopsisdiv> <synopsis> UNLISTEN { <replaceable class="PARAMETER">name</replaceable> | * } diff --git a/doc/src/sgml/ref/update.sgml b/doc/src/sgml/ref/update.sgml index 1fe85b995ed..c7020e85a7a 100644 --- a/doc/src/sgml/ref/update.sgml +++ b/doc/src/sgml/ref/update.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/update.sgml,v 1.23 2003/07/03 16:32:12 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/update.sgml,v 1.23.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>update rows of a table</refpurpose> </refnamediv> + <indexterm zone="sql-update"> + <primary>UPDATE</primary> + </indexterm> + <refsynopsisdiv> <synopsis> UPDATE [ ONLY ] <replaceable class="PARAMETER">table</replaceable> SET <replaceable class="PARAMETER">column</replaceable> = { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] diff --git a/doc/src/sgml/ref/vacuum.sgml b/doc/src/sgml/ref/vacuum.sgml index 3f532c02448..3cfba61f445 100644 --- a/doc/src/sgml/ref/vacuum.sgml +++ b/doc/src/sgml/ref/vacuum.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/vacuum.sgml,v 1.31 2003/04/26 23:56:51 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/vacuum.sgml,v 1.31.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -14,6 +14,10 @@ PostgreSQL documentation <refpurpose>garbage-collect and optionally analyze a database</refpurpose> </refnamediv> + <indexterm zone="sql-vacuum"> + <primary>VACUUM</primary> + </indexterm> + <refsynopsisdiv> <synopsis> VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ <replaceable class="PARAMETER">table</replaceable> ] diff --git a/doc/src/sgml/ref/vacuumdb.sgml b/doc/src/sgml/ref/vacuumdb.sgml index e04cf16c3fe..5bc236ccd8b 100644 --- a/doc/src/sgml/ref/vacuumdb.sgml +++ b/doc/src/sgml/ref/vacuumdb.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/vacuumdb.sgml,v 1.29 2003/06/18 12:19:11 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/vacuumdb.sgml,v 1.29.2.1 2003/09/07 04:36:46 momjian Exp $ PostgreSQL documentation --> @@ -15,6 +15,10 @@ PostgreSQL documentation <refpurpose>garbage-collect and analyze a <productname>PostgreSQL</productname> database</refpurpose> </refnamediv> + <indexterm zone="app-vacuumdb"> + <primary>vacuumdb</primary> + </indexterm> + <refsynopsisdiv> <cmdsynopsis> <command>vacuumdb</command> @@ -59,10 +63,11 @@ PostgreSQL documentation <para> - <application>vacuumdb</application> might need to connect several - times to the <productname>PostgreSQL</productname> server, asking for - a password each time. It is convenient to have a - <filename>$HOME/.pgpass</> file in such cases. + <application>vacuumdb</application> might need to connect several + times to the <productname>PostgreSQL</productname> server, asking + for a password each time. It is convenient to have a + <filename>$HOME/.pgpass</> file in such cases. See <xref + linkend="libpq-pgpass"> for more information. </para> </refsect1> @@ -234,7 +239,7 @@ PostgreSQL documentation <term><computeroutput>VACUUM</computeroutput></term> <listitem> <para> - Everything went well. + The database was successfully vacuumed. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/regress.sgml b/doc/src/sgml/regress.sgml index a5dac7a1411..52ea13fae0e 100644 --- a/doc/src/sgml/regress.sgml +++ b/doc/src/sgml/regress.sgml @@ -1,8 +1,16 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/regress.sgml,v 1.32 2003/04/06 17:47:24 tgl Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/regress.sgml,v 1.32.2.1 2003/09/07 04:36:43 momjian Exp $ --> <chapter id="regress"> <title id="regress-title">Regression Tests</title> + <indexterm zone="regress"> + <primary>regression tests</primary> + </indexterm> + + <indexterm zone="regress"> + <primary>test</primary> + </indexterm> + <para> The regression tests are a comprehensive set of tests for the SQL implementation in <productname>PostgreSQL</productname>. They test diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml index 1f4538c7c87..9ff2cb05cce 100644 --- a/doc/src/sgml/release.sgml +++ b/doc/src/sgml/release.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.204 2003/07/31 04:48:15 momjian Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.204.2.1 2003/09/07 04:36:43 momjian Exp $ --> <appendix id="release"> @@ -456,8 +456,8 @@ Properly escape jdbc setObject() strings to improve security (Barry) application examines the system catalogs, additional changes will be required due to the introduction of schemas in 7.3; for more information, see: <ulink - url="http://www.ca.postgresql.org/docs/momjian/upgrade_tips_7.3"> - http://www.ca.postgresql.org/docs/momjian/upgrade_tips_7.3</>. + url="http://developer.postgresql.org/~momjian/upgrade_tips_7.3"> + http://developer.postgresql.org/~momjian/upgrade_tips_7.3</>. </para> <para> @@ -4901,7 +4901,7 @@ Contributors (appologies to any missed) * david bennett <dave@bensoft.com> * ernst.molitor@uni-bonn.de * Julian Assange <proff@suburbia.net> - * Bruce Momjian <maillist@candle.pha.pa.us> + * Bruce Momjian <pgman@candle.pha.pa.us> * Paul "Shag" Walmsley <ccshag@cclabs.missouri.edu> * "Alistair G. Crooks" <azcb0@sde.uts.amdahl.com> --> diff --git a/doc/src/sgml/rules.sgml b/doc/src/sgml/rules.sgml index 66d20cb11b7..2d485b4d595 100644 --- a/doc/src/sgml/rules.sgml +++ b/doc/src/sgml/rules.sgml @@ -1,10 +1,10 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/rules.sgml,v 1.28 2003/04/11 13:22:35 petere Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/rules.sgml,v 1.28.2.1 2003/09/07 04:36:43 momjian Exp $ --> <Chapter Id="rules"> <Title>The Rule System</Title> <indexterm zone="rules"> - <primary>rules</primary> + <primary>rule</primary> </indexterm> <Para> @@ -35,6 +35,10 @@ <Sect1 id="querytree"> <Title>The Query Tree</Title> +<indexterm zone="querytree"> + <primary>query tree</primary> +</indexterm> + <Para> To understand how the rule system works it is necessary to know when it is invoked and what its input and results are. @@ -146,6 +150,7 @@ <Term> the target list </Term> + <indexterm><primary>target list</></> <ListItem> <Para> The target list is a list of expressions that define the @@ -258,7 +263,16 @@ <Sect1 id="rules-views"> <Title>Views and the Rule System</Title> -<indexterm zone="rules-views"><primary>rules</><secondary>and views</></> + +<indexterm zone="rules-views"> + <primary>rule</primary> + <secondary>and views</secondary> +</indexterm> + +<indexterm zone="rules-views"> + <primary>view</> + <secondary>implementation through rules</> +</indexterm> <Para> Views in <ProductName>PostgreSQL</ProductName> are implemented @@ -286,9 +300,14 @@ CREATE RULE "_RETURN" AS ON SELECT TO myview DO INSTEAD same thing: relations. </Para> -<Sect2> +<Sect2 id="rules-select"> <Title>How <command>SELECT</command> Rules Work</Title> +<indexterm zone="rules-select"> + <primary>rule</primary> + <secondary sortas="SELECT">for SELECT</secondary> +</indexterm> + <Para> Rules <literal>ON SELECT</> are applied to all queries as the last step, even if the command given is an <command>INSERT</command>, @@ -736,7 +755,7 @@ SELECT t1.a, t2.b FROM t1, t2 WHERE t1.a = t2.a; To resolve this problem, another entry is added to the target list in <command>UPDATE</command> (and also in <command>DELETE</command>) statements: the current tuple ID - (<acronym>CTID</>). This is a system column containing the + (<acronym>CTID</>).<indexterm><primary>CTID</></> This is a system column containing the file block number and position in the block for the row. Knowing the table, the <acronym>CTID</> can be used to retrieve the original row of <literal>t1</> to be updated. After adding the <acronym>CTID</> @@ -817,6 +836,21 @@ SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a; <Sect1 id="rules-update"> <Title>Rules on <command>INSERT</>, <command>UPDATE</>, and <command>DELETE</></Title> +<indexterm zone="rules-update"> + <primary>rule</primary> + <secondary sortas="INSERT">for INSERT</secondary> +</indexterm> + +<indexterm zone="rules-update"> + <primary>rule</primary> + <secondary sortas="UPDATE">for UPDATE</secondary> +</indexterm> + +<indexterm zone="rules-update"> + <primary>rule</primary> + <secondary sortas="DELETE">for DELETE</secondary> +</indexterm> + <Para> Rules that are defined on <command>INSERT</>, <command>UPDATE</>, and <command>DELETE</> are significantly different from the view rules @@ -1243,7 +1277,7 @@ SELECT shoelace_data.sl_name, 0, <Sect2 id="rules-update-views"> <Title>Cooperation with Views</Title> -<indexterm zone="rules-update-views"><primary>views</><secondary>updating</></> +<indexterm zone="rules-update-views"><primary>view</><secondary>updating</></> <Para> A simple way to protect view relations from the mentioned @@ -1654,6 +1688,16 @@ SELECT * FROM shoelace; <Sect1 id="rules-privileges"> <Title>Rules and Privileges</Title> +<indexterm zone="rules-privileges"> + <primary>privilege</primary> + <secondary sortas="Regeln">with rules</secondary> +</indexterm> + +<indexterm zone="rules-privileges"> + <primary>privilege</primary> + <secondary sortas="Sichten">with views</secondary> +</indexterm> + <Para> Due to rewriting of queries by the <ProductName>PostgreSQL</ProductName> rule system, other tables/views than those used in the original @@ -1796,6 +1840,16 @@ GRANT SELECT ON phone_number TO secretary; <Sect1 id="rules-triggers"> <Title>Rules versus Triggers</Title> +<indexterm zone="rules-triggers"> + <primary>rule</primary> + <secondary sortas="Trigger">compared with triggers</secondary> +</indexterm> + +<indexterm zone="rules-triggers"> + <primary>trigger</primary> + <secondary sortas="Regeln">compared with rules</secondary> +</indexterm> + <Para> Many things that can be done using triggers can also be implemented using the <ProductName>PostgreSQL</ProductName> diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 6adfd85df0f..37168a47b0b 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.199 2003/08/10 01:20:34 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.199.2.1 2003/09/07 04:36:43 momjian Exp $ --> <Chapter Id="runtime"> @@ -69,7 +69,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.199 2003/08/10 01:20:34 tg default, although locations such as <filename>/usr/local/pgsql/data</filename> or <filename>/var/lib/pgsql/data</filename> are popular. To initialize a - database cluster, use the command <command>initdb</command>, which is + database cluster, use the command <command>initdb</command>,<indexterm><primary>initdb</></> which is installed with <productname>PostgreSQL</productname>. The desired file system location of your database system is indicated by the <option>-D</option> option, for example @@ -120,11 +120,13 @@ postgres$ <userinput>initdb -D /usr/local/pgsql/data</userinput> <para> However, while the directory contents are secure, the default client authentication setup allows any local user to connect to the - database and even become the database superuser. If you do not trust - other local users, we recommend you use <command>initdb</command>'s - <option>-W</option> or <option>--pwprompt</option> option to assign a - password to the database superuser. After <command>initdb</command>, - modify the <filename>pg_hba.conf</filename> file to use <literal>md5</> or + database and even become the database superuser. If you do not + trust other local users, we recommend you use + <command>initdb</command>'s <option>-W</option> or + <option>--pwprompt</option> option to assign a password to the + database superuser.<indexterm><primary>password</><secondary>of the + superuser</></indexterm> After <command>initdb</command>, modify + the <filename>pg_hba.conf</filename> file to use <literal>md5</> or <literal>password</> instead of <literal>trust</> authentication <emphasis>before</> you start the server for the first time. (Other approaches include using <literal>ident</literal> authentication or @@ -207,8 +209,9 @@ pg_ctl start -l logfile <para> Normally, you will want to start the database server when the - computer boots. Autostart scripts are operating system-specific. - There are a few distributed with + computer boots.<indexterm><primary>booting</><secondary>starting + the server during</></> Autostart scripts are operating + system-specific. There are a few distributed with <productname>PostgreSQL</productname> in the <filename>contrib/start-scripts</> directory. This may require root privileges. @@ -240,7 +243,7 @@ su -c 'pg_ctl start -D /usr/local/pgsql/data -l serverlog' postgres For <productname>FreeBSD</productname>, look at the file <filename>contrib/start-scripts/freebsd</filename> in the <productname>PostgreSQL</productname> source distribution. - <indexterm><primary>FreeBSD</></> + <indexterm><primary>FreeBSD</><secondary>start script</secondary></> </para> </listitem> @@ -248,7 +251,7 @@ su -c 'pg_ctl start -D /usr/local/pgsql/data -l serverlog' postgres <para> On <productname>OpenBSD</productname>, add the following lines to the file <filename>/etc/rc.local</filename>: - <indexterm><primary>OpenBSD</></> + <indexterm><primary>OpenBSD</><secondary>start script</secondary></> <programlisting> if [ -x /usr/local/pgsql/bin/pg_ctl -a -x /usr/local/pgsql/bin/postmaster ]; then su - -c '/usr/local/pgsql/bin/pg_ctl start -l /var/postgresql/log -s' postgres @@ -261,7 +264,7 @@ fi <listitem> <para> On <productname>Linux</productname> systems either add - <indexterm><primary>Linux</></> + <indexterm><primary>Linux</><secondary>start script</secondary></> <programlisting> /usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data </programlisting> @@ -276,7 +279,7 @@ fi On <productname>NetBSD</productname>, either use the <productname>FreeBSD</productname> or <productname>Linux</productname> start scripts, depending on - preference. <indexterm><primary>NetBSD</></> + preference. <indexterm><primary>NetBSD</><secondary>start script</secondary></> </para> </listitem> @@ -285,7 +288,7 @@ fi On <productname>Solaris</productname>, create a file called <filename>/etc/init.d/postgresql</filename> that contains the following line: - <indexterm><primary>Solaris</></> + <indexterm><primary>Solaris</><secondary>start script</secondary></> <programlisting> su - postgres -c "/usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data" </programlisting> @@ -441,7 +444,7 @@ psql: could not connect to server: Connection refused <indexterm> <primary>configuration</primary> - <secondary>server</secondary> + <secondary>of the server</secondary> </indexterm> <para> @@ -462,7 +465,7 @@ psql: could not connect to server: Connection refused <para> One way to set these options is to edit the file - <filename>postgresql.conf</filename> in the data directory. (A + <filename>postgresql.conf</filename><indexterm><primary>postgresql.conf</></> in the data directory. (A default file is installed there.) An example of what this file might look like is: <programlisting> @@ -626,7 +629,7 @@ SET ENABLE_SEQSCAN TO OFF; <term><varname>TCPIP_SOCKET</varname> (<type>boolean</type>)</term> <listitem> <para> - If this is true, then the server will accept TCP/IP connections. + If this is true, then the server will accept TCP/IP connections.<indexterm><primary>TCP/IP</></> Otherwise only local Unix domain socket connections are accepted. It is off by default. This option can only be set at server start. @@ -781,7 +784,8 @@ SET ENABLE_SEQSCAN TO OFF; <variablelist> <varlistentry> <term><varname>AUTHENTICATION_TIMEOUT</varname> (<type>integer</type>)</term> - <indexterm><primary>timeout</><secondary>authentication</></indexterm> + <indexterm><primary>timeout</><secondary>client authentication</></indexterm> + <indexterm><primary>client authentication</><secondary>timeout during</></indexterm> <listitem> <para> Maximum time to complete client authentication, in seconds. If a @@ -1514,8 +1518,17 @@ SET ENABLE_SEQSCAN TO OFF; <sect2 id="runtime-config-logging"> <title>Error Reporting and Logging</title> + <indexterm zone="runtime-config-logging"> + <primary>server log</primary> + </indexterm> + <sect3 id="runtime-config-logging-syslog"> <title>Syslog</title> + + <indexterm zone="runtime-config-logging-syslog"> + <primary>syslog</primary> + </indexterm> + <variablelist> <varlistentry> @@ -2137,7 +2150,7 @@ SET ENABLE_SEQSCAN TO OFF; <varlistentry> <term><varname>AUSTRALIAN_TIMEZONES</varname> (<type>boolean</type>)</term> - <indexterm><primary>Australian time zones</></> + <indexterm><primary>time zone</><secondary>Australian</></> <listitem> <para> If set to true, <literal>ACST</literal>, @@ -2154,8 +2167,8 @@ SET ENABLE_SEQSCAN TO OFF; <primary>significant digits</primary> </indexterm> <indexterm> - <primary>display</primary> - <secondary>of float numbers</secondary> + <primary>floating-point</primary> + <secondary>display</secondary> </indexterm> <term><varname>EXTRA_FLOAT_DIGITS</varname> (<type>integer</type>)</term> @@ -2175,7 +2188,7 @@ SET ENABLE_SEQSCAN TO OFF; <varlistentry> <term><varname>CLIENT_ENCODING</varname> (<type>string</type>)</term> - <indexterm><primary>character set encoding</></> + <indexterm><primary>character set</></> <listitem> <para> Sets the client-side encoding (character set). @@ -2338,7 +2351,7 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir' <varlistentry> <indexterm> <primary>deadlock</primary> - <secondary>timeout</secondary> + <secondary>timeout during</secondary> </indexterm> <indexterm> <primary>timeout</primary> @@ -2388,14 +2401,22 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir' <title>Version and Platform Compatibility</title> <sect3 id="runtime-config-compatible-version"> - <title>Previous Postgres Versions</title> + <title>Previous PostgreSQL Versions</title> <variablelist> <varlistentry> <term><varname>ADD_MISSING_FROM</varname> (<type>boolean</type>)</term> - <indexterm><primary>missing from</></> + <indexterm><primary>FROM</><secondary>missing</></> <listitem> <para> + When <literal>true</>, tables that are referenced by a query will be + automatically added to the <literal>FROM</> clause if not already + present. The default is <literal>true</> for compatibility with + previous releases of <productname>PostgreSQL</>. However, this + behavior is not SQL-standard, and many people dislike it because it + can mask mistakes. Set to <literal>false</> for the SQL-standard + behavior of rejecting references to tables that are not listed in + <literal>FROM</>. </para> </listitem> </varlistentry> @@ -2905,7 +2926,7 @@ $ <userinput>postmaster -o '-S 1024 -s'</userinput> <varlistentry> <term><systemitem class="osname">BSD/OS</></term> - <indexterm><primary>BSD/OS</></> + <indexterm><primary>BSD/OS</><secondary>IPC configuration</></> <listitem> <formalpara> <title>Shared Memory</> @@ -2966,9 +2987,9 @@ options "SEMMNS=240" <term><systemitem class="osname">FreeBSD</></term> <term><systemitem class="osname">NetBSD</></term> <term><systemitem class="osname">OpenBSD</></term> - <indexterm><primary>FreeBSD</></> - <indexterm><primary>NetBSD</></> - <indexterm><primary>OpenBSD</></> + <indexterm><primary>FreeBSD</><secondary>IPC configuration</></> + <indexterm><primary>NetBSD</><secondary>IPC configuration</></> + <indexterm><primary>OpenBSD</><secondary>IPC configuration</></> <listitem> <para> The options <varname>SYSVSHM</> and <varname>SYSVSEM</> need @@ -3002,7 +3023,7 @@ options SEMMAP=256 <varlistentry> <term><systemitem class="osname">HP-UX</></term> - <indexterm><primary>HP-UX</></> + <indexterm><primary>HP-UX</><secondary>IPC configuration</></> <listitem> <para> The default settings tend to suffice for normal installations. @@ -3023,7 +3044,7 @@ options SEMMAP=256 <varlistentry> <term><systemitem class="osname">Linux</></term> - <indexterm><primary>Linux</></> + <indexterm><primary>Linux</><secondary>IPC configuration</></> <listitem> <para> The default shared memory limit (both @@ -3060,14 +3081,61 @@ kernel.shmmax = 134217728 </para> <para> - Linux has poor default memory overcommit behavior. Rather than - failing if it can not reserve enough memory, it returns success, - but later fails when the memory can't be mapped and terminates - the application with <literal>kill -9</>. To prevent unpredictable - process termination, use: + Linux kernel version 2.4.* has poor default memory overcommit + behavior, which can result in the postmaster being killed by the + kernel due to memory demands by another process if the system + runs out of memory. + </para> + + <para> + The symptom of this occuring is a kernel message looking like + this (consult your system documentation and configuration on + where to look for such a message): +<programlisting> + Out of Memory: Killed process 12345 (postmaster). +</programlisting> + </para> + + <para> + To avoid this situation, run <productname>PostgreSQL</productname> + on a machine where you + can be sure that other processes will not run the machine out + of memory. If your kernel supports strict and/or paranoid modes + of overcommit handling, you can also relieve this problem by + altering the system's default behaviour. This can be determined + by examining the function <function>vm_enough_memory</> + in the file <filename>mm/mmap.c</> in the kernel source. + If this file reveals that strict and/or paranoid modes are + supported by your kernel, turn one of these modes on by using +<programlisting> +sysctl -w vm.overcommit_memory=2 +</programlisting> + for strict mode or <programlisting> sysctl -w vm.overcommit_memory=3 </programlisting> + for paranoid mode, or placing an equivalent entry in + <filename>/etc/sysctl.conf</>. + </para> + + <note> + <para> + Warning: using these settings in a kernel which does not support + these modes will almost certainly increase the danger of the + kernel killing the postmaster, rather than reducing it. + If in any doubt, consult a kernel expert or your kernel vendor. + </para> + </note> + + <para> + These modes are expected to be supported in all 2.6 and later + kernels. Some vendor 2.4 kernels may also support these modes. + However, it is known that some vendor documents suggest that + they support them while examination of the kernel source reveals + that they do not. + </para> + + <para> Note, you will need enough swap space to cover all your memory needs. </para> </listitem> @@ -3076,7 +3144,7 @@ sysctl -w vm.overcommit_memory=3 <varlistentry> <term><systemitem class="osname">MacOS X</></term> - <indexterm><primary>MacOS X</></> + <indexterm><primary>MacOS X</><secondary>IPC configuration</></> <listitem> <para> Edit the file @@ -3096,7 +3164,7 @@ sysctl -w kern.sysv.shmall <varlistentry> <term><systemitem class="osname">SCO OpenServer</></term> - <indexterm><primary>SCO OpenServer</></> + <indexterm><primary>SCO OpenServer</><secondary>IPC configuration</></> <listitem> <para> In the default configuration, only 512 kB of shared memory per @@ -3124,7 +3192,7 @@ sysctl -w kern.sysv.shmall <varlistentry> <term><systemitem class="osname">Solaris</></term> - <indexterm><primary>Solaris</></> + <indexterm><primary>Solaris</><secondary>IPC configuration</></> <listitem> <para> At least in version 2.6, the default maximum size of a shared @@ -3157,7 +3225,7 @@ set semsys:seminfo_semmsl=32 <varlistentry> <term><systemitem class="osname">UnixWare</></term> - <indexterm><primary>UnixWare</></> + <indexterm><primary>UnixWare</><secondary>IPC configuration</></> <listitem> <para> On <productname>UnixWare</> 7, the maximum size for shared @@ -3277,13 +3345,17 @@ default:\ <sect1 id="postmaster-shutdown"> <title>Shutting Down the Server</title> + <indexterm zone="postmaster-shutdown"> + <primary>shutdown</> + </indexterm> + <para> There are several ways to shut down the database server. You control the type of shutdown by sending different signals to the server process. <variablelist> <varlistentry> - <term><systemitem>SIGTERM</systemitem></term> + <term><systemitem>SIGTERM</systemitem><indexterm><primary>SIGTERM</></></term> <listitem> <para> After receiving <systemitem>SIGTERM</systemitem>, the server @@ -3296,7 +3368,7 @@ default:\ </varlistentry> <varlistentry> - <term><systemitem>SIGINT</systemitem></term> + <term><systemitem>SIGINT</systemitem><indexterm><primary>SIGINT</></></term> <listitem> <para> The server disallows new connections and sends all existing @@ -3309,7 +3381,7 @@ default:\ </varlistentry> <varlistentry> - <term><systemitem>SIGQUIT</systemitem></term> + <term><systemitem>SIGQUIT</systemitem><indexterm><primary>SIGQUIT</></></term> <listitem> <para> This is the <firstterm>Immediate Shutdown</firstterm>, which diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml index b3c65204c44..795db64a6bf 100644 --- a/doc/src/sgml/spi.sgml +++ b/doc/src/sgml/spi.sgml @@ -1,3821 +1,2462 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/spi.sgml,v 1.25 2003/01/21 22:06:11 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/spi.sgml,v 1.25.2.1 2003/09/07 04:36:44 momjian Exp $ --> -<Chapter id="spi"> -<DocInfo> -<AuthorGroup> -<Author> -<FirstName>Vadim</FirstName> -<Surname>Mikheev</Surname> -</Author> -</AuthorGroup> -<Date>Transcribed 1998-01-16</Date> -</DocInfo> - -<Title>Server Programming Interface</Title> - -<Para> -The <FirstTerm>Server Programming Interface</FirstTerm> -(<Acronym>SPI</Acronym>) gives users the -ability to run <Acronym>SQL</Acronym> queries inside user-defined -<Acronym>C</Acronym> functions. -</Para> - -<note> -<para> -The available Procedural Languages (<Acronym>PL</Acronym>) give an alternate -means to build functions that can execute queries. -</para> -</note> - -<Para> -In fact, <Acronym>SPI</Acronym> is just a set of native interface functions -to simplify access to the Parser, Planner, Optimizer and Executor. -<Acronym>SPI</Acronym> also does some memory management. -</Para> - -<Para> -To avoid misunderstanding we'll use <FirstTerm>function</FirstTerm> -to mean <Acronym>SPI</Acronym> interface functions and -<FirstTerm>procedure</FirstTerm> for user-defined C-functions -using <Acronym>SPI</Acronym>. -</Para> - -<Para> -Procedures which use <Acronym>SPI</Acronym> are called by the -Executor. The <Acronym>SPI</Acronym> calls recursively invoke the -Executor in turn to run queries. When the Executor is invoked -recursively, it may itself call procedures which may make -<Acronym>SPI</Acronym> calls. -</Para> - -<Para> -Note that if during execution of a query from a procedure the transaction is -aborted, then control will not be returned to your procedure. Rather, all work -will be rolled back and the server will wait for the next command from the -client. This will probably be changed in future versions. -</Para> - -<Para> -A related restriction is the inability to execute BEGIN, END and ABORT -(transaction control statements). This will also be -changed in the future. -</Para> - -<Para> -If successful, <Acronym>SPI</Acronym> functions return a non-negative result (either via -a returned integer value or in SPI_result global variable, as described below). -On error, a negative or NULL result will be returned. -</Para> - -<Sect1 id="spi-interface"> -<Title>Interface Functions</Title> - -<REFENTRY ID="SPI-SPICONNECT"> -<REFMETA> -<REFENTRYTITLE>SPI_connect</REFENTRYTITLE> -<REFMISCINFO>SPI - Connection Management</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_connect -</REFNAME> -<REFPURPOSE> - Connects your procedure to the SPI manager. -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPICONNECT-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPICONNECT-2"><PRIMARY>SPI_connect</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> +<chapter id="spi"> + <title>Server Programming Interface</title> + + <indexterm zone="spi"> + <primary>SPI</primary> + </indexterm> + + <para> + The <firstterm>Server Programming Interface</firstterm> + (<acronym>SPI</acronym>) gives users the ability to run + <acronym>SQL</acronym> commands inside user-defined + <acronym>C</acronym> functions. <acronym>SPI</acronym> is a set of + interface functions to simplify access to the parser, planner, + optimizer, and executor. <acronym>SPI</acronym> also does some + memory management. + </para> + + <para> + To avoid misunderstanding we'll use the term <quote>function</quote> + when we speak of <acronym>SPI</acronym> interface functions and + <quote>procedure</quote> for user-defined C-functions, which may be + using <acronym>SPI</acronym>. + </para> + + <para> + Note that if during the execution of a procedure the transaction is + aborted because of an error in a command, then control will not be + returned to your procedure. Rather, all work will be rolled back + and the server will wait for the next command from the client. A + related restriction is the inability to execute + <command>BEGIN</command>, <command>COMMIT</command>, and + <command>ROLLBACK</command> (transaction control statements) inside + a procedure. Both of these restrictions will probably be changed in + the future. + </para> + + <para> + <acronym>SPI</acronym> functions return a nonnegative result on + success (either via a returned integer value or in the global + variable <varname>SPI_result</varname>, as described below). On + error, a negative result or <symbol>NULL</symbol> will be returned. + </para> + + <para> + Source code files that use SPI must include the header file + <filename>executor/spi.h</filename>. + </para> + + <note> + <para> + The available procedural languages provide different means to + execute SQL commands from procedures. Some of these are modelled + after SPI, so this documentation might be of use for those users as + well. + </para> + </note> + + +<sect1 id="spi-interface"> + <title>Interface Functions</title> + + <refentry id="spi-spi-connect"> + <refmeta> + <refentrytitle>SPI_connect</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_connect</refname> + <refpurpose>connect a procedure to the SPI manager</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_connect</primary></indexterm> + + <refsynopsisdiv> +<synopsis> int SPI_connect(void) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPICONNECT-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<PARA>None -</PARA> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPICONNECT-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM>int -</TERM> -<LISTITEM> -<PARA> -Return status -<VARIABLELIST> -<VARLISTENTRY> -<TERM><ReturnValue>SPI_OK_CONNECT</ReturnValue> -</TERM> -<LISTITEM> -<PARA> - if connected -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM><ReturnValue>SPI_ERROR_CONNECT</ReturnValue> -</TERM> -<LISTITEM> -<PARA> - if not connected -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</para> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPICONNECT-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_connect</FUNCTION> opens a connection from a procedure -invocation to the SPI manager. - You must call this function if you will need to execute queries. Some - utility SPI functions may be called from un-connected procedures. -</PARA> -<PARA> - If your procedure is already connected, - <Function>SPI_connect</Function> will return an - <ReturnValue>SPI_ERROR_CONNECT</ReturnValue> error. Note that this - may happen if a procedure which has called - <Function>SPI_connect</Function> directly calls another procedure - which itself calls <Function>SPI_connect</Function>. While - recursive calls to the <Acronym>SPI</Acronym> manager are permitted - when an <Acronym>SPI</Acronym> query invokes another function which - uses <Acronym>SPI</Acronym>, directly nested calls to - <Function>SPI_connect</Function> and - <Function>SPI_finish</Function> are forbidden. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPICONNECT-2"> -<TITLE>Usage -</TITLE> -<PARA> -<!-- -XXX thomas 1997-12-24 ---> -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPICONNECT-3"> -<TITLE>Algorithm -</TITLE> -<PARA><FUNCTION>SPI_connect</FUNCTION> performs the following: - Initializes the SPI internal - structures for query execution and memory management. -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPICONNECT-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIFINISH"> -<REFMETA> -<REFENTRYTITLE>SPI_finish</REFENTRYTITLE> -<REFMISCINFO>SPI - Connection Management</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_finish -</REFNAME> -<REFPURPOSE> - Disconnects your procedure from the SPI manager. -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIFINISH-1"><PRIMARY>SPI</PRIMARY><SECONDARY>disconnecting</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIFINISH-2"><PRIMARY>SPI_finish</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_finish(void) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIFINISH-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<PARA>None -</PARA> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIFINISH-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM>int -</TERM> -<LISTITEM> -<PARA> -<SimpleList> -<Member> -<ReturnValue>SPI_OK_FINISH</ReturnValue> - if properly disconnected -</Member> -<Member> -<ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> - if called from an un-connected procedure -</Member> -</SimpleList> -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIFINISH-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_finish</FUNCTION> closes an existing connection to the -SPI manager. - You must call this function after completing the SPI operations needed - during your procedure's current invocation. -</para> -<PARA> - You may get the error return <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if <Function>SPI_finish</Function> is - called without having a current valid connection. - There is no fundamental problem - with this; it means that nothing was done by the SPI manager. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIFINISH-2"> -<TITLE>Usage -</TITLE> -<PARA> - <Function>SPI_finish</Function> <Emphasis>must</Emphasis> be called as a final step by a connected procedure, - or you may get - unpredictable results! However, you do not need to worry about making -this happen if the transaction is aborted via elog(ERROR). In that case -SPI will clean itself up. - -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIFINISH-3"> -<TITLE>Algorithm -</TITLE> -<PARA><FUNCTION>SPI_finish</FUNCTION> performs the following: - Disconnects your procedure from the SPI manager and frees all memory - allocations made by your procedure via <Function>palloc</Function> since - the <Function>SPI_connect</Function>. - These allocations can't be used any more! See Memory management. -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIFINISH-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIEXEC"> -<REFMETA> -<REFENTRYTITLE>SPI_exec</REFENTRYTITLE> -<REFMISCINFO>SPI - Connection Management</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_exec -</REFNAME> -<REFPURPOSE> - Creates an execution plan (parser+planner+optimizer) and executes a query. -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIEXEC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>executing</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIEXEC-2"><PRIMARY>SPI_exec</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_exec(<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIEXEC-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -const char * <REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -String containing query plan -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -int <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Maximum number of tuples to return -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIEXEC-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM>int -</TERM> -<LISTITEM> -<PARA> -<SimpleList> -<Member> - <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if called from an un-connected procedure -</Member> -<Member> - <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if query is NULL or <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> < 0. -</Member> -<Member> - <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if procedure is unconnected. -</Member> -<Member> - <ReturnValue>SPI_ERROR_COPY</ReturnValue> if COPY TO/FROM stdin. -</Member> -<Member> - <ReturnValue>SPI_ERROR_CURSOR</ReturnValue> if DECLARE/CLOSE CURSOR, FETCH. -</Member> -<Member> - <ReturnValue>SPI_ERROR_TRANSACTION</ReturnValue> if BEGIN/ABORT/END. -</Member> -<Member> - <ReturnValue>SPI_ERROR_OPUNKNOWN</ReturnValue> if type of query is unknown (this shouldn't occur). -</Member> -</SimpleList> -</para> -<Para> - If execution of your query was successful then one of the following - (non-negative) values will be returned: -<SimpleList> -<Member> - <ReturnValue>SPI_OK_UTILITY</ReturnValue> if some utility (e.g. CREATE TABLE ...) was executed -</Member> -<Member> - <ReturnValue>SPI_OK_SELECT</ReturnValue> if SELECT (but not SELECT ... INTO!) was executed -</Member> -<Member> - <ReturnValue>SPI_OK_SELINTO</ReturnValue> if SELECT ... INTO was executed -</Member> -<Member> - <ReturnValue>SPI_OK_INSERT</ReturnValue> if INSERT (or INSERT ... SELECT) was executed -</Member> -<Member> - <ReturnValue>SPI_OK_DELETE</ReturnValue> if DELETE was executed -</Member> -<Member> - <ReturnValue>SPI_OK_UPDATE</ReturnValue> if UPDATE was executed -</Member> -</SimpleList> -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIEXEC-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_exec</FUNCTION> creates an execution plan (parser+planner+optimizer) - and executes the query for <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> tuples. - -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIEXEC-2"> -<TITLE>Usage -</TITLE> -<PARA> - This should only be called from a connected procedure. - If <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> is zero then it executes the query for all tuples returned by the - query scan. Using <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> > 0 you may restrict the number of tuples for - which the query will be executed (much like a LIMIT clause). For example, - -<ProgramListing> -SPI_exec ("INSERT INTO tab SELECT * FROM tab", 5); -</ProgramListing> - -will allow at most 5 tuples to be inserted into table. - - If execution of your query was successful then a non-negative value will be returned. - -<Note> -<Para> -You may pass multiple queries in one string or query string may be - re-written by RULEs. <Function>SPI_exec</Function> returns the result for the last query - executed. -</Para> -</Note> -</para> -<Para> - The actual number of tuples for which the (last) query was executed is - returned in the global variable SPI_processed (if not <ReturnValue>SPI_OK_UTILITY</ReturnValue>). - - If <ReturnValue>SPI_OK_SELECT</ReturnValue> is returned then you may use global - pointer SPITupleTable *SPI_tuptable to access the result tuples. -</Para> - -<Para> - <Function>SPI_exec</Function> may return one of the following (negative) values: -<SimpleList> -<Member> - <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if query is NULL or <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> < 0. -</Member> -<Member> - <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if procedure is unconnected. -</Member> -<Member> - <ReturnValue>SPI_ERROR_COPY</ReturnValue> if COPY TO/FROM stdin. -</Member> -<Member> - <ReturnValue>SPI_ERROR_CURSOR</ReturnValue> if DECLARE/CLOSE CURSOR, FETCH. -</Member> -<Member> - <ReturnValue>SPI_ERROR_TRANSACTION</ReturnValue> if BEGIN/ABORT/END. -</Member> -<Member> - <ReturnValue>SPI_ERROR_OPUNKNOWN</ReturnValue> if type of query is unknown (this shouldn't occur). -</Member> -</SimpleList> - -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIEXEC-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -</PARA> -</REFSECT1> ---> -<REFSECT1 ID="R1-SPI-SPIEXEC-4"> -<TITLE>Structures -</TITLE> -<Para> - If <ReturnValue>SPI_OK_SELECT</ReturnValue> is returned then you may use the global - pointer SPITupleTable *SPI_tuptable to access the selected tuples. -</Para> - -<Para> - Structure SPITupleTable is defined in spi.h: -<ProgramListing> - typedef struct - { - MemoryContext tuptabcxt; /* memory context of result table */ - uint32 alloced; /* # of alloced vals */ - uint32 free; /* # of free vals */ - TupleDesc tupdesc; /* tuple descriptor */ - HeapTuple *vals; /* tuples */ - } SPITupleTable; -</ProgramListing> -</Para> - -<Para> - <structfield>vals</> is an array of pointers to tuples (the number of useful entries - is given by SPI_processed). <structfield>tupdesc</> is - a tuple descriptor which you may pass to SPI functions dealing with - tuples. <structfield>tuptabcxt</>, <structfield>alloced</>, and <structfield>free</> are internal fields not intended - for use by SPI callers. -</Para> - -<note> -<Para> - Functions <Function>SPI_exec</Function>, <Function>SPI_execp</Function> and - <Function>SPI_prepare</Function> change both SPI_processed and SPI_tuptable - (just the pointer, not the contents of the structure). - Save these two global variables into local procedure variables if you need - to access the result of one <Function>SPI_exec</Function> or - <Function>SPI_execp</Function> across later calls. -</Para> -</note> - -<Para> - <Function>SPI_finish</Function> frees all SPITupleTables allocated during - the current procedure. You can free a particular result table earlier, - if you are done with it, by calling <Function>SPI_freetuptable</Function>. -</Para> -</REFSECT1> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIPREPARE"> -<REFMETA> -<REFENTRYTITLE>SPI_prepare</REFENTRYTITLE> -<REFMISCINFO>SPI - Plan Preparation</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_prepare -</REFNAME> -<REFPURPOSE> - Prepares a plan for a query, without executing it yet -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIPREPARE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIPREPARE-2"><PRIMARY>SPI_prepare</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_prepare(<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">nargs</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">argtypes</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIPREPARE-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -const char * <REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Query string -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -int <REPLACEABLE CLASS="PARAMETER">nargs</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Number of input parameters ($1 ... $nargs - as in SQL-functions) -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -Oid * <REPLACEABLE CLASS="PARAMETER">argtypes</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Pointer to array of type <Acronym>OID</Acronym>s for input parameter types -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIPREPARE-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM>void * -</TERM> -<LISTITEM> -<PARA> -Pointer to an execution plan (parser+planner+optimizer) -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIPREPARE-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_prepare</FUNCTION> - creates and returns an execution plan (parser+planner+optimizer) but doesn't - execute the query. Should only be called from a connected procedure. - -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIPREPARE-2"> -<TITLE>Usage -</TITLE> -<Para> - When the same or similar query is to be executed repeatedly, it may - be advantageous to perform query planning only once. - <FUNCTION>SPI_prepare</FUNCTION> converts a query string into an execution - plan that can be passed repeatedly to <FUNCTION>SPI_execp</FUNCTION>. -</para> -<PARA> - A prepared query can be generalized by writing parameters ($1, $2, etc) - in place of what would be constants in a normal query. The values of - the parameters are then specified when <FUNCTION>SPI_execp</FUNCTION> - is called. This allows the prepared query to be used over a wider - range of situations than would be possible without parameters. -</para> -<note> -<PARA> - However, there is a disadvantage: since the planner does not know the - values that will be supplied for the parameters, it may make worse - query planning choices than it would make for a simple query with - all constants visible. -</para> -</note> -<PARA> - If the query uses parameters, their number and data types must be - specified in the call to <FUNCTION>SPI_prepare</FUNCTION>. -</para> -<Para> -The plan returned by <Function>SPI_prepare</Function> may be used only in current - invocation of the procedure since <Function>SPI_finish</Function> frees memory allocated for a plan. - But see <Function>SPI_saveplan</Function> to save a plan for longer. -</para> -<Para> - If successful, a non-null pointer will be returned. Otherwise, you'll get - a NULL plan. In both cases SPI_result will be set like the value returned - by SPI_exec, except that it is set to - <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if query is NULL or nargs < 0 or nargs > 0 && argtypes - is NULL. - -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIPREPARE-3"> -<TITLE>Algorithm -</TITLE> -<PARA><FUNCTION>SPI_prepare</FUNCTION> performs the following: -TBD -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPIPREPARE-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> +</synopsis> + </refsynopsisdiv> -<REFENTRY ID="SPI-SPIEXECP"> -<REFMETA> -<REFENTRYTITLE>SPI_execp</REFENTRYTITLE> -<REFMISCINFO>SPI - Plan Execution</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_execp -</REFNAME> -<REFPURPOSE> -Executes a plan from <Function>SPI_prepare</Function> -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIEXECP-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIEXECP-2"><PRIMARY>SPI_execp</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_execp(<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>, -<REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE>, -<REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE>, -<REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIEXECP-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -void *<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Execution plan -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -Datum *<REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Actual parameter values -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -const char *<REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Array describing which parameters are NULLs -<SimpleList> -<Member><literal>n</literal> indicates NULL (values[] entry ignored)</Member> -<Member>space indicates not NULL (values[] entry is valid)</Member> -</SimpleList> -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -int <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Number of tuples for which plan is to be executed -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIEXECP-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM>int -</TERM> -<LISTITEM> -<PARA> - Returns the same value as <Function>SPI_exec</Function> as well as -<SimpleList> -<Member> - <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> - if <REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE> - is NULL or <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> < 0 -</Member> -<Member> - <ReturnValue>SPI_ERROR_PARAM</ReturnValue> - if <REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE> - is NULL - and <REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE> - was prepared with some parameters. -</Member> -</SimpleList> -</para> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM>SPI_tuptable -</TERM> -<LISTITEM> -<PARA> -initialized as in - <Function>SPI_exec</Function> if successful -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM>SPI_processed -</TERM> -<LISTITEM> -<PARA> -initialized as in - <Function>SPI_exec</Function> if successful -</para> -</listitem> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIEXECP-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_execp</FUNCTION> - executes a plan prepared by <Function>SPI_prepare</Function>. - <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> has the same - interpretation as in <Function>SPI_exec</Function>. -</para> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIEXECP-2"> -<TITLE>Usage -</TITLE> -<Para> - If <REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE> -is NULL then - <Function>SPI_execp</Function> -assumes that all parameters (if any) are NOT NULL. - -<Note> -<Para> - If one of the objects (a relation, function, etc.) referenced by the prepared - plan is dropped during your session (by your backend or another process) then the - results of <Function>SPI_execp</Function> for this plan will be unpredictable. -</Para> -</Note> - -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIEXECP-3"> -<TITLE>Algorithm -</TITLE> -<PARA><FUNCTION>SPI_execp</FUNCTION> performs the following: -TBD -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPIEXECP-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> + <refsect1> + <title>Description</title> -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> + <para> + <function>SPI_connect</function> opens a connection from a + procedure invocation to the SPI manager. You must call this + function if you want to execute commands through SPI. Some utility + SPI functions may be called from unconnected procedures. + </para> -<REFENTRY ID="SPI-SPICURSOR-OPEN"> -<REFMETA> -<REFENTRYTITLE>SPI_cursor_open</REFENTRYTITLE> -<REFMISCINFO>SPI - Cursor Support</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_cursor_open -</REFNAME> -<REFPURPOSE> -Sets up a cursor using a plan created with <Function>SPI_prepare</Function> -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPICURSOR-OPEN-1"><PRIMARY>SPI</PRIMARY><SECONDARY>cursors</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPICURSOR-OPEN-2"><PRIMARY>SPI_cursor_open</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>2001-11-14</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_cursor_open(<REPLACEABLE CLASS="PARAMETER">name</REPLACEABLE>, -<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>, -<REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE>, -<REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPICURSOR-OPEN-1"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -const char *<REPLACEABLE CLASS="PARAMETER">name</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Name for portal, or NULL to let the system select a name -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -void *<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Execution plan -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -Datum *<REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Actual parameter values -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -const char *<REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Array describing which parameters are NULLs -<SimpleList> -<Member><literal>n</literal> indicates NULL (values[] entry ignored)</Member> -<Member>space indicates not NULL (values[] entry is valid)</Member> -</SimpleList> -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPICURSOR-OPEN-2"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM>Portal -</TERM> -<LISTITEM> -<PARA> - Pointer to Portal containing cursor, or NULL on error -</para> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPICURSOR-OPEN-1"> -<REFSECT1INFO> -<DATE>2001-11-14</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_cursor_open</FUNCTION> - sets up a cursor (internally, a Portal) that will execute a plan - prepared by <Function>SPI_prepare</Function>. -</para> -<para> + <para> + If your procedure is already connected, + <function>SPI_connect</function> will return the error code + <returnvalue>SPI_ERROR_CONNECT</returnvalue>. This could happen if + a procedure that has called <function>SPI_connect</function> + directly calls another procedure that calls + <function>SPI_connect</function>. While recursive calls to the + <acronym>SPI</acronym> manager are permitted when an SQL command + called through SPI invokes another function that uses + <acronym>SPI</acronym>, directly nested calls to + <function>SPI_connect</function> and + <function>SPI_finish</function> are forbidden. + </para> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <variablelist> + <varlistentry> + <term><symbol>SPI_OK_CONNECT</symbol></term> + <listitem> + <para> + on success + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_CONNECT</symbol></term> + <listitem> + <para> + on error + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-finish"> + <refmeta> + <refentrytitle>SPI_finish</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_finish</refname> + <refpurpose>disconnect a procedure from the SPI manager</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_finish</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +int SPI_finish(void) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_finish</function> closes an existing connection to + the SPI manager. You must call this function after completing the + SPI operations needed during your procedure's current invocation. + You do not need to worry about making this happen, however, if you + abort the transaction via <literal>elog(ERROR)</literal>. In that + case SPI will clean itself up automatically. + </para> + + <para> + If <function>SPI_finish</function> is called without having a valid + connection, it will return <symbol>SPI_ERROR_UNCONNECTED</symbol>. + There is no fundamental problem with this; it means that the SPI + manager has nothing to do. + </para> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <variablelist> + <varlistentry> + <term><symbol>SPI_OK_FINISH</symbol></term> + <listitem> + <para> + if properly disconnected + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_UNCONNECTED</symbol></term> + <listitem> + <para> + if called from an unconnected procedure + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-exec"> + <refmeta> + <refentrytitle>SPI_exec</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_exec</refname> + <refpurpose>execute a command</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_exec</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +int SPI_exec(const char * <parameter>command</parameter>, int <parameter>count</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_exec</function> executes the specified SQL command + for <parameter>count</parameter> rows. + </para> + + <para> + This function should only be called from a connected procedure. If + <parameter>count</parameter> is zero then it executes the command + for all rows that it applies to. If <parameter>count</parameter> + is greater than 0, then the number of rows for which the command + will be executed is restricted (much like a + <literal>LIMIT</literal> clause). For example, +<programlisting> +SPI_exec("INSERT INTO tab SELECT * FROM tab", 5); +</programlisting> + will allow at most 5 rows to be inserted into the table. + </para> + + <para> + You may pass multiple commands in one string, and the command may + be rewritten by rules. <function>SPI_exec</function> returns the + result for the command executed last. + </para> + + <para> + The actual number of rows for which the (last) command was executed + is returned in the global variable <varname>SPI_processed</varname> + (unless the return value of the function is + <symbol>SPI_OK_UTILITY</symbol>). If the return value of the + function is <symbol>SPI_OK_SELECT</symbol> then you may the use + global pointer <literal>SPITupleTable *SPI_tuptable</literal> to + access the result rows. + </para> + + <para> + The structure <structname>SPITupleTable</structname> is defined + thus: +<programlisting> +typedef struct +{ + MemoryContext tuptabcxt; /* memory context of result table */ + uint32 alloced; /* number of alloced vals */ + uint32 free; /* number of free vals */ + TupleDesc tupdesc; /* row descriptor */ + HeapTuple *vals; /* rows */ +} SPITupleTable; +</programlisting> + <structfield>vals</> is an array of pointers to rows. (The number + of valid entries is given by <varname>SPI_processed</varname>). + <structfield>tupdesc</> is a row descriptor which you may pass to + SPI functions dealing with rows. <structfield>tuptabcxt</>, + <structfield>alloced</>, and <structfield>free</> are internal + fields not intended for use by SPI callers. + </para> + + <para> + <function>SPI_finish</function> frees all + <structname>SPITupleTable</>s allocated during the current + procedure. You can free a particular result table earlier, if you + are done with it, by calling <function>SPI_freetuptable</function>. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>const char * <parameter>command</parameter></literal></term> + <listitem> + <para> + string containing command to execute + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int <parameter>count</parameter></literal></term> + <listitem> + <para> + maximum number of rows to process or return + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + If the execution of the command was successful then one of the + following (nonnegative) values will be returned: + + <variablelist> + <varlistentry> + <term><symbol>SPI_OK_SELECT</symbol></term> + <listitem> + <para> + if a <command>SELECT</command> (but not <command>SELECT + ... INTO</>) was executed + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_OK_SELINTO</symbol></term> + <listitem> + <para> + if a <command>SELECT ... INTO</command> was executed + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_OK_DELETE</symbol></term> + <listitem> + <para> + if a <command>DELETE</command> was executed + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_OK_INSERT</symbol></term> + <listitem> + <para> + if an <command>INSERT</command> was executed + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_OK_UPDATE</symbol></term> + <listitem> + <para> + if an <command>UPDATE</command> was executed + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_OK_UTILITY</symbol></term> + <listitem> + <para> + if a utility command (e.g., <command>CREATE TABLE</command>) + was executed + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + + <para> + On error, one of the following negative values is returned: + + <variablelist> + <varlistentry> + <term><symbol>SPI_ERROR_ARGUMENT</symbol></term> + <listitem> + <para> + if <parameter>command</parameter> is <symbol>NULL</symbol> or + <parameter>count</parameter> is less than 0 + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_COPY</symbol></term> + <listitem> + <para> + if <command>COPY TO stdout</> or <command>COPY FROM stdin</> + was attempted + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_CURSOR</symbol></term> + <listitem> + <para> + if <command>DECLARE</>, <command>CLOSE</>, or <command>FETCH</> + was attempted + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_TRANSACTION</symbol></term> + <listitem> + <para> + if <command>BEGIN</>, <command>COMMIT</>, or + <command>ROLLBACK</> was attempted + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_OPUNKNOWN</symbol></term> + <listitem> + <para> + if the command type is unknown (shouldn't happen) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_UNCONNECTED</symbol></term> + <listitem> + <para> + if called from an unconnected procedure + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect1> + + <refsect1> + <title>Notes</title> + + <para> + The functions <function>SPI_exec</function>, + <function>SPI_execp</function>, and + <function>SPI_prepare</function> change both + <varname>SPI_processed</varname> and + <varname>SPI_tuptable</varname> (just the pointer, not the contents + of the structure). Save these two global variables into local + procedure variables if you need to access the result of + <function>SPI_exec</function> or <function>SPI_execp</function> + across later calls. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-prepare"> + <refmeta> + <refentrytitle>SPI_prepare</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_prepare</refname> + <refpurpose>prepare a plan for a command, without executing it yet</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_prepare</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +void * SPI_prepare(const char * <parameter>command</parameter>, int <parameter>nargs</parameter>, Oid * <parameter>argtypes</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_prepare</function> creates and returns an execution + plan for the specified command but doesn't execute the command. + This function should only be called from a connected procedure. + </para> + + <para> + When the same or a similar command is to be executed repeatedly, it + may be advantageous to perform the planning only once. + <function>SPI_prepare</function> converts a command string into an + execution plan that can be executed repeatedly using + <function>SPI_execp</function>. + </para> + + <para> + A prepared command can be generalized by writing parameters + (<literal>$1</>, <literal>$2</>, etc.) in place of what would be + constants in a normal command. The actual values of the parameters + are then specified when <function>SPI_execp</function> is called. + This allows the prepared command to be used over a wider range of + situations than would be possible without parameters. + </para> + + <para> + The plan returned by <function>SPI_prepare</function> can be used + only in the current invocation of the procedure since + <function>SPI_finish</function> frees memory allocated for a plan. + But a plan can be saved for longer using the function + <function>SPI_saveplan</function>. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>const char * <parameter>command</parameter></literal></term> + <listitem> + <para> + command string + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int <parameter>nargs</parameter></literal></term> + <listitem> + <para> + number of input parameters (<literal>$1</>, <literal>$2</>, etc.) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Oid * <parameter>argtypes</parameter></literal></term> + <listitem> + <para> + pointer to an array containing the <acronym>OID</acronym>s of + the data types of the parameters + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + <function>SPI_prepare</function> returns non-null pointer to an + execution plan. On error, <symbol>NULL</symbol> will be returned. + In both cases, <varname>SPI_result</varname> will be set analogous + to the value returned by <function>SPI_exec</function>, except that + it is set to <symbol>SPI_ERROR_ARGUMENT</symbol> if + <parameter>command</parameter> is <symbol>NULL</symbol>, or if + <parameter>nargs</> is less than 0, or if <parameter>nargs</> is + greater than 0 and <parameter>argtypes</> is <symbol>NULL</symbol>. + </para> + </refsect1> + + <refsect1> + <title>Notes</title> + + <para> + There is a disadvantage to using parameters: since the planner does + not know the values that will be supplied for the parameters, it + may make worse planning choices than it would make for a normal + command with all constants visible. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-execp"> + <refmeta> + <refentrytitle>SPI_execp</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_execp</refname> + <refpurpose>executes a plan prepared by <function>SPI_prepare</function></refpurpose> + </refnamediv> + + <indexterm><primary>SPI_execp</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +int SPI_execp(void * <parameter>plan</parameter>, Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>, int <parameter>count</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_execp</function> executes a plan prepared by + <function>SPI_prepare</function>. <parameter>tcount</parameter> + has the same interpretation as in <function>SPI_exec</function>. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>void * <parameter>plan</parameter></literal></term> + <listitem> + <para> + execution plan (returned by <function>SPI_prepare</function>) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Datum *<parameter>values</parameter></literal></term> + <listitem> + <para> + actual parameter values + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>const char * <parameter>nulls</parameter></literal></term> + <listitem> + <para> + An array describing which parameters are null. + <literal>n</literal> indicates a null value (entry in + <parameter>values</> will be ignored); a space indicates a + nonnull value (entry in <parameter>values</> is valid). + </para> + + <para> + If <parameter>nulls</parameter> is <symbol>NULL</symbol> then + <function>SPI_execp</function> assumes that no parameters are + null. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int <parameter>count</parameter></literal></term> + <listitem> + <para> + number of row for which plan is to be executed + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + The return value is the same as for <function>SPI_exec</function> + or one of the following: + + <variablelist> + <varlistentry> + <term><symbol>SPI_ERROR_ARGUMENT</symbol></term> + <listitem> + <para> + if <parameter>plan</parameter> is <symbol>NULL</symbol> or + <parameter>count</parameter> is less than 0 + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_PARAM</symbol></term> + <listitem> + <para> + if <parameter>values</parameter> is <symbol>NULL</symbol> and + <parameter>plan</parameter> was prepared with some parameters + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + + <para> + <varname>SPI_processed</varname> and + <varname>SPI_tuptable</varname> are set as in + <function>SPI_exec</function> if successful. + </para> + </refsect1> + + <refsect1> + <title>Notes</title> + + <para> + If one of the objects (a table, function, etc.) referenced by the + prepared plan is dropped during the session then the result of + <function>SPI_execp</function> for this plan will be unpredictable. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-cursor-open"> + <refmeta> + <refentrytitle>SPI_cursor_open</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_cursor_open</refname> + <refpurpose>set up a cursor using a plan created with <function>SPI_prepare</function></refpurpose> + </refnamediv> + + <indexterm><primary>SPI_cursor_open</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +Portal SPI_cursor_open(const char * <parameter>name</parameter>, void * <parameter>plan</parameter>, Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_cursor_open</function> sets up a cursor (internally, + a portal) that will execute a plan prepared by + <function>SPI_prepare</function>. + </para> + + <para> Using a cursor instead of executing the plan directly has two benefits. First, the result rows can be retrieved a few at a time, avoiding memory overrun for queries that return many rows. Second, - a Portal can outlive the current procedure (it can, in fact, live to - the end of the current transaction). Returning the portal name to - the procedure's caller provides a way of returning a rowset result. -</para> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPICURSOR-OPEN-2"> -<TITLE>Usage -</TITLE> -<Para> - If <REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE> -is NULL then - <Function>SPI_cursor_open</Function> -assumes that all parameters (if any) are NOT NULL. -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPICURSOR-OPEN-3"> -<TITLE>Algorithm -</TITLE> -<PARA><FUNCTION>SPI_cursor_open</FUNCTION> performs the following: -TBD -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPICURSOR-FIND"> -<REFMETA> -<REFENTRYTITLE>SPI_cursor_find</REFENTRYTITLE> -<REFMISCINFO>SPI - Cursor Support</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_cursor_find -</REFNAME> -<REFPURPOSE> -Finds an existing cursor (Portal) by name -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPICURSOR-FIND-1"><PRIMARY>SPI</PRIMARY><SECONDARY>cursors</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPICURSOR-FIND-2"><PRIMARY>SPI_cursor_find</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>2001-11-14</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_cursor_find(<REPLACEABLE CLASS="PARAMETER">name</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPICURSOR-FIND-1"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -const char *<REPLACEABLE CLASS="PARAMETER">name</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Name of portal -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPICURSOR-FIND-2"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM>Portal -</TERM> -<LISTITEM> -<PARA> - Pointer to Portal with given name, or NULL if not found -</para> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPICURSOR-FIND-1"> -<REFSECT1INFO> -<DATE>2001-11-14</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_cursor_find</FUNCTION> - finds a pre-existing Portal by name. This is primarily useful - to resolve a cursor name returned as text by some other function. -</para> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPICURSOR-FIND-2"> -<TITLE>Usage -</TITLE> -<Para> -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPICURSOR-FIND-3"> -<TITLE>Algorithm -</TITLE> -<PARA><FUNCTION>SPI_cursor_find</FUNCTION> performs the following: -TBD -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPICURSOR-FETCH"> -<REFMETA> -<REFENTRYTITLE>SPI_cursor_fetch</REFENTRYTITLE> -<REFMISCINFO>SPI - Cursor Support</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_cursor_fetch -</REFNAME> -<REFPURPOSE> -Fetches some rows from a cursor -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPICURSOR-FETCH-1"><PRIMARY>SPI</PRIMARY><SECONDARY>cursors</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPICURSOR-FETCH-2"><PRIMARY>SPI_cursor_fetch</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>2001-11-14</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_cursor_fetch(<REPLACEABLE CLASS="PARAMETER">portal</REPLACEABLE>, -<REPLACEABLE CLASS="PARAMETER">forward</REPLACEABLE>, -<REPLACEABLE CLASS="PARAMETER">count</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPICURSOR-FETCH-1"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -Portal <REPLACEABLE CLASS="PARAMETER">portal</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Portal containing cursor -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -bool <REPLACEABLE CLASS="PARAMETER">forward</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -True for fetch forward, false for fetch backward -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -int <REPLACEABLE CLASS="PARAMETER">count</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Maximum number of rows to fetch -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPICURSOR-FETCH-2"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM>SPI_tuptable -</TERM> -<LISTITEM> -<PARA> -initialized as in - <Function>SPI_exec</Function> if successful -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM>SPI_processed -</TERM> -<LISTITEM> -<PARA> -initialized as in - <Function>SPI_exec</Function> if successful -</para> -</listitem> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPICURSOR-FETCH-1"> -<REFSECT1INFO> -<DATE>2001-11-14</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_cursor_fetch</FUNCTION> - fetches some (more) rows from a cursor. This is equivalent to the - SQL command <command>FETCH</>. -</para> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPICURSOR-FETCH-2"> -<TITLE>Usage -</TITLE> -<Para> -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPICURSOR-FETCH-3"> -<TITLE>Algorithm -</TITLE> -<PARA><FUNCTION>SPI_cursor_fetch</FUNCTION> performs the following: -TBD -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPICURSOR-MOVE"> -<REFMETA> -<REFENTRYTITLE>SPI_cursor_move</REFENTRYTITLE> -<REFMISCINFO>SPI - Cursor Support</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_cursor_move -</REFNAME> -<REFPURPOSE> -Moves a cursor -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPICURSOR-MOVE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>cursors</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPICURSOR-MOVE-2"><PRIMARY>SPI_cursor_move</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>2001-11-14</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_cursor_move(<REPLACEABLE CLASS="PARAMETER">portal</REPLACEABLE>, -<REPLACEABLE CLASS="PARAMETER">forward</REPLACEABLE>, -<REPLACEABLE CLASS="PARAMETER">count</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPICURSOR-MOVE-1"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -Portal <REPLACEABLE CLASS="PARAMETER">portal</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Portal containing cursor -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -bool <REPLACEABLE CLASS="PARAMETER">forward</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -True for move forward, false for move backward -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -int <REPLACEABLE CLASS="PARAMETER">count</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Maximum number of rows to move -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPICURSOR-MOVE-2"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM>None -</TERM> -<LISTITEM> -<PARA> -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPICURSOR-MOVE-1"> -<REFSECT1INFO> -<DATE>2001-11-14</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_cursor_move</FUNCTION> - skips over some number of rows in a cursor. This is equivalent to the - SQL command <command>MOVE</>. -</para> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPICURSOR-MOVE-2"> -<TITLE>Usage -</TITLE> -<Para> -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPICURSOR-MOVE-3"> -<TITLE>Algorithm -</TITLE> -<PARA><FUNCTION>SPI_cursor_move</FUNCTION> performs the following: -TBD -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPICURSOR-CLOSE"> -<REFMETA> -<REFENTRYTITLE>SPI_cursor_close</REFENTRYTITLE> -<REFMISCINFO>SPI - Cursor Support</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_cursor_close -</REFNAME> -<REFPURPOSE> -Closes a cursor -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPICURSOR-CLOSE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>cursors</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPICURSOR-CLOSE-2"><PRIMARY>SPI_cursor_close</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>2001-11-14</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_cursor_close(<REPLACEABLE CLASS="PARAMETER">portal</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPICURSOR-CLOSE-1"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -Portal <REPLACEABLE CLASS="PARAMETER">portal</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Portal containing cursor -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPICURSOR-CLOSE-2"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM>None -</TERM> -<LISTITEM> -<PARA> -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPICURSOR-CLOSE-1"> -<REFSECT1INFO> -<DATE>2001-11-14</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_cursor_close</FUNCTION> - closes a previously created cursor and releases its Portal storage. -</para> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPICURSOR-CLOSE-2"> -<TITLE>Usage -</TITLE> -<Para> - All open cursors are closed implicitly at transaction end. - <FUNCTION>SPI_cursor_close</FUNCTION> need only be invoked if - it is desirable to release resources sooner. -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPICURSOR-CLOSE-3"> -<TITLE>Algorithm -</TITLE> -<PARA><FUNCTION>SPI_cursor_close</FUNCTION> performs the following: -TBD -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPISAVEPLAN"> -<REFMETA> -<REFENTRYTITLE>SPI_saveplan</REFENTRYTITLE> -<REFMISCINFO>SPI - Plan Storage</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_saveplan -</REFNAME> -<REFPURPOSE> - Saves a passed plan -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPISAVEPLAN-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPISAVEPLAN-2"><PRIMARY>SPI_saveplan</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_saveplan(<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPISAVEPLAN-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -void *<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Passed plan -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPISAVEPLAN-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM>void * -</TERM> -<LISTITEM> -<PARA> -Execution plan location. NULL if unsuccessful. -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM>SPI_result -</TERM> -<LISTITEM> -<PARA> -<SimpleList> -<Member> - <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if plan is NULL -</Member> -<Member> - <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if procedure is un-connected -</Member> -</SimpleList> -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPISAVEPLAN-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_saveplan</FUNCTION> - stores a plan prepared by <Function>SPI_prepare</Function> in safe memory - protected from freeing by <Function>SPI_finish</Function> or the transaction manager. -</para> -<Para> - In the current version of <ProductName>PostgreSQL</ProductName> there is no ability to - store prepared plans in the system - catalog and fetch them from there for execution. This will be implemented - in future versions. - - As an alternative, there is the ability to reuse prepared plans in the - subsequent invocations of your procedure in the current session. - Use <Function>SPI_execp</Function> to execute this saved plan. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPISAVEPLAN-2"> -<TITLE>Usage -</TITLE> -<Para> - <Function>SPI_saveplan</Function> saves a passed plan (prepared by <Function>SPI_prepare</Function>) in memory - protected from freeing by <Function>SPI_finish</Function> and by the transaction manager and - returns a pointer to the saved plan. You may save the pointer returned in - a local variable. Always check if this pointer is NULL or not either when - preparing a plan or using an already prepared plan in SPI_execp (see below). - -<Note> -<Para> - If one of the objects (a relation, function, etc.) referenced by the prepared - plan is dropped during your session (by your backend or another process) then the - results of <Function>SPI_execp</Function> for this plan will be unpredictable. -</Para> -</Note> - -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPISAVEPLAN-3"> -<TITLE>Algorithm -</TITLE> -<PARA><FUNCTION>SPI_saveplan</FUNCTION> performs the following: -TBD -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPISAVEPLAN-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -</Sect1> - -<Sect1 id="spi-interface-support"> -<Title>Interface Support Functions</Title> - -<Para> -The functions described here provide convenient interfaces for extracting -information from tuple sets returned by <function>SPI_exec</> and other -SPI interface functions. -</Para> - -<Para> -All functions described in this section may be used by both connected and -unconnected procedures. -</Para> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIFNUMBER"> -<REFMETA> -<REFENTRYTITLE>SPI_fnumber</REFENTRYTITLE> -<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_fnumber -</REFNAME> -<REFPURPOSE> -Finds the attribute number for specified attribute name -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIFNUMBER-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIFNUMBER-2"><PRIMARY>SPI_fnumber</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_fnumber(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fname</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIFNUMBER-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input tuple description -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -const char * <REPLACEABLE CLASS="PARAMETER">fname</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Field name -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIFNUMBER-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -int -</TERM> -<LISTITEM> -<PARA> -Attribute number -<SimpleList> -<Member> -Valid one-based index number of attribute -</Member> -<Member> -<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> if the named attribute is not found -</Member> -</SimpleList> -</para> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIFNUMBER-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_fnumber</FUNCTION> - returns the attribute number for the attribute with name in fname. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIFNUMBER-2"> -<TITLE>Usage -</TITLE> -<Para> -Attribute numbers are 1 based. -</Para> -<Para> -If the given fname refers to a system attribute (eg, <literal>oid</>) -then the appropriate negative attribute number will be returned. -The caller should be careful to test for exact equality to -<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> to detect error; -testing for result <= 0 is not correct unless system attributes -should be rejected. -</Para> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIFNUMBER-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPIFNUMBER-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIFNAME"> -<REFMETA> -<REFENTRYTITLE>SPI_fname</REFENTRYTITLE> -<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_fname -</REFNAME> -<REFPURPOSE> -Finds the attribute name for the specified attribute number -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIFNAME-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIFNAME-2"><PRIMARY>SPI_fname</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_fname(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIFNAME-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input tuple description -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Attribute number -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIFNAME-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -char * -</TERM> -<LISTITEM> -<PARA> -Attribute name -<SimpleList> -<Member> -NULL if fnumber is out of range -</Member> -<Member> -SPI_result set to -<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> on error -</Member> -</SimpleList> -</para> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIFNAME-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_fname</FUNCTION> - returns the attribute name for the specified attribute. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIFNAME-2"> -<TITLE>Usage -</TITLE> -<Para> -Attribute numbers are 1 based. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIFNAME-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -Returns a newly-allocated copy of the attribute name. -(Use pfree() to release the copy when done with it.) -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIFNAME-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIGETVALUE"> -<REFMETA> -<REFENTRYTITLE>SPI_getvalue</REFENTRYTITLE> -<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_getvalue -</REFNAME> -<REFPURPOSE> -Returns the string value of the specified attribute -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIGETVALUE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIGETVALUE-2"><PRIMARY>SPI_getvalue</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_getvalue(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIGETVALUE-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input tuple to be examined -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input tuple description -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Attribute number -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIGETVALUE-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -char * -</TERM> -<LISTITEM> -<PARA> -Attribute value or NULL if -<SimpleList> -<Member> -attribute is NULL -</Member> -<Member> -fnumber is out of range -(SPI_result set to -<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue>) -</Member> -<Member> -no output function available -(SPI_result set to -<ReturnValue>SPI_ERROR_NOOUTFUNC</ReturnValue>) -</Member> -</SimpleList> -</para> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIGETVALUE-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_getvalue</FUNCTION> - returns an external (string) representation of the value of the specified attribute. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIGETVALUE-2"> -<TITLE>Usage -</TITLE> -<Para> -Attribute numbers are 1 based. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIGETVALUE-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -The result is returned as a palloc'd string. -(Use pfree() to release the string when done with it.) -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIGETVALUE-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIGETBINVAL"> -<REFMETA> -<REFENTRYTITLE>SPI_getbinval</REFENTRYTITLE> -<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_getbinval -</REFNAME> -<REFPURPOSE> -Returns the binary value of the specified attribute -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIGETBINVAL-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIGETBINVAL-2"><PRIMARY>SPI_getbinval</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_getbinval(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">isnull</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIGETBINVAL-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input tuple to be examined -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input tuple description -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Attribute number -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIGETBINVAL-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -Datum -</TERM> -<LISTITEM> -<PARA> -Attribute binary value -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -bool * <REPLACEABLE CLASS="PARAMETER">isnull</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -flag for null value in attribute -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -SPI_result -</TERM> -<LISTITEM> -<PARA> -<SimpleList> -<Member> -<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> -</Member> -</SimpleList> -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIGETBINVAL-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_getbinval</FUNCTION> - returns the specified attribute's value in internal form (as a Datum). -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIGETBINVAL-2"> -<TITLE>Usage -</TITLE> -<Para> -Attribute numbers are 1 based. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIGETBINVAL-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -Does not allocate new space for the datum. In the case of a pass-by- -reference data type, the Datum will be a pointer into the given tuple. -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIGETBINVAL-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIGETTYPE"> -<REFMETA> -<REFENTRYTITLE>SPI_gettype</REFENTRYTITLE> -<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_gettype -</REFNAME> -<REFPURPOSE> -Returns the type name of the specified attribute -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIGETTYPE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIGETTYPE-2"><PRIMARY>SPI_gettype</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_gettype(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIGETTYPE-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input tuple description -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Attribute number -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIGETTYPE-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -char * -</TERM> -<LISTITEM> -<PARA> -The type name for the specified attribute number -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -SPI_result -</TERM> -<LISTITEM> -<PARA> -<SimpleList> -<Member> -<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> -</Member> -</SimpleList> -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIGETTYPE-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_gettype</FUNCTION> - returns a copy of the type name for the specified attribute, - or NULL on error. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIGETTYPE-2"> -<TITLE>Usage -</TITLE> -<Para> -Attribute numbers are 1 based. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIGETTYPE-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -Returns a newly-allocated copy of the type name. -(Use pfree() to release the copy when done with it.) -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIGETTYPE-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIGETTYPEID"> -<REFMETA> -<REFENTRYTITLE>SPI_gettypeid</REFENTRYTITLE> -<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_gettypeid -</REFNAME> -<REFPURPOSE> -Returns the type <Acronym>OID</Acronym> of the specified attribute -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIGETTYPEID-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIGETTYPEID-2"><PRIMARY>SPI_gettypeid</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_gettypeid(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIGETTYPEID-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input tuple description -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Attribute number -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIGETTYPEID-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -<Acronym>OID</Acronym> -</TERM> -<LISTITEM> -<PARA> -The type <Acronym>OID</Acronym> for the specified attribute number -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -SPI_result -</TERM> -<LISTITEM> -<PARA> -<SimpleList> -<Member> -<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> -</Member> -</SimpleList> -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIGETTYPEID-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_gettypeid</FUNCTION> - returns the type <Acronym>OID</Acronym> for the specified attribute. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIGETTYPEID-2"> -<TITLE>Usage -</TITLE> -<Para> -Attribute numbers are 1 based. -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIGETTYPEID-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -TBD -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPIGETTYPEID-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIGETRELNAME"> -<REFMETA> -<REFENTRYTITLE>SPI_getrelname</REFENTRYTITLE> -<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_getrelname -</REFNAME> -<REFPURPOSE> -Returns the name of the specified relation -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIGETRELNAME-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIGETRELNAME-2"><PRIMARY>SPI_getrelname</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_getrelname(<REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIGETRELNAME-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -Relation <REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input relation -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIGETRELNAME-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -char * -</TERM> -<LISTITEM> -<PARA> -The name of the specified relation -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIGETRELNAME-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_getrelname</FUNCTION> - returns the name of the specified relation. -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIGETRELNAME-2"> -<TITLE>Usage -</TITLE> -<Para> -TBD -</PARA> -</REFSECT1> ---> -<REFSECT1 ID="R1-SPI-SPIGETRELNAME-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -Returns a newly-allocated copy of the rel name. -(Use pfree() to release the copy when done with it.) -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIGETRELNAME-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -</Sect1> - -<Sect1 id="spi-memory"> -<Title>Memory Management</Title> - -<Para> -<ProductName>PostgreSQL</ProductName> allocates memory within memory -<firstterm>contexts</firstterm>, which provide a convenient method of -managing allocations made in many different places that need to live -for differing amounts of time. Destroying a context releases all the -memory that was allocated in it. Thus, it is not necessary to keep track -of individual objects to avoid memory leaks --- only a relatively small number -of contexts have to be managed. <Function>palloc</Function> and related -functions allocate memory from the <quote>current</> context. -</Para> -<Para> -<Function>SPI_connect</Function> creates a new memory context and makes -it current. <Function>SPI_finish</Function> restores the previous -current memory context and destroys the context created by -<Function>SPI_connect</Function>. These actions ensure that transient -memory allocations made inside your procedure are reclaimed at procedure -exit, avoiding memory leakage. -</Para> -<Para> -However, if your procedure needs to return an allocated memory object -(such as a value of a pass-by-reference data type), you can't allocate -the return object using <Function>palloc</Function>, at least not while -you are connected to SPI. If you try, the object will be deallocated -during <Function>SPI_finish</Function>, and your procedure will not -work reliably! -</Para> -<Para> -To solve this problem, use <Function>SPI_palloc</Function> to allocate -your return object. <Function>SPI_palloc</Function> allocates space -from <quote>upper Executor</> memory --- that is, the memory context -that was current when <Function>SPI_connect</Function> was called, -which is precisely the right context for return values of your procedure. -</Para> -<Para> -If called while not connected to SPI, <Function>SPI_palloc</Function> -acts the same as plain <Function>palloc</Function>. -</Para> -<Para> - Before a procedure connects to the SPI manager, the current memory context -is the upper Executor context, so all allocations made by the procedure via -<Function>palloc</Function> or by SPI utility functions are -made in this context. -</Para> -<Para> - After <Function>SPI_connect</Function> is called, the current context is - the procedure's private context made by <Function>SPI_connect</Function>. - All allocations made via -<Function>palloc</Function>/<Function>repalloc</Function> or by SPI utility -functions (except for <Function>SPI_copytuple</Function>, -<Function>SPI_copytupledesc</Function>, -<Function>SPI_copytupleintoslot</Function>, -<Function>SPI_modifytuple</Function>, -and <Function>SPI_palloc</Function>) are -made in this context. -</Para> -<Para> -When a procedure disconnects from the SPI manager (via -<Function>SPI_finish</Function>) the -current context is restored to the upper Executor context, and all allocations -made in the procedure memory context are freed and can't be used any more! -</Para> - -<Para> -All functions described in this section may be used by both connected and -unconnected procedures. In an unconnected procedure, they act the same -as the underlying ordinary backend functions (<function>palloc</> etc). -</Para> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPICOPYTUPLE"> -<REFMETA> -<REFENTRYTITLE>SPI_copytuple</REFENTRYTITLE> -<REFMISCINFO>SPI - Tuple Copy</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_copytuple -</REFNAME> -<REFPURPOSE> -Makes copy of tuple in upper Executor context -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPICOPYTUPLE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>copying tuples</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPICOPYTUPLE-2"><PRIMARY>SPI_copytuple</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_copytuple(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPICOPYTUPLE-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input tuple to be copied -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPICOPYTUPLE-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -HeapTuple -</TERM> -<LISTITEM> -<PARA> -Copied tuple -<SimpleList> -<Member> - <ReturnValue>non-NULL</ReturnValue> - if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> - is not NULL and the copy was successful -</Member> -<Member> - <ReturnValue>NULL</ReturnValue> - only if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> - is NULL -</Member> -</SimpleList> -</para> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPICOPYTUPLE-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_copytuple</FUNCTION> - makes a copy of tuple in upper Executor context. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPICOPYTUPLE-2"> -<TITLE>Usage -</TITLE> -<Para> -TBD -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPICOPYTUPLE-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPICOPYTUPLE-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPICOPYTUPLEDESC"> -<REFMETA> -<REFENTRYTITLE>SPI_copytupledesc</REFENTRYTITLE> -<REFMISCINFO>SPI - Tuple Descriptor Copy</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_copytupledesc -</REFNAME> -<REFPURPOSE> -Makes copy of tuple descriptor in upper Executor context -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPICOPYTUPLEDESC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>copying tuple descriptors</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPICOPYTUPLEDESC-2"><PRIMARY>SPI_copytupledesc</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>2001-08-02</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_copytupledesc(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPICOPYTUPLEDESC-1"> -<REFSECT2INFO> -<DATE>2001-08-02</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input tuple descriptor to be copied -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPICOPYTUPLEDESC-2"> -<REFSECT2INFO> -<DATE>2001-08-02</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -TupleDesc -</TERM> -<LISTITEM> -<PARA> -Copied tuple descriptor -<SimpleList> -<Member> - <ReturnValue>non-NULL</ReturnValue> - if <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> - is not NULL and the copy was successful -</Member> -<Member> - <ReturnValue>NULL</ReturnValue> - only if <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> - is NULL -</Member> -</SimpleList> -</para> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPICOPYTUPLEDESC-1"> -<REFSECT1INFO> -<DATE>2001-08-02</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_copytupledesc</FUNCTION> - makes a copy of tupdesc in upper Executor context. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPICOPYTUPLEDESC-2"> -<TITLE>Usage -</TITLE> -<Para> -TBD -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPICOPYTUPLEDESC-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPICOPYTUPLEDESC-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPICOPYTUPLEINTOSLOT"> -<REFMETA> -<REFENTRYTITLE>SPI_copytupleintoslot</REFENTRYTITLE> -<REFMISCINFO>SPI - Tuple and Descriptor Copy</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_copytupleintoslot -</REFNAME> -<REFPURPOSE> -Makes copy of tuple and descriptor in upper Executor context -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPICOPYTUPLEINTOSLOT-1"><PRIMARY>SPI</PRIMARY><SECONDARY>copying tuples</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPICOPYTUPLEINTOSLOT-2"><PRIMARY>SPI_copytupleintoslot</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_copytupleintoslot(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPICOPYTUPLEINTOSLOT-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input tuple to be copied -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input tuple descriptor to be copied -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPICOPYTUPLEINTOSLOT-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -TupleTableSlot * -</TERM> -<LISTITEM> -<PARA> -Tuple slot containing copied tuple and descriptor -<SimpleList> -<Member> - <ReturnValue>non-NULL</ReturnValue> - if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> - and <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> - are not NULL and the copy was successful -</Member> -<Member> - <ReturnValue>NULL</ReturnValue> - only if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> - or <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> - is NULL -</Member> -</SimpleList> -</para> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPICOPYTUPLEINTOSLOT-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_copytupleintoslot</FUNCTION> - makes a copy of tuple in upper Executor context, returning it in the - form of a filled-in TupleTableSlot. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPICOPYTUPLEINTOSLOT-2"> -<TITLE>Usage -</TITLE> -<Para> -TBD -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPICOPYTUPLEINTOSLOT-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPICOPYTUPLEINTOSLOT-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIMODIFYTUPLE"> -<REFMETA> -<REFENTRYTITLE>SPI_modifytuple</REFENTRYTITLE> -<REFMISCINFO>SPI - Tuple Modify</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_modifytuple -</REFNAME> -<REFPURPOSE> -Creates a tuple by replacing selected fields of a given tuple -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIMODIFYTUPLE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>modifying tuples</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIMODIFYTUPLE-2"><PRIMARY>SPI_modifytuple</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_modifytuple(<REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">nattrs</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">attnum</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">Values</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">Nulls</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIMODIFYTUPLE-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -Relation <REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Used only as source of tuple descriptor for tuple. (Passing a relation -rather than a tuple descriptor is a misfeature.) -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Input tuple to be modified -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -int <REPLACEABLE CLASS="PARAMETER">nattrs</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Number of attribute numbers in attnum array -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -int * <REPLACEABLE CLASS="PARAMETER">attnum</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Array of numbers of the attributes that are to be changed -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -Datum * <REPLACEABLE CLASS="PARAMETER">Values</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -New values for the attributes specified -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -const char * <REPLACEABLE CLASS="PARAMETER">Nulls</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Which new values are NULL, if any -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIMODIFYTUPLE-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -HeapTuple -</TERM> -<LISTITEM> -<PARA> -New tuple with modifications -<SimpleList> -<Member> - <ReturnValue>non-NULL</ReturnValue> - if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> - is not NULL and the modify was successful -</Member> -<Member> - <ReturnValue>NULL</ReturnValue> - only if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> - is NULL -</Member> -</SimpleList> -</para> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -SPI_result -</TERM> -<LISTITEM> -<PARA> -<SimpleList> -<Member> - <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if rel is NULL or tuple is NULL or natts <= 0 or - attnum is NULL or Values is NULL. -</Member> -<Member> - <ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> if there is an invalid - attribute number in attnum (attnum <= 0 or > number of - attributes in tuple) -</Member> -</SimpleList> -</para> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_modifytuple</FUNCTION> -creates a new tuple by substituting new values for selected attributes, -copying the original tuple's attributes at other positions. The input -tuple is not modified. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-2"> -<TITLE>Usage -</TITLE> -<Para> -If successful, a pointer to the new tuple is returned. The new tuple is -allocated in upper Executor context. -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIPALLOC"> -<REFMETA> -<REFENTRYTITLE>SPI_palloc</REFENTRYTITLE> -<REFMISCINFO>SPI - Memory Management</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_palloc -</REFNAME> -<REFPURPOSE> -Allocates memory in upper Executor context -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIPALLOC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIPALLOC-2"><PRIMARY>SPI_palloc</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_palloc(<REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIPALLOC-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -Size <REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Octet size of storage to allocate -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIPALLOC-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -void * -</TERM> -<LISTITEM> -<PARA> -New storage space of specified size -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIPALLOC-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_palloc</FUNCTION> - allocates memory in upper Executor context. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIPALLOC-2"> -<TITLE>Usage -</TITLE> -<Para> -TBD -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIPALLOC-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -TBD -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPIPALLOC-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIREPALLOC"> -<REFMETA> -<REFENTRYTITLE>SPI_repalloc</REFENTRYTITLE> -<REFMISCINFO>SPI - Memory Management</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_repalloc -</REFNAME> -<REFPURPOSE> -Re-allocates memory in upper Executor context -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIREPALLOC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIREPALLOC-2"><PRIMARY>SPI_repalloc</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_repalloc(<REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIREPALLOC-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -void * <REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Pointer to existing storage -</PARA> -</LISTITEM> -</VARLISTENTRY> -<VARLISTENTRY> -<TERM> -Size <REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Octet size of storage to allocate -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIREPALLOC-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -void * -</TERM> -<LISTITEM> -<PARA> -New storage space of specified size with contents copied from existing area -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIREPALLOC-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_repalloc</FUNCTION> - re-allocates memory in upper Executor context. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIREPALLOC-2"> -<TITLE>Usage -</TITLE> -<Para> -This function is no longer different from plain <FUNCTION>repalloc</FUNCTION>. -It's kept just for backward compatibility of existing code. -</PARA> -</REFSECT1> -<!-- -<REFSECT1 ID="R1-SPI-SPIREPALLOC-3"> -<TITLE>Algorithm -</TITLE> -<PARA> -TBD -</PARA> -</REFSECT1> ---> -<!-- -<REFSECT1 ID="R1-SPI-SPIREPALLOC-4"> -<TITLE>Structures -</TITLE> -<PARA>None -</PARA> -</REFSECT1> ---> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIPFREE"> -<REFMETA> -<REFENTRYTITLE>SPI_pfree</REFENTRYTITLE> -<REFMISCINFO>SPI - Memory Management</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_pfree -</REFNAME> -<REFPURPOSE> -Frees memory in upper Executor context -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIPFREE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIPFREE-2"><PRIMARY>SPI_pfree</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_pfree(<REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIPFREE-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -void * <REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Pointer to existing storage -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIPFREE-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -None -</TERM> -<LISTITEM> -<PARA> -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIPFREE-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_pfree</FUNCTION> - frees memory in upper Executor context. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIPFREE-2"> -<TITLE>Usage -</TITLE> -<Para> -This function is no longer different from plain <FUNCTION>pfree</FUNCTION>. -It's kept just for backward compatibility of existing code. -</PARA> -</REFSECT1> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIFREETUPLE"> -<REFMETA> -<REFENTRYTITLE>SPI_freetuple</REFENTRYTITLE> -<REFMISCINFO>SPI - Memory Management</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_freetuple -</REFNAME> -<REFPURPOSE> -Frees a tuple allocated in upper Executor context -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIFREETUPLE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIFREETUPLE-2"><PRIMARY>SPI_freetuple</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>1997-12-24</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_freetuple(<REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIFREETUPLE-1"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -HeapTuple <REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Pointer to allocated tuple -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIFREETUPLE-2"> -<REFSECT2INFO> -<DATE>1997-12-24</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -None -</TERM> -<LISTITEM> -<PARA> -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIFREETUPLE-1"> -<REFSECT1INFO> -<DATE>1997-12-24</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_freetuple</FUNCTION> - frees a tuple previously allocated in upper Executor context. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIFREETUPLE-2"> -<TITLE>Usage -</TITLE> -<Para> -This function is no longer different from plain <FUNCTION>heap_freetuple</FUNCTION>. -It's kept just for backward compatibility of existing code. -</PARA> -</REFSECT1> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIFREETUPTABLE"> -<REFMETA> -<REFENTRYTITLE>SPI_freetuptable</REFENTRYTITLE> -<REFMISCINFO>SPI - Memory Management</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_freetuptable -</REFNAME> -<REFPURPOSE> -Frees a tuple set created by <function>SPI_exec</> or similar function -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIFREETUPTABLE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIFREETUPTABLE-2"><PRIMARY>SPI_freetuptable</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>2001-11-14</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_freetuptable(<REPLACEABLE CLASS="PARAMETER">tuptable</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIFREETUPTABLE-1"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -SPITupleTable * <REPLACEABLE CLASS="PARAMETER">tuptable</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Pointer to tuple table -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIFREETUPTABLE-2"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -None -</TERM> -<LISTITEM> -<PARA> -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIFREETUPTABLE-1"> -<REFSECT1INFO> -<DATE>2001-11-14</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_freetuptable</FUNCTION> - frees a tuple set created by a prior SPI query function, such as - <function>SPI_exec</>. -</PARA> -</REFSECT1> -<REFSECT1 ID="R1-SPI-SPIFREETUPTABLE-2"> -<TITLE>Usage -</TITLE> -<Para> -This function is useful if a SPI procedure needs to execute multiple -queries and does not want to keep the results of earlier queries around -until it ends. Note that any unfreed tuple sets will be freed anyway -at <function>SPI_finish</>. -</PARA> -</REFSECT1> -</REFENTRY> - -<!-- *********************************************** --> -<!-- *********************************************** --> -<!-- *********************************************** --> - -<REFENTRY ID="SPI-SPIFREEPLAN"> -<REFMETA> -<REFENTRYTITLE>SPI_freeplan</REFENTRYTITLE> -<REFMISCINFO>SPI - Memory Management</REFMISCINFO> -</REFMETA> -<REFNAMEDIV> -<REFNAME>SPI_freeplan -</REFNAME> -<REFPURPOSE> - Releases a previously saved plan -</REFPURPOSE> -<INDEXTERM ID="IX-SPI-SPIFREEPLAN-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM> -<INDEXTERM ID="IX-SPI-SPIFREEPLAN-2"><PRIMARY>SPI_freeplan</PRIMARY></INDEXTERM> -</REFNAMEDIV> -<REFSYNOPSISDIV> -<REFSYNOPSISDIVINFO> -<DATE>2001-11-14</DATE> -</REFSYNOPSISDIVINFO> -<SYNOPSIS> -SPI_freeplan(<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>) -</SYNOPSIS> - -<REFSECT2 ID="R2-SPI-SPIFREEPLAN-1"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Inputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM> -void *<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE> -</TERM> -<LISTITEM> -<PARA> -Passed plan -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> - -<REFSECT2 ID="R2-SPI-SPIFREEPLAN-2"> -<REFSECT2INFO> -<DATE>2001-11-14</DATE> -</REFSECT2INFO> -<TITLE>Outputs -</TITLE> -<VARIABLELIST> -<VARLISTENTRY> -<TERM>int -</TERM> -<LISTITEM> -<PARA> -<SimpleList> -<Member> - <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if plan is NULL -</Member> -</SimpleList> -</PARA> -</LISTITEM> -</VARLISTENTRY> -</VARIABLELIST> -</REFSECT2> -</REFSYNOPSISDIV> - -<REFSECT1 ID="R1-SPI-SPIFREEPLAN-1"> -<REFSECT1INFO> -<DATE>2001-11-14</DATE> -</REFSECT1INFO> -<TITLE>Description -</TITLE> -<PARA> -<FUNCTION>SPI_freeplan</FUNCTION> - releases a query plan previously returned by - <Function>SPI_prepare</Function> or saved by - <Function>SPI_saveplan</Function>. -</para> -</REFSECT1> -</REFENTRY> - -</Sect1> - -<Sect1 id="spi-visibility"> -<Title>Visibility of Data Changes</Title> - -<Para> -<ProductName>PostgreSQL</ProductName> data changes visibility rule: during a query execution, data -changes made by the query itself (via SQL-function, SPI-function, triggers) -are invisible to the query scan. For example, in query + a portal can outlive the current procedure (it can, in fact, live + to the end of the current transaction). Returning the portal name + to the procedure's caller provides a way of returning a row set as + result. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>const char * <parameter>name</parameter></literal></term> + <listitem> + <para> + name for portal, or <symbol>NULL</symbol> to let the system + select a name + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>void * <parameter>plan</parameter></literal></term> + <listitem> + <para> + execution plan (returned by <function>SPI_prepare</function>) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Datum * <parameter>values</parameter></literal></term> + <listitem> + <para> + actual parameter values + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>const char *<parameter>nulls</parameter></literal></term> + <listitem> + <para> + An array describing which parameters are null values. + <literal>n</literal> indicates a null value (entry in + <parameter>values</> will be ignored); a space indicates a + nonnull value (entry in <parameter>values</> is valid). If + <parameter>nulls</parameter> is <symbol>NULL</> then + <function>SPI_cursor_open</function> assumes that no parameters + are null. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + pointer to portal containing the cursor, or <symbol>NULL</symbol> + on error + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-cursor-find"> + <refmeta> + <refentrytitle>SPI_cursor_find</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_cursor_find</refname> + <refpurpose>find an existing cursor by name</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_cursor_find</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +Portal SPI_cursor_find(const char * <parameter>name</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_cursor_find</function> finds an existing portal by + name. This is primarily useful to resolve a cursor name returned + as text by some other function. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>const char * <parameter>name</parameter></literal></term> + <listitem> + <para> + name of the portal + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + pointer to the portal with the specified name, or + <symbol>NULL</symbol> if none was found + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-cursor-fetch"> + <refmeta> + <refentrytitle>SPI_cursor_fetch</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_cursor_fetch</refname> + <refpurpose>fetch some rows from a cursor</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_cursor_fetch</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +void SPI_cursor_fetch(Portal <parameter>portal</parameter>, bool <parameter>forward</parameter>, int <parameter>count</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_cursor_fetch</function> fetches some rows from a + cursor. This is equivalent to the SQL command <command>FETCH</>. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>Portal <parameter>portal</parameter></literal></term> + <listitem> + <para> + portal containing the cursor + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool <parameter>forward</parameter></literal></term> + <listitem> + <para> + true for fetch forward, false for fetch backward + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int <parameter>count</parameter></literal></term> + <listitem> + <para> + maximum number of rows to fetch + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + <varname>SPI_processed</varname> and + <varname>SPI_tuptable</varname> are set as in + <function>SPI_exec</function> if successful. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-cursor-move"> + <refmeta> + <refentrytitle>SPI_cursor_move</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_cursor_move</refname> + <refpurpose>move a cursor</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_cursor_move</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +void SPI_cursor_move(Portal <parameter>portal</parameter>, bool <parameter>forward</parameter>, int <parameter>count</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_cursor_move</function> skips over some number of rows + in a cursor. This is equivalent to the SQL command + <command>MOVE</>. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>Portal <parameter>portal</parameter></literal></term> + <listitem> + <para> + portal containing the cursor + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool <parameter>forward</parameter></literal></term> + <listitem> + <para> + true for move forward, false for move backward + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int <parameter>count</parameter></literal></term> + <listitem> + <para> + maximum number of rows to move + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-cursor-close"> + <refmeta> + <refentrytitle>SPI_cursor_close</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_cursor_close</refname> + <refpurpose>close a cursor</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_cursor_close</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +void SPI_cursor_close(Portal <parameter>portal</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_cursor_close</function> closes a previously created + cursor and releases its portal storage. + </para> + + <para> + All open cursors are closed automatically at the end of a + transaction. <function>SPI_cursor_close</function> need only be + invoked if it is desirable to release resources sooner. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>Portal <parameter>portal</parameter></literal></term> + <listitem> + <para> + portal containing the cursor + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-saveplan"> + <refmeta> + <refentrytitle>SPI_saveplan</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_saveplan</refname> + <refpurpose>save a plan</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_saveplan</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +void * SPI_saveplan(void * <parameter>plan</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_saveplan</function> saves a passed plan (prepared by + <function>SPI_prepare</function>) in memory protected from freeing + by <function>SPI_finish</function> and by the transaction manager + and returns a pointer to the saved plan. This gives you the + ability to reuse prepared plans in the subsequent invocations of + your procedure in the current session. You may save the pointer + returned in a local variable. Always check if this pointer is + <symbol>NULL</symbol> or not either when preparing a plan or using + an already prepared plan in <function>SPI_execp</function>. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>void * <parameter>plan</parameter></literal></term> + <listitem> + <para> + the plan to be saved + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + Pointer to the saved plan; <symbol>NULL</symbol> if unsuccessful. + On error, <varname>SPI_result</varname> is set thus: + + <variablelist> + <varlistentry> + <term><symbol>SPI_ERROR_ARGUMENT</symbol></term> + <listitem> + <para> + if <parameter>plan</parameter> is <symbol>NULL</symbol> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_UNCONNECTED</symbol></term> + <listitem> + <para> + if called from an unconnected procedure + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect1> + + <refsect1> + <title>Notes</title> + + <para> + If one of the objects (a table, function, etc.) referenced by the + prepared plan is dropped during the session then the results of + <function>SPI_execp</function> for this plan will be unpredictable. + </para> + </refsect1> +</refentry> + +</sect1> + +<sect1 id="spi-interface-support"> + <title>Interface Support Functions</title> + + <para> + The functions described here provide an interface for extracting + information from result sets returned by <function>SPI_exec</> and + other SPI functions. + </para> + + <para> + All functions described in this section may be used by both + connected and unconnected procedures. + </para> + +<!-- *********************************************** --> + +<refentry id="spi-spi-fname"> + <refmeta> + <refentrytitle>SPI_fname</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_fname</refname> + <refpurpose>determine the column name for the specified column number</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_fname</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +char * SPI_fname(TupleDesc <parameter>rowdesc</parameter>, int <parameter>colnumber</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_fname</function> returns the column name of the + specified column. (You can use <function>pfree</function> to + release the copy of the name when you don't need it anymore.) + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term> + <listitem> + <para> + input row description + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int <parameter>colnumber</parameter></literal></term> + <listitem> + <para> + column number (count starts at 1) + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + The column name; <symbol>NULL</symbol> if + <parameter>colnumber</parameter> is out of range. + <varname>SPI_result</varname> set to + <symbol>SPI_ERROR_NOATTRIBUTE</symbol> on error. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-fnumber"> + <refmeta> + <refentrytitle>SPI_fnumber</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_fnumber</refname> + <refpurpose>determine the column number for the specified column name</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_fnumber</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +int SPI_fnumber(TupleDesc <parameter>rowdesc</parameter>, const char * <parameter>colname</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_fnumber</function> returns the column number for the + column with the specified name. + </para> + + <para> + If <parameter>colname</parameter> refers to a system column (e.g., + <literal>oid</>) then the appropriate negative column number will + be returned. The caller should be careful to test the return value + for exact equality to <symbol>SPI_ERROR_NOATTRIBUTE</symbol> to + detect an error; testing the result for less than or equal to 0 is + not correct unless system columns should be rejected. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term> + <listitem> + <para> + input row description + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>const char * <parameter>colname</parameter></literal></term> + <listitem> + <para> + column name + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + Column number (count starts at 1), or + <symbol>SPI_ERROR_NOATTRIBUTE</symbol> if the named column was not + found. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-getvalue"> + <refmeta> + <refentrytitle>SPI_getvalue</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_getvalue</refname> + <refpurpose>return the string value of the specified column</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_getvalue</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +char * SPI_getvalue(HeapTuple <parameter>row</parameter>, TupleDesc <parameter>rowdesc</parameter>, int <parameter>colnumber</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_getvalue</function> returns the string representation + of the value of the specified column. + </para> + + <para> + The result is returned in memory allocated using + <function>palloc</function>. (You can use + <function>pfree</function> to release the memory when you don't + need it anymore.) + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>HeapTuple <parameter>row</parameter></literal></term> + <listitem> + <para> + input row to be examined + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term> + <listitem> + <para> + input row description + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int <parameter>colnumber</parameter></literal></term> + <listitem> + <para> + column number (count starts at 1) + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + Column value, or <symbol>NULL</symbol> if the column is null, + <parameter>colnumber</parameter> is out of range + (<varname>SPI_result</varname> is set to + <symbol>SPI_ERROR_NOATTRIBUTE</symbol>), or no no output function + available (<varname>SPI_result</varname> is set to + <symbol>SPI_ERROR_NOOUTFUNC</symbol>). + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-getbinval"> + <refmeta> + <refentrytitle>SPI_getbinval</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_getbinval</refname> + <refpurpose>return the binary value of the specified column</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_getbinval</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +Datum SPI_getbinval(HeapTuple <parameter>row</parameter>, TupleDesc <parameter>rowdesc</parameter>, int <parameter>colnumber</parameter>, bool * <parameter>isnull</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_getbinval</function> returns the value of the + specified column in the internal form (as type <type>Datum</type>). + </para> + + <para> + This function does not allocate new space for the datum. In the + case of a pass-by-reference data type, the return value will be a + pointer into the passed row. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>HeapTuple <parameter>row</parameter></literal></term> + <listitem> + <para> + input row to be examined + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term> + <listitem> + <para> + input row description + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int <parameter>rownumber</parameter></literal></term> + <listitem> + <para> + column number (count starts at 1) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool * <parameter>isnull</parameter></literal></term> + <listitem> + <para> + flag for a null value in the column + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + The binary value of the column is returned. The variable pointed + to by <parameter>isnull</parameter> is set to true if the column is + null, else to false. + </para> + + <para> + <varname>SPI_result</varname> is set to + <symbol>SPI_ERROR_NOATTRIBUTE</symbol> on error. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-gettype"> + <refmeta> + <refentrytitle>SPI_gettype</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_gettype</refname> + <refpurpose>return the data type name of the specified column</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_gettype</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +char * SPI_gettype(TupleDesc <parameter>rowdesc</parameter>, int <parameter>colnumber</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_gettype</function> returns the data type name of the + specified column. (You can use <function>pfree</function> to + release the copy of the name when you don't need it anymore.) + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term> + <listitem> + <para> + input row description + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int <parameter>colnumber</parameter></literal></term> + <listitem> + <para> + column number (count starts at 1) + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + The data type name of the specified column, or + <symbol>NULL</symbol> on error. <varname>SPI_result</varname> is + set to <symbol>SPI_ERROR_NOATTRIBUTE</symbol> on error. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-gettypeid"> + <refmeta> + <refentrytitle>SPI_gettypeid</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_gettypeid</refname> + <refpurpose>return the data type <acronym>OID</acronym> of the specified column</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_gettypeid</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +Oid SPI_gettypeid(TupleDesc <parameter>rowdesc</parameter>, int <parameter>colnumber</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_gettypeid</function> returns the + <acronym>OID</acronym> of the data type of the specified column. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term> + <listitem> + <para> + input row description + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int <parameter>colnumber</parameter></literal></term> + <listitem> + <para> + column number (count starts at 1) + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + The <acronym>OID</acronym> of the data type of the specified column + or <symbol>InvalidOid</symbol> on error. On error, + <varname>SPI_result</varname> is set to + <symbol>SPI_ERROR_NOATTRIBUTE</symbol>. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-getrelname"> + <refmeta> + <refentrytitle>SPI_getrelname</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_getrelname</refname> + <refpurpose>return the name of the specified relation</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_getrelname</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +char * SPI_getrelname(Relation <parameter>rel</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_getrelname</function> returns the name of the + specified relation. (You can use <function>pfree</function> to + release the copy of the name when you don't need it anymore.) + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>Relation <parameter>rel</parameter></literal></term> + <listitem> + <para> + input relation + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + The name of the specified relation. + </para> + </refsect1> +</refentry> + + </sect1> + + <sect1 id="spi-memory"> + <title>Memory Management</title> + + <para> + <productname>PostgreSQL</productname> allocates memory within + <firstterm>memory contexts</firstterm><indexterm><primary>memory + context</primary><secondary>in SPI</secondary></indexterm>, which provide a convenient method of + managing allocations made in many different places that need to + live for differing amounts of time. Destroying a context releases + all the memory that was allocated in it. Thus, it is not necessary + to keep track of individual objects to avoid memory leaks; instead + only a relatively small number of contexts have to be managed. + <function>palloc</function> and related functions allocate memory + from the <quote>current</> context. + </para> + + <para> + <function>SPI_connect</function> creates a new memory context and + makes it current. <function>SPI_finish</function> restores the + previous current memory context and destroys the context created by + <function>SPI_connect</function>. These actions ensure that + transient memory allocations made inside your procedure are + reclaimed at procedure exit, avoiding memory leakage. + </para> + + <para> + However, if your procedure needs to return an object in allocated + memory (such as a value of a pass-by-reference data type), you + cannot allocate that memory using <function>palloc</function>, at + least not while you are connected to SPI. If you try, the object + will be deallocated by <function>SPI_finish</function>, and your + procedure will not work reliably. To solve this problem, use + <function>SPI_palloc</function> to allocate memory for your return + object. <function>SPI_palloc</function> allocates memory in the + <quote>upper executor context</quote>, that is, the memory context + that was current when <function>SPI_connect</function> was called, + which is precisely the right context for return a value from your + procedure. + </para> + + <para> + If <function>SPI_palloc</function> is called while the procedure is + not connected to SPI, then it acts the same as a normal + <function>palloc</function>. Before a procedure connects to the + SPI manager, the current memory context is the upper executor + context, so all allocations made by the procedure via + <function>palloc</function> or by SPI utility functions are made in + this context. + </para> + + <para> + When <function>SPI_connect</function> is called, the private + context of the procedure, which is created by + <function>SPI_connect</function>, is made the current context. All + allocations made by <function>palloc</function>, + <function>repalloc</function>, or SPI utility functions (except for + <function>SPI_copytuple</function>, + <function>SPI_copytupledesc</function>, + <function>SPI_copytupleintoslot</function>, + <function>SPI_modifytuple</function>, and + <function>SPI_palloc</function>) are made in this context. When a + procedure disconnects from the SPI manager (via + <function>SPI_finish</function>) the current context is restored to + the upper executor context, and all allocations made in the + procedure memory context are freed and cannot be used any more. + </para> + + <para> + All functions described in this section may be used by both + connected and unconnected procedures. In an unconnected procedure, + they act the same as the underlying ordinary server functions + (<function>palloc</>, etc.). + </para> + +<!-- *********************************************** --> + +<refentry id="spi-spi-palloc"> + <refmeta> + <refentrytitle>SPI_palloc</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_palloc</refname> + <refpurpose>allocate memory in the upper executor context</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_palloc</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +void * SPI_palloc(Size <parameter>size</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_palloc</function> allocates memory in the upper + executor context. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>Size <parameter>size</parameter></literal></term> + <listitem> + <para> + size in bytes of storage to allocate + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + pointer to new storage space of the specified size + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-realloc"> + <refmeta> + <refentrytitle>SPI_repalloc</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_repalloc</refname> + <refpurpose>reallocate memory in the upper executor context</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_repalloc</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +void * SPI_repalloc(void * <parameter>pointer</parameter>, Size <parameter>size</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_repalloc</function> changes the size of a memory + segment previously allocated using <function>SPI_palloc</function>. + </para> + + <para> + This function is no longer different from plain + <function>repalloc</function>. It's kept just for backward + compatibility of existing code. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>void * <parameter>pointer</parameter></literal></term> + <listitem> + <para> + pointer to existing storage to change + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Size <parameter>size</parameter></literal></term> + <listitem> + <para> + size in bytes of storage to allocate + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + pointer to new storage space of specified size with the contents + copied from the existing area + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-pfree"> + <refmeta> + <refentrytitle>SPI_pfree</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_pfree</refname> + <refpurpose>free memory in the upper executor context</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_pfree</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +void SPI_pfree(void * <parameter>pointer</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_pfree</function> frees memory previously allocated + using <function>SPI_palloc</function> or + <function>SPI_repalloc</function>. + </para> + + <para> + This function is no longer different from plain + <function>pfree</function>. It's kept just for backward + compatibility of existing code. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>void * <parameter>pointer</parameter></literal></term> + <listitem> + <para> + pointer to existing storage to free + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-copytuple"> + <refmeta> + <refentrytitle>SPI_copytuple</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_copytuple</refname> + <refpurpose>make a copy of a row in the upper executor context</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_copytuple</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +HeapTuple SPI_copytuple(HeapTuple <parameter>row</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_copytuple</function> makes a copy of a row in the + upper executor context. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>HeapTuple <parameter>row</parameter></literal></term> + <listitem> + <para> + row to be copied + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + the copied row; <symbol>NULL</symbol> only if + <parameter>tuple</parameter> is <symbol>NULL</symbol> + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-copytupledesc"> + <refmeta> + <refentrytitle>SPI_copytupledesc</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_copytupledesc</refname> + <refpurpose>make a copy of a row descriptor in the upper executor context</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_copytupledesc</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +TupleDesc SPI_copytupledesc(TupleDesc <parameter>tupdesc</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_copytupledesc</function> makes a copy of a row + descriptor in the upper executor context. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>TupleDesc <parameter>tupdesc</parameter></literal></term> + <listitem> + <para> + row descriptor to be copied + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + the copied row descriptor; <symbol>NULL</symbol> only if + <parameter>tupdesc</parameter> is <symbol>NULL</symbol> + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-copytupleintoslot"> + <refmeta> + <refentrytitle>SPI_copytupleintoslot</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_copytupleintoslot</refname> + <refpurpose>make a copy of a row and descriptor in the upper executor context</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_copytupleintoslot</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +TupleTableSlot * SPI_copytupleintoslot(HeapTuple <parameter>row</parameter>, TupleDesc <parameter>rowdesc</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_copytupleintoslot</function> makes a copy of a row in + the upper executor context, returning it in the form of a filled-in + <type>TupleTableSlot</type> structure. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>HeapTuple <parameter>row</parameter></literal></term> + <listitem> + <para> + row to be copied + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term> + <listitem> + <para> + row descriptor to be copied + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + <type>TupleTableSlot</type> containing the copied row and + descriptor; <symbol>NULL</symbol> only if + <parameter>row</parameter> or <parameter>rowdesc</parameter> are + <symbol>NULL</symbol> + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-modifytuple"> + <refmeta> + <refentrytitle>SPI_modifytuple</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_modifytuple</refname> + <refpurpose>create a row by replacing selected fields of a given row</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_modifytuple</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +HeapTuple SPI_modifytuple(Relation <parameter>rel</parameter>, HeapTuple <parameter>row</parameter>, <parameter>ncols</parameter>, <parameter>colnum</parameter>, Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_modifytuple</function> creates a new row by + substituting new values for selected columns, copying the original + row's columns at other positions. The input row is not modified. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>Relation <parameter>rel</parameter></literal></term> + <listitem> + <para> + Used only as the source of the row descriptor for the row. + (Passing a relation rather than a row descriptor is a + misfeature.) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>HeapTuple <parameter>row</parameter></literal></term> + <listitem> + <para> + row to be modified + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int <parameter>ncols</parameter></literal></term> + <listitem> + <para> + number of column numbers in the array + <parameter>colnum</parameter> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int * <parameter>colnum</parameter></literal></term> + <listitem> + <para> + array of the numbers of the columns that are to be changed + (count starts at 1) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Datum * <parameter>values</parameter></literal></term> + <listitem> + <para> + new values for the specified columns + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>const char * <parameter>Nulls</parameter></literal></term> + <listitem> + <para> + which new values are null, if any (see <function>SPI_execp</function> for the format) + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + new row with modifications, allocated in the upper executor + context; <symbol>NULL</symbol> only if <parameter>row</parameter> + is <symbol>NULL</symbol> + </para> + + <para> + On error, <varname>SPI_result</varname> is set as follows: + <variablelist> + <varlistentry> + <term><symbol>SPI_ERROR_ARGUMENT</symbol></term> + <listitem> + <para> + if <parameter>rel</> is <symbol>NULL</>, or if + <parameter>row</> is <symbol>NULL</>, or if <parameter>ncols</> + is less than or equal to 0, or if <parameter>colnum</> is + <symbol>NULL</>, or if <parameter>values</> is <symbol>NULL</>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_NOATTRIBUTE</symbol></term> + <listitem> + <para> + if <parameter>colnum</> contains an invalid column number (less + than or equal to 0 or greater than the number of column in + <parameter>row</>) + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-freetuple"> + <refmeta> + <refentrytitle>SPI_freetuple</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_freetuple</refname> + <refpurpose>frees a row allocated in the upper executor context</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_freetuple</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +void SPI_freetuple(HeapTuple <parameter>row</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_freetuple</function> frees a row previously allocated + in the upper executor context. + </para> + + <para> + This function is no longer different from plain + <function>heap_freetuple</function>. It's kept just for backward + compatibility of existing code. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>HeapTuple <parameter>row</parameter></literal></term> + <listitem> + <para> + row to free + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-freetupletable"> + <refmeta> + <refentrytitle>SPI_freetuptable</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_freetuptable</refname> + <refpurpose>free a row set created by <function>SPI_exec</> or a similar function</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_freetuptable</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +void SPI_freetuptable(SPITupleTable * <parameter>tuptable</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_freetuptable</function> frees a row set created by a + prior SPI command execution function, such as + <function>SPI_exec</>. Therefore, this function is usually called + with the global variable <varname>SPI_tupletable</varname> as + argument. + </para> + + <para> + This function is useful if a SPI procedure needs to execute + multiple commands and does not want to keep the results of earlier + commands around until it ends. Note that any unfreed row sets will + be freed anyway at <function>SPI_finish</>. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>SPITupleTable * <parameter>tuptable</parameter></literal></term> + <listitem> + <para> + pointer to row set to free + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-freeplan"> + <refmeta> + <refentrytitle>SPI_freeplan</refentrytitle> + </refmeta> + + <refnamediv> + <refname>SPI_freeplan</refname> + <refpurpose>free a previously saved plan</refpurpose> + </refnamediv> + + <indexterm><primary>SPI_freeplan</primary></indexterm> + + <refsynopsisdiv> +<synopsis> +int SPI_freeplan(void *<parameter>plan</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_freeplan</function> releases a command execution plan + previously returned by <function>SPI_prepare</function> or saved by + <function>SPI_saveplan</function>. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>void * <parameter>plan</parameter></literal></term> + <listitem> + <para> + pointer to plan to free + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + <symbol>SPI_ERROR_ARGUMENT</symbol> if <parameter>plan</parameter> + is <symbol>NULL</symbol>. + </para> + </refsect1> +</refentry> + + </sect1> + + <sect1 id="spi-visibility"> + <title>Visibility of Data Changes</title> + + <para> + The following two rules govern the visibility of data changes in + functions that use SPI (or any other C function): + + <itemizedlist> + <listitem> + <para> + During the execution of an SQL command, any data changes made by + the command (or by function called by the command, including + trigger functions) are invisible to the command. For + example, in command <programlisting> - INSERT INTO a SELECT * FROM a +INSERT INTO a SELECT * FROM a; </programlisting> - tuples inserted are invisible for SELECT's scan. In effect, this -duplicates the database table within itself (subject to unique index -rules, of course) without recursing. -</Para> - -<Para> - Changes made by query Q are visible to queries that are started after -query Q, no matter whether they are started inside Q (during the execution -of Q) or after Q is done. -</Para> -</Sect1> - -<Sect1 id="spi-examples"> -<Title>Examples</Title> - -<Para> - This example of SPI usage demonstrates the visibility rule. - There are more complex examples in src/test/regress/regress.c and -in contrib/spi. -</Para> - -<Para> - This is a very simple example of SPI usage. The procedure execq accepts -an SQL-query in its first argument and tcount in its second, executes the -query using SPI_exec and returns the number of tuples for which the query -executed: - -<ProgramListing> -#include "executor/spi.h" /* this is what you need to work with SPI */ + the inserted rows are invisible to the <command>SELECT</command> + part. + </para> + </listitem> + + <listitem> + <para> + Changes made by a command C are visible to all commands that are + started after C, no matter whether they are started inside C + (during the execution of C) or after C is done. + </para> + </listitem> + </itemizedlist> + </para> + + <para> + The next section contains an example that illustrates the + application of these rules. + </para> + </sect1> + + <sect1 id="spi-examples"> + <title>Examples</title> + + <para> + This section contains a very simple example of SPI usage. The + procedure <function>execq</function> takes an SQL command as its + first argument and a row count as its second, executes the command + using <function>SPI_exec</function> and returns the number of rows + that were processed by the command. You can find more complex + examples for SPI in the source tree in + <filename>src/test/regress/regress.c</filename> and in + <filename>contrib/spi</filename>. + </para> + +<programlisting> +#include "executor/spi.h" int execq(text *sql, int cnt); int execq(text *sql, int cnt) { - char *query; + char *command; int ret; int proc; - /* Convert given TEXT object to a C string */ - query = DatumGetCString(DirectFunctionCall1(textout, - PointerGetDatum(sql))); + /* Convert given text object to a C string */ + command = DatumGetCString(DirectFunctionCall1(textout, + PointerGetDatum(sql))); SPI_connect(); - ret = SPI_exec(query, cnt); + ret = SPI_exec(command, cnt); proc = SPI_processed; /* - * If this is SELECT and some tuple(s) fetched - - * returns tuples to the caller via elog (INFO). + * If this is a SELECT and some rows were fetched, + * then the rows are printed via elog(INFO). */ - if ( ret == SPI_OK_SELECT && SPI_processed > 0 ) + if (ret == SPI_OK_SELECT && SPI_processed > 0) { TupleDesc tupdesc = SPI_tuptable->tupdesc; SPITupleTable *tuptable = SPI_tuptable; char buf[8192]; - int i,j; + int i, j; for (j = 0; j < proc; j++) { HeapTuple tuple = tuptable->vals[j]; for (i = 1, buf[0] = 0; i <= tupdesc->natts; i++) - snprintf(buf + strlen (buf), sizeof(buf) - strlen(buf)," %s%s", + snprintf(buf + strlen (buf), sizeof(buf) - strlen(buf), " %s%s", SPI_getvalue(tuple, tupdesc, i), (i == tupdesc->natts) ? " " : " |"); elog (INFO, "EXECQ: %s", buf); @@ -3823,99 +2464,105 @@ execq(text *sql, int cnt) } SPI_finish(); - - pfree(query); + pfree(command); return (proc); } -</ProgramListing> -</Para> +</programlisting> + + <para> + (This function uses call convention version 0, to make the example + easier to understand. In real applications you should user the new + version 1 interface.) + </para> -<Para> - Now, compile and create the function: + <para> + This is how you declare the function after having compiled it into + a shared library: -<ProgramListing> -CREATE FUNCTION execq (text, integer) RETURNS integer - AS '...path_to_so' +<programlisting> +CREATE FUNCTION execq(text, integer) RETURNS integer + AS '<replaceable>filename</replaceable>' LANGUAGE C; -</ProgramListing> +</programlisting> + </para> + + <para> + Here is a sample session: -<ProgramListing> -vac=> SELECT execq('CREATE TABLE a (x INTEGER)', 0); -execq ------ - 0 +<programlisting> +=> SELECT execq('CREATE TABLE a (x integer)', 0); + execq +------- + 0 (1 row) -vac=> INSERT INTO a VALUES (execq('INSERT INTO a VALUES (0)',0)); +=> INSERT INTO a VALUES (execq('INSERT INTO a VALUES (0)', 0)); INSERT 167631 1 -vac=> SELECT execq('SELECT * FROM a',0); -INFO: EXECQ: 0 <<< inserted by execq - -INFO: EXECQ: 1 <<< value returned by execq and inserted by upper INSERT +=> SELECT execq('SELECT * FROM a', 0); +INFO: EXECQ: 0 -- inserted by execq +INFO: EXECQ: 1 -- returned by execq and inserted by upper INSERT -execq ------ - 2 + execq +------- + 2 (1 row) -vac=> SELECT execq('INSERT INTO a SELECT x + 2 FROM a',1); -execq ------ - 1 +=> SELECT execq('INSERT INTO a SELECT x + 2 FROM a', 1); + execq +------- + 1 (1 row) -vac=> SELECT execq('SELECT * FROM a', 10); -INFO: EXECQ: 0 +=> SELECT execq('SELECT * FROM a', 10); +INFO: EXECQ: 0 +INFO: EXECQ: 1 +INFO: EXECQ: 2 -- 0 + 2, only one row inserted - as specified -INFO: EXECQ: 1 - -INFO: EXECQ: 2 <<< 0 + 2, only one tuple inserted - as specified - -execq ------ - 3 <<< 10 is max value only, 3 is real # of tuples + execq +------- + 3 -- 10 is the max value only, 3 is the real number of rows (1 row) -vac=> DELETE FROM a; +=> DELETE FROM a; DELETE 3 -vac=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); +=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); INSERT 167712 1 -vac=> SELECT * FROM a; -x -- -1 <<< no tuples in a (0) + 1 +=> SELECT * FROM a; + x +--- + 1 -- no rows in a (0) + 1 (1 row) -vac=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); -INFO: EXECQ: 0 +=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); +INFO: EXECQ: 0 INSERT 167713 1 -vac=> SELECT * FROM a; -x -- -1 -2 <<< there was single tuple in a + 1 +=> SELECT * FROM a; + x +--- + 1 + 2 -- there was one row in a + 1 (2 rows) --- This demonstrates data changes visibility rule: +-- This demonstrates the data changes visibility rule: -vac=> INSERT INTO a SELECT execq('SELECT * FROM a', 0) * x FROM a; -INFO: EXECQ: 1 -INFO: EXECQ: 2 -INFO: EXECQ: 1 -INFO: EXECQ: 2 -INFO: EXECQ: 2 +=> INSERT INTO a SELECT execq('SELECT * FROM a', 0) * x FROM a; +INFO: EXECQ: 1 +INFO: EXECQ: 2 +INFO: EXECQ: 1 +INFO: EXECQ: 2 +INFO: EXECQ: 2 INSERT 0 2 -vac=> SELECT * FROM a; -x -- -1 -2 -2 <<< 2 tuples * 1 (x in first tuple) -6 <<< 3 tuples (2 + 1 just inserted) * 2 (x in second tuple) -(4 rows) ^^^^^^^^ - tuples visible to execq() in different invocations -</ProgramListing> -</Para> -</Sect1> -</Chapter> +=> SELECT * FROM a; + x +--- + 1 + 2 + 2 -- 2 rows * 1 (x in first row) + 6 -- 3 rows (2 + 1 just inserted) * 2 (x in second row) +(4 rows) ^^^^^^ + rows visible to execq() in different invocations +</programlisting> + </para> + </sect1> +</chapter> diff --git a/doc/src/sgml/syntax.sgml b/doc/src/sgml/syntax.sgml index 8151c63c8c3..774de140223 100644 --- a/doc/src/sgml/syntax.sgml +++ b/doc/src/sgml/syntax.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.82 2003/08/14 23:13:27 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.82.2.1 2003/09/07 04:36:44 momjian Exp $ --> <chapter id="sql-syntax"> @@ -26,6 +26,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.82 2003/08/14 23:13:27 tgl <sect1 id="sql-syntax-lexical"> <title>Lexical Structure</title> + <indexterm> + <primary>token</primary> + </indexterm> + <para> SQL input consists of a sequence of <firstterm>commands</firstterm>. A command is composed of a @@ -80,12 +84,18 @@ INSERT INTO MY_TABLE VALUES (3, 'hi there'); <title>Identifiers and Key Words</title> <indexterm zone="sql-syntax-identifiers"> - <primary>identifiers</primary> + <primary>identifier</primary> + <secondary>syntax of</secondary> </indexterm> <indexterm zone="sql-syntax-identifiers"> - <primary>key words</primary> - <secondary>syntax</secondary> + <primary>name</primary> + <secondary>syntax of</secondary> + </indexterm> + + <indexterm zone="sql-syntax-identifiers"> + <primary>key word</primary> + <secondary>syntax of</secondary> </indexterm> <para> @@ -121,6 +131,7 @@ INSERT INTO MY_TABLE VALUES (3, 'hi there'); </para> <para> + <indexterm><primary>identifier</primary><secondary>length</secondary></indexterm> The system uses no more than <symbol>NAMEDATALEN</symbol>-1 characters of an identifier; longer names can be written in commands, but they will be truncated. By default, @@ -133,7 +144,7 @@ INSERT INTO MY_TABLE VALUES (3, 'hi there'); <para> <indexterm> <primary>case sensitivity</primary> - <secondary>SQL commands</secondary> + <secondary>of SQL commands</secondary> </indexterm> Identifier and key word names are case insensitive. Therefore <programlisting> @@ -152,7 +163,7 @@ UPDATE my_table SET a = 5; <para> <indexterm> - <primary>quotes</primary> + <primary>quotation marks</primary> <secondary>and identifiers</secondary> </indexterm> There is a second kind of identifier: the <firstterm>delimited @@ -207,7 +218,7 @@ UPDATE "my_table" SET "a" = 5; <title>Constants</title> <indexterm zone="sql-syntax-constants"> - <primary>constants</primary> + <primary>constant</primary> </indexterm> <para> @@ -224,13 +235,13 @@ UPDATE "my_table" SET "a" = 5; <title>String Constants</title> <indexterm zone="sql-syntax-strings"> - <primary>character strings</primary> - <secondary>constants</secondary> + <primary>character string</primary> + <secondary>constant</secondary> </indexterm> <para> <indexterm> - <primary>quotes</primary> + <primary>quotation marks</primary> <secondary>escaping</secondary> </indexterm> A string constant in SQL is an arbitrary sequence of characters @@ -286,8 +297,8 @@ SELECT 'foo' 'bar'; <title>Bit-String Constants</title> <indexterm zone="sql-syntax-bit-strings"> - <primary>bit strings</primary> - <secondary>constants</secondary> + <primary>bit string</primary> + <secondary>constant</secondary> </indexterm> <para> @@ -316,8 +327,8 @@ SELECT 'foo' 'bar'; <title>Numeric Constants</title> <indexterm> - <primary>numeric</primary> - <secondary>constants</secondary> + <primary>number</primary> + <secondary>constant</secondary> </indexterm> <para> @@ -351,6 +362,9 @@ SELECT 'foo' 'bar'; </para> <para> + <indexterm><primary>integer</primary></indexterm> + <indexterm><primary>bigint</primary></indexterm> + <indexterm><primary>numeric</primary></indexterm> A numeric constant that contains neither a decimal point nor an exponent is initially presumed to be type <type>integer</> if its value fits in type <type>integer</> (32 bits); otherwise it is @@ -363,13 +377,13 @@ SELECT 'foo' 'bar'; <para> The initially assigned data type of a numeric constant is just a - starting point for the type resolution algorithms. In most - cases the constant will be automatically coerced to the most - appropriate type depending on context. When necessary, you - can force a numeric value to be interpreted as a specific - data type by casting it. For example, you can force a numeric - value to be treated as type <type>real</> (<type>float4</>) - by writing + starting point for the type resolution algorithms. In most cases + the constant will be automatically coerced to the most + appropriate type depending on context. When necessary, you can + force a numeric value to be interpreted as a specific data type + by casting it.<indexterm><primary>type cast</primary></indexterm> + For example, you can force a numeric value to be treated as type + <type>real</> (<type>float4</>) by writing <programlisting> REAL '1.23' -- string style @@ -382,8 +396,8 @@ REAL '1.23' -- string style <title>Constants of Other Types</title> <indexterm> - <primary>data types</primary> - <secondary>constants</secondary> + <primary>data type</primary> + <secondary>constant</secondary> </indexterm> <para> @@ -431,8 +445,8 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) <title>Array constants</title> <indexterm> - <primary>arrays</primary> - <secondary>constants</secondary> + <primary>array</primary> + <secondary>constant</secondary> </indexterm> <para> @@ -468,7 +482,7 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) <title>Operators</title> <indexterm zone="sql-syntax-operators"> - <primary>operators</primary> + <primary>operator</primary> <secondary>syntax</secondary> </indexterm> @@ -600,8 +614,8 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) <title>Comments</title> <indexterm zone="sql-syntax-comments"> - <primary>comments</primary> - <secondary>in SQL</secondary> + <primary>comment</primary> + <secondary sortas="SQL">in SQL</secondary> </indexterm> <para> @@ -636,7 +650,7 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) <title>Lexical Precedence</title> <indexterm zone="sql-precedence"> - <primary>operators</primary> + <primary>operator</primary> <secondary>precedence</secondary> </indexterm> @@ -828,6 +842,20 @@ SELECT 3 OPERATOR(pg_catalog.+) 4; <sect1 id="sql-expressions"> <title>Value Expressions</title> + <indexterm zone="sql-expressions"> + <primary>expression</primary> + <secondary>syntax</secondary> + </indexterm> + + <indexterm zone="sql-expressions"> + <primary>value expression</primary> + </indexterm> + + <indexterm> + <primary>scalar</primary> + <see>expression</see> + </indexterm> + <para> Value expressions are used in a variety of contexts, such as in the target list of the <command>SELECT</command> command, as @@ -903,7 +931,9 @@ SELECT 3 OPERATOR(pg_catalog.+) 4; <listitem> <para> - Another value expression in parentheses, useful to group subexpressions and override precedence. + Another value expression in parentheses, useful to group + subexpressions and override + precedence.<indexterm><primary>parenthesis</></> </para> </listitem> </itemizedlist> @@ -927,6 +957,10 @@ SELECT 3 OPERATOR(pg_catalog.+) 4; <sect2> <title>Column References</title> + <indexterm> + <primary>column reference</primary> + </indexterm> + <para> A column can be referenced in the form <synopsis> @@ -962,6 +996,15 @@ SELECT 3 OPERATOR(pg_catalog.+) 4; <sect2> <title>Positional Parameters</title> + <indexterm> + <primary>parameter</primary> + <secondary>syntax</secondary> + </indexterm> + + <indexterm> + <primary>$</primary> + </indexterm> + <para> A positional parameter reference is used to indicate a value that is supplied externally to an SQL statement. Parameters are @@ -993,6 +1036,11 @@ CREATE FUNCTION dept(text) RETURNS dept <sect2> <title>Operator Invocations</title> + <indexterm> + <primary>operator</primary> + <secondary>invocation</secondary> + </indexterm> + <para> There are three possible syntaxes for an operator invocation: <simplelist> @@ -1017,6 +1065,11 @@ CREATE FUNCTION dept(text) RETURNS dept <sect2> <title>Function Calls</title> + <indexterm> + <primary>function</primary> + <secondary>invocation</secondary> + </indexterm> + <para> The syntax for a function call is the name of a function (possibly qualified with a schema name), followed by its argument list @@ -1044,7 +1097,8 @@ sqrt(2) <title>Aggregate Expressions</title> <indexterm zone="syntax-aggregates"> - <primary>aggregate functions</primary> + <primary>aggregate function</primary> + <secondary>invocation</secondary> </indexterm> <para> @@ -1123,10 +1177,14 @@ sqrt(2) <sect2 id="sql-syntax-type-casts"> <title>Type Casts</title> - <indexterm> - <primary>data types</primary> - <secondary>type casts</secondary> - </indexterm> + <indexterm> + <primary>data type</primary> + <secondary>type cast</secondary> + </indexterm> + + <indexterm> + <primary>type cast</primary> + </indexterm> <para> A type cast specifies a conversion from one data type to another. @@ -1193,6 +1251,10 @@ CAST ( <replaceable>expression</replaceable> AS <replaceable>type</replaceable> <sect2 id="sql-syntax-scalar-subqueries"> <title>Scalar Subqueries</title> + <indexterm> + <primary>subquery</primary> + </indexterm> + <para> A scalar subquery is an ordinary <command>SELECT</command> query in parentheses that returns exactly one @@ -1221,10 +1283,10 @@ SELECT name, (SELECT max(pop) FROM cities WHERE cities.state = states.name) <sect2 id="sql-syntax-array-constructors"> <title>Array Constructors</title> - <indexterm> - <primary>arrays</primary> - <secondary>constructors</secondary> - </indexterm> + <indexterm> + <primary>array</primary> + <secondary>constructor</secondary> + </indexterm> <para> An <firstterm>array constructor</> is an expression that builds an @@ -1271,6 +1333,23 @@ SELECT ARRAY[[1,2],[3,4]]; </para> <para> + Multidimensional array constructor elements can be anything yielding + an array of the proper kind, not only a sub-<literal>ARRAY</> construct. + For example: +<programlisting> +create table arr(f1 int[], f2 int[]); +CREATE TABLE +insert into arr values (ARRAY[[1,2],[3,4]],ARRAY[[5,6],[7,8]]); +INSERT 2635544 1 +select ARRAY[f1, f2, '{{9,10},{11,12}}'::int[]] from arr; + array +------------------------------------------------ + {{{1,2},{3,4}},{{5,6},{7,8}},{{9,10},{11,12}}} +(1 row) +</programlisting> + </para> + + <para> It is also possible to construct an array from the results of a subquery. In this form, the array constructor is written with the keyword <literal>ARRAY</literal> followed by a parenthesized (not @@ -1299,6 +1378,11 @@ SELECT ARRAY(SELECT oid FROM pg_proc WHERE proname LIKE 'bytea%'); <sect2 id="syntax-express-eval"> <title>Expression Evaluation Rules</title> + <indexterm> + <primary>expression</primary> + <secondary>order of evaluation</secondary> + </indexterm> + <para> The order of evaluation of subexpressions is not defined. In particular, the inputs of an operator or function are not necessarily diff --git a/doc/src/sgml/trigger.sgml b/doc/src/sgml/trigger.sgml index d9ee33a2963..c3cc7fe020d 100644 --- a/doc/src/sgml/trigger.sgml +++ b/doc/src/sgml/trigger.sgml @@ -1,10 +1,14 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.29 2003/08/10 01:20:34 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.29.2.1 2003/09/07 04:36:44 momjian Exp $ --> <chapter id="triggers"> <title>Triggers</title> + <indexterm zone="triggers"> + <primary>trigger</primary> + </indexterm> + <para> This chapter describes how to write trigger functions. In particular, it describes the C-language interface for trigger @@ -98,18 +102,20 @@ $Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.29 2003/08/10 01:20:34 tgl <para> When a trigger is being defined, arguments can be specified for - it. The purpose of including arguments in the trigger definition - is to allow different triggers with similar requirements to call - the same function. As an example, there could be a generalized - trigger function that takes as its arguments two column names and - puts the current user in one and the current time stamp in the - other. Properly written, this trigger function would be - independent of the specific table it is triggering on. So the - same function could be used for <command>INSERT</command> events - on any table with suitable columns, to automatically track creation - of records in a transaction table for example. It could also be - used to track last-update events if defined as an - <command>UPDATE</command> trigger. + it.<indexterm><primary>trigger</><secondary>arguments for trigger + functions</></indexterm> The purpose of including arguments in the + trigger definition is to allow different triggers with similar + requirements to call the same function. As an example, there + could be a generalized trigger function that takes as its + arguments two column names and puts the current user in one and + the current time stamp in the other. Properly written, this + trigger function would be independent of the specific table it is + triggering on. So the same function could be used for + <command>INSERT</command> events on any table with suitable + columns, to automatically track creation of records in a + transaction table for example. It could also be used to track + last-update events if defined as an <command>UPDATE</command> + trigger. </para> </sect1> @@ -117,6 +123,11 @@ $Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.29 2003/08/10 01:20:34 tgl <sect1 id="trigger-manager"> <title>Interaction with the Trigger Manager</title> + <indexterm zone="trigger-manager"> + <primary>trigger</primary> + <secondary>in C</secondary> + </indexterm> + <para> This section describes the low-level details of the interface to a trigger function. This information is only needed when writing a diff --git a/doc/src/sgml/typeconv.sgml b/doc/src/sgml/typeconv.sgml index 18bad527ff7..82c8fa6a6a0 100644 --- a/doc/src/sgml/typeconv.sgml +++ b/doc/src/sgml/typeconv.sgml @@ -1,10 +1,15 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/typeconv.sgml,v 1.32 2003/08/14 23:13:27 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/typeconv.sgml,v 1.32.2.1 2003/09/07 04:36:44 momjian Exp $ --> <chapter Id="typeconv"> <title>Type Conversion</title> +<indexterm zone="typeconv"> + <primary>data type</primary> + <secondary>conversion</secondary> +</indexterm> + <para> <acronym>SQL</acronym> statements can, intentionally or not, require mixing of different data types in the same expression. @@ -139,6 +144,11 @@ between the built-in types has been carefully crafted and is best not altered.) </para> +<indexterm> + <primary>data type</primary> + <secondary>category</secondary> +</indexterm> + <para> An additional heuristic is provided in the parser to allow better guesses at proper behavior for <acronym>SQL</acronym> standard types. There are @@ -204,6 +214,11 @@ should use this new function and will no longer do the implicit conversion using <sect1 id="typeconv-oper"> <title>Operators</title> +<indexterm zone="typeconv-oper"> + <primary>operator</primary> + <secondary>type resolution in an invocation</secondary> +</indexterm> + <para> The specific operator to be used in an operator invocation is determined by following @@ -452,6 +467,11 @@ SELECT CAST('20' AS int8) ! AS "factorial"; <sect1 id="typeconv-func"> <title>Functions</title> +<indexterm zone="typeconv-func"> + <primary>function</primary> + <secondary>type resolution in an invocation</secondary> +</indexterm> + <para> The specific function to be used in a function invocation is determined according to the following steps. @@ -755,8 +775,22 @@ padding spaces. </sect1> <sect1 id="typeconv-union-case"> -<title><literal>UNION</literal>, <literal>CASE</literal>, and -<literal>ARRAY</literal> Constructs</title> +<title><literal>UNION</literal>, <literal>CASE</literal>, and <literal>ARRAY</literal> Constructs</title> + +<indexterm zone="typeconv-union-case"> + <primary>UNION</primary> + <secondary>determination of result type</secondary> +</indexterm> + +<indexterm zone="typeconv-union-case"> + <primary>CASE</primary> + <secondary>determination of result type</secondary> +</indexterm> + +<indexterm zone="typeconv-union-case"> + <primary>ARRAY</primary> + <secondary>determination of result type</secondary> +</indexterm> <para> SQL <literal>UNION</> constructs must match up possibly dissimilar types to diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml index 660d1ccd75d..82481084ee2 100644 --- a/doc/src/sgml/user-manag.sgml +++ b/doc/src/sgml/user-manag.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/user-manag.sgml,v 1.21 2003/08/10 01:20:34 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/user-manag.sgml,v 1.21.2.1 2003/09/07 04:36:44 momjian Exp $ --> <chapter id="user-manag"> @@ -22,6 +22,18 @@ $Header: /cvsroot/pgsql/doc/src/sgml/user-manag.sgml,v 1.21 2003/08/10 01:20:34 <sect1 id="database-users"> <title>Database Users</title> + <indexterm zone="database-users"> + <primary>user</primary> + </indexterm> + + <indexterm> + <primary>CREATE USER</primary> + </indexterm> + + <indexterm> + <primary>DROP USER</primary> + </indexterm> + <para> Database users are conceptually completely separate from operating system users. In practice it might be convenient to @@ -41,6 +53,14 @@ DROP USER <replaceable>name</replaceable>; </synopsis> </para> + <indexterm> + <primary>createuser</primary> + </indexterm> + + <indexterm> + <primary>dropuser</primary> + </indexterm> + <para> For convenience, the programs <command>createuser</command> and <command>dropuser</command> are provided as wrappers @@ -99,7 +119,7 @@ dropuser <replaceable>name</replaceable> <variablelist> <varlistentry> - <term>superuser</term> + <term>superuser<indexterm><primary>superuser</></></term> <listitem> <para> A database superuser bypasses all permission checks. Also, @@ -111,7 +131,7 @@ dropuser <replaceable>name</replaceable> </varlistentry> <varlistentry> - <term>database creation</term> + <term>database creation<indexterm><primary>database</><secondary>privilege to create</></></term> <listitem> <para> A user must be explicitly given permission to create databases @@ -123,7 +143,7 @@ dropuser <replaceable>name</replaceable> </varlistentry> <varlistentry> - <term>password</term> + <term>password<indexterm><primary>password</></></term> <listitem> <para> A password is only significant if the client authentication @@ -140,7 +160,7 @@ dropuser <replaceable>name</replaceable> </variablelist> A user's attributes can be modified after creation with - <command>ALTER USER</command>. + <command>ALTER USER</command>.<indexterm><primary>ALTER USER</></> See the reference pages for <command>CREATE USER</command> and <command>ALTER USER</command> for details. </para> @@ -166,6 +186,10 @@ ALTER USER myname SET enable_indexscan TO off; <sect1 id="groups"> <title>Groups</title> + <indexterm zone="groups"> + <primary>group</primary> + </indexterm> + <para> As in Unix, groups are a way of logically grouping users to ease management of privileges: privileges can be granted to, or revoked @@ -184,6 +208,22 @@ ALTER GROUP <replaceable>name</replaceable> DROP USER <replaceable>uname1</repla <sect1 id="privileges"> <title>Privileges</title> + <indexterm zone="privileges"> + <primary>privilege</primary> + </indexterm> + + <indexterm zone="privileges"> + <primary>owner</primary> + </indexterm> + + <indexterm zone="privileges"> + <primary>GRANT</primary> + </indexterm> + + <indexterm zone="privileges"> + <primary>REVOKE</primary> + </indexterm> + <comment>Being moved to the DDL chapter. Will eventually disappear here.</comment> <para> diff --git a/doc/src/sgml/wal.sgml b/doc/src/sgml/wal.sgml index 279364a65d8..8a957b546e8 100644 --- a/doc/src/sgml/wal.sgml +++ b/doc/src/sgml/wal.sgml @@ -1,8 +1,17 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/wal.sgml,v 1.23 2003/03/24 14:32:51 petere Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/wal.sgml,v 1.23.2.1 2003/09/07 04:36:44 momjian Exp $ --> <chapter id="wal"> <title>Write-Ahead Logging (<acronym>WAL</acronym>)</title> + <indexterm zone="wal"> + <primary>WAL</primary> + </indexterm> + + <indexterm> + <primary>transaction log</primary> + <see>WAL</see> + </indexterm> + <para> <firstterm>Write-Ahead Logging</firstterm> (<acronym>WAL</acronym>) is a standard approach to transaction logging. Its detailed @@ -24,6 +33,10 @@ <sect1 id="wal-benefits-now"> <title>Benefits of <acronym>WAL</acronym></title> + <indexterm zone="wal-benefits-now"> + <primary>fsync</primary> + </indexterm> + <para> The first obvious benefit of using <acronym>WAL</acronym> is a significantly reduced number of disk writes, since only the log @@ -86,7 +99,7 @@ <para> With UNDO, it will also be possible to implement - <firstterm>savepoints</firstterm> to allow partial rollback of + <firstterm>savepoints</firstterm><indexterm><primary>savepoint</></> to allow partial rollback of invalid transaction operations (parser errors caused by mistyping commands, insertion of duplicate primary/unique keys and so on) with the ability to continue or commit valid operations made by @@ -133,7 +146,7 @@ </para> <para> - <firstterm>Checkpoints</firstterm> are points in the sequence of + <firstterm>Checkpoints</firstterm><indexterm><primary>checkpoint</></> are points in the sequence of transactions at which it is guaranteed that the data files have been updated with all information logged before the checkpoint. At checkpoint time, all dirty data pages are flushed to disk and a @@ -301,7 +314,7 @@ <para> The aim of <acronym>WAL</acronym>, to ensure that the log is written before database records are altered, may be subverted by - disk drives that falsely report a successful write to the kernel, + disk drives<indexterm><primary>disk drive</></> that falsely report a successful write to the kernel, when, in fact, they have only cached the data and not yet stored it on the disk. A power failure in such a situation may still lead to irrecoverable data corruption. Administrators should try to ensure diff --git a/doc/src/sgml/xaggr.sgml b/doc/src/sgml/xaggr.sgml index 7b82af322ea..cb6f0b58f15 100644 --- a/doc/src/sgml/xaggr.sgml +++ b/doc/src/sgml/xaggr.sgml @@ -1,13 +1,13 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/xaggr.sgml,v 1.21 2003/08/09 22:50:22 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/xaggr.sgml,v 1.21.2.1 2003/09/07 04:36:44 momjian Exp $ --> <sect1 id="xaggr"> <title>User-Defined Aggregates</title> <indexterm zone="xaggr"> - <primary>aggregate functions</primary> - <secondary>extending</secondary> + <primary>aggregate function</primary> + <secondary>user-defined</secondary> </indexterm> <para> @@ -115,7 +115,7 @@ CREATE AGGREGATE avg ( Aggregate functions may use polymorphic state transition functions or final functions, so that the same functions can be used to implement multiple aggregates. - See <xref linkend="types-polymorphic"> + See <xref linkend="extend-types-polymorphic"> for an explanation of polymorphic functions. Going a step further, the aggregate function itself may be specified with a polymorphic base type and state type, allowing a single diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 0193691a08e..00fb6118329 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1,11 +1,14 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.72 2003/08/10 01:20:34 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.72.2.1 2003/09/07 04:36:44 momjian Exp $ --> <sect1 id="xfunc"> <title>User-Defined Functions</title> - <indexterm zone="xfunc"><primary>function</></> + <indexterm zone="xfunc"> + <primary>function</primary> + <secondary>user-defined</secondary> + </indexterm> <para> <productname>PostgreSQL</productname> provides four kinds of @@ -70,7 +73,11 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.72 2003/08/10 01:20:34 tgl E <sect1 id="xfunc-sql"> <title>Query Language (<acronym>SQL</acronym>) Functions</title> - <indexterm zone="xfunc-sql"><primary>function</><secondary>SQL</></> + <indexterm zone="xfunc-sql"> + <primary>function</primary> + <secondary>user-defined</secondary> + <tertiary>in SQL</tertiary> + </indexterm> <para> SQL functions execute an arbitrary list of SQL statements, returning @@ -84,12 +91,12 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.72 2003/08/10 01:20:34 tgl E </para> <para> - <indexterm><primary>SETOF</><seealso>function</></> - Alternatively, an SQL function may be declared to return a set, - by specifying the function's return type - as <literal>SETOF <replaceable>sometype</></literal>. In this case - all rows of the last query's result are returned. Further details - appear below. + <indexterm><primary>SETOF</><seealso>function</></> Alternatively, + an SQL function may be declared to return a set, by specifying the + function's return type as <literal>SETOF + <replaceable>sometype</></literal>.<indexterm><primary>SETOF</></> + In this case all rows of the last query's result are returned. + Further details appear below. </para> <para> @@ -523,7 +530,7 @@ SELECT name, listchildren(name) FROM nodes; <acronym>SQL</acronym> functions may be declared to accept and return the <quote>polymorphic</> types <type>anyelement</type> and <type>anyarray</type>. - See <xref linkend="types-polymorphic"> for a more detailed explanation + See <xref linkend="extend-types-polymorphic"> for a more detailed explanation of polymorphic functions. Here is a polymorphic function <function>make_array</function> that builds up an array from two arbitrary data type elements: @@ -644,6 +651,12 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision <sect1 id="xfunc-c"> <title>C-Language Functions</title> + <indexterm zone="xfunc-sql"> + <primary>function</primary> + <secondary>user-defined</secondary> + <tertiary>in C</tertiary> + </indexterm> + <para> User-defined functions can be written in C (or a language that can be made compatible with C, such as C++). Such functions are @@ -670,6 +683,10 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision <sect2 id="xfunc-c-dynload"> <title>Dynamic Loading</title> + <indexterm zone="xfunc-c-dynload"> + <primary>dynamic loading</primary> + </indexterm> + <para> The first time a user-defined function in a particular loadable object file is called in a session, @@ -787,9 +804,14 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision </sect2> - <sect2> + <sect2 id="xfunc-c-basetype"> <title>Base Types in C-Language Functions</title> + <indexterm zone="xfunc-c-basetype"> + <primary>data type</primary> + <secondary>internal organisation</secondary> + </indexterm> + <para> To know how to write C-language functions, you need to know how PostgreSQL internally represents base data types and how they can @@ -1479,7 +1501,7 @@ concat_text(PG_FUNCTION_ARGS) <listitem> <para> Use <literal>pg_config - --includedir-server</literal><indexterm><primary>pg_config</></> + --includedir-server</literal><indexterm><primary>pg_config</><secondary>with user-defined C functions</></> to find out where the <productname>PostgreSQL</> server header files are installed on your system (or the system that your users will be running on). This option is new with @@ -1498,7 +1520,7 @@ concat_text(PG_FUNCTION_ARGS) <para> When allocating memory, use the <productname>PostgreSQL</productname> functions - <function>palloc</function> and <function>pfree</function> + <function>palloc</function><indexterm><primary>palloc</></> and <function>pfree</function><indexterm><primary>pfree</></> instead of the corresponding C library functions <function>malloc</function> and <function>free</function>. The memory allocated by <function>palloc</function> will be @@ -2075,7 +2097,7 @@ CREATE OR REPLACE FUNCTION testpassbyval(integer, integer) RETURNS SETOF __testp C-language functions may be declared to accept and return the <quote>polymorphic</> types <type>anyelement</type> and <type>anyarray</type>. - See <xref linkend="types-polymorphic"> for a more detailed explanation + See <xref linkend="extend-types-polymorphic"> for a more detailed explanation of polymorphic functions. When function arguments or return types are defined as polymorphic types, the function author cannot know in advance what data type it will be called with, or @@ -2155,7 +2177,10 @@ CREATE FUNCTION make_array(anyelement) <sect1 id="xfunc-overload"> <title>Function Overloading</title> - <indexterm zone="xfunc-overload"><primary>overloading</></> + <indexterm zone="xfunc-overload"> + <primary>overloading</primary> + <secondary>functions</secondary> + </indexterm> <para> More than one function may be defined with the same SQL name, so long @@ -2216,6 +2241,11 @@ CREATE FUNCTION test(int, int) RETURNS int <sect1 id="xfunc-plhandler"> <title>Procedural Language Handlers</title> + <indexterm zone="xfunc-plhandler"> + <primary>procedural language</primary> + <secondary>handler for</secondary> + </indexterm> + <para> All calls to functions that are written in a language other than the current <quote>version 1</quote> interface for compiled diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml index 6416183c95a..b0b870bcb44 100644 --- a/doc/src/sgml/xindex.sgml +++ b/doc/src/sgml/xindex.sgml @@ -1,10 +1,15 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.30 2003/04/13 09:57:35 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.30.2.1 2003/09/07 04:36:44 momjian Exp $ --> <sect1 id="xindex"> <title>Interfacing Extensions To Indexes</title> + <indexterm zone="xindex"> + <primary>index</primary> + <secondary>for user-defined data type</secondary> + </indexterm> + <para> The procedures described thus far let you define new types, new functions, and new operators. However, we cannot yet define an @@ -43,15 +48,18 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.30 2003/04/13 09:57:35 pete <para> The routines for an index method do not directly know anything - about the data types that the index method will operate on. Instead, an - <firstterm>operator class</> identifies the set of operations that the - index method needs to use to work with a particular data type. - Operator classes are so called because one thing they specify is the set - of <literal>WHERE</>-clause operators that can be used with an index (i.e., can be - converted into an index-scan qualification). An operator class may also - specify some <firstterm>support procedures</> that are needed by the - internal operations of the index method, but do not directly - correspond to any <literal>WHERE</>-clause operator that can be used with the index. + about the data types that the index method will operate on. + Instead, an <firstterm>operator + class</><indexterm><primary>operator class</></indexterm> + identifies the set of operations that the index method needs to use + to work with a particular data type. Operator classes are so + called because one thing they specify is the set of + <literal>WHERE</>-clause operators that can be used with an index + (i.e., can be converted into an index-scan qualification). An + operator class may also specify some <firstterm>support + procedures</> that are needed by the internal operations of the + index method, but do not directly correspond to any + <literal>WHERE</>-clause operator that can be used with the index. </para> <para> @@ -452,7 +460,7 @@ CREATE OPERATOR = ( </programlisting> It is important to specify the restriction and join selectivity functions, otherwise the optimizer will be unable to make effective - use of the index. Note that there less-than, equal, and + use of the index. Note that the less-than, equal, and greater-than cases should use different selectivity functions. </para> @@ -551,13 +559,68 @@ CREATE OPERATOR CLASS complex_abs_ops </para> </sect2> + <sect2 id="xindex-opclass-dependencies"> + <title>System Dependencies on Operator Classes</title> + + <indexterm> + <primary>ordering operator</primary> + </indexterm> + + <para> + <productname>PostgreSQL</productname> uses operator classes to infer the + properties of operators in more ways than just whether they can be used + with indexes. Therefore, you might want to create operator classes + even if you have no intention of indexing any columns of your datatype. + </para> + + <para> + In particular, there are SQL features such as <literal>ORDER BY</> and + <literal>DISTINCT</> that require comparison and sorting of values. + To implement these features on a user-defined datatype, + <productname>PostgreSQL</productname> looks for the default B-tree operator + class for the datatype. The <quote>equals</> member of this operator + class defines the system's notion of equality of values for + <literal>GROUP BY</> and <literal>DISTINCT</>, and the sort ordering + imposed by the operator class defines the default <literal>ORDER BY</> + ordering. + </para> + + <para> + Comparison of arrays of user-defined types also relies on the semantics + defined by the default B-tree operator class. + </para> + + <para> + If there is no default B-tree operator class for a datatype, the system + will look for a default hash operator class. But since that kind of + operator class only provides equality, in practice it is only enough + to support array equality. + </para> + + <para> + When there is no default operator class for a datatype, you will get + errors like <quote>could not identify an ordering operator</> if you + try to use these SQL features with the datatype. + </para> + + <note> + <para> + In <ProductName>PostgreSQL</ProductName> versions before 7.4, + sorting and grouping operations would implicitly use operators named + <literal>=</>, <literal><</>, and <literal>></>. The new + behavior of relying on default operator classes avoids having to make + any assumption about the behavior of operators with particular names. + </para> + </note> + </sect2> + <sect2 id="xindex-opclass-features"> <title>Special Features of Operator Classes</title> <para> There are two special features of operator classes that we have - not discussed yet, mainly because they are not very useful - with the default B-tree index method. + not discussed yet, mainly because they are not useful + with the most commonly used index methods. </para> <para> diff --git a/doc/src/sgml/xoper.sgml b/doc/src/sgml/xoper.sgml index a2705eb6636..bb04e2854d1 100644 --- a/doc/src/sgml/xoper.sgml +++ b/doc/src/sgml/xoper.sgml @@ -1,10 +1,15 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/xoper.sgml,v 1.24 2003/06/22 22:04:54 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/xoper.sgml,v 1.24.2.1 2003/09/07 04:36:44 momjian Exp $ --> <sect1 id="xoper"> <title>User-defined Operators</title> + <indexterm zone="xoper"> + <primary>operator</primary> + <secondary>user-defined</secondary> + </indexterm> + <Para> Every operator is <quote>syntactic sugar</quote> for a call to an underlying function that does the real work; so you must @@ -18,9 +23,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xoper.sgml,v 1.24 2003/06/22 22:04:54 tgl E <Para> <productname>PostgreSQL</productname> supports left unary, right - unary, and binary operators. Operators can be overloaded; that is, - the same operator name can be used for different operators that - have different numbers and types of operands. When a query is + unary, and binary operators. Operators can be + overloaded;<indexterm><primary>overloading</primary><secondary>operators</secondary></indexterm> + that is, the same operator name can be used for different operators + that have different numbers and types of operands. When a query is executed, the system determines the operator to call from the number and types of the provided operands. </Para> @@ -473,17 +479,6 @@ table1.column1 OP table2.column2 <note> <para> - <literal>GROUP BY</> and <literal>DISTINCT</> operations require each - datatype being grouped or compared to have a mergejoinable - equality operator named <literal>=</>. The equality operator and its - associated <literal>SORT1</> operator are used to implement these - operations. Also, the associated <literal>SORT1</> operator is the - default ordering operator for <literal>ORDER BY</>. - </para> - </note> - - <note> - <para> In <ProductName>PostgreSQL</ProductName> versions before 7.3, the <literal>MERGES</> shorthand was not available: to make a merge-joinable operator one had to write both <literal>SORT1</> and diff --git a/doc/src/sgml/xplang.sgml b/doc/src/sgml/xplang.sgml index d350ba25ea8..b0b1622fa9a 100644 --- a/doc/src/sgml/xplang.sgml +++ b/doc/src/sgml/xplang.sgml @@ -1,10 +1,14 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.22 2003/06/30 18:31:42 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.22.2.1 2003/09/07 04:36:44 momjian Exp $ --> <chapter id="xplang"> <title id="xplang-title">Procedural Languages</title> + <indexterm zone="xplang"> + <primary>procedural language</primary> + </indexterm> + <para> <productname>PostgreSQL</productname> allows users to add new programming languages to be available for writing functions and diff --git a/doc/src/sgml/xtypes.sgml b/doc/src/sgml/xtypes.sgml index 74ced8cd83e..2816f59baf8 100644 --- a/doc/src/sgml/xtypes.sgml +++ b/doc/src/sgml/xtypes.sgml @@ -1,13 +1,13 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/xtypes.sgml,v 1.19 2003/08/10 01:20:34 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/xtypes.sgml,v 1.19.2.1 2003/09/07 04:36:44 momjian Exp $ --> <sect1 id="xtypes"> <title>User-Defined Types</title> <indexterm zone="xtypes"> - <primary>data types</primary> - <secondary>extending</secondary> + <primary>data type</primary> + <secondary>user-defined</secondary> </indexterm> <comment> @@ -34,13 +34,17 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xtypes.sgml,v 1.19 2003/08/10 01:20:34 tgl <indexterm> <primary>output function</primary> </indexterm> - A user-defined type must always have input and output functions. + A user-defined type must always have input and output + functions.<indexterm><primary>input function</primary><secondary>of + a data type</secondary></indexterm><indexterm><primary>output + function</primary><secondary>of a data type</secondary></indexterm> These functions determine how the type appears in strings (for input by the user and output to the user) and how the type is organized in memory. The input function takes a null-terminated character string - as its argument and returns the internal (in memory) representation of - the type. The output function takes the internal representation of - the type as argument and returns a null-terminated character string. + as its argument and returns the internal (in memory) representation + of the type. The output function takes the internal representation + of the type as argument and returns a null-terminated character + string. </para> <para> diff --git a/src/Makefile.global.in b/src/Makefile.global.in index 083198089b0..34840ed76d3 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -1,5 +1,5 @@ # -*-makefile-*- -# $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.166 2003/08/08 04:52:20 momjian Exp $ +# $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.166.2.1 2003/09/07 04:36:46 momjian Exp $ #------------------------------------------------------------------------------ # All PostgreSQL makefiles include this file and use the variables it sets, @@ -132,10 +132,7 @@ enable_rpath = @enable_rpath@ enable_nls = @enable_nls@ enable_debug = @enable_debug@ -python_version = @python_version@ python_includespec = @python_includespec@ -python_moduledir = @python_moduledir@ -python_moduleexecdir = @python_moduleexecdir@ python_libspec = @python_libspec@ python_configdir = @python_configdir@ @@ -266,6 +263,9 @@ host_tuple = @host@ host_os = @host_os@ host_cpu = @host_cpu@ +# Make HAVE_IPV6 available for initdb script creation +HAVE_IPV6= @HAVE_IPV6@ + # The HP-UX port makefile, for one, needs access to this symbol HAVE_POSIX_SIGNALS= @HAVE_POSIX_SIGNALS@ diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index fbdf0dc04c8..f387418b129 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.65 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.65.2.1 2003/09/07 04:36:46 momjian Exp $ * * NOTES * This file contains only the public interface routines. @@ -27,9 +27,6 @@ #include "miscadmin.h" -bool BuildingHash = false; - - /* Working state for hashbuild and its callback */ typedef struct { @@ -61,9 +58,6 @@ hashbuild(PG_FUNCTION_ARGS) double reltuples; HashBuildState buildstate; - /* set flag to disable locking */ - BuildingHash = true; - /* * We expect to be called exactly once for any index relation. If * that's not the case, big trouble's what we have. @@ -82,9 +76,6 @@ hashbuild(PG_FUNCTION_ARGS) reltuples = IndexBuildHeapScan(heap, index, indexInfo, hashbuildCallback, (void *) &buildstate); - /* all done */ - BuildingHash = false; - /* * Since we just counted the tuples in the heap, we update its stats * in pg_class to guarantee that the planner takes advantage of the @@ -212,11 +203,19 @@ hashgettuple(PG_FUNCTION_ARGS) IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1); HashScanOpaque so = (HashScanOpaque) scan->opaque; + Relation rel = scan->indexRelation; Page page; OffsetNumber offnum; bool res; /* + * We hold pin but not lock on current buffer while outside the hash AM. + * Reacquire the read lock here. + */ + if (BufferIsValid(so->hashso_curbuf)) + _hash_chgbufaccess(rel, so->hashso_curbuf, HASH_NOLOCK, HASH_READ); + + /* * If we've already initialized this scan, we can just advance it in * the appropriate direction. If we haven't done so yet, we call a * routine to get the first item in the scan. @@ -267,6 +266,10 @@ hashgettuple(PG_FUNCTION_ARGS) } } + /* Release read lock on current buffer, but keep it pinned */ + if (BufferIsValid(so->hashso_curbuf)) + _hash_chgbufaccess(rel, so->hashso_curbuf, HASH_READ, HASH_NOLOCK); + PG_RETURN_BOOL(res); } @@ -285,6 +288,8 @@ hashbeginscan(PG_FUNCTION_ARGS) scan = RelationGetIndexScan(rel, keysz, scankey); so = (HashScanOpaque) palloc(sizeof(HashScanOpaqueData)); + so->hashso_bucket_valid = false; + so->hashso_bucket_blkno = 0; so->hashso_curbuf = so->hashso_mrkbuf = InvalidBuffer; scan->opaque = so; @@ -303,28 +308,38 @@ hashrescan(PG_FUNCTION_ARGS) IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); ScanKey scankey = (ScanKey) PG_GETARG_POINTER(1); HashScanOpaque so = (HashScanOpaque) scan->opaque; - ItemPointer iptr; + Relation rel = scan->indexRelation; - /* we hold a read lock on the current page in the scan */ - if (ItemPointerIsValid(iptr = &(scan->currentItemData))) + /* if we are called from beginscan, so is still NULL */ + if (so) { - _hash_relbuf(scan->indexRelation, so->hashso_curbuf, HASH_READ); + /* release any pins we still hold */ + if (BufferIsValid(so->hashso_curbuf)) + _hash_dropbuf(rel, so->hashso_curbuf); so->hashso_curbuf = InvalidBuffer; - ItemPointerSetInvalid(iptr); - } - if (ItemPointerIsValid(iptr = &(scan->currentMarkData))) - { - _hash_relbuf(scan->indexRelation, so->hashso_mrkbuf, HASH_READ); + + if (BufferIsValid(so->hashso_mrkbuf)) + _hash_dropbuf(rel, so->hashso_mrkbuf); so->hashso_mrkbuf = InvalidBuffer; - ItemPointerSetInvalid(iptr); + + /* release lock on bucket, too */ + if (so->hashso_bucket_blkno) + _hash_droplock(rel, so->hashso_bucket_blkno, HASH_SHARE); + so->hashso_bucket_blkno = 0; } + /* set positions invalid (this will cause _hash_first call) */ + ItemPointerSetInvalid(&(scan->currentItemData)); + ItemPointerSetInvalid(&(scan->currentMarkData)); + /* Update scan key, if a new one is given */ if (scankey && scan->numberOfKeys > 0) { memmove(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData)); + if (so) + so->hashso_bucket_valid = false; } PG_RETURN_VOID(); @@ -337,32 +352,32 @@ Datum hashendscan(PG_FUNCTION_ARGS) { IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); - ItemPointer iptr; - HashScanOpaque so; + HashScanOpaque so = (HashScanOpaque) scan->opaque; + Relation rel = scan->indexRelation; - so = (HashScanOpaque) scan->opaque; + /* don't need scan registered anymore */ + _hash_dropscan(scan); - /* release any locks we still hold */ - if (ItemPointerIsValid(iptr = &(scan->currentItemData))) - { - _hash_relbuf(scan->indexRelation, so->hashso_curbuf, HASH_READ); - so->hashso_curbuf = InvalidBuffer; - ItemPointerSetInvalid(iptr); - } + /* release any pins we still hold */ + if (BufferIsValid(so->hashso_curbuf)) + _hash_dropbuf(rel, so->hashso_curbuf); + so->hashso_curbuf = InvalidBuffer; - if (ItemPointerIsValid(iptr = &(scan->currentMarkData))) - { - if (BufferIsValid(so->hashso_mrkbuf)) - _hash_relbuf(scan->indexRelation, so->hashso_mrkbuf, HASH_READ); - so->hashso_mrkbuf = InvalidBuffer; - ItemPointerSetInvalid(iptr); - } + if (BufferIsValid(so->hashso_mrkbuf)) + _hash_dropbuf(rel, so->hashso_mrkbuf); + so->hashso_mrkbuf = InvalidBuffer; - /* don't need scan registered anymore */ - _hash_dropscan(scan); + /* release lock on bucket, too */ + if (so->hashso_bucket_blkno) + _hash_droplock(rel, so->hashso_bucket_blkno, HASH_SHARE); + so->hashso_bucket_blkno = 0; /* be tidy */ - pfree(scan->opaque); + ItemPointerSetInvalid(&(scan->currentItemData)); + ItemPointerSetInvalid(&(scan->currentMarkData)); + + pfree(so); + scan->opaque = NULL; PG_RETURN_VOID(); } @@ -374,25 +389,21 @@ Datum hashmarkpos(PG_FUNCTION_ARGS) { IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); - ItemPointer iptr; - HashScanOpaque so; - - so = (HashScanOpaque) scan->opaque; + HashScanOpaque so = (HashScanOpaque) scan->opaque; + Relation rel = scan->indexRelation; - /* release lock on old marked data, if any */ - if (ItemPointerIsValid(iptr = &(scan->currentMarkData))) - { - _hash_relbuf(scan->indexRelation, so->hashso_mrkbuf, HASH_READ); - so->hashso_mrkbuf = InvalidBuffer; - ItemPointerSetInvalid(iptr); - } + /* release pin on old marked data, if any */ + if (BufferIsValid(so->hashso_mrkbuf)) + _hash_dropbuf(rel, so->hashso_mrkbuf); + so->hashso_mrkbuf = InvalidBuffer; + ItemPointerSetInvalid(&(scan->currentMarkData)); - /* bump lock on currentItemData and copy to currentMarkData */ + /* bump pin count on currentItemData and copy to currentMarkData */ if (ItemPointerIsValid(&(scan->currentItemData))) { - so->hashso_mrkbuf = _hash_getbuf(scan->indexRelation, + so->hashso_mrkbuf = _hash_getbuf(rel, BufferGetBlockNumber(so->hashso_curbuf), - HASH_READ); + HASH_NOLOCK); scan->currentMarkData = scan->currentItemData; } @@ -406,26 +417,21 @@ Datum hashrestrpos(PG_FUNCTION_ARGS) { IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); - ItemPointer iptr; - HashScanOpaque so; + HashScanOpaque so = (HashScanOpaque) scan->opaque; + Relation rel = scan->indexRelation; - so = (HashScanOpaque) scan->opaque; + /* release pin on current data, if any */ + if (BufferIsValid(so->hashso_curbuf)) + _hash_dropbuf(rel, so->hashso_curbuf); + so->hashso_curbuf = InvalidBuffer; + ItemPointerSetInvalid(&(scan->currentItemData)); - /* release lock on current data, if any */ - if (ItemPointerIsValid(iptr = &(scan->currentItemData))) - { - _hash_relbuf(scan->indexRelation, so->hashso_curbuf, HASH_READ); - so->hashso_curbuf = InvalidBuffer; - ItemPointerSetInvalid(iptr); - } - - /* bump lock on currentMarkData and copy to currentItemData */ + /* bump pin count on currentMarkData and copy to currentItemData */ if (ItemPointerIsValid(&(scan->currentMarkData))) { - so->hashso_curbuf = _hash_getbuf(scan->indexRelation, + so->hashso_curbuf = _hash_getbuf(rel, BufferGetBlockNumber(so->hashso_mrkbuf), - HASH_READ); - + HASH_NOLOCK); scan->currentItemData = scan->currentMarkData; } @@ -449,40 +455,163 @@ hashbulkdelete(PG_FUNCTION_ARGS) BlockNumber num_pages; double tuples_removed; double num_index_tuples; - IndexScanDesc iscan; + double orig_ntuples; + Bucket orig_maxbucket; + Bucket cur_maxbucket; + Bucket cur_bucket; + Buffer metabuf; + HashMetaPage metap; + HashMetaPageData local_metapage; tuples_removed = 0; num_index_tuples = 0; /* - * XXX generic implementation --- should be improved! + * Read the metapage to fetch original bucket and tuple counts. Also, + * we keep a copy of the last-seen metapage so that we can use its + * hashm_spares[] values to compute bucket page addresses. This is a + * bit hokey but perfectly safe, since the interesting entries in the + * spares array cannot change under us; and it beats rereading the + * metapage for each bucket. */ + metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ); + metap = (HashMetaPage) BufferGetPage(metabuf); + _hash_checkpage(rel, (Page) metap, LH_META_PAGE); + orig_maxbucket = metap->hashm_maxbucket; + orig_ntuples = metap->hashm_ntuples; + memcpy(&local_metapage, metap, sizeof(local_metapage)); + _hash_relbuf(rel, metabuf); + + /* Scan the buckets that we know exist */ + cur_bucket = 0; + cur_maxbucket = orig_maxbucket; + +loop_top: + while (cur_bucket <= cur_maxbucket) + { + BlockNumber bucket_blkno; + BlockNumber blkno; + bool bucket_dirty = false; - /* walk through the entire index */ - iscan = index_beginscan(NULL, rel, SnapshotAny, 0, (ScanKey) NULL); - /* including killed tuples */ - iscan->ignore_killed_tuples = false; + /* Get address of bucket's start page */ + bucket_blkno = BUCKET_TO_BLKNO(&local_metapage, cur_bucket); - while (index_getnext_indexitem(iscan, ForwardScanDirection)) - { - if (callback(&iscan->xs_ctup.t_self, callback_state)) - { - ItemPointerData indextup = iscan->currentItemData; + /* Exclusive-lock the bucket so we can shrink it */ + _hash_getlock(rel, bucket_blkno, HASH_EXCLUSIVE); - /* adjust any active scans that will be affected by deletion */ - /* (namely, my own scan) */ - _hash_adjscans(rel, &indextup); + /* Shouldn't have any active scans locally, either */ + if (_hash_has_active_scan(rel, cur_bucket)) + elog(ERROR, "hash index has active scan during VACUUM"); + + /* Scan each page in bucket */ + blkno = bucket_blkno; + while (BlockNumberIsValid(blkno)) + { + Buffer buf; + Page page; + HashPageOpaque opaque; + OffsetNumber offno; + OffsetNumber maxoffno; + bool page_dirty = false; + + buf = _hash_getbuf(rel, blkno, HASH_WRITE); + page = BufferGetPage(buf); + _hash_checkpage(rel, page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); + opaque = (HashPageOpaque) PageGetSpecialPointer(page); + Assert(opaque->hasho_bucket == cur_bucket); + + /* Scan each tuple in page */ + offno = FirstOffsetNumber; + maxoffno = PageGetMaxOffsetNumber(page); + while (offno <= maxoffno) + { + HashItem hitem; + ItemPointer htup; + + hitem = (HashItem) PageGetItem(page, + PageGetItemId(page, offno)); + htup = &(hitem->hash_itup.t_tid); + if (callback(htup, callback_state)) + { + /* delete the item from the page */ + PageIndexTupleDelete(page, offno); + bucket_dirty = page_dirty = true; + + /* don't increment offno, instead decrement maxoffno */ + maxoffno = OffsetNumberPrev(maxoffno); + + tuples_removed += 1; + } + else + { + offno = OffsetNumberNext(offno); + + num_index_tuples += 1; + } + } - /* delete the data from the page */ - _hash_pagedel(rel, &indextup); + /* + * Write page if needed, advance to next page. + */ + blkno = opaque->hasho_nextblkno; - tuples_removed += 1; + if (page_dirty) + _hash_wrtbuf(rel, buf); + else + _hash_relbuf(rel, buf); } + + /* If we deleted anything, try to compact free space */ + if (bucket_dirty) + _hash_squeezebucket(rel, cur_bucket, bucket_blkno); + + /* Release bucket lock */ + _hash_droplock(rel, bucket_blkno, HASH_EXCLUSIVE); + + /* Advance to next bucket */ + cur_bucket++; + } + + /* Write-lock metapage and check for split since we started */ + metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE); + metap = (HashMetaPage) BufferGetPage(metabuf); + _hash_checkpage(rel, (Page) metap, LH_META_PAGE); + + if (cur_maxbucket != metap->hashm_maxbucket) + { + /* There's been a split, so process the additional bucket(s) */ + cur_maxbucket = metap->hashm_maxbucket; + memcpy(&local_metapage, metap, sizeof(local_metapage)); + _hash_relbuf(rel, metabuf); + goto loop_top; + } + + /* Okay, we're really done. Update tuple count in metapage. */ + + if (orig_maxbucket == metap->hashm_maxbucket && + orig_ntuples == metap->hashm_ntuples) + { + /* + * No one has split or inserted anything since start of scan, + * so believe our count as gospel. + */ + metap->hashm_ntuples = num_index_tuples; + } + else + { + /* + * Otherwise, our count is untrustworthy since we may have + * double-scanned tuples in split buckets. Proceed by + * dead-reckoning. + */ + if (metap->hashm_ntuples > tuples_removed) + metap->hashm_ntuples -= tuples_removed; else - num_index_tuples += 1; + metap->hashm_ntuples = 0; + num_index_tuples = metap->hashm_ntuples; } - index_endscan(iscan); + _hash_wrtbuf(rel, metabuf); /* return statistics */ num_pages = RelationGetNumberOfBlocks(rel); diff --git a/src/backend/access/hash/hashinsert.c b/src/backend/access/hash/hashinsert.c index d9da5e1ee37..4cb3266a944 100644 --- a/src/backend/access/hash/hashinsert.c +++ b/src/backend/access/hash/hashinsert.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hashinsert.c,v 1.27 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hashinsert.c,v 1.27.2.1 2003/09/07 04:36:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -16,136 +16,124 @@ #include "postgres.h" #include "access/hash.h" +#include "storage/lmgr.h" + + +static OffsetNumber _hash_pgaddtup(Relation rel, Buffer buf, + Size itemsize, HashItem hitem); -static InsertIndexResult _hash_insertonpg(Relation rel, Buffer buf, int keysz, ScanKey scankey, HashItem hitem, Buffer metabuf); -static OffsetNumber _hash_pgaddtup(Relation rel, Buffer buf, int keysz, ScanKey itup_scankey, Size itemsize, HashItem hitem); /* * _hash_doinsert() -- Handle insertion of a single HashItem in the table. * * This routine is called by the public interface routines, hashbuild - * and hashinsert. By here, hashitem is filled in, and has a unique - * (xid, seqno) pair. The datum to be used as a "key" is in the - * hashitem. + * and hashinsert. By here, hashitem is completely filled in. + * The datum to be used as a "key" is in the hashitem. */ InsertIndexResult _hash_doinsert(Relation rel, HashItem hitem) { Buffer buf; Buffer metabuf; - BlockNumber blkno; HashMetaPage metap; IndexTuple itup; + BlockNumber itup_blkno; + OffsetNumber itup_off; InsertIndexResult res; - ScanKey itup_scankey; - int natts; + BlockNumber blkno; Page page; - - metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ); - metap = (HashMetaPage) BufferGetPage(metabuf); - _hash_checkpage((Page) metap, LH_META_PAGE); - - /* we need a scan key to do our search, so build one */ - itup = &(hitem->hash_itup); - if ((natts = rel->rd_rel->relnatts) != 1) - elog(ERROR, "Hash indexes support only one index key"); - itup_scankey = _hash_mkscankey(rel, itup); + HashPageOpaque pageopaque; + Size itemsz; + bool do_expand; + uint32 hashkey; + Bucket bucket; + Datum datum; + bool isnull; /* - * find the first page in the bucket chain containing this key and - * place it in buf. _hash_search obtains a read lock for us. + * Compute the hash key for the item. We do this first so as not to + * need to hold any locks while running the hash function. */ - _hash_search(rel, natts, itup_scankey, &buf, metap); - page = BufferGetPage(buf); - _hash_checkpage(page, LH_BUCKET_PAGE); + itup = &(hitem->hash_itup); + if (rel->rd_rel->relnatts != 1) + elog(ERROR, "hash indexes support only one index key"); + datum = index_getattr(itup, 1, RelationGetDescr(rel), &isnull); + Assert(!isnull); + hashkey = _hash_datum2hashkey(rel, datum); + + /* compute item size too */ + itemsz = IndexTupleDSize(hitem->hash_itup) + + (sizeof(HashItemData) - sizeof(IndexTupleData)); + + itemsz = MAXALIGN(itemsz); /* be safe, PageAddItem will do this but + * we need to be consistent */ /* - * trade in our read lock for a write lock so that we can do the - * insertion. + * Acquire shared split lock so we can compute the target bucket + * safely (see README). */ - blkno = BufferGetBlockNumber(buf); - _hash_relbuf(rel, buf, HASH_READ); - buf = _hash_getbuf(rel, blkno, HASH_WRITE); + _hash_getlock(rel, 0, HASH_SHARE); + /* Read the metapage */ + metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ); + metap = (HashMetaPage) BufferGetPage(metabuf); + _hash_checkpage(rel, (Page) metap, LH_META_PAGE); /* - * XXX btree comment (haven't decided what to do in hash): don't think - * the bucket can be split while we're reading the metapage. - * - * If the page was split between the time that we surrendered our read - * lock and acquired our write lock, then this page may no longer be - * the right place for the key we want to insert. + * Check whether the item can fit on a hash page at all. (Eventually, + * we ought to try to apply TOAST methods if not.) Note that at this + * point, itemsz doesn't include the ItemId. */ + if (itemsz > HashMaxItemSize((Page) metap)) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("index tuple size %lu exceeds hash maximum, %lu", + (unsigned long) itemsz, + (unsigned long) HashMaxItemSize((Page) metap)))); - /* do the insertion */ - res = _hash_insertonpg(rel, buf, natts, itup_scankey, - hitem, metabuf); + /* + * Compute the target bucket number, and convert to block number. + */ + bucket = _hash_hashkey2bucket(hashkey, + metap->hashm_maxbucket, + metap->hashm_highmask, + metap->hashm_lowmask); - /* be tidy */ - _hash_freeskey(itup_scankey); + blkno = BUCKET_TO_BLKNO(metap, bucket); - return res; -} + /* release lock on metapage, but keep pin since we'll need it again */ + _hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK); -/* - * _hash_insertonpg() -- Insert a tuple on a particular page in the table. - * - * This recursive procedure does the following things: - * - * + if necessary, splits the target page. - * + inserts the tuple. - * - * On entry, we must have the right buffer on which to do the - * insertion, and the buffer must be pinned and locked. On return, - * we will have dropped both the pin and the write lock on the buffer. - * - */ -static InsertIndexResult -_hash_insertonpg(Relation rel, - Buffer buf, - int keysz, - ScanKey scankey, - HashItem hitem, - Buffer metabuf) -{ - InsertIndexResult res; - Page page; - BlockNumber itup_blkno; - OffsetNumber itup_off; - Size itemsz; - HashPageOpaque pageopaque; - bool do_expand = false; - Buffer ovflbuf; - HashMetaPage metap; - Bucket bucket; + /* + * Acquire share lock on target bucket; then we can release split lock. + */ + _hash_getlock(rel, blkno, HASH_SHARE); - metap = (HashMetaPage) BufferGetPage(metabuf); - _hash_checkpage((Page) metap, LH_META_PAGE); + _hash_droplock(rel, 0, HASH_SHARE); + /* Fetch the primary bucket page for the bucket */ + buf = _hash_getbuf(rel, blkno, HASH_WRITE); page = BufferGetPage(buf); - _hash_checkpage(page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); + _hash_checkpage(rel, page, LH_BUCKET_PAGE); pageopaque = (HashPageOpaque) PageGetSpecialPointer(page); - bucket = pageopaque->hasho_bucket; - - itemsz = IndexTupleDSize(hitem->hash_itup) - + (sizeof(HashItemData) - sizeof(IndexTupleData)); - itemsz = MAXALIGN(itemsz); + Assert(pageopaque->hasho_bucket == bucket); + /* Do the insertion */ while (PageGetFreeSpace(page) < itemsz) { /* * no space on this page; check for an overflow page */ - if (BlockNumberIsValid(pageopaque->hasho_nextblkno)) + BlockNumber nextblkno = pageopaque->hasho_nextblkno; + + if (BlockNumberIsValid(nextblkno)) { /* * ovfl page exists; go get it. if it doesn't have room, * we'll find out next pass through the loop test above. */ - ovflbuf = _hash_getbuf(rel, pageopaque->hasho_nextblkno, - HASH_WRITE); - _hash_relbuf(rel, buf, HASH_WRITE); - buf = ovflbuf; + _hash_relbuf(rel, buf); + buf = _hash_getbuf(rel, nextblkno, HASH_WRITE); page = BufferGetPage(buf); } else @@ -154,68 +142,72 @@ _hash_insertonpg(Relation rel, * we're at the end of the bucket chain and we haven't found a * page with enough room. allocate a new overflow page. */ - do_expand = true; - ovflbuf = _hash_addovflpage(rel, &metabuf, buf); - _hash_relbuf(rel, buf, HASH_WRITE); - buf = ovflbuf; + + /* release our write lock without modifying buffer */ + _hash_chgbufaccess(rel, buf, HASH_READ, HASH_NOLOCK); + + /* chain to a new overflow page */ + buf = _hash_addovflpage(rel, metabuf, buf); page = BufferGetPage(buf); - if (PageGetFreeSpace(page) < itemsz) - { - /* it doesn't fit on an empty page -- give up */ - elog(ERROR, "hash item too large"); - } + /* should fit now, given test above */ + Assert(PageGetFreeSpace(page) >= itemsz); } - _hash_checkpage(page, LH_OVERFLOW_PAGE); + _hash_checkpage(rel, page, LH_OVERFLOW_PAGE); pageopaque = (HashPageOpaque) PageGetSpecialPointer(page); Assert(pageopaque->hasho_bucket == bucket); } - itup_off = _hash_pgaddtup(rel, buf, keysz, scankey, itemsz, hitem); + /* found page with enough space, so add the item here */ + itup_off = _hash_pgaddtup(rel, buf, itemsz, hitem); itup_blkno = BufferGetBlockNumber(buf); - /* by here, the new tuple is inserted */ - res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData)); + /* write and release the modified page */ + _hash_wrtbuf(rel, buf); - ItemPointerSet(&(res->pointerData), itup_blkno, itup_off); + /* We can drop the bucket lock now */ + _hash_droplock(rel, blkno, HASH_SHARE); - if (res != NULL) - { - /* - * Increment the number of keys in the table. We switch lock - * access type just for a moment to allow greater accessibility to - * the metapage. - */ - metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, - HASH_READ, HASH_WRITE); - metap->hashm_nkeys += 1; - metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, - HASH_WRITE, HASH_READ); + /* + * Write-lock the metapage so we can increment the tuple count. + * After incrementing it, check to see if it's time for a split. + */ + _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE); - } + metap->hashm_ntuples += 1; - _hash_wrtbuf(rel, buf); + /* Make sure this stays in sync with _hash_expandtable() */ + do_expand = metap->hashm_ntuples > + (double) metap->hashm_ffactor * (metap->hashm_maxbucket + 1); - if (do_expand || - (metap->hashm_nkeys / (metap->hashm_maxbucket + 1)) - > metap->hashm_ffactor) + /* Write out the metapage and drop lock, but keep pin */ + _hash_chgbufaccess(rel, metabuf, HASH_WRITE, HASH_NOLOCK); + + /* Attempt to split if a split is needed */ + if (do_expand) _hash_expandtable(rel, metabuf); - _hash_relbuf(rel, metabuf, HASH_READ); + + /* Finally drop our pin on the metapage */ + _hash_dropbuf(rel, metabuf); + + /* Create the return data structure */ + res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData)); + + ItemPointerSet(&(res->pointerData), itup_blkno, itup_off); + return res; } /* * _hash_pgaddtup() -- add a tuple to a particular page in the index. * - * This routine adds the tuple to the page as requested, and keeps the - * write lock and reference associated with the page's buffer. It is - * an error to call pgaddtup() without a write lock and reference. + * This routine adds the tuple to the page as requested; it does + * not write out the page. It is an error to call pgaddtup() without + * a write lock and pin. */ static OffsetNumber _hash_pgaddtup(Relation rel, Buffer buf, - int keysz, - ScanKey itup_scankey, Size itemsize, HashItem hitem) { @@ -223,7 +215,7 @@ _hash_pgaddtup(Relation rel, Page page; page = BufferGetPage(buf); - _hash_checkpage(page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); + _hash_checkpage(rel, page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); itup_off = OffsetNumberNext(PageGetMaxOffsetNumber(page)); if (PageAddItem(page, (Item) hitem, itemsize, itup_off, LP_USED) @@ -231,8 +223,5 @@ _hash_pgaddtup(Relation rel, elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(rel)); - /* write the buffer, but hold our lock */ - _hash_wrtnorelbuf(buf); - return itup_off; } diff --git a/src/backend/access/hash/hashovfl.c b/src/backend/access/hash/hashovfl.c index 06233b817b7..6470ec38f30 100644 --- a/src/backend/access/hash/hashovfl.c +++ b/src/backend/access/hash/hashovfl.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hashovfl.c,v 1.37 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hashovfl.c,v 1.37.2.1 2003/09/07 04:36:47 momjian Exp $ * * NOTES * Overflow pages look like ordinary relation pages. @@ -20,253 +20,314 @@ #include "access/hash.h" -static OverflowPageAddress _hash_getovfladdr(Relation rel, Buffer *metabufp); +static BlockNumber _hash_getovflpage(Relation rel, Buffer metabuf); static uint32 _hash_firstfreebit(uint32 map); + +/* + * Convert overflow page bit number (its index in the free-page bitmaps) + * to block number within the index. + */ +static BlockNumber +bitno_to_blkno(HashMetaPage metap, uint32 ovflbitnum) +{ + uint32 splitnum = metap->hashm_ovflpoint; + uint32 i; + + /* Convert zero-based bitnumber to 1-based page number */ + ovflbitnum += 1; + + /* Determine the split number for this page (must be >= 1) */ + for (i = 1; + i < splitnum && ovflbitnum > metap->hashm_spares[i]; + i++) + /* loop */ ; + + /* + * Convert to absolute page number by adding the number of bucket pages + * that exist before this split point. + */ + return (BlockNumber) ((1 << i) + ovflbitnum); +} + +/* + * Convert overflow page block number to bit number for free-page bitmap. + */ +static uint32 +blkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno) +{ + uint32 splitnum = metap->hashm_ovflpoint; + uint32 i; + uint32 bitnum; + + /* Determine the split number containing this page */ + for (i = 1; i <= splitnum; i++) + { + if (ovflblkno <= (BlockNumber) (1 << i)) + break; /* oops */ + bitnum = ovflblkno - (1 << i); + if (bitnum <= metap->hashm_spares[i]) + return bitnum - 1; /* -1 to convert 1-based to 0-based */ + } + + elog(ERROR, "invalid overflow block number %u", ovflblkno); + return 0; /* keep compiler quiet */ +} + /* * _hash_addovflpage * - * Add an overflow page to the page currently pointed to by the buffer - * argument 'buf'. + * Add an overflow page to the bucket whose last page is pointed to by 'buf'. * - * *Metabufp has a read lock upon entering the function; buf has a - * write lock. + * On entry, the caller must hold a pin but no lock on 'buf'. The pin is + * dropped before exiting (we assume the caller is not interested in 'buf' + * anymore). The returned overflow page will be pinned and write-locked; + * it is guaranteed to be empty. * + * The caller must hold a pin, but no lock, on the metapage buffer. + * That buffer is returned in the same state. + * + * The caller must hold at least share lock on the bucket, to ensure that + * no one else tries to compact the bucket meanwhile. This guarantees that + * 'buf' won't stop being part of the bucket while it's unlocked. + * + * NB: since this could be executed concurrently by multiple processes, + * one should not assume that the returned overflow page will be the + * immediate successor of the originally passed 'buf'. Additional overflow + * pages might have been added to the bucket chain in between. */ Buffer -_hash_addovflpage(Relation rel, Buffer *metabufp, Buffer buf) +_hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf) { - - OverflowPageAddress oaddr; BlockNumber ovflblkno; Buffer ovflbuf; - HashMetaPage metap; - HashPageOpaque ovflopaque; - HashPageOpaque pageopaque; Page page; Page ovflpage; - - /* this had better be the last page in a bucket chain */ - page = BufferGetPage(buf); - _hash_checkpage(page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); - pageopaque = (HashPageOpaque) PageGetSpecialPointer(page); - Assert(!BlockNumberIsValid(pageopaque->hasho_nextblkno)); - - metap = (HashMetaPage) BufferGetPage(*metabufp); - _hash_checkpage((Page) metap, LH_META_PAGE); + HashPageOpaque pageopaque; + HashPageOpaque ovflopaque; /* allocate an empty overflow page */ - oaddr = _hash_getovfladdr(rel, metabufp); - if (oaddr == InvalidOvflAddress) - elog(ERROR, "_hash_getovfladdr failed"); - ovflblkno = OADDR_TO_BLKNO(OADDR_OF(SPLITNUM(oaddr), OPAGENUM(oaddr))); - Assert(BlockNumberIsValid(ovflblkno)); + ovflblkno = _hash_getovflpage(rel, metabuf); + + /* lock the overflow page */ ovflbuf = _hash_getbuf(rel, ovflblkno, HASH_WRITE); - Assert(BufferIsValid(ovflbuf)); ovflpage = BufferGetPage(ovflbuf); - /* initialize the new overflow page */ + /* + * Write-lock the tail page. It is okay to hold two buffer locks here + * since there cannot be anyone else contending for access to ovflbuf. + */ + _hash_chgbufaccess(rel, buf, HASH_NOLOCK, HASH_WRITE); + + /* loop to find current tail page, in case someone else inserted too */ + for (;;) + { + BlockNumber nextblkno; + + page = BufferGetPage(buf); + _hash_checkpage(rel, page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); + pageopaque = (HashPageOpaque) PageGetSpecialPointer(page); + nextblkno = pageopaque->hasho_nextblkno; + + if (!BlockNumberIsValid(nextblkno)) + break; + + /* we assume we do not need to write the unmodified page */ + _hash_relbuf(rel, buf); + + buf = _hash_getbuf(rel, nextblkno, HASH_WRITE); + } + + /* now that we have correct backlink, initialize new overflow page */ _hash_pageinit(ovflpage, BufferGetPageSize(ovflbuf)); ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage); ovflopaque->hasho_prevblkno = BufferGetBlockNumber(buf); ovflopaque->hasho_nextblkno = InvalidBlockNumber; - ovflopaque->hasho_flag = LH_OVERFLOW_PAGE; - ovflopaque->hasho_oaddr = oaddr; ovflopaque->hasho_bucket = pageopaque->hasho_bucket; - _hash_wrtnorelbuf(ovflbuf); + ovflopaque->hasho_flag = LH_OVERFLOW_PAGE; + ovflopaque->hasho_filler = HASHO_FILL; + _hash_wrtnorelbuf(rel, ovflbuf); /* logically chain overflow page to previous page */ pageopaque->hasho_nextblkno = ovflblkno; - _hash_wrtnorelbuf(buf); + _hash_wrtbuf(rel, buf); + return ovflbuf; } /* - * _hash_getovfladdr() - * - * Find an available overflow page and return its address. + * _hash_getovflpage() * - * When we enter this function, we have a read lock on *metabufp which - * we change to a write lock immediately. Before exiting, the write lock - * is exchanged for a read lock. + * Find an available overflow page and return its block number. * + * The caller must hold a pin, but no lock, on the metapage buffer. + * The buffer is returned in the same state. */ -static OverflowPageAddress -_hash_getovfladdr(Relation rel, Buffer *metabufp) +static BlockNumber +_hash_getovflpage(Relation rel, Buffer metabuf) { HashMetaPage metap; Buffer mapbuf = 0; BlockNumber blkno; - PageOffset offset; - OverflowPageAddress oaddr; - SplitNumber splitnum; + uint32 orig_firstfree; + uint32 splitnum; uint32 *freep = NULL; - uint32 max_free; + uint32 max_ovflpg; uint32 bit; uint32 first_page; - uint32 free_bit; - uint32 free_page; - uint32 in_use_bits; + uint32 last_bit; + uint32 last_page; uint32 i, j; - metap = (HashMetaPage) _hash_chgbufaccess(rel, metabufp, HASH_READ, HASH_WRITE); + /* Get exclusive lock on the meta page */ + _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE); - splitnum = metap->hashm_ovflpoint; - max_free = metap->hashm_spares[splitnum]; + metap = (HashMetaPage) BufferGetPage(metabuf); + _hash_checkpage(rel, (Page) metap, LH_META_PAGE); - free_page = (max_free - 1) >> (metap->hashm_bshift + BYTE_TO_BIT); - free_bit = (max_free - 1) & (BMPGSZ_BIT(metap) - 1); + /* start search at hashm_firstfree */ + orig_firstfree = metap->hashm_firstfree; + first_page = orig_firstfree >> BMPG_SHIFT(metap); + bit = orig_firstfree & BMPG_MASK(metap); + i = first_page; + j = bit / BITS_PER_MAP; + bit &= ~(BITS_PER_MAP - 1); - /* Look through all the free maps to find the first free block */ - first_page = metap->hashm_lastfreed >> (metap->hashm_bshift + BYTE_TO_BIT); - for (i = first_page; i <= free_page; i++) + /* outer loop iterates once per bitmap page */ + for (;;) { + BlockNumber mapblkno; Page mappage; + uint32 last_inpage; - blkno = metap->hashm_mapp[i]; - mapbuf = _hash_getbuf(rel, blkno, HASH_WRITE); - mappage = BufferGetPage(mapbuf); - _hash_checkpage(mappage, LH_BITMAP_PAGE); - freep = HashPageGetBitmap(mappage); - Assert(freep); + /* want to end search with the last existing overflow page */ + splitnum = metap->hashm_ovflpoint; + max_ovflpg = metap->hashm_spares[splitnum] - 1; + last_page = max_ovflpg >> BMPG_SHIFT(metap); + last_bit = max_ovflpg & BMPG_MASK(metap); - if (i == free_page) - in_use_bits = free_bit; - else - in_use_bits = BMPGSZ_BIT(metap) - 1; + if (i > last_page) + break; - if (i == first_page) - { - bit = metap->hashm_lastfreed & (BMPGSZ_BIT(metap) - 1); - j = bit / BITS_PER_MAP; - bit = bit & ~(BITS_PER_MAP - 1); - } + Assert(i < metap->hashm_nmaps); + mapblkno = metap->hashm_mapp[i]; + + if (i == last_page) + last_inpage = last_bit; else + last_inpage = BMPGSZ_BIT(metap) - 1; + + /* Release exclusive lock on metapage while reading bitmap page */ + _hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK); + + mapbuf = _hash_getbuf(rel, mapblkno, HASH_WRITE); + mappage = BufferGetPage(mapbuf); + _hash_checkpage(rel, mappage, LH_BITMAP_PAGE); + freep = HashPageGetBitmap(mappage); + + for (; bit <= last_inpage; j++, bit += BITS_PER_MAP) { - bit = 0; - j = 0; - } - for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP) if (freep[j] != ALL_SET) goto found; + } + + /* No free space here, try to advance to next map page */ + _hash_relbuf(rel, mapbuf); + i++; + j = 0; /* scan from start of next map page */ + bit = 0; + + /* Reacquire exclusive lock on the meta page */ + _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE); } /* No Free Page Found - have to allocate a new page */ - metap->hashm_lastfreed = metap->hashm_spares[splitnum]; + bit = metap->hashm_spares[splitnum]; metap->hashm_spares[splitnum]++; - offset = metap->hashm_spares[splitnum] - - (splitnum ? metap->hashm_spares[splitnum - 1] : 0); - - if (offset > SPLITMASK) - { - if (++splitnum >= NCACHED) - ereport(ERROR, - (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("out of overflow pages in hash index \"%s\"", - RelationGetRelationName(rel)))); - metap->hashm_ovflpoint = splitnum; - metap->hashm_spares[splitnum] = metap->hashm_spares[splitnum - 1]; - metap->hashm_spares[splitnum - 1]--; - offset = 0; - } /* Check if we need to allocate a new bitmap page */ - if (free_bit == (uint32) (BMPGSZ_BIT(metap) - 1)) + if (last_bit == (uint32) (BMPGSZ_BIT(metap) - 1)) { - /* won't be needing old map page */ - - _hash_relbuf(rel, mapbuf, HASH_WRITE); - - free_page++; - if (free_page >= NCACHED) - ereport(ERROR, - (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("out of overflow pages in hash index \"%s\"", - RelationGetRelationName(rel)))); - /* - * This is tricky. The 1 indicates that you want the new page - * allocated with 1 clear bit. Actually, you are going to - * allocate 2 pages from this map. The first is going to be the - * map page, the second is the overflow page we were looking for. - * The init_bitmap routine automatically, sets the first bit of - * itself to indicate that the bitmap itself is in use. We would - * explicitly set the second bit, but don't have to if we tell - * init_bitmap not to leave it clear in the first place. + * We create the new bitmap page with all pages marked "in use". + * Actually two pages in the new bitmap's range will exist + * immediately: the bitmap page itself, and the following page + * which is the one we return to the caller. Both of these are + * correctly marked "in use". Subsequent pages do not exist yet, + * but it is convenient to pre-mark them as "in use" too. */ - if (_hash_initbitmap(rel, metap, OADDR_OF(splitnum, offset), - 1, free_page)) - elog(ERROR, "_hash_initbitmap failed"); + _hash_initbitmap(rel, metap, bitno_to_blkno(metap, bit)); + + bit = metap->hashm_spares[splitnum]; metap->hashm_spares[splitnum]++; - offset++; - if (offset > SPLITMASK) - { - if (++splitnum >= NCACHED) - ereport(ERROR, - (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("out of overflow pages in hash index \"%s\"", - RelationGetRelationName(rel)))); - metap->hashm_ovflpoint = splitnum; - metap->hashm_spares[splitnum] = metap->hashm_spares[splitnum - 1]; - metap->hashm_spares[splitnum - 1]--; - offset = 0; - } } else { /* - * Free_bit addresses the last used bit. Bump it to address the - * first available bit. + * Nothing to do here; since the page was past the last used page, + * we know its bitmap bit was preinitialized to "in use". */ - free_bit++; - SETBIT(freep, free_bit); - _hash_wrtbuf(rel, mapbuf); } /* Calculate address of the new overflow page */ - oaddr = OADDR_OF(splitnum, offset); - _hash_chgbufaccess(rel, metabufp, HASH_WRITE, HASH_READ); - return oaddr; + blkno = bitno_to_blkno(metap, bit); + + /* + * Adjust hashm_firstfree to avoid redundant searches. But don't + * risk changing it if someone moved it while we were searching + * bitmap pages. + */ + if (metap->hashm_firstfree == orig_firstfree) + metap->hashm_firstfree = bit + 1; + + /* Write updated metapage and release lock, but not pin */ + _hash_chgbufaccess(rel, metabuf, HASH_WRITE, HASH_NOLOCK); + + return blkno; found: - bit = bit + _hash_firstfreebit(freep[j]); + /* convert bit to bit number within page */ + bit += _hash_firstfreebit(freep[j]); + + /* mark page "in use" in the bitmap */ SETBIT(freep, bit); _hash_wrtbuf(rel, mapbuf); + /* Reacquire exclusive lock on the meta page */ + _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE); + + /* convert bit to absolute bit number */ + bit += (i << BMPG_SHIFT(metap)); + + /* Calculate address of the new overflow page */ + blkno = bitno_to_blkno(metap, bit); + /* - * Bits are addressed starting with 0, but overflow pages are - * addressed beginning at 1. Bit is a bit addressnumber, so we need to - * increment it to convert it to a page number. + * Adjust hashm_firstfree to avoid redundant searches. But don't + * risk changing it if someone moved it while we were searching + * bitmap pages. */ + if (metap->hashm_firstfree == orig_firstfree) + { + metap->hashm_firstfree = bit + 1; - bit = 1 + bit + (i * BMPGSZ_BIT(metap)); - if (bit >= metap->hashm_lastfreed) - metap->hashm_lastfreed = bit - 1; - - /* Calculate the split number for this page */ - for (i = 0; (i < splitnum) && (bit > metap->hashm_spares[i]); i++) - ; - offset = (i ? bit - metap->hashm_spares[i - 1] : bit); - if (offset >= SPLITMASK) - ereport(ERROR, - (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("out of overflow pages in hash index \"%s\"", - RelationGetRelationName(rel)))); + /* Write updated metapage and release lock, but not pin */ + _hash_chgbufaccess(rel, metabuf, HASH_WRITE, HASH_NOLOCK); + } + else + { + /* We didn't change the metapage, so no need to write */ + _hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK); + } - /* initialize this page */ - oaddr = OADDR_OF(i, offset); - _hash_chgbufaccess(rel, metabufp, HASH_WRITE, HASH_READ); - return oaddr; + return blkno; } /* * _hash_firstfreebit() * - * Return the first bit that is not set in the argument 'map'. This - * function is used to find an available overflow page within a - * splitnumber. - * + * Return the number of the first bit that is not set in the word 'map'. */ static uint32 _hash_firstfreebit(uint32 map) @@ -279,61 +340,64 @@ _hash_firstfreebit(uint32 map) { if (!(mask & map)) return i; - mask = mask << 1; + mask <<= 1; } - return i; + + elog(ERROR, "firstfreebit found no free bit"); + + return 0; /* keep compiler quiet */ } /* * _hash_freeovflpage() - * - * Mark this overflow page as free and return a buffer with - * the page that follows it (which may be defined as - * InvalidBuffer). + * Remove this overflow page from its bucket's chain, and mark the page as + * free. On entry, ovflbuf is write-locked; it is released before exiting. + * + * Returns the block number of the page that followed the given page + * in the bucket, or InvalidBlockNumber if no following page. * + * NB: caller must not hold lock on metapage, nor on either page that's + * adjacent in the bucket chain. The caller had better hold exclusive lock + * on the bucket, too. */ -Buffer +BlockNumber _hash_freeovflpage(Relation rel, Buffer ovflbuf) { HashMetaPage metap; Buffer metabuf; Buffer mapbuf; + BlockNumber ovflblkno; BlockNumber prevblkno; BlockNumber blkno; BlockNumber nextblkno; HashPageOpaque ovflopaque; Page ovflpage; Page mappage; - OverflowPageAddress addr; - SplitNumber splitnum; uint32 *freep; - uint32 ovflpgno; + uint32 ovflbitno; int32 bitmappage, bitmapbit; Bucket bucket; - metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE); - metap = (HashMetaPage) BufferGetPage(metabuf); - _hash_checkpage((Page) metap, LH_META_PAGE); - + /* Get information from the doomed page */ + ovflblkno = BufferGetBlockNumber(ovflbuf); ovflpage = BufferGetPage(ovflbuf); - _hash_checkpage(ovflpage, LH_OVERFLOW_PAGE); + _hash_checkpage(rel, ovflpage, LH_OVERFLOW_PAGE); ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage); - addr = ovflopaque->hasho_oaddr; nextblkno = ovflopaque->hasho_nextblkno; prevblkno = ovflopaque->hasho_prevblkno; bucket = ovflopaque->hasho_bucket; + + /* Zero the page for debugging's sake; then write and release it */ MemSet(ovflpage, 0, BufferGetPageSize(ovflbuf)); _hash_wrtbuf(rel, ovflbuf); /* - * fix up the bucket chain. this is a doubly-linked list, so we must + * Fix up the bucket chain. this is a doubly-linked list, so we must * fix up the bucket chain members behind and ahead of the overflow - * page being deleted. - * - * XXX this should look like: - lock prev/next - modify/write prev/next - * (how to do write ordering with a doubly-linked list?) - unlock - * prev/next + * page being deleted. No concurrency issues since we hold exclusive + * lock on the entire bucket. */ if (BlockNumberIsValid(prevblkno)) { @@ -341,7 +405,7 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf) Page prevpage = BufferGetPage(prevbuf); HashPageOpaque prevopaque = (HashPageOpaque) PageGetSpecialPointer(prevpage); - _hash_checkpage(prevpage, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); + _hash_checkpage(rel, prevpage, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); Assert(prevopaque->hasho_bucket == bucket); prevopaque->hasho_nextblkno = nextblkno; _hash_wrtbuf(rel, prevbuf); @@ -352,44 +416,55 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf) Page nextpage = BufferGetPage(nextbuf); HashPageOpaque nextopaque = (HashPageOpaque) PageGetSpecialPointer(nextpage); - _hash_checkpage(nextpage, LH_OVERFLOW_PAGE); + _hash_checkpage(rel, nextpage, LH_OVERFLOW_PAGE); Assert(nextopaque->hasho_bucket == bucket); nextopaque->hasho_prevblkno = prevblkno; _hash_wrtbuf(rel, nextbuf); } - /* - * Fix up the overflow page bitmap that tracks this particular - * overflow page. The bitmap can be found in the MetaPageData array - * element hashm_mapp[bitmappage]. - */ - splitnum = (addr >> SPLITSHIFT); - ovflpgno = (splitnum ? metap->hashm_spares[splitnum - 1] : 0) + (addr & SPLITMASK) - 1; + /* Read the metapage so we can determine which bitmap page to use */ + metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ); + metap = (HashMetaPage) BufferGetPage(metabuf); + _hash_checkpage(rel, (Page) metap, LH_META_PAGE); - if (ovflpgno < metap->hashm_lastfreed) - metap->hashm_lastfreed = ovflpgno; + /* Identify which bit to set */ + ovflbitno = blkno_to_bitno(metap, ovflblkno); - bitmappage = (ovflpgno >> (metap->hashm_bshift + BYTE_TO_BIT)); - bitmapbit = ovflpgno & (BMPGSZ_BIT(metap) - 1); + bitmappage = ovflbitno >> BMPG_SHIFT(metap); + bitmapbit = ovflbitno & BMPG_MASK(metap); + if (bitmappage >= metap->hashm_nmaps) + elog(ERROR, "invalid overflow bit number %u", ovflbitno); blkno = metap->hashm_mapp[bitmappage]; + + /* Release metapage lock while we access the bitmap page */ + _hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK); + + /* Clear the bitmap bit to indicate that this overflow page is free */ mapbuf = _hash_getbuf(rel, blkno, HASH_WRITE); mappage = BufferGetPage(mapbuf); - _hash_checkpage(mappage, LH_BITMAP_PAGE); + _hash_checkpage(rel, mappage, LH_BITMAP_PAGE); freep = HashPageGetBitmap(mappage); + Assert(ISSET(freep, bitmapbit)); CLRBIT(freep, bitmapbit); _hash_wrtbuf(rel, mapbuf); - _hash_relbuf(rel, metabuf, HASH_WRITE); + /* Get write-lock on metapage to update firstfree */ + _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE); - /* - * now instantiate the page that replaced this one, if it exists, and - * return that buffer with a write lock. - */ - if (BlockNumberIsValid(nextblkno)) - return _hash_getbuf(rel, nextblkno, HASH_WRITE); + /* if this is now the first free page, update hashm_firstfree */ + if (ovflbitno < metap->hashm_firstfree) + { + metap->hashm_firstfree = ovflbitno; + _hash_wrtbuf(rel, metabuf); + } else - return InvalidBuffer; + { + /* no need to change metapage */ + _hash_relbuf(rel, metabuf); + } + + return nextblkno; } @@ -397,65 +472,58 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf) * _hash_initbitmap() * * Initialize a new bitmap page. The metapage has a write-lock upon - * entering the function. + * entering the function, and must be written by caller after return. + * + * 'blkno' is the block number of the new bitmap page. * - * 'pnum' is the OverflowPageAddress of the new bitmap page. - * 'nbits' is how many bits to clear (i.e., make available) in the new - * bitmap page. the remainder of the bits (as well as the first bit, - * representing the bitmap page itself) will be set. - * 'ndx' is the 0-based offset of the new bitmap page within the - * metapage's array of bitmap page OverflowPageAddresses. + * All bits in the new bitmap page are set to "1", indicating "in use". */ - -#define INT_MASK ((1 << INT_TO_BIT) -1) - -int32 -_hash_initbitmap(Relation rel, - HashMetaPage metap, - int32 pnum, - int32 nbits, - int32 ndx) +void +_hash_initbitmap(Relation rel, HashMetaPage metap, BlockNumber blkno) { Buffer buf; - BlockNumber blkno; Page pg; HashPageOpaque op; uint32 *freep; - int clearbytes, - clearints; - blkno = OADDR_TO_BLKNO(pnum); + /* + * It is okay to write-lock the new bitmap page while holding metapage + * write lock, because no one else could be contending for the new page. + * + * There is some loss of concurrency in possibly doing I/O for the new + * page while holding the metapage lock, but this path is taken so + * seldom that it's not worth worrying about. + */ buf = _hash_getbuf(rel, blkno, HASH_WRITE); pg = BufferGetPage(buf); + + /* initialize the page */ _hash_pageinit(pg, BufferGetPageSize(buf)); op = (HashPageOpaque) PageGetSpecialPointer(pg); - op->hasho_oaddr = InvalidOvflAddress; op->hasho_prevblkno = InvalidBlockNumber; op->hasho_nextblkno = InvalidBlockNumber; - op->hasho_flag = LH_BITMAP_PAGE; op->hasho_bucket = -1; + op->hasho_flag = LH_BITMAP_PAGE; + op->hasho_filler = HASHO_FILL; + /* set all of the bits to 1 */ freep = HashPageGetBitmap(pg); + MemSet((char *) freep, 0xFF, BMPGSZ_BYTE(metap)); - /* set all of the bits above 'nbits' to 1 */ - clearints = ((nbits - 1) >> INT_TO_BIT) + 1; - clearbytes = clearints << INT_TO_BYTE; - MemSet((char *) freep, 0, clearbytes); - MemSet(((char *) freep) + clearbytes, 0xFF, - BMPGSZ_BYTE(metap) - clearbytes); - freep[clearints - 1] = ALL_SET << (nbits & INT_MASK); - - /* bit 0 represents the new bitmap page */ - SETBIT(freep, 0); + /* write out the new bitmap page (releasing write lock and pin) */ + _hash_wrtbuf(rel, buf); + /* add the new bitmap page to the metapage's list of bitmaps */ /* metapage already has a write lock */ - metap->hashm_nmaps++; - metap->hashm_mapp[ndx] = blkno; + if (metap->hashm_nmaps >= HASH_MAX_BITMAPS) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("out of overflow pages in hash index \"%s\"", + RelationGetRelationName(rel)))); - /* write out the new bitmap page (releasing its locks) */ - _hash_wrtbuf(rel, buf); + metap->hashm_mapp[metap->hashm_nmaps] = blkno; - return 0; + metap->hashm_nmaps++; } @@ -470,11 +538,20 @@ _hash_initbitmap(Relation rel, * first page in the bucket chain. The read page works backward and * the write page works forward; the procedure terminates when the * read page and write page are the same page. + * + * At completion of this procedure, it is guaranteed that all pages in + * the bucket are nonempty, unless the bucket is totally empty (in + * which case all overflow pages will be freed). The original implementation + * required that to be true on entry as well, but it's a lot easier for + * callers to leave empty overflow pages and let this guy clean it up. + * + * Caller must hold exclusive lock on the target bucket. This allows + * us to safely lock multiple pages in the bucket. */ void _hash_squeezebucket(Relation rel, - HashMetaPage metap, - Bucket bucket) + Bucket bucket, + BlockNumber bucket_blkno) { Buffer wbuf; Buffer rbuf = 0; @@ -492,10 +569,10 @@ _hash_squeezebucket(Relation rel, /* * start squeezing into the base bucket page. */ - wblkno = BUCKET_TO_BLKNO(bucket); + wblkno = bucket_blkno; wbuf = _hash_getbuf(rel, wblkno, HASH_WRITE); wpage = BufferGetPage(wbuf); - _hash_checkpage(wpage, LH_BUCKET_PAGE); + _hash_checkpage(rel, wpage, LH_BUCKET_PAGE); wopaque = (HashPageOpaque) PageGetSpecialPointer(wpage); /* @@ -503,29 +580,23 @@ _hash_squeezebucket(Relation rel, */ if (!BlockNumberIsValid(wopaque->hasho_nextblkno)) { - _hash_relbuf(rel, wbuf, HASH_WRITE); + _hash_relbuf(rel, wbuf); return; } /* * find the last page in the bucket chain by starting at the base * bucket page and working forward. - * - * XXX if chains tend to be long, we should probably move forward using - * HASH_READ and then _hash_chgbufaccess to HASH_WRITE when we reach - * the end. if they are short we probably don't care very much. if - * the hash function is working at all, they had better be short.. */ ropaque = wopaque; do { rblkno = ropaque->hasho_nextblkno; if (ropaque != wopaque) - _hash_relbuf(rel, rbuf, HASH_WRITE); + _hash_relbuf(rel, rbuf); rbuf = _hash_getbuf(rel, rblkno, HASH_WRITE); rpage = BufferGetPage(rbuf); - _hash_checkpage(rpage, LH_OVERFLOW_PAGE); - Assert(!PageIsEmpty(rpage)); + _hash_checkpage(rel, rpage, LH_OVERFLOW_PAGE); ropaque = (HashPageOpaque) PageGetSpecialPointer(rpage); Assert(ropaque->hasho_bucket == bucket); } while (BlockNumberIsValid(ropaque->hasho_nextblkno)); @@ -536,87 +607,97 @@ _hash_squeezebucket(Relation rel, roffnum = FirstOffsetNumber; for (;;) { - hitem = (HashItem) PageGetItem(rpage, PageGetItemId(rpage, roffnum)); - itemsz = IndexTupleDSize(hitem->hash_itup) - + (sizeof(HashItemData) - sizeof(IndexTupleData)); - itemsz = MAXALIGN(itemsz); - - /* - * walk up the bucket chain, looking for a page big enough for - * this item. - */ - while (PageGetFreeSpace(wpage) < itemsz) + /* this test is needed in case page is empty on entry */ + if (roffnum <= PageGetMaxOffsetNumber(rpage)) { - wblkno = wopaque->hasho_nextblkno; - - _hash_wrtbuf(rel, wbuf); + hitem = (HashItem) PageGetItem(rpage, + PageGetItemId(rpage, roffnum)); + itemsz = IndexTupleDSize(hitem->hash_itup) + + (sizeof(HashItemData) - sizeof(IndexTupleData)); + itemsz = MAXALIGN(itemsz); - if (!BlockNumberIsValid(wblkno) || (rblkno == wblkno)) + /* + * Walk up the bucket chain, looking for a page big enough for + * this item. Exit if we reach the read page. + */ + while (PageGetFreeSpace(wpage) < itemsz) { - _hash_wrtbuf(rel, rbuf); - /* wbuf is already released */ - return; - } + Assert(!PageIsEmpty(wpage)); - wbuf = _hash_getbuf(rel, wblkno, HASH_WRITE); - wpage = BufferGetPage(wbuf); - _hash_checkpage(wpage, LH_OVERFLOW_PAGE); - Assert(!PageIsEmpty(wpage)); - wopaque = (HashPageOpaque) PageGetSpecialPointer(wpage); - Assert(wopaque->hasho_bucket == bucket); - } + wblkno = wopaque->hasho_nextblkno; + Assert(BlockNumberIsValid(wblkno)); - /* - * if we're here, we have found room so insert on the "write" - * page. - */ - woffnum = OffsetNumberNext(PageGetMaxOffsetNumber(wpage)); - if (PageAddItem(wpage, (Item) hitem, itemsz, woffnum, LP_USED) - == InvalidOffsetNumber) - elog(ERROR, "failed to add index item to \"%s\"", - RelationGetRelationName(rel)); + _hash_wrtbuf(rel, wbuf); - /* - * delete the tuple from the "read" page. PageIndexTupleDelete - * repacks the ItemId array, so 'roffnum' will be "advanced" to - * the "next" ItemId. - */ - PageIndexTupleDelete(rpage, roffnum); - _hash_wrtnorelbuf(rbuf); + if (rblkno == wblkno) + { + /* wbuf is already released */ + _hash_wrtbuf(rel, rbuf); + return; + } + + wbuf = _hash_getbuf(rel, wblkno, HASH_WRITE); + wpage = BufferGetPage(wbuf); + _hash_checkpage(rel, wpage, LH_OVERFLOW_PAGE); + wopaque = (HashPageOpaque) PageGetSpecialPointer(wpage); + Assert(wopaque->hasho_bucket == bucket); + } + + /* + * we have found room so insert on the "write" page. + */ + woffnum = OffsetNumberNext(PageGetMaxOffsetNumber(wpage)); + if (PageAddItem(wpage, (Item) hitem, itemsz, woffnum, LP_USED) + == InvalidOffsetNumber) + elog(ERROR, "failed to add index item to \"%s\"", + RelationGetRelationName(rel)); + + /* + * delete the tuple from the "read" page. PageIndexTupleDelete + * repacks the ItemId array, so 'roffnum' will be "advanced" to + * the "next" ItemId. + */ + PageIndexTupleDelete(rpage, roffnum); + } /* - * if the "read" page is now empty because of the deletion, free - * it. + * if the "read" page is now empty because of the deletion (or + * because it was empty when we got to it), free it. + * + * Tricky point here: if our read and write pages are adjacent in the + * bucket chain, our write lock on wbuf will conflict with + * _hash_freeovflpage's attempt to update the sibling links of the + * removed page. However, in that case we are done anyway, so we can + * simply drop the write lock before calling _hash_freeovflpage. */ - if (PageIsEmpty(rpage) && (ropaque->hasho_flag & LH_OVERFLOW_PAGE)) + if (PageIsEmpty(rpage)) { rblkno = ropaque->hasho_prevblkno; Assert(BlockNumberIsValid(rblkno)); - /* - * free this overflow page. the extra _hash_relbuf is because - * _hash_freeovflpage gratuitously returns the next page (we - * want the previous page and will get it ourselves later). - */ - rbuf = _hash_freeovflpage(rel, rbuf); - if (BufferIsValid(rbuf)) - _hash_relbuf(rel, rbuf, HASH_WRITE); - + /* are we freeing the page adjacent to wbuf? */ if (rblkno == wblkno) { - /* rbuf is already released */ + /* yes, so release wbuf lock first */ _hash_wrtbuf(rel, wbuf); + /* free this overflow page (releases rbuf) */ + _hash_freeovflpage(rel, rbuf); + /* done */ return; } + /* free this overflow page, then get the previous one */ + _hash_freeovflpage(rel, rbuf); + rbuf = _hash_getbuf(rel, rblkno, HASH_WRITE); rpage = BufferGetPage(rbuf); - _hash_checkpage(rpage, LH_OVERFLOW_PAGE); - Assert(!PageIsEmpty(rpage)); + _hash_checkpage(rel, rpage, LH_OVERFLOW_PAGE); ropaque = (HashPageOpaque) PageGetSpecialPointer(rpage); Assert(ropaque->hasho_bucket == bucket); roffnum = FirstOffsetNumber; } } + + /* NOTREACHED */ } diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c index b6ea8cf31a2..c5b94929808 100644 --- a/src/backend/access/hash/hashpage.c +++ b/src/backend/access/hash/hashpage.c @@ -8,179 +8,100 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.38 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.38.2.1 2003/09/07 04:36:47 momjian Exp $ * * NOTES * Postgres hash pages look like ordinary relation pages. The opaque * data at high addresses includes information about the page including - * whether a page is an overflow page or a true bucket, the block - * numbers of the preceding and following pages, and the overflow - * address of the page if it is an overflow page. + * whether a page is an overflow page or a true bucket, the bucket + * number, and the block numbers of the preceding and following pages + * in the same bucket. * * The first page in a hash relation, page zero, is special -- it stores * information describing the hash table; it is referred to as the * "meta page." Pages one and higher store the actual data. * + * There are also bitmap pages, which are not manipulated here; + * see hashovfl.c. + * *------------------------------------------------------------------------- */ - #include "postgres.h" #include "access/genam.h" #include "access/hash.h" -#include "miscadmin.h" #include "storage/lmgr.h" +#include "utils/lsyscache.h" + +static void _hash_splitbucket(Relation rel, Buffer metabuf, + Bucket obucket, Bucket nbucket, + BlockNumber start_oblkno, + BlockNumber start_nblkno, + uint32 maxbucket, + uint32 highmask, uint32 lowmask); -static void _hash_setpagelock(Relation rel, BlockNumber blkno, int access); -static void _hash_unsetpagelock(Relation rel, BlockNumber blkno, int access); -static void _hash_splitpage(Relation rel, Buffer metabuf, Bucket obucket, Bucket nbucket); /* - * We use high-concurrency locking on hash indices. There are two cases in - * which we don't do locking. One is when we're building the index. - * Since the creating transaction has not committed, no one can see - * the index, and there's no reason to share locks. The second case - * is when we're just starting up the database system. We use some - * special-purpose initialization code in the relation cache manager - * (see utils/cache/relcache.c) to allow us to do indexed scans on - * the system catalogs before we'd normally be able to. This happens - * before the lock table is fully initialized, so we can't use it. - * Strictly speaking, this violates 2pl, but we don't do 2pl on the - * system catalogs anyway. - * - * Note that our page locks are actual lockmanager locks, not buffer - * locks (as are used by btree, for example). This is a good idea because - * the algorithms are not deadlock-free, and we'd better be able to detect - * and recover from deadlocks. - * - * Another important difference from btree is that a hash indexscan - * retains both a lock and a buffer pin on the current index page - * between hashgettuple() calls (btree keeps only a buffer pin). - * Because of this, it's safe to do item deletions with only a regular - * write lock on a hash page --- there cannot be an indexscan stopped on - * the page being deleted, other than an indexscan of our own backend, - * which will be taken care of by _hash_adjscans. + * We use high-concurrency locking on hash indexes (see README for an overview + * of the locking rules). There are two cases in which we don't do locking. + * One is when the index is newly created in the current transaction. Since + * the creating transaction has not committed, no one else can see the index, + * and there's no reason to take locks. The second case is for temp + * relations, which no one else can see either. (We still take buffer-level + * locks, but not lmgr locks.) */ - - -#define USELOCKING (!BuildingHash && !IsInitProcessingMode()) +#define USELOCKING(rel) (!((rel)->rd_isnew || (rel)->rd_istemp)) /* - * _hash_metapinit() -- Initialize the metadata page of a hash index, - * the two buckets that we begin with and the initial - * bitmap page. + * _hash_getlock() -- Acquire an lmgr lock. + * + * 'whichlock' should be zero to acquire the split-control lock, or the + * block number of a bucket's primary bucket page to acquire the per-bucket + * lock. (See README for details of the use of these locks.) + * + * 'access' must be HASH_SHARE or HASH_EXCLUSIVE. */ void -_hash_metapinit(Relation rel) +_hash_getlock(Relation rel, BlockNumber whichlock, int access) { - HashMetaPage metap; - HashPageOpaque pageopaque; - Buffer metabuf; - Buffer buf; - Page pg; - int nbuckets; - uint32 nelem; /* number elements */ - uint32 lg2nelem; /* _hash_log2(nelem) */ - uint16 i; - - /* can't be sharing this with anyone, now... */ - if (USELOCKING) - LockRelation(rel, AccessExclusiveLock); - - if (RelationGetNumberOfBlocks(rel) != 0) - elog(ERROR, "cannot initialize non-empty hash index \"%s\"", - RelationGetRelationName(rel)); - - metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE); - pg = BufferGetPage(metabuf); - metap = (HashMetaPage) pg; - _hash_pageinit(pg, BufferGetPageSize(metabuf)); - - metap->hashm_magic = HASH_MAGIC; - metap->hashm_version = HASH_VERSION; - metap->hashm_nkeys = 0; - metap->hashm_nmaps = 0; - metap->hashm_ffactor = DEFAULT_FFACTOR; - metap->hashm_bsize = BufferGetPageSize(metabuf); - metap->hashm_bshift = _hash_log2(metap->hashm_bsize); - for (i = metap->hashm_bshift; i > 0; --i) - { - if ((1 << i) < (metap->hashm_bsize - - (MAXALIGN(sizeof(PageHeaderData)) + - MAXALIGN(sizeof(HashPageOpaqueData))))) - break; - } - Assert(i); - metap->hashm_bmsize = 1 << i; - metap->hashm_procid = index_getprocid(rel, 1, HASHPROC); - - /* - * Make nelem = 2 rather than 0 so that we end up allocating space for - * the next greater power of two number of buckets. - */ - nelem = 2; - lg2nelem = 1; /* _hash_log2(MAX(nelem, 2)) */ - nbuckets = 2; /* 1 << lg2nelem */ - - MemSet((char *) metap->hashm_spares, 0, sizeof(metap->hashm_spares)); - MemSet((char *) metap->hashm_mapp, 0, sizeof(metap->hashm_mapp)); - - metap->hashm_spares[lg2nelem] = 2; /* lg2nelem + 1 */ - metap->hashm_spares[lg2nelem + 1] = 2; /* lg2nelem + 1 */ - metap->hashm_ovflpoint = 1; /* lg2nelem */ - metap->hashm_lastfreed = 2; - - metap->hashm_maxbucket = metap->hashm_lowmask = 1; /* nbuckets - 1 */ - metap->hashm_highmask = 3; /* (nbuckets << 1) - 1 */ - - pageopaque = (HashPageOpaque) PageGetSpecialPointer(pg); - pageopaque->hasho_oaddr = InvalidOvflAddress; - pageopaque->hasho_prevblkno = InvalidBlockNumber; - pageopaque->hasho_nextblkno = InvalidBlockNumber; - pageopaque->hasho_flag = LH_META_PAGE; - pageopaque->hasho_bucket = -1; - - /* - * First bitmap page is at: splitpoint lg2nelem page offset 1 which - * turns out to be page 3. Couldn't initialize page 3 until we - * created the first two buckets above. - */ - if (_hash_initbitmap(rel, metap, OADDR_OF(lg2nelem, 1), lg2nelem + 1, 0)) - elog(ERROR, "_hash_initbitmap failed"); - - /* all done */ - _hash_wrtnorelbuf(metabuf); - - /* - * initialize the first two buckets - */ - for (i = 0; i <= 1; i++) - { - buf = _hash_getbuf(rel, BUCKET_TO_BLKNO(i), HASH_WRITE); - pg = BufferGetPage(buf); - _hash_pageinit(pg, BufferGetPageSize(buf)); - pageopaque = (HashPageOpaque) PageGetSpecialPointer(pg); - pageopaque->hasho_oaddr = InvalidOvflAddress; - pageopaque->hasho_prevblkno = InvalidBlockNumber; - pageopaque->hasho_nextblkno = InvalidBlockNumber; - pageopaque->hasho_flag = LH_BUCKET_PAGE; - pageopaque->hasho_bucket = i; - _hash_wrtbuf(rel, buf); - } + if (USELOCKING(rel)) + LockPage(rel, whichlock, access); +} - _hash_relbuf(rel, metabuf, HASH_WRITE); +/* + * _hash_try_getlock() -- Acquire an lmgr lock, but only if it's free. + * + * Same as above except we return FALSE without blocking if lock isn't free. + */ +bool +_hash_try_getlock(Relation rel, BlockNumber whichlock, int access) +{ + if (USELOCKING(rel)) + return ConditionalLockPage(rel, whichlock, access); + else + return true; +} - if (USELOCKING) - UnlockRelation(rel, AccessExclusiveLock); +/* + * _hash_droplock() -- Release an lmgr lock. + */ +void +_hash_droplock(Relation rel, BlockNumber whichlock, int access) +{ + if (USELOCKING(rel)) + UnlockPage(rel, whichlock, access); } /* * _hash_getbuf() -- Get a buffer by block number for read or write. * + * 'access' must be HASH_READ, HASH_WRITE, or HASH_NOLOCK. + * * When this routine returns, the appropriate lock is set on the - * requested buffer its reference count is correct. + * requested buffer and its reference count has been incremented + * (ie, the buffer is "locked and pinned"). * * XXX P_NEW is not used because, unlike the tree structures, we * need the bucket blocks to be at certain block numbers. we must @@ -194,61 +115,59 @@ _hash_getbuf(Relation rel, BlockNumber blkno, int access) if (blkno == P_NEW) elog(ERROR, "hash AM does not use P_NEW"); - switch (access) - { - case HASH_WRITE: - case HASH_READ: - _hash_setpagelock(rel, blkno, access); - break; - default: - elog(ERROR, "unrecognized hash access code: %d", access); - break; - } + buf = ReadBuffer(rel, blkno); + if (access != HASH_NOLOCK) + LockBuffer(buf, access); + /* ref count and lock type are correct */ return buf; } /* * _hash_relbuf() -- release a locked buffer. + * + * Lock and pin (refcount) are both dropped. Note that either read or + * write lock can be dropped this way, but if we modified the buffer, + * this is NOT the right way to release a write lock. */ void -_hash_relbuf(Relation rel, Buffer buf, int access) +_hash_relbuf(Relation rel, Buffer buf) { - BlockNumber blkno; - - blkno = BufferGetBlockNumber(buf); - - switch (access) - { - case HASH_WRITE: - case HASH_READ: - _hash_unsetpagelock(rel, blkno, access); - break; - default: - elog(ERROR, "unrecognized hash access code: %d", access); - break; - } + LockBuffer(buf, BUFFER_LOCK_UNLOCK); + ReleaseBuffer(buf); +} +/* + * _hash_dropbuf() -- release an unlocked buffer. + * + * This is used to unpin a buffer on which we hold no lock. It is assumed + * that the buffer is not dirty. + */ +void +_hash_dropbuf(Relation rel, Buffer buf) +{ ReleaseBuffer(buf); } /* * _hash_wrtbuf() -- write a hash page to disk. * - * This routine releases the lock held on the buffer and our reference - * to it. It is an error to call _hash_wrtbuf() without a write lock - * or a reference to the buffer. + * This routine releases the lock held on the buffer and our refcount + * for it. It is an error to call _hash_wrtbuf() without a write lock + * and a pin on the buffer. + * + * NOTE: actually, the buffer manager just marks the shared buffer page + * dirty here; the real I/O happens later. This is okay since we are not + * relying on write ordering anyway. The WAL mechanism is responsible for + * guaranteeing correctness after a crash. */ void _hash_wrtbuf(Relation rel, Buffer buf) { - BlockNumber blkno; - - blkno = BufferGetBlockNumber(buf); + LockBuffer(buf, BUFFER_LOCK_UNLOCK); WriteBuffer(buf); - _hash_unsetpagelock(rel, blkno, HASH_WRITE); } /* @@ -256,147 +175,181 @@ _hash_wrtbuf(Relation rel, Buffer buf) * our reference or lock. * * It is an error to call _hash_wrtnorelbuf() without a write lock - * or a reference to the buffer. + * and a pin on the buffer. + * + * See above NOTE. */ void -_hash_wrtnorelbuf(Buffer buf) +_hash_wrtnorelbuf(Relation rel, Buffer buf) { - BlockNumber blkno; - - blkno = BufferGetBlockNumber(buf); WriteNoReleaseBuffer(buf); } -Page +/* + * _hash_chgbufaccess() -- Change the lock type on a buffer, without + * dropping our pin on it. + * + * from_access and to_access may be HASH_READ, HASH_WRITE, or HASH_NOLOCK, + * the last indicating that no buffer-level lock is held or wanted. + * + * When from_access == HASH_WRITE, we assume the buffer is dirty and tell + * bufmgr it must be written out. If the caller wants to release a write + * lock on a page that's not been modified, it's okay to pass from_access + * as HASH_READ (a bit ugly, but handy in some places). + */ +void _hash_chgbufaccess(Relation rel, - Buffer *bufp, + Buffer buf, int from_access, int to_access) { - BlockNumber blkno; + if (from_access != HASH_NOLOCK) + LockBuffer(buf, BUFFER_LOCK_UNLOCK); + if (from_access == HASH_WRITE) + WriteNoReleaseBuffer(buf); - blkno = BufferGetBlockNumber(*bufp); - - switch (from_access) - { - case HASH_WRITE: - _hash_wrtbuf(rel, *bufp); - break; - case HASH_READ: - _hash_relbuf(rel, *bufp, from_access); - break; - default: - elog(ERROR, "unrecognized hash access code: %d", from_access); - break; - } - *bufp = _hash_getbuf(rel, blkno, to_access); - return BufferGetPage(*bufp); + if (to_access != HASH_NOLOCK) + LockBuffer(buf, to_access); } + /* - * _hash_pageinit() -- Initialize a new page. + * _hash_metapinit() -- Initialize the metadata page of a hash index, + * the two buckets that we begin with and the initial + * bitmap page. + * + * We are fairly cavalier about locking here, since we know that no one else + * could be accessing this index. In particular the rule about not holding + * multiple buffer locks is ignored. */ void -_hash_pageinit(Page page, Size size) +_hash_metapinit(Relation rel) { - Assert(PageIsNew(page)); - PageInit(page, size, sizeof(HashPageOpaqueData)); -} + HashMetaPage metap; + HashPageOpaque pageopaque; + Buffer metabuf; + Buffer buf; + Page pg; + int32 data_width; + int32 item_width; + int32 ffactor; + uint16 i; -static void -_hash_setpagelock(Relation rel, - BlockNumber blkno, - int access) -{ + /* safety check */ + if (RelationGetNumberOfBlocks(rel) != 0) + elog(ERROR, "cannot initialize non-empty hash index \"%s\"", + RelationGetRelationName(rel)); - if (USELOCKING) - { - switch (access) - { - case HASH_WRITE: - LockPage(rel, blkno, ExclusiveLock); - break; - case HASH_READ: - LockPage(rel, blkno, ShareLock); - break; - default: - elog(ERROR, "unrecognized hash access code: %d", access); - break; - } - } -} + /* + * Determine the target fill factor (tuples per bucket) for this index. + * The idea is to make the fill factor correspond to pages about 3/4ths + * full. We can compute it exactly if the index datatype is fixed-width, + * but for var-width there's some guessing involved. + */ + data_width = get_typavgwidth(RelationGetDescr(rel)->attrs[0]->atttypid, + RelationGetDescr(rel)->attrs[0]->atttypmod); + item_width = MAXALIGN(sizeof(HashItemData)) + MAXALIGN(data_width) + + sizeof(ItemIdData); /* include the line pointer */ + ffactor = (BLCKSZ * 3 / 4) / item_width; + /* keep to a sane range */ + if (ffactor < 10) + ffactor = 10; -static void -_hash_unsetpagelock(Relation rel, - BlockNumber blkno, - int access) -{ + metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE); + pg = BufferGetPage(metabuf); + _hash_pageinit(pg, BufferGetPageSize(metabuf)); + + pageopaque = (HashPageOpaque) PageGetSpecialPointer(pg); + pageopaque->hasho_prevblkno = InvalidBlockNumber; + pageopaque->hasho_nextblkno = InvalidBlockNumber; + pageopaque->hasho_bucket = -1; + pageopaque->hasho_flag = LH_META_PAGE; + pageopaque->hasho_filler = HASHO_FILL; + + metap = (HashMetaPage) pg; - if (USELOCKING) + metap->hashm_magic = HASH_MAGIC; + metap->hashm_version = HASH_VERSION; + metap->hashm_ntuples = 0; + metap->hashm_nmaps = 0; + metap->hashm_ffactor = ffactor; + metap->hashm_bsize = BufferGetPageSize(metabuf); + /* find largest bitmap array size that will fit in page size */ + for (i = _hash_log2(metap->hashm_bsize); i > 0; --i) { - switch (access) - { - case HASH_WRITE: - UnlockPage(rel, blkno, ExclusiveLock); - break; - case HASH_READ: - UnlockPage(rel, blkno, ShareLock); - break; - default: - elog(ERROR, "unrecognized hash access code: %d", access); - break; - } + if ((1 << i) <= (metap->hashm_bsize - + (MAXALIGN(sizeof(PageHeaderData)) + + MAXALIGN(sizeof(HashPageOpaqueData))))) + break; } -} + Assert(i > 0); + metap->hashm_bmsize = 1 << i; + metap->hashm_bmshift = i + BYTE_TO_BIT; + Assert((1 << BMPG_SHIFT(metap)) == (BMPG_MASK(metap) + 1)); -/* - * Delete a hash index item. - * - * It is safe to delete an item after acquiring a regular WRITE lock on - * the page, because no other backend can hold a READ lock on the page, - * and that means no other backend currently has an indexscan stopped on - * any item of the item being deleted. Our own backend might have such - * an indexscan (in fact *will*, since that's how VACUUM found the item - * in the first place), but _hash_adjscans will fix the scan position. - */ -void -_hash_pagedel(Relation rel, ItemPointer tid) -{ - Buffer buf; - Buffer metabuf; - Page page; - BlockNumber blkno; - OffsetNumber offno; - HashMetaPage metap; - HashPageOpaque opaque; + metap->hashm_procid = index_getprocid(rel, 1, HASHPROC); - blkno = ItemPointerGetBlockNumber(tid); - offno = ItemPointerGetOffsetNumber(tid); + /* + * We initialize the index with two buckets, 0 and 1, occupying physical + * blocks 1 and 2. The first freespace bitmap page is in block 3. + */ + metap->hashm_maxbucket = metap->hashm_lowmask = 1; /* nbuckets - 1 */ + metap->hashm_highmask = 3; /* (nbuckets << 1) - 1 */ - buf = _hash_getbuf(rel, blkno, HASH_WRITE); - page = BufferGetPage(buf); - _hash_checkpage(page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); - opaque = (HashPageOpaque) PageGetSpecialPointer(page); + MemSet((char *) metap->hashm_spares, 0, sizeof(metap->hashm_spares)); + MemSet((char *) metap->hashm_mapp, 0, sizeof(metap->hashm_mapp)); - PageIndexTupleDelete(page, offno); - _hash_wrtnorelbuf(buf); + metap->hashm_spares[1] = 1; /* the first bitmap page is only spare */ + metap->hashm_ovflpoint = 1; + metap->hashm_firstfree = 0; - if (PageIsEmpty(page) && (opaque->hasho_flag & LH_OVERFLOW_PAGE)) + /* + * Initialize the first two buckets + */ + for (i = 0; i <= 1; i++) { - buf = _hash_freeovflpage(rel, buf); - if (BufferIsValid(buf)) - _hash_relbuf(rel, buf, HASH_WRITE); + buf = _hash_getbuf(rel, BUCKET_TO_BLKNO(metap, i), HASH_WRITE); + pg = BufferGetPage(buf); + _hash_pageinit(pg, BufferGetPageSize(buf)); + pageopaque = (HashPageOpaque) PageGetSpecialPointer(pg); + pageopaque->hasho_prevblkno = InvalidBlockNumber; + pageopaque->hasho_nextblkno = InvalidBlockNumber; + pageopaque->hasho_bucket = i; + pageopaque->hasho_flag = LH_BUCKET_PAGE; + pageopaque->hasho_filler = HASHO_FILL; + _hash_wrtbuf(rel, buf); } - else - _hash_relbuf(rel, buf, HASH_WRITE); - metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE); - metap = (HashMetaPage) BufferGetPage(metabuf); - _hash_checkpage((Page) metap, LH_META_PAGE); - metap->hashm_nkeys--; + /* + * Initialize first bitmap page. Can't do this until we + * create the first two buckets, else smgr will complain. + */ + _hash_initbitmap(rel, metap, 3); + + /* all done */ _hash_wrtbuf(rel, metabuf); } +/* + * _hash_pageinit() -- Initialize a new hash index page. + */ +void +_hash_pageinit(Page page, Size size) +{ + Assert(PageIsNew(page)); + PageInit(page, size, sizeof(HashPageOpaqueData)); +} + +/* + * Attempt to expand the hash table by creating one new bucket. + * + * This will silently do nothing if it cannot get the needed locks. + * + * The caller should hold no locks on the hash index. + * + * The caller must hold a pin, but no lock, on the metapage buffer. + * The buffer is returned in the same state. + */ void _hash_expandtable(Relation rel, Buffer metabuf) { @@ -404,62 +357,172 @@ _hash_expandtable(Relation rel, Buffer metabuf) Bucket old_bucket; Bucket new_bucket; uint32 spare_ndx; + BlockNumber start_oblkno; + BlockNumber start_nblkno; + uint32 maxbucket; + uint32 highmask; + uint32 lowmask; + + /* + * Obtain the page-zero lock to assert the right to begin a split + * (see README). + * + * Note: deadlock should be impossible here. Our own backend could only + * be holding bucket sharelocks due to stopped indexscans; those will not + * block other holders of the page-zero lock, who are only interested in + * acquiring bucket sharelocks themselves. Exclusive bucket locks are + * only taken here and in hashbulkdelete, and neither of these operations + * needs any additional locks to complete. (If, due to some flaw in this + * reasoning, we manage to deadlock anyway, it's okay to error out; the + * index will be left in a consistent state.) + */ + _hash_getlock(rel, 0, HASH_EXCLUSIVE); + + /* Write-lock the meta page */ + _hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE); metap = (HashMetaPage) BufferGetPage(metabuf); - _hash_checkpage((Page) metap, LH_META_PAGE); + _hash_checkpage(rel, (Page) metap, LH_META_PAGE); - metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_READ, HASH_WRITE); - new_bucket = ++metap->hashm_maxbucket; - metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_WRITE, HASH_READ); - old_bucket = (metap->hashm_maxbucket & metap->hashm_lowmask); + /* + * Check to see if split is still needed; someone else might have already + * done one while we waited for the lock. + * + * Make sure this stays in sync with_hash_doinsert() + */ + if (metap->hashm_ntuples <= + (double) metap->hashm_ffactor * (metap->hashm_maxbucket + 1)) + goto fail; /* - * If the split point is increasing (hashm_maxbucket's log base 2 * - * increases), we need to copy the current contents of the spare split - * bucket to the next bucket. + * Determine which bucket is to be split, and attempt to lock the old + * bucket. If we can't get the lock, give up. + * + * The lock protects us against other backends, but not against our own + * backend. Must check for active scans separately. + * + * Ideally we would lock the new bucket too before proceeding, but if + * we are about to cross a splitpoint then the BUCKET_TO_BLKNO mapping + * isn't correct yet. For simplicity we update the metapage first and + * then lock. This should be okay because no one else should be trying + * to lock the new bucket yet... */ - spare_ndx = _hash_log2(metap->hashm_maxbucket + 1); - if (spare_ndx > metap->hashm_ovflpoint) - { + new_bucket = metap->hashm_maxbucket + 1; + old_bucket = (new_bucket & metap->hashm_lowmask); - metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_READ, HASH_WRITE); - metap->hashm_spares[spare_ndx] = metap->hashm_spares[metap->hashm_ovflpoint]; - metap->hashm_ovflpoint = spare_ndx; - metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_WRITE, HASH_READ); - } + start_oblkno = BUCKET_TO_BLKNO(metap, old_bucket); + + if (_hash_has_active_scan(rel, old_bucket)) + goto fail; + + if (!_hash_try_getlock(rel, start_oblkno, HASH_EXCLUSIVE)) + goto fail; + + /* + * Okay to proceed with split. Update the metapage bucket mapping info. + */ + metap->hashm_maxbucket = new_bucket; if (new_bucket > metap->hashm_highmask) { - /* Starting a new doubling */ - metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_READ, HASH_WRITE); metap->hashm_lowmask = metap->hashm_highmask; metap->hashm_highmask = new_bucket | metap->hashm_lowmask; - metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_WRITE, HASH_READ); + } + /* + * If the split point is increasing (hashm_maxbucket's log base 2 + * increases), we need to adjust the hashm_spares[] array and + * hashm_ovflpoint so that future overflow pages will be created beyond + * this new batch of bucket pages. + * + * XXX should initialize new bucket pages to prevent out-of-order + * page creation? Don't wanna do it right here though. + */ + spare_ndx = _hash_log2(metap->hashm_maxbucket + 1); + if (spare_ndx > metap->hashm_ovflpoint) + { + Assert(spare_ndx == metap->hashm_ovflpoint + 1); + metap->hashm_spares[spare_ndx] = metap->hashm_spares[metap->hashm_ovflpoint]; + metap->hashm_ovflpoint = spare_ndx; } + + /* now we can compute the new bucket's primary block number */ + start_nblkno = BUCKET_TO_BLKNO(metap, new_bucket); + + Assert(!_hash_has_active_scan(rel, new_bucket)); + + if (!_hash_try_getlock(rel, start_nblkno, HASH_EXCLUSIVE)) + elog(PANIC, "could not get lock on supposedly new bucket"); + + /* + * Copy bucket mapping info now; this saves re-accessing the meta page + * inside _hash_splitbucket's inner loop. Note that once we drop the + * split lock, other splits could begin, so these values might be out of + * date before _hash_splitbucket finishes. That's okay, since all it + * needs is to tell which of these two buckets to map hashkeys into. + */ + maxbucket = metap->hashm_maxbucket; + highmask = metap->hashm_highmask; + lowmask = metap->hashm_lowmask; + + /* Write out the metapage and drop lock, but keep pin */ + _hash_chgbufaccess(rel, metabuf, HASH_WRITE, HASH_NOLOCK); + + /* Release split lock; okay for other splits to occur now */ + _hash_droplock(rel, 0, HASH_EXCLUSIVE); + /* Relocate records to the new bucket */ - _hash_splitpage(rel, metabuf, old_bucket, new_bucket); + _hash_splitbucket(rel, metabuf, old_bucket, new_bucket, + start_oblkno, start_nblkno, + maxbucket, highmask, lowmask); + + /* Release bucket locks, allowing others to access them */ + _hash_droplock(rel, start_oblkno, HASH_EXCLUSIVE); + _hash_droplock(rel, start_nblkno, HASH_EXCLUSIVE); + + return; + + /* Here if decide not to split or fail to acquire old bucket lock */ +fail: + + /* We didn't write the metapage, so just drop lock */ + _hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK); + + /* Release split lock */ + _hash_droplock(rel, 0, HASH_EXCLUSIVE); } /* - * _hash_splitpage -- split 'obucket' into 'obucket' and 'nbucket' + * _hash_splitbucket -- split 'obucket' into 'obucket' and 'nbucket' + * + * We are splitting a bucket that consists of a base bucket page and zero + * or more overflow (bucket chain) pages. We must relocate tuples that + * belong in the new bucket, and compress out any free space in the old + * bucket. * - * this routine is actually misnamed -- we are splitting a bucket that - * consists of a base bucket page and zero or more overflow (bucket - * chain) pages. + * The caller must hold exclusive locks on both buckets to ensure that + * no one else is trying to access them (see README). + * + * The caller must hold a pin, but no lock, on the metapage buffer. + * The buffer is returned in the same state. (The metapage is only + * touched if it becomes necessary to add or remove overflow pages.) */ static void -_hash_splitpage(Relation rel, - Buffer metabuf, - Bucket obucket, - Bucket nbucket) +_hash_splitbucket(Relation rel, + Buffer metabuf, + Bucket obucket, + Bucket nbucket, + BlockNumber start_oblkno, + BlockNumber start_nblkno, + uint32 maxbucket, + uint32 highmask, + uint32 lowmask) { Bucket bucket; Buffer obuf; Buffer nbuf; - Buffer ovflbuf; BlockNumber oblkno; BlockNumber nblkno; bool null; @@ -467,7 +530,6 @@ _hash_splitpage(Relation rel, HashItem hitem; HashPageOpaque oopaque; HashPageOpaque nopaque; - HashMetaPage metap; IndexTuple itup; Size itemsz; OffsetNumber ooffnum; @@ -475,65 +537,36 @@ _hash_splitpage(Relation rel, OffsetNumber omaxoffnum; Page opage; Page npage; - TupleDesc itupdesc; + TupleDesc itupdesc = RelationGetDescr(rel); - metap = (HashMetaPage) BufferGetPage(metabuf); - _hash_checkpage((Page) metap, LH_META_PAGE); - - /* get the buffers & pages */ - oblkno = BUCKET_TO_BLKNO(obucket); - nblkno = BUCKET_TO_BLKNO(nbucket); + /* + * It should be okay to simultaneously write-lock pages from each + * bucket, since no one else can be trying to acquire buffer lock + * on pages of either bucket. + */ + oblkno = start_oblkno; + nblkno = start_nblkno; obuf = _hash_getbuf(rel, oblkno, HASH_WRITE); nbuf = _hash_getbuf(rel, nblkno, HASH_WRITE); opage = BufferGetPage(obuf); npage = BufferGetPage(nbuf); - /* initialize the new bucket */ + _hash_checkpage(rel, opage, LH_BUCKET_PAGE); + oopaque = (HashPageOpaque) PageGetSpecialPointer(opage); + + /* initialize the new bucket's primary page */ _hash_pageinit(npage, BufferGetPageSize(nbuf)); nopaque = (HashPageOpaque) PageGetSpecialPointer(npage); nopaque->hasho_prevblkno = InvalidBlockNumber; nopaque->hasho_nextblkno = InvalidBlockNumber; - nopaque->hasho_flag = LH_BUCKET_PAGE; - nopaque->hasho_oaddr = InvalidOvflAddress; nopaque->hasho_bucket = nbucket; - _hash_wrtnorelbuf(nbuf); - - /* - * make sure the old bucket isn't empty. advance 'opage' and friends - * through the overflow bucket chain until we find a non-empty page. - * - * XXX we should only need this once, if we are careful to preserve the - * invariant that overflow pages are never empty. - */ - _hash_checkpage(opage, LH_BUCKET_PAGE); - oopaque = (HashPageOpaque) PageGetSpecialPointer(opage); - if (PageIsEmpty(opage)) - { - oblkno = oopaque->hasho_nextblkno; - _hash_relbuf(rel, obuf, HASH_WRITE); - if (!BlockNumberIsValid(oblkno)) - { - /* - * the old bucket is completely empty; of course, the new - * bucket will be as well, but since it's a base bucket page - * we don't care. - */ - _hash_relbuf(rel, nbuf, HASH_WRITE); - return; - } - obuf = _hash_getbuf(rel, oblkno, HASH_WRITE); - opage = BufferGetPage(obuf); - _hash_checkpage(opage, LH_OVERFLOW_PAGE); - if (PageIsEmpty(opage)) - elog(ERROR, "empty hash overflow page %u", oblkno); - oopaque = (HashPageOpaque) PageGetSpecialPointer(opage); - } + nopaque->hasho_flag = LH_BUCKET_PAGE; + nopaque->hasho_filler = HASHO_FILL; /* - * we are now guaranteed that 'opage' is not empty. partition the - * tuples in the old bucket between the old bucket and the new bucket, - * advancing along their respective overflow bucket chains and adding - * overflow pages as needed. + * Partition the tuples in the old bucket between the old bucket and the + * new bucket, advancing along the old bucket's overflow bucket chain + * and adding overflow pages to the new bucket as needed. */ ooffnum = FirstOffsetNumber; omaxoffnum = PageGetMaxOffsetNumber(opage); @@ -547,47 +580,39 @@ _hash_splitpage(Relation rel, /* check if we're at the end of the page */ if (ooffnum > omaxoffnum) { - /* at end of page, but check for overflow page */ + /* at end of page, but check for an(other) overflow page */ oblkno = oopaque->hasho_nextblkno; - if (BlockNumberIsValid(oblkno)) - { - /* - * we ran out of tuples on this particular page, but we - * have more overflow pages; re-init values. - */ - _hash_wrtbuf(rel, obuf); - obuf = _hash_getbuf(rel, oblkno, HASH_WRITE); - opage = BufferGetPage(obuf); - _hash_checkpage(opage, LH_OVERFLOW_PAGE); - oopaque = (HashPageOpaque) PageGetSpecialPointer(opage); - /* we're guaranteed that an ovfl page has at least 1 tuple */ - if (PageIsEmpty(opage)) - elog(ERROR, "empty hash overflow page %u", oblkno); - ooffnum = FirstOffsetNumber; - omaxoffnum = PageGetMaxOffsetNumber(opage); - } - else - { - /* - * we're at the end of the bucket chain, so now we're - * really done with everything. before quitting, call - * _hash_squeezebucket to ensure the tuples in the bucket - * (including the overflow pages) are packed as tightly as - * possible. - */ - _hash_wrtbuf(rel, obuf); - _hash_wrtbuf(rel, nbuf); - _hash_squeezebucket(rel, metap, obucket); - return; - } + if (!BlockNumberIsValid(oblkno)) + break; + /* + * we ran out of tuples on this particular page, but we + * have more overflow pages; advance to next page. + */ + _hash_wrtbuf(rel, obuf); + + obuf = _hash_getbuf(rel, oblkno, HASH_WRITE); + opage = BufferGetPage(obuf); + _hash_checkpage(rel, opage, LH_OVERFLOW_PAGE); + oopaque = (HashPageOpaque) PageGetSpecialPointer(opage); + ooffnum = FirstOffsetNumber; + omaxoffnum = PageGetMaxOffsetNumber(opage); + continue; } - /* hash on the tuple */ + /* + * Re-hash the tuple to determine which bucket it now belongs in. + * + * It is annoying to call the hash function while holding locks, + * but releasing and relocking the page for each tuple is unappealing + * too. + */ hitem = (HashItem) PageGetItem(opage, PageGetItemId(opage, ooffnum)); itup = &(hitem->hash_itup); - itupdesc = RelationGetDescr(rel); datum = index_getattr(itup, 1, itupdesc, &null); - bucket = _hash_call(rel, metap, datum); + Assert(!null); + + bucket = _hash_hashkey2bucket(_hash_datum2hashkey(rel, datum), + maxbucket, highmask, lowmask); if (bucket == nbucket) { @@ -603,11 +628,13 @@ _hash_splitpage(Relation rel, if (PageGetFreeSpace(npage) < itemsz) { - ovflbuf = _hash_addovflpage(rel, &metabuf, nbuf); - _hash_wrtbuf(rel, nbuf); - nbuf = ovflbuf; + /* write out nbuf and drop lock, but keep pin */ + _hash_chgbufaccess(rel, nbuf, HASH_WRITE, HASH_NOLOCK); + /* chain to a new overflow page */ + nbuf = _hash_addovflpage(rel, metabuf, nbuf); npage = BufferGetPage(nbuf); - _hash_checkpage(npage, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); + _hash_checkpage(rel, npage, LH_OVERFLOW_PAGE); + /* we don't need nopaque within the loop */ } noffnum = OffsetNumberNext(PageGetMaxOffsetNumber(npage)); @@ -615,7 +642,6 @@ _hash_splitpage(Relation rel, == InvalidOffsetNumber) elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(rel)); - _hash_wrtnorelbuf(nbuf); /* * now delete the tuple from the old bucket. after this @@ -627,40 +653,7 @@ _hash_splitpage(Relation rel, * instead of calling PageGetMaxOffsetNumber. */ PageIndexTupleDelete(opage, ooffnum); - _hash_wrtnorelbuf(obuf); omaxoffnum = OffsetNumberPrev(omaxoffnum); - - /* - * tidy up. if the old page was an overflow page and it is - * now empty, we must free it (we want to preserve the - * invariant that overflow pages cannot be empty). - */ - if (PageIsEmpty(opage) && - (oopaque->hasho_flag & LH_OVERFLOW_PAGE)) - { - obuf = _hash_freeovflpage(rel, obuf); - - /* check that we're not through the bucket chain */ - if (BufferIsInvalid(obuf)) - { - _hash_wrtbuf(rel, nbuf); - _hash_squeezebucket(rel, metap, obucket); - return; - } - - /* - * re-init. again, we're guaranteed that an ovfl page has - * at least one tuple. - */ - opage = BufferGetPage(obuf); - _hash_checkpage(opage, LH_OVERFLOW_PAGE); - oblkno = BufferGetBlockNumber(obuf); - oopaque = (HashPageOpaque) PageGetSpecialPointer(opage); - if (PageIsEmpty(opage)) - elog(ERROR, "empty hash overflow page %u", oblkno); - ooffnum = FirstOffsetNumber; - omaxoffnum = PageGetMaxOffsetNumber(opage); - } } else { @@ -668,12 +661,20 @@ _hash_splitpage(Relation rel, * the tuple stays on this page. we didn't move anything, so * we didn't delete anything and therefore we don't have to * change 'omaxoffnum'. - * - * XXX any hash value from [0, nbucket-1] will map to this - * bucket, which doesn't make sense to me. */ + Assert(bucket == obucket); ooffnum = OffsetNumberNext(ooffnum); } } - /* NOTREACHED */ + + /* + * We're at the end of the old bucket chain, so we're done partitioning + * the tuples. Before quitting, call _hash_squeezebucket to ensure the + * tuples remaining in the old bucket (including the overflow pages) are + * packed as tightly as possible. The new bucket is already tight. + */ + _hash_wrtbuf(rel, obuf); + _hash_wrtbuf(rel, nbuf); + + _hash_squeezebucket(rel, obucket, start_oblkno); } diff --git a/src/backend/access/hash/hashscan.c b/src/backend/access/hash/hashscan.c index a0b124cbee4..98c7f1134db 100644 --- a/src/backend/access/hash/hashscan.c +++ b/src/backend/access/hash/hashscan.c @@ -8,22 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hashscan.c,v 1.30 2003/08/04 02:39:57 momjian Exp $ - * - * NOTES - * Because we can be doing an index scan on a relation while we - * update it, we need to avoid missing data that moves around in - * the index. The routines and global variables in this file - * guarantee that all scans in the local address space stay - * correctly positioned. This is all we need to worry about, since - * write locking guarantees that no one else will be on the same - * page at the same time as we are. - * - * The scheme is to manage a list of active scans in the current - * backend. Whenever we add or remove records from an index, we - * check the list of active scans to see if any has been affected. - * A scan is affected only if it is on the same relation, and the - * same page, as the update. + * $Header: /cvsroot/pgsql/src/backend/access/hash/hashscan.c,v 1.30.2.1 2003/09/07 04:36:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -44,10 +29,6 @@ typedef HashScanListData *HashScanList; static HashScanList HashScans = (HashScanList) NULL; -static void _hash_scandel(IndexScanDesc scan, - BlockNumber blkno, OffsetNumber offno); - - /* * AtEOXact_hash() --- clean up hash subsystem at xact abort or commit. * @@ -67,9 +48,6 @@ AtEOXact_hash(void) * at end of transaction anyway. */ HashScans = NULL; - - /* If we were building a hash, we ain't anymore. */ - BuildingHash = false; } /* @@ -112,70 +90,26 @@ _hash_dropscan(IndexScanDesc scan) pfree(chk); } -void -_hash_adjscans(Relation rel, ItemPointer tid) +/* + * Is there an active scan in this bucket? + */ +bool +_hash_has_active_scan(Relation rel, Bucket bucket) { + Oid relid = RelationGetRelid(rel); HashScanList l; - Oid relid; - relid = RelationGetRelid(rel); - for (l = HashScans; l != (HashScanList) NULL; l = l->hashsl_next) + for (l = HashScans; l != NULL; l = l->hashsl_next) { if (relid == l->hashsl_scan->indexRelation->rd_id) - _hash_scandel(l->hashsl_scan, ItemPointerGetBlockNumber(tid), - ItemPointerGetOffsetNumber(tid)); - } -} + { + HashScanOpaque so = (HashScanOpaque) l->hashsl_scan->opaque; -static void -_hash_scandel(IndexScanDesc scan, BlockNumber blkno, OffsetNumber offno) -{ - ItemPointer current; - ItemPointer mark; - Buffer buf; - Buffer metabuf; - HashScanOpaque so; - - so = (HashScanOpaque) scan->opaque; - current = &(scan->currentItemData); - mark = &(scan->currentMarkData); - - if (ItemPointerIsValid(current) - && ItemPointerGetBlockNumber(current) == blkno - && ItemPointerGetOffsetNumber(current) >= offno) - { - metabuf = _hash_getbuf(scan->indexRelation, HASH_METAPAGE, HASH_READ); - buf = so->hashso_curbuf; - _hash_step(scan, &buf, BackwardScanDirection, metabuf); + if (so->hashso_bucket_valid && + so->hashso_bucket == bucket) + return true; + } } - if (ItemPointerIsValid(mark) - && ItemPointerGetBlockNumber(mark) == blkno - && ItemPointerGetOffsetNumber(mark) >= offno) - { - /* - * The idea here is to exchange the current and mark positions, - * then step backwards (affecting current), then exchange again. - */ - ItemPointerData tmpitem; - Buffer tmpbuf; - - tmpitem = *mark; - *mark = *current; - *current = tmpitem; - tmpbuf = so->hashso_mrkbuf; - so->hashso_mrkbuf = so->hashso_curbuf; - so->hashso_curbuf = tmpbuf; - - metabuf = _hash_getbuf(scan->indexRelation, HASH_METAPAGE, HASH_READ); - buf = so->hashso_curbuf; - _hash_step(scan, &buf, BackwardScanDirection, metabuf); - - tmpitem = *mark; - *mark = *current; - *current = tmpitem; - tmpbuf = so->hashso_mrkbuf; - so->hashso_mrkbuf = so->hashso_curbuf; - so->hashso_curbuf = tmpbuf; - } + return false; } diff --git a/src/backend/access/hash/hashsearch.c b/src/backend/access/hash/hashsearch.c index 53796c7e765..f156dec40d9 100644 --- a/src/backend/access/hash/hashsearch.c +++ b/src/backend/access/hash/hashsearch.c @@ -8,49 +8,17 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hashsearch.c,v 1.31 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hashsearch.c,v 1.31.2.1 2003/09/07 04:36:47 momjian Exp $ * *------------------------------------------------------------------------- */ - #include "postgres.h" #include "access/hash.h" +#include "storage/lmgr.h" /* - * _hash_search() -- Finds the page/bucket that the contains the - * scankey and loads it into *bufP. the buffer has a read lock. - */ -void -_hash_search(Relation rel, - int keysz, - ScanKey scankey, - Buffer *bufP, - HashMetaPage metap) -{ - BlockNumber blkno; - Datum keyDatum; - Bucket bucket; - - if (scankey == (ScanKey) NULL || - (keyDatum = scankey[0].sk_argument) == (Datum) NULL) - { - /* - * If the scankey argument is NULL, all tuples will satisfy the - * scan so we start the scan at the first bucket (bucket 0). - */ - bucket = 0; - } - else - bucket = _hash_call(rel, metap, keyDatum); - - blkno = BUCKET_TO_BLKNO(bucket); - - *bufP = _hash_getbuf(rel, blkno, HASH_READ); -} - -/* * _hash_next() -- Get the next item in a scan. * * On entry, we have a valid currentItemData in the scan, and a @@ -62,38 +30,30 @@ _hash_search(Relation rel, bool _hash_next(IndexScanDesc scan, ScanDirection dir) { - Relation rel; + Relation rel = scan->indexRelation; + HashScanOpaque so = (HashScanOpaque) scan->opaque; Buffer buf; - Buffer metabuf; Page page; OffsetNumber offnum; ItemPointer current; HashItem hitem; IndexTuple itup; - HashScanOpaque so; - - rel = scan->indexRelation; - so = (HashScanOpaque) scan->opaque; - /* we still have the buffer pinned and locked */ + /* we still have the buffer pinned and read-locked */ buf = so->hashso_curbuf; Assert(BufferIsValid(buf)); - metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ); - /* - * step to next valid tuple. note that _hash_step releases our lock - * on 'metabuf'; if we switch to a new 'buf' while looking for the - * next tuple, we come back with a lock on that buffer. + * step to next valid tuple. */ - if (!_hash_step(scan, &buf, dir, metabuf)) + if (!_hash_step(scan, &buf, dir)) return false; /* if we're here, _hash_step found a valid tuple */ current = &(scan->currentItemData); offnum = ItemPointerGetOffsetNumber(current); page = BufferGetPage(buf); - _hash_checkpage(page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); + _hash_checkpage(rel, page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); hitem = (HashItem) PageGetItem(page, PageGetItemId(page, offnum)); itup = &hitem->hash_itup; scan->xs_ctup.t_self = itup->t_tid; @@ -101,6 +61,9 @@ _hash_next(IndexScanDesc scan, ScanDirection dir) return true; } +/* + * Advance to next page in a bucket, if any. + */ static void _hash_readnext(Relation rel, Buffer *bufp, Page *pagep, HashPageOpaque *opaquep) @@ -108,18 +71,20 @@ _hash_readnext(Relation rel, BlockNumber blkno; blkno = (*opaquep)->hasho_nextblkno; - _hash_relbuf(rel, *bufp, HASH_READ); + _hash_relbuf(rel, *bufp); *bufp = InvalidBuffer; if (BlockNumberIsValid(blkno)) { *bufp = _hash_getbuf(rel, blkno, HASH_READ); *pagep = BufferGetPage(*bufp); - _hash_checkpage(*pagep, LH_OVERFLOW_PAGE); + _hash_checkpage(rel, *pagep, LH_OVERFLOW_PAGE); *opaquep = (HashPageOpaque) PageGetSpecialPointer(*pagep); - Assert(!PageIsEmpty(*pagep)); } } +/* + * Advance to previous page in a bucket, if any. + */ static void _hash_readprev(Relation rel, Buffer *bufp, Page *pagep, HashPageOpaque *opaquep) @@ -127,36 +92,34 @@ _hash_readprev(Relation rel, BlockNumber blkno; blkno = (*opaquep)->hasho_prevblkno; - _hash_relbuf(rel, *bufp, HASH_READ); + _hash_relbuf(rel, *bufp); *bufp = InvalidBuffer; if (BlockNumberIsValid(blkno)) { *bufp = _hash_getbuf(rel, blkno, HASH_READ); *pagep = BufferGetPage(*bufp); - _hash_checkpage(*pagep, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); + _hash_checkpage(rel, *pagep, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); *opaquep = (HashPageOpaque) PageGetSpecialPointer(*pagep); - if (PageIsEmpty(*pagep)) - { - Assert((*opaquep)->hasho_flag & LH_BUCKET_PAGE); - _hash_relbuf(rel, *bufp, HASH_READ); - *bufp = InvalidBuffer; - } } } /* * _hash_first() -- Find the first item in a scan. * - * Find the first item in the tree that + * Find the first item in the index that * satisfies the qualification associated with the scan descriptor. On - * exit, the page containing the current index tuple is read locked + * success, the page containing the current index tuple is read locked * and pinned, and the scan's opaque data entry is updated to * include the buffer. */ bool _hash_first(IndexScanDesc scan, ScanDirection dir) { - Relation rel; + Relation rel = scan->indexRelation; + HashScanOpaque so = (HashScanOpaque) scan->opaque; + uint32 hashkey; + Bucket bucket; + BlockNumber blkno; Buffer buf; Buffer metabuf; Page page; @@ -166,73 +129,92 @@ _hash_first(IndexScanDesc scan, ScanDirection dir) IndexTuple itup; ItemPointer current; OffsetNumber offnum; - HashScanOpaque so; - rel = scan->indexRelation; - so = (HashScanOpaque) scan->opaque; current = &(scan->currentItemData); + ItemPointerSetInvalid(current); + /* + * We do not support hash scans with no index qualification, because + * we would have to read the whole index rather than just one bucket. + * That creates a whole raft of problems, since we haven't got a + * practical way to lock all the buckets against splits or compactions. + */ + if (scan->numberOfKeys < 1) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("hash indexes do not support whole-index scans"))); + + /* + * If the constant in the index qual is NULL, assume it cannot match + * any items in the index. + */ + if (scan->keyData[0].sk_flags & SK_ISNULL) + return false; + + /* + * Okay to compute the hash key. We want to do this before acquiring + * any locks, in case a user-defined hash function happens to be slow. + */ + hashkey = _hash_datum2hashkey(rel, scan->keyData[0].sk_argument); + + /* + * Acquire shared split lock so we can compute the target bucket + * safely (see README). + */ + _hash_getlock(rel, 0, HASH_SHARE); + + /* Read the metapage */ metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ); metap = (HashMetaPage) BufferGetPage(metabuf); - _hash_checkpage((Page) metap, LH_META_PAGE); + _hash_checkpage(rel, (Page) metap, LH_META_PAGE); /* - * XXX -- The attribute number stored in the scan key is the attno in - * the heap relation. We need to transmogrify this into the index - * relation attno here. For the moment, we have hardwired attno == 1. + * Compute the target bucket number, and convert to block number. */ + bucket = _hash_hashkey2bucket(hashkey, + metap->hashm_maxbucket, + metap->hashm_highmask, + metap->hashm_lowmask); - /* find the correct bucket page and load it into buf */ - _hash_search(rel, 1, scan->keyData, &buf, metap); - page = BufferGetPage(buf); - _hash_checkpage(page, LH_BUCKET_PAGE); - opaque = (HashPageOpaque) PageGetSpecialPointer(page); + blkno = BUCKET_TO_BLKNO(metap, bucket); + + /* done with the metapage */ + _hash_relbuf(rel, metabuf); /* - * if we are scanning forward, we need to find the first non-empty - * page (if any) in the bucket chain. since overflow pages are never - * empty, this had better be either the bucket page or the first - * overflow page. - * - * if we are scanning backward, we always go all the way to the end of - * the bucket chain. + * Acquire share lock on target bucket; then we can release split lock. */ - if (PageIsEmpty(page)) - { - if (BlockNumberIsValid(opaque->hasho_nextblkno)) - _hash_readnext(rel, &buf, &page, &opaque); - else - { - ItemPointerSetInvalid(current); - so->hashso_curbuf = InvalidBuffer; - - /* - * If there is no scankeys, all tuples will satisfy the scan - - * so we continue in _hash_step to get tuples from all - * buckets. - vadim 04/29/97 - */ - if (scan->numberOfKeys >= 1) - { - _hash_relbuf(rel, buf, HASH_READ); - _hash_relbuf(rel, metabuf, HASH_READ); - return false; - } - } - } + _hash_getlock(rel, blkno, HASH_SHARE); + + _hash_droplock(rel, 0, HASH_SHARE); + + /* Update scan opaque state to show we have lock on the bucket */ + so->hashso_bucket = bucket; + so->hashso_bucket_valid = true; + so->hashso_bucket_blkno = blkno; + + /* Fetch the primary bucket page for the bucket */ + buf = _hash_getbuf(rel, blkno, HASH_READ); + page = BufferGetPage(buf); + _hash_checkpage(rel, page, LH_BUCKET_PAGE); + opaque = (HashPageOpaque) PageGetSpecialPointer(page); + Assert(opaque->hasho_bucket == bucket); + + /* If a backwards scan is requested, move to the end of the chain */ if (ScanDirectionIsBackward(dir)) { while (BlockNumberIsValid(opaque->hasho_nextblkno)) _hash_readnext(rel, &buf, &page, &opaque); } - if (!_hash_step(scan, &buf, dir, metabuf)) + /* Now find the first tuple satisfying the qualification */ + if (!_hash_step(scan, &buf, dir)) return false; /* if we're here, _hash_step found a valid tuple */ - current = &(scan->currentItemData); offnum = ItemPointerGetOffsetNumber(current); page = BufferGetPage(buf); - _hash_checkpage(page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); + _hash_checkpage(rel, page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); hitem = (HashItem) PageGetItem(page, PageGetItemId(page, offnum)); itup = &hitem->hash_itup; scan->xs_ctup.t_self = itup->t_tid; @@ -247,19 +229,16 @@ _hash_first(IndexScanDesc scan, ScanDirection dir) * false. Else, return true and set the CurrentItemData for the * scan to the right thing. * - * 'bufP' points to the buffer which contains the current page - * that we'll step through. - * - * 'metabuf' is released when this returns. + * 'bufP' points to the current buffer, which is pinned and read-locked. + * On success exit, we have pin and read-lock on whichever page + * contains the right item; on failure, we have released all buffers. */ bool -_hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir, Buffer metabuf) +_hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir) { - Relation rel; + Relation rel = scan->indexRelation; + HashScanOpaque so = (HashScanOpaque) scan->opaque; ItemPointer current; - HashScanOpaque so; - int allbuckets; - HashMetaPage metap; Buffer buf; Page page; HashPageOpaque opaque; @@ -270,18 +249,13 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir, Buffer metabuf) HashItem hitem; IndexTuple itup; - rel = scan->indexRelation; current = &(scan->currentItemData); - so = (HashScanOpaque) scan->opaque; - allbuckets = (scan->numberOfKeys < 1); - - metap = (HashMetaPage) BufferGetPage(metabuf); - _hash_checkpage((Page) metap, LH_META_PAGE); buf = *bufP; page = BufferGetPage(buf); - _hash_checkpage(page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); + _hash_checkpage(rel, page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); opaque = (HashPageOpaque) PageGetSpecialPointer(page); + bucket = opaque->hasho_bucket; /* * If _hash_step is called from _hash_first, current will not be @@ -302,107 +276,63 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir, Buffer metabuf) */ do { - bucket = opaque->hasho_bucket; - switch (dir) { case ForwardScanDirection: if (offnum != InvalidOffsetNumber) - { offnum = OffsetNumberNext(offnum); /* move forward */ - } else - { offnum = FirstOffsetNumber; /* new page */ - } + while (offnum > maxoff) { - - /*-------- + /* * either this page is empty * (maxoff == InvalidOffsetNumber) * or we ran off the end. - *-------- */ _hash_readnext(rel, &buf, &page, &opaque); - if (BufferIsInvalid(buf)) - { /* end of chain */ - if (allbuckets && bucket < metap->hashm_maxbucket) - { - ++bucket; - blkno = BUCKET_TO_BLKNO(bucket); - buf = _hash_getbuf(rel, blkno, HASH_READ); - page = BufferGetPage(buf); - _hash_checkpage(page, LH_BUCKET_PAGE); - opaque = (HashPageOpaque) PageGetSpecialPointer(page); - Assert(opaque->hasho_bucket == bucket); - while (PageIsEmpty(page) && - BlockNumberIsValid(opaque->hasho_nextblkno)) - _hash_readnext(rel, &buf, &page, &opaque); - maxoff = PageGetMaxOffsetNumber(page); - offnum = FirstOffsetNumber; - } - else - { - maxoff = offnum = InvalidOffsetNumber; - break; /* while */ - } - } - else + if (BufferIsValid(buf)) { - /* _hash_readnext never returns an empty page */ maxoff = PageGetMaxOffsetNumber(page); offnum = FirstOffsetNumber; } + else + { + /* end of bucket */ + maxoff = offnum = InvalidOffsetNumber; + break; /* exit while */ + } } break; + case BackwardScanDirection: if (offnum != InvalidOffsetNumber) - { offnum = OffsetNumberPrev(offnum); /* move back */ - } else - { offnum = maxoff; /* new page */ - } + while (offnum < FirstOffsetNumber) { - - /*--------- + /* * either this page is empty * (offnum == InvalidOffsetNumber) * or we ran off the end. - *--------- */ _hash_readprev(rel, &buf, &page, &opaque); - if (BufferIsInvalid(buf)) - { /* end of chain */ - if (allbuckets && bucket > 0) - { - --bucket; - blkno = BUCKET_TO_BLKNO(bucket); - buf = _hash_getbuf(rel, blkno, HASH_READ); - page = BufferGetPage(buf); - _hash_checkpage(page, LH_BUCKET_PAGE); - opaque = (HashPageOpaque) PageGetSpecialPointer(page); - Assert(opaque->hasho_bucket == bucket); - while (BlockNumberIsValid(opaque->hasho_nextblkno)) - _hash_readnext(rel, &buf, &page, &opaque); - maxoff = offnum = PageGetMaxOffsetNumber(page); - } - else - { - maxoff = offnum = InvalidOffsetNumber; - break; /* while */ - } + if (BufferIsValid(buf)) + { + maxoff = offnum = PageGetMaxOffsetNumber(page); } else { - /* _hash_readprev never returns an empty page */ - maxoff = offnum = PageGetMaxOffsetNumber(page); + /* end of bucket */ + maxoff = offnum = InvalidOffsetNumber; + break; /* exit while */ } } break; + default: /* NoMovementScanDirection */ /* this should not be reached */ @@ -412,7 +342,6 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir, Buffer metabuf) /* we ran off the end of the world without finding a match */ if (offnum == InvalidOffsetNumber) { - _hash_relbuf(rel, metabuf, HASH_READ); *bufP = so->hashso_curbuf = InvalidBuffer; ItemPointerSetInvalid(current); return false; @@ -424,7 +353,6 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir, Buffer metabuf) } while (!_hash_checkqual(scan, itup)); /* if we made it to here, we've found a valid tuple */ - _hash_relbuf(rel, metabuf, HASH_READ); blkno = BufferGetBlockNumber(buf); *bufP = so->hashso_curbuf = buf; ItemPointerSet(current, blkno, offnum); diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c index 83126fccb42..f3ac58085bc 100644 --- a/src/backend/access/hash/hashutil.c +++ b/src/backend/access/hash/hashutil.c @@ -8,11 +8,10 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hashutil.c,v 1.33 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hashutil.c,v 1.33.2.1 2003/09/07 04:36:47 momjian Exp $ * *------------------------------------------------------------------------- */ - #include "postgres.h" #include "access/genam.h" @@ -20,55 +19,19 @@ #include "access/iqual.h" -ScanKey -_hash_mkscankey(Relation rel, IndexTuple itup) -{ - ScanKey skey; - TupleDesc itupdesc; - int natts; - AttrNumber i; - Datum arg; - FmgrInfo *procinfo; - bool isnull; - - natts = rel->rd_rel->relnatts; - itupdesc = RelationGetDescr(rel); - - skey = (ScanKey) palloc(natts * sizeof(ScanKeyData)); - - for (i = 0; i < natts; i++) - { - arg = index_getattr(itup, i + 1, itupdesc, &isnull); - procinfo = index_getprocinfo(rel, i + 1, HASHPROC); - ScanKeyEntryInitializeWithInfo(&skey[i], - 0x0, - (AttrNumber) (i + 1), - procinfo, - CurrentMemoryContext, - arg); - } - - return skey; -} - -void -_hash_freeskey(ScanKey skey) -{ - pfree(skey); -} - - +/* + * _hash_checkqual -- does the index tuple satisfy the scan conditions? + */ bool _hash_checkqual(IndexScanDesc scan, IndexTuple itup) { - if (scan->numberOfKeys > 0) - return (index_keytest(itup, - RelationGetDescr(scan->indexRelation), - scan->numberOfKeys, scan->keyData)); - else - return true; + return index_keytest(itup, RelationGetDescr(scan->indexRelation), + scan->numberOfKeys, scan->keyData); } +/* + * _hash_formitem -- construct a hash index entry + */ HashItem _hash_formitem(IndexTuple itup) { @@ -82,30 +45,49 @@ _hash_formitem(IndexTuple itup) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("hash indexes cannot include null keys"))); - /* make a copy of the index tuple with room for the sequence number */ + /* + * make a copy of the index tuple (XXX do we still need to copy?) + * + * HashItemData used to have more fields than IndexTupleData, but no + * longer... + */ tuplen = IndexTupleSize(itup); nbytes_hitem = tuplen + (sizeof(HashItemData) - sizeof(IndexTupleData)); hitem = (HashItem) palloc(nbytes_hitem); - memmove((char *) &(hitem->hash_itup), (char *) itup, tuplen); + memcpy((char *) &(hitem->hash_itup), (char *) itup, tuplen); return hitem; } -Bucket -_hash_call(Relation rel, HashMetaPage metap, Datum key) +/* + * _hash_datum2hashkey -- given a Datum, call the index's hash procedure + */ +uint32 +_hash_datum2hashkey(Relation rel, Datum key) { FmgrInfo *procinfo; - uint32 n; - Bucket bucket; /* XXX assumes index has only one attribute */ procinfo = index_getprocinfo(rel, 1, HASHPROC); - n = DatumGetUInt32(FunctionCall1(procinfo, key)); - bucket = n & metap->hashm_highmask; - if (bucket > metap->hashm_maxbucket) - bucket = bucket & metap->hashm_lowmask; + + return DatumGetUInt32(FunctionCall1(procinfo, key)); +} + +/* + * _hash_hashkey2bucket -- determine which bucket the hashkey maps to. + */ +Bucket +_hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket, + uint32 highmask, uint32 lowmask) +{ + Bucket bucket; + + bucket = hashkey & highmask; + if (bucket > maxbucket) + bucket = bucket & lowmask; + return bucket; } @@ -119,7 +101,7 @@ _hash_log2(uint32 num) limit; limit = 1; - for (i = 0; limit < num; limit = limit << 1, i++) + for (i = 0; limit < num; limit <<= 1, i++) ; return i; } @@ -128,22 +110,44 @@ _hash_log2(uint32 num) * _hash_checkpage -- sanity checks on the format of all hash pages */ void -_hash_checkpage(Page page, int flags) +_hash_checkpage(Relation rel, Page page, int flags) { - HashPageOpaque opaque; - Assert(page); + /* + * When checking the metapage, always verify magic number and version. + */ + if (flags == LH_META_PAGE) + { + HashMetaPage metap = (HashMetaPage) page; + + if (metap->hashm_magic != HASH_MAGIC) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" is not a hash index", + RelationGetRelationName(rel)))); + + if (metap->hashm_version != HASH_VERSION) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" has wrong hash version, please REINDEX it", + RelationGetRelationName(rel)))); + } + + /* + * These other checks are for debugging purposes only. + */ +#ifdef USE_ASSERT_CHECKING Assert(((PageHeader) (page))->pd_lower >= SizeOfPageHeaderData); -#if 1 Assert(((PageHeader) (page))->pd_upper <= (BLCKSZ - MAXALIGN(sizeof(HashPageOpaqueData)))); Assert(((PageHeader) (page))->pd_special == (BLCKSZ - MAXALIGN(sizeof(HashPageOpaqueData)))); Assert(PageGetPageSize(page) == BLCKSZ); -#endif if (flags) { - opaque = (HashPageOpaque) PageGetSpecialPointer(page); + HashPageOpaque opaque = (HashPageOpaque) PageGetSpecialPointer(page); + Assert(opaque->hasho_flag & flags); } +#endif /* USE_ASSERT_CHECKING */ } diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index 02d842434c2..2dd14f9fb61 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.104 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.104.2.1 2003/09/07 04:36:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -189,27 +189,39 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel, BlockNumber nblkno; /* - * make sure the offset points to an actual key before trying to - * compare it... + * make sure the offset points to an actual item before trying to + * examine it... */ if (offset <= maxoff) { - /* - * _bt_compare returns 0 for (1,NULL) and (1,NULL) - this's - * how we handling NULLs - and so we must not use _bt_compare - * in real comparison, but only for ordering/finding items on - * pages. - vadim 03/24/97 - */ - if (!_bt_isequal(itupdesc, page, offset, natts, itup_scankey)) - break; /* we're past all the equal tuples */ - curitemid = PageGetItemId(page, offset); /* - * We can skip the heap fetch if the item is marked killed. + * We can skip items that are marked killed. + * + * Formerly, we applied _bt_isequal() before checking the kill + * flag, so as to fall out of the item loop as soon as possible. + * However, in the presence of heavy update activity an index + * may contain many killed items with the same key; running + * _bt_isequal() on each killed item gets expensive. Furthermore + * it is likely that the non-killed version of each key appears + * first, so that we didn't actually get to exit any sooner anyway. + * So now we just advance over killed items as quickly as we can. + * We only apply _bt_isequal() when we get to a non-killed item or + * the end of the page. */ if (!ItemIdDeleted(curitemid)) { + /* + * _bt_compare returns 0 for (1,NULL) and (1,NULL) - this's + * how we handling NULLs - and so we must not use _bt_compare + * in real comparison, but only for ordering/finding items on + * pages. - vadim 03/24/97 + */ + if (!_bt_isequal(itupdesc, page, offset, natts, itup_scankey)) + break; /* we're past all the equal tuples */ + + /* okay, we gotta fetch the heap tuple ... */ cbti = (BTItem) PageGetItem(page, curitemid); htup.t_self = cbti->bti_itup.t_tid; if (heap_fetch(heapRel, SnapshotDirty, &htup, &hbuffer, @@ -1547,7 +1559,7 @@ _bt_pgaddtup(Relation rel, * _bt_isequal - used in _bt_doinsert in check for duplicates. * * This is very similar to _bt_compare, except for NULL handling. - * Rule is simple: NOT_NULL not equal NULL, NULL not_equal NULL too. + * Rule is simple: NOT_NULL not equal NULL, NULL not equal NULL too. */ static bool _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum, @@ -1576,7 +1588,7 @@ _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum, datum = index_getattr(itup, attno, itupdesc, &isNull); /* NULLs are never equal to anything */ - if (entry->sk_flags & SK_ISNULL || isNull) + if ((entry->sk_flags & SK_ISNULL) || isNull) return false; result = DatumGetInt32(FunctionCall2(&entry->sk_func, diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index d4c10a983d9..f1b4b6d2bea 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.165 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.165.2.1 2003/09/07 04:36:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -368,9 +368,15 @@ BootstrapMain(int argc, char *argv[]) Assert(DataDir); ValidatePgVersion(DataDir); + /* Acquire configuration parameters */ + if (IsUnderPostmaster) + { #ifdef EXEC_BACKEND - read_nondefault_variables(); + read_nondefault_variables(); #endif + } + else + ProcessConfigFile(PGC_POSTMASTER); if (IsUnderPostmaster) { diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index b861d76629b..f2398e83206 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.87 2003/08/04 02:39:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.87.2.1 2003/09/07 04:36:47 momjian Exp $ * * NOTES * See acl.h. @@ -72,6 +72,8 @@ dumpacl(Acl *acl) * If is_grant is true, adds the given privileges for the list of * grantees to the existing old_acl. If is_grant is false, the * privileges for the given grantees are removed from old_acl. + * + * NB: the original old_acl is pfree'd. */ static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, @@ -92,24 +94,25 @@ merge_acl_with_grant(Acl *old_acl, bool is_grant, foreach(j, grantees) { PrivGrantee *grantee = (PrivGrantee *) lfirst(j); - AclItem aclitem; + AclItem aclitem; uint32 idtype; + Acl *newer_acl; if (grantee->username) { - aclitem. ai_grantee = get_usesysid(grantee->username); + aclitem.ai_grantee = get_usesysid(grantee->username); idtype = ACL_IDTYPE_UID; } else if (grantee->groupname) { - aclitem. ai_grantee = get_grosysid(grantee->groupname); + aclitem.ai_grantee = get_grosysid(grantee->groupname); idtype = ACL_IDTYPE_GID; } else { - aclitem. ai_grantee = ACL_ID_WORLD; + aclitem.ai_grantee = ACL_ID_WORLD; idtype = ACL_IDTYPE_WORLD; } @@ -126,14 +129,18 @@ merge_acl_with_grant(Acl *old_acl, bool is_grant, (errcode(ERRCODE_INVALID_GRANT_OPERATION), errmsg("grant options can only be granted to individual users"))); - aclitem. ai_grantor = GetUserId(); + aclitem.ai_grantor = GetUserId(); ACLITEM_SET_PRIVS_IDTYPE(aclitem, (is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS, (grant_option || !is_grant) ? privileges : ACL_NO_RIGHTS, idtype); - new_acl = aclinsert3(new_acl, &aclitem, modechg, behavior); + newer_acl = aclinsert3(new_acl, &aclitem, modechg, behavior); + + /* avoid memory leak when there are many grantees */ + pfree(new_acl); + new_acl = newer_acl; #ifdef ACLDEBUG dumpacl(new_acl); @@ -269,7 +276,6 @@ ExecuteGrantStmt_Relation(GrantStmt *stmt) /* keep the catalog indexes up to date */ CatalogUpdateIndexes(relation, newtuple); - pfree(old_acl); pfree(new_acl); heap_close(relation, RowExclusiveLock); @@ -366,7 +372,6 @@ ExecuteGrantStmt_Database(GrantStmt *stmt) /* keep the catalog indexes up to date */ CatalogUpdateIndexes(relation, newtuple); - pfree(old_acl); pfree(new_acl); heap_endscan(scan); @@ -465,7 +470,6 @@ ExecuteGrantStmt_Function(GrantStmt *stmt) /* keep the catalog indexes up to date */ CatalogUpdateIndexes(relation, newtuple); - pfree(old_acl); pfree(new_acl); heap_close(relation, RowExclusiveLock); @@ -565,7 +569,6 @@ ExecuteGrantStmt_Language(GrantStmt *stmt) /* keep the catalog indexes up to date */ CatalogUpdateIndexes(relation, newtuple); - pfree(old_acl); pfree(new_acl); heap_close(relation, RowExclusiveLock); @@ -662,7 +665,6 @@ ExecuteGrantStmt_Namespace(GrantStmt *stmt) /* keep the catalog indexes up to date */ CatalogUpdateIndexes(relation, newtuple); - pfree(old_acl); pfree(new_acl); heap_close(relation, RowExclusiveLock); diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 2272d7bf3fb..858afc6c60f 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.58 2003/08/04 02:39:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.58.2.1 2003/09/07 04:36:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -390,7 +390,6 @@ examine_attribute(Relation onerel, int attnum) { Form_pg_attribute attr = onerel->rd_att->attrs[attnum - 1]; Operator func_operator; - Oid oprrest; HeapTuple typtuple; Oid eqopr = InvalidOid; Oid eqfunc = InvalidOid; @@ -409,12 +408,8 @@ examine_attribute(Relation onerel, int attnum) func_operator = equality_oper(attr->atttypid, true); if (func_operator != NULL) { - oprrest = ((Form_pg_operator) GETSTRUCT(func_operator))->oprrest; - if (oprrest == F_EQSEL) - { - eqopr = oprid(func_operator); - eqfunc = oprfuncid(func_operator); - } + eqopr = oprid(func_operator); + eqfunc = oprfuncid(func_operator); ReleaseSysCache(func_operator); } if (!OidIsValid(eqfunc)) @@ -447,9 +442,7 @@ examine_attribute(Relation onerel, int attnum) func_operator = ordering_oper(attr->atttypid, true); if (func_operator != NULL) { - oprrest = ((Form_pg_operator) GETSTRUCT(func_operator))->oprrest; - if (oprrest == F_SCALARLTSEL) - ltopr = oprid(func_operator); + ltopr = oprid(func_operator); ReleaseSysCache(func_operator); } stats->ltopr = ltopr; @@ -694,6 +687,12 @@ pageloop:; */ *totalrows = floor((double) onerel->rd_nblocks * tuplesperpage + 0.5); + /* + * Emit some interesting relation info + */ + elog(elevel, " pages = %d rows/page = %d rows = %.0f", + onerel->rd_nblocks, (int)tuplesperpage, *totalrows); + return numrows; } diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index bf798288f1b..280ae7f51d3 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.209 2003/08/13 18:56:21 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.209.2.1 2003/09/07 04:36:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -432,7 +432,7 @@ CopyGetData(void *databuf, int datasize) avail = datasize; pq_copymsgbytes(copy_msgbuf, databuf, avail); databuf = (void *) ((char *) databuf + avail); - datasize = -avail; + datasize -= avail; } break; } diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 36baf4690e3..8a15f189c97 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.105 2003/08/04 02:39:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.105.2.1 2003/09/07 04:36:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -529,7 +529,8 @@ GetDefaultOpClass(Oid attrType, Oid accessMethodId) * than one exact match, then someone put bogus entries in pg_opclass. * * The initial search is done by namespace.c so that we only consider - * opclasses visible in the current namespace search path. + * opclasses visible in the current namespace search path. (See also + * typcache.c, which applies the same logic, but over all opclasses.) */ for (opclass = OpclassGetCandidates(accessMethodId); opclass != NULL; diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index 0677751ead4..300a80aeb0d 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.17 2003/08/04 02:39:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.17.2.1 2003/09/07 04:36:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -261,7 +261,9 @@ DefineOpClass(CreateOpClassStmt *stmt) /* * If we are creating a default opclass, check there isn't one - * already. (XXX should we restrict this test to visible opclasses?) + * already. (Note we do not restrict this test to visible opclasses; + * this ensures that typcache.c can find unique solutions to its + * questions.) */ if (stmt->isDefault) { diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c index c11b48db4c1..7a95959c98e 100644 --- a/src/backend/commands/portalcmds.c +++ b/src/backend/commands/portalcmds.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.23 2003/08/08 21:41:32 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.23.2.1 2003/09/07 04:36:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -88,10 +88,9 @@ PerformCursorOpen(DeclareCursorStmt *stmt) /* * Create a portal and copy the query and plan into its memory - * context. (If a duplicate cursor name already exists, warn and drop - * it.) + * context. */ - portal = CreatePortal(stmt->portalname, true, false); + portal = CreatePortal(stmt->portalname, false, false); oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); @@ -168,13 +167,10 @@ PerformPortalFetch(FetchStmt *stmt, portal = GetPortalByName(stmt->portalname); if (!PortalIsValid(portal)) { - /* FIXME: shouldn't this be an ERROR? */ - ereport(WARNING, + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_CURSOR), - errmsg("portal \"%s\" does not exist", stmt->portalname))); - if (completionTag) - strcpy(completionTag, stmt->ismove ? "MOVE 0" : "FETCH 0"); - return; + errmsg("cursor \"%s\" does not exist", stmt->portalname))); + return; /* keep compiler happy */ } /* Adjust dest if needed. MOVE wants destination None */ @@ -218,11 +214,10 @@ PerformPortalClose(const char *name) portal = GetPortalByName(name); if (!PortalIsValid(portal)) { - ereport(WARNING, + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_CURSOR), - errmsg("portal \"%s\" does not exist", name), - errfunction("PerformPortalClose"))); /* for ecpg */ - return; + errmsg("cursor \"%s\" does not exist", name))); + return; /* keep compiler happy */ } /* diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 77885802335..ecbdad05195 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.79 2003/08/08 21:41:32 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.79.2.1 2003/09/07 04:36:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -2008,7 +2008,7 @@ AlterTableAlterColumnDropNotNull(Oid myrelid, bool recurse, } } - /* -= now do the thing on this relation =- */ + /* now do the thing on this relation */ /* * get the number of the attribute @@ -2152,7 +2152,7 @@ AlterTableAlterColumnSetNotNull(Oid myrelid, bool recurse, } } - /* -= now do the thing on this relation =- */ + /* now do the thing on this relation */ /* * get the number of the attribute @@ -2280,7 +2280,7 @@ AlterTableAlterColumnDefault(Oid myrelid, bool recurse, } } - /* -= now do the thing on this relation =- */ + /* now do the thing on this relation */ /* * get the number of the attribute @@ -2445,7 +2445,7 @@ AlterTableAlterColumnFlags(Oid myrelid, bool recurse, } } - /* -= now do the thing on this relation =- */ + /* now do the thing on this relation */ attrelation = heap_openr(AttributeRelationName, RowExclusiveLock); diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c index 100e7a1c375..0307386c9e0 100644 --- a/src/backend/executor/execGrouping.c +++ b/src/backend/executor/execGrouping.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execGrouping.c,v 1.7 2003/08/08 21:41:34 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execGrouping.c,v 1.7.2.1 2003/09/07 04:36:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -23,6 +23,13 @@ #include "utils/syscache.h" +static TupleHashTable CurTupleHashTable = NULL; + +static uint32 TupleHashTableHash(const void *key, Size keysize); +static int TupleHashTableMatch(const void *key1, const void *key2, + Size keysize); + + /***************************************************************************** * Utility routines for grouping tuples together *****************************************************************************/ @@ -272,7 +279,7 @@ execTuplesHashPrepare(TupleDesc tupdesc, * numCols, keyColIdx: identify the tuple fields to use as lookup key * eqfunctions: equality comparison functions to use * hashfunctions: datatype-specific hashing functions to use - * nbuckets: number of buckets to make + * nbuckets: initial estimate of hashtable size * entrysize: size of each entry (at least sizeof(TupleHashEntryData)) * tablecxt: memory context in which to store table and table entries * tempcxt: short-lived context for evaluation hash and comparison functions @@ -290,14 +297,13 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx, MemoryContext tablecxt, MemoryContext tempcxt) { TupleHashTable hashtable; - Size tabsize; + HASHCTL hash_ctl; Assert(nbuckets > 0); Assert(entrysize >= sizeof(TupleHashEntryData)); - tabsize = sizeof(TupleHashTableData) + - (nbuckets - 1) *sizeof(TupleHashEntry); - hashtable = (TupleHashTable) MemoryContextAllocZero(tablecxt, tabsize); + hashtable = (TupleHashTable) MemoryContextAlloc(tablecxt, + sizeof(TupleHashTableData)); hashtable->numCols = numCols; hashtable->keyColIdx = keyColIdx; @@ -306,7 +312,20 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx, hashtable->tablecxt = tablecxt; hashtable->tempcxt = tempcxt; hashtable->entrysize = entrysize; - hashtable->nbuckets = nbuckets; + + MemSet(&hash_ctl, 0, sizeof(hash_ctl)); + hash_ctl.keysize = sizeof(TupleHashEntryData); + hash_ctl.entrysize = entrysize; + hash_ctl.hash = TupleHashTableHash; + hash_ctl.match = TupleHashTableMatch; + hash_ctl.hcxt = tablecxt; + hashtable->hashtab = hash_create("TupleHashTable", (long) nbuckets, + &hash_ctl, + HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT); + if (hashtable->hashtab == NULL) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); return hashtable; } @@ -327,19 +346,93 @@ TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew) { - int numCols = hashtable->numCols; - AttrNumber *keyColIdx = hashtable->keyColIdx; HeapTuple tuple = slot->val; TupleDesc tupdesc = slot->ttc_tupleDescriptor; - uint32 hashkey = 0; - int i; - int bucketno; TupleHashEntry entry; MemoryContext oldContext; + TupleHashTable saveCurHT; + bool found; - /* Need to run the hash function in short-lived context */ + /* Need to run the hash functions in short-lived context */ oldContext = MemoryContextSwitchTo(hashtable->tempcxt); + /* + * Set up data needed by hash and match functions + * + * We save and restore CurTupleHashTable just in case someone manages + * to invoke this code re-entrantly. + */ + hashtable->tupdesc = tupdesc; + saveCurHT = CurTupleHashTable; + CurTupleHashTable = hashtable; + + /* Search the hash table */ + entry = (TupleHashEntry) hash_search(hashtable->hashtab, + &tuple, + isnew ? HASH_ENTER : HASH_FIND, + &found); + + if (isnew) + { + if (found) + { + /* found pre-existing entry */ + *isnew = false; + } + else + { + /* created new entry ... we hope */ + if (entry == NULL) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + + /* + * Zero any caller-requested space in the entry. (This zaps + * the "key data" dynahash.c copied into the new entry, but + * we don't care since we're about to overwrite it anyway.) + */ + MemSet(entry, 0, hashtable->entrysize); + + /* Copy the first tuple into the table context */ + MemoryContextSwitchTo(hashtable->tablecxt); + entry->firstTuple = heap_copytuple(tuple); + + *isnew = true; + } + } + + CurTupleHashTable = saveCurHT; + + MemoryContextSwitchTo(oldContext); + + return entry; +} + +/* + * Compute the hash value for a tuple + * + * The passed-in key is a pointer to a HeapTuple pointer -- this is either + * the firstTuple field of a TupleHashEntry struct, or the key value passed + * to hash_search. We ignore the keysize. + * + * CurTupleHashTable must be set before calling this, since dynahash.c + * doesn't provide any API that would let us get at the hashtable otherwise. + * + * Also, the caller must select an appropriate memory context for running + * the hash functions. (dynahash.c doesn't change CurrentMemoryContext.) + */ +static uint32 +TupleHashTableHash(const void *key, Size keysize) +{ + HeapTuple tuple = *(const HeapTuple *) key; + TupleHashTable hashtable = CurTupleHashTable; + int numCols = hashtable->numCols; + AttrNumber *keyColIdx = hashtable->keyColIdx; + TupleDesc tupdesc = hashtable->tupdesc; + uint32 hashkey = 0; + int i; + for (i = 0; i < numCols; i++) { AttrNumber att = keyColIdx[i]; @@ -360,72 +453,36 @@ LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, hashkey ^= hkey; } } - bucketno = hashkey % (uint32) hashtable->nbuckets; - - for (entry = hashtable->buckets[bucketno]; - entry != NULL; - entry = entry->next) - { - /* Quick check using hashkey */ - if (entry->hashkey != hashkey) - continue; - if (execTuplesMatch(entry->firstTuple, - tuple, - tupdesc, - numCols, keyColIdx, - hashtable->eqfunctions, - hashtable->tempcxt)) - { - if (isnew) - *isnew = false; - MemoryContextSwitchTo(oldContext); - return entry; - } - } - - /* Not there, so build a new one if requested */ - if (isnew) - { - MemoryContextSwitchTo(hashtable->tablecxt); - - entry = (TupleHashEntry) palloc0(hashtable->entrysize); - - entry->hashkey = hashkey; - entry->firstTuple = heap_copytuple(tuple); - - entry->next = hashtable->buckets[bucketno]; - hashtable->buckets[bucketno] = entry; - - *isnew = true; - } - - MemoryContextSwitchTo(oldContext); - return entry; + return hashkey; } /* - * Walk through all the entries of a hash table, in no special order. - * Returns NULL when no more entries remain. + * See whether two tuples (presumably of the same hash value) match + * + * As above, the passed pointers are pointers to HeapTuple pointers. * - * Iterator state must be initialized with ResetTupleHashIterator() macro. + * CurTupleHashTable must be set before calling this, since dynahash.c + * doesn't provide any API that would let us get at the hashtable otherwise. + * + * Also, the caller must select an appropriate memory context for running + * the compare functions. (dynahash.c doesn't change CurrentMemoryContext.) */ -TupleHashEntry -ScanTupleHashTable(TupleHashTable hashtable, TupleHashIterator *state) +static int +TupleHashTableMatch(const void *key1, const void *key2, Size keysize) { - TupleHashEntry entry; - - entry = state->next_entry; - while (entry == NULL) - { - if (state->next_bucket >= hashtable->nbuckets) - { - /* No more entries in hashtable, so done */ - return NULL; - } - entry = hashtable->buckets[state->next_bucket++]; - } - state->next_entry = entry->next; - - return entry; + HeapTuple tuple1 = *(const HeapTuple *) key1; + HeapTuple tuple2 = *(const HeapTuple *) key2; + TupleHashTable hashtable = CurTupleHashTable; + + if (execTuplesMatch(tuple1, + tuple2, + hashtable->tupdesc, + hashtable->numCols, + hashtable->keyColIdx, + hashtable->eqfunctions, + hashtable->tempcxt)) + return 0; + else + return 1; } diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 4ecae71cd68..cce62237085 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.141 2003/08/08 21:41:39 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.141.2.1 2003/09/07 04:36:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1620,16 +1620,18 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, ArrayType *result; List *element; Oid element_type = arrayExpr->element_typeid; - int ndims = arrayExpr->ndims; + int ndims = 0; int dims[MAXDIM]; int lbs[MAXDIM]; - if (ndims == 1) + if (!arrayExpr->multidims) { + /* Elements are presumably of scalar type */ int nelems; Datum *dvalues; int i = 0; + ndims = 1; nelems = length(astate->elements); /* Shouldn't happen here, but if length is 0, return NULL */ @@ -1667,6 +1669,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, } else { + /* Must be nested array expressions */ char *dat = NULL; Size ndatabytes = 0; int nbytes; @@ -1677,12 +1680,6 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, bool firstone = true; int i; - if (ndims <= 0 || ndims > MAXDIM) - ereport(ERROR, - (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("number of array dimensions exceeds the maximum allowed, %d", - MAXDIM))); - /* loop through and get data area from each element */ foreach(element, astate->elements) { @@ -1701,14 +1698,32 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, array = DatumGetArrayTypeP(arraydatum); + /* run-time double-check on element type */ + if (element_type != ARR_ELEMTYPE(array)) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("cannot merge incompatible arrays"), + errdetail("Array with element type %s cannot be " + "included in ARRAY construct with element type %s.", + format_type_be(ARR_ELEMTYPE(array)), + format_type_be(element_type)))); + if (firstone) { /* Get sub-array details from first member */ elem_ndims = ARR_NDIM(array); + ndims = elem_ndims + 1; + if (ndims <= 0 || ndims > MAXDIM) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("number of array dimensions exceeds " \ + "the maximum allowed, %d", MAXDIM))); + elem_dims = (int *) palloc(elem_ndims * sizeof(int)); memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int)); elem_lbs = (int *) palloc(elem_ndims * sizeof(int)); memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int)); + firstone = false; } else diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index d8fb9a9565d..1ac046b65f4 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -45,7 +45,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.115 2003/08/08 21:41:41 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.115.2.1 2003/09/07 04:36:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -905,7 +905,7 @@ agg_fill_hash_table(AggState *aggstate) aggstate->table_filled = true; /* Initialize to walk the hash table */ - ResetTupleHashIterator(&aggstate->hashiter); + ResetTupleHashIterator(aggstate->hashtable, &aggstate->hashiter); } /* @@ -920,7 +920,6 @@ agg_retrieve_hash_table(AggState *aggstate) bool *aggnulls; AggStatePerAgg peragg; AggStatePerGroup pergroup; - TupleHashTable hashtable; AggHashEntry entry; TupleTableSlot *firstSlot; TupleTableSlot *resultSlot; @@ -935,7 +934,6 @@ agg_retrieve_hash_table(AggState *aggstate) aggnulls = econtext->ecxt_aggnulls; projInfo = aggstate->ss.ps.ps_ProjInfo; peragg = aggstate->peragg; - hashtable = aggstate->hashtable; firstSlot = aggstate->ss.ss_ScanTupleSlot; /* @@ -950,8 +948,7 @@ agg_retrieve_hash_table(AggState *aggstate) /* * Find the next entry in the hash table */ - entry = (AggHashEntry) ScanTupleHashTable(hashtable, - &aggstate->hashiter); + entry = (AggHashEntry) ScanTupleHashTable(&aggstate->hashiter); if (entry == NULL) { /* No more entries in hashtable, so done */ @@ -1440,7 +1437,7 @@ ExecReScanAgg(AggState *node, ExprContext *exprCtxt) */ if (((PlanState *) node)->lefttree->chgParam == NULL) { - ResetTupleHashIterator(&node->hashiter); + ResetTupleHashIterator(node->hashtable, &node->hashiter); return; } } diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index bfbcaf208de..1ea753ea303 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.82 2003/08/04 02:39:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.82.2.1 2003/09/07 04:36:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -28,19 +28,51 @@ #include "access/heapam.h" #include "executor/execdebug.h" #include "executor/nodeIndexscan.h" +#include "miscadmin.h" #include "nodes/nodeFuncs.h" #include "optimizer/clauses.h" #include "parser/parsetree.h" -/* ---------------- - * Misc stuff to move to executor.h soon -cim 6/5/90 - * ---------------- - */ + #define NO_OP 0 #define LEFT_OP 1 #define RIGHT_OP 2 +/* + * In a multiple-index plan, we must take care to return any given tuple + * only once, even if it matches conditions of several index scans. Our + * preferred way to do this is to record already-returned tuples in a hash + * table (using the TID as unique identifier). However, in a very large + * scan this could conceivably run out of memory. We limit the hash table + * to no more than SortMem KB; if it grows past that, we fall back to the + * pre-7.4 technique: evaluate the prior-scan index quals again for each + * tuple (which is space-efficient, but slow). + * + * When scanning backwards, we use scannum to determine when to emit the + * tuple --- we have to re-emit a tuple in the same scan as it was first + * encountered. + * + * Note: this code would break if the planner were ever to create a multiple + * index plan with overall backwards direction, because the hashtable code + * will emit a tuple the first time it is encountered (which would be the + * highest scan in which it matches the index), but the evaluate-the-quals + * code will emit a tuple in the lowest-numbered scan in which it's valid. + * This could be fixed at need by making the evaluate-the-quals case more + * complex. Currently the planner will never create such a plan (since it + * considers multi-index plans unordered anyway), so there's no need for + * more complexity. + */ +typedef struct +{ + /* tid is the hash key and so must be first! */ + ItemPointerData tid; /* TID of a tuple we've returned */ + int scannum; /* number of scan we returned it in */ +} DupHashTabEntry; + + static TupleTableSlot *IndexNext(IndexScanState *node); +static void create_duphash(IndexScanState *node); + /* ---------------------------------------------------------------- * IndexNext @@ -163,7 +195,7 @@ IndexNext(IndexScanState *node) while ((tuple = index_getnext(scandesc, direction)) != NULL) { /* - * store the scanned tuple in the scan tuple slot of the scan + * Store the scanned tuple in the scan tuple slot of the scan * state. Note: we pass 'false' because tuples returned by * amgetnext are pointers onto disk pages and must not be * pfree()'d. @@ -174,36 +206,80 @@ IndexNext(IndexScanState *node) false); /* don't pfree */ /* - * We must check to see if the current tuple was already - * matched by an earlier index, so we don't double-report it. - * We do this by passing the tuple through ExecQual and - * checking for failure with all previous qualifications. + * If it's a multiple-index scan, make sure not to double-report + * a tuple matched by more than one index. (See notes above.) */ - if (node->iss_IndexPtr > 0) + if (numIndices > 1) { - bool prev_matches = false; - int prev_index; - List *qual; - - econtext->ecxt_scantuple = slot; - ResetExprContext(econtext); - qual = node->indxqualorig; - for (prev_index = 0; - prev_index < node->iss_IndexPtr; - prev_index++) + /* First try the hash table */ + if (node->iss_DupHash) { - if (ExecQual((List *) lfirst(qual), econtext, false)) + DupHashTabEntry *entry; + bool found; + + entry = (DupHashTabEntry *) + hash_search(node->iss_DupHash, + &tuple->t_data->t_ctid, + HASH_ENTER, + &found); + if (entry == NULL || + node->iss_DupHash->hctl->nentries > node->iss_MaxHash) + { + /* out of memory (either hard or soft limit) */ + /* release hash table and fall thru to old code */ + hash_destroy(node->iss_DupHash); + node->iss_DupHash = NULL; + } + else if (found) { - prev_matches = true; - break; + /* pre-existing entry */ + + /* + * It's duplicate if first emitted in a different + * scan. If same scan, we must be backing up, so + * okay to emit again. + */ + if (entry->scannum != node->iss_IndexPtr) + { + /* Dup, so drop it and loop back for another */ + ExecClearTuple(slot); + continue; + } + } + else + { + /* new entry, finish filling it in */ + entry->scannum = node->iss_IndexPtr; } - qual = lnext(qual); } - if (prev_matches) + /* If hash table has overflowed, do it the hard way */ + if (node->iss_DupHash == NULL && + node->iss_IndexPtr > 0) { - /* Duplicate, so drop it and loop back for another */ - ExecClearTuple(slot); - continue; + bool prev_matches = false; + int prev_index; + List *qual; + + econtext->ecxt_scantuple = slot; + ResetExprContext(econtext); + qual = node->indxqualorig; + for (prev_index = 0; + prev_index < node->iss_IndexPtr; + prev_index++) + { + if (ExecQual((List *) lfirst(qual), econtext, false)) + { + prev_matches = true; + break; + } + qual = lnext(qual); + } + if (prev_matches) + { + /* Dup, so drop it and loop back for another */ + ExecClearTuple(slot); + continue; + } } } @@ -383,6 +459,14 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt) return; } + /* reset hash table */ + if (numIndices > 1) + { + if (node->iss_DupHash) + hash_destroy(node->iss_DupHash); + create_duphash(node); + } + /* reset index scans */ if (ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indxorderdir)) node->iss_IndexPtr = numIndices; @@ -432,6 +516,10 @@ ExecEndIndexScan(IndexScanState *node) ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); + /* drop hash table */ + if (node->iss_DupHash) + hash_destroy(node->iss_DupHash); + /* * close the index relations */ @@ -507,7 +595,7 @@ ExecIndexRestrPos(IndexScanState *node) /* ---------------------------------------------------------------- * ExecInitIndexScan - * + * * Initializes the index scan's state information, creates * scan keys, and opens the base and index relations. * @@ -920,11 +1008,41 @@ ExecInitIndexScan(IndexScan *node, EState *estate) ExecAssignScanProjectionInfo(&indexstate->ss); /* + * Initialize hash table if needed. + */ + if (numIndices > 1) + create_duphash(indexstate); + else + indexstate->iss_DupHash = NULL; + + /* * all done. */ return indexstate; } +static void +create_duphash(IndexScanState *node) +{ + HASHCTL hash_ctl; + + MemSet(&hash_ctl, 0, sizeof(hash_ctl)); + hash_ctl.keysize = SizeOfIptrData; + hash_ctl.entrysize = sizeof(DupHashTabEntry); + hash_ctl.hash = tag_hash; + hash_ctl.hcxt = CurrentMemoryContext; + node->iss_DupHash = hash_create("DupHashTable", + (long) ceil(node->ss.ps.plan->plan_rows), + &hash_ctl, + HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + if (node->iss_DupHash == NULL) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + node->iss_MaxHash = (SortMem * 1024L) / + (MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(sizeof(DupHashTabEntry))); +} + int ExecCountSlotsIndexScan(IndexScan *node) { diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index 7530be263f3..71209fe246d 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.54 2003/08/08 21:41:42 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.54.2.1 2003/09/07 04:36:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -627,8 +627,8 @@ findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot) TupleHashIterator hashiter; TupleHashEntry entry; - ResetTupleHashIterator(&hashiter); - while ((entry = ScanTupleHashTable(hashtable, &hashiter)) != NULL) + ResetTupleHashIterator(hashtable, &hashiter); + while ((entry = ScanTupleHashTable(&hashiter)) != NULL) { if (!execTuplesUnequal(entry->firstTuple, tuple, diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index f2ca627eba2..114faab5128 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.111 2003/08/04 02:39:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.111.2.1 2003/09/07 04:36:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -550,12 +550,12 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) char *token; char *db; char *user; - struct addrinfo *file_ip_addr = NULL, - *file_ip_mask = NULL; + struct addrinfo *gai_result; struct addrinfo hints; - struct sockaddr_storage *mask; - char *cidr_slash; int ret; + struct sockaddr_storage addr; + struct sockaddr_storage mask; + char *cidr_slash; Assert(line != NIL); line_number = lfirsti(line); @@ -648,6 +648,7 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) if (cidr_slash) *cidr_slash = '\0'; + /* Get the IP address either way */ hints.ai_flags = AI_NUMERICHOST; hints.ai_family = PF_UNSPEC; hints.ai_socktype = 0; @@ -657,9 +658,8 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) hints.ai_addr = NULL; hints.ai_next = NULL; - /* Get the IP address either way */ - ret = getaddrinfo_all(token, NULL, &hints, &file_ip_addr); - if (ret || !file_ip_addr) + ret = getaddrinfo_all(token, NULL, &hints, &gai_result); + if (ret || !gai_result) { ereport(LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), @@ -667,24 +667,21 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) token, gai_strerror(ret)))); if (cidr_slash) *cidr_slash = '/'; + if (gai_result) + freeaddrinfo_all(hints.ai_family, gai_result); goto hba_syntax; } if (cidr_slash) *cidr_slash = '/'; - if (file_ip_addr->ai_family != port->raddr.addr.ss_family) - { - /* Wrong address family. */ - freeaddrinfo_all(hints.ai_family, file_ip_addr); - return; - } + memcpy(&addr, gai_result->ai_addr, gai_result->ai_addrlen); + freeaddrinfo_all(hints.ai_family, gai_result); /* Get the netmask */ if (cidr_slash) { - if (SockAddr_cidr_mask(&mask, cidr_slash + 1, - file_ip_addr->ai_family) < 0) + if (SockAddr_cidr_mask(&mask, cidr_slash + 1, addr.ss_family) < 0) goto hba_syntax; } else @@ -695,16 +692,47 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) goto hba_syntax; token = lfirst(line); - ret = getaddrinfo_all(token, NULL, &hints, &file_ip_mask); - if (ret || !file_ip_mask) + ret = getaddrinfo_all(token, NULL, &hints, &gai_result); + if (ret || !gai_result) + { + if (gai_result) + freeaddrinfo_all(hints.ai_family, gai_result); goto hba_syntax; + } - mask = (struct sockaddr_storage *) file_ip_mask->ai_addr; + memcpy(&mask, gai_result->ai_addr, gai_result->ai_addrlen); + freeaddrinfo_all(hints.ai_family, gai_result); - if (file_ip_addr->ai_family != mask->ss_family) + if (addr.ss_family != mask.ss_family) goto hba_syntax; } + if (addr.ss_family != port->raddr.addr.ss_family) + { + /* + * Wrong address family. We allow only one case: if the + * file has IPv4 and the port is IPv6, promote the file + * address to IPv6 and try to match that way. + */ +#ifdef HAVE_IPV6 + if (addr.ss_family == AF_INET && + port->raddr.addr.ss_family == AF_INET6) + { + promote_v4_to_v6_addr(&addr); + promote_v4_to_v6_mask(&mask); + } + else +#endif /* HAVE_IPV6 */ + { + /* Line doesn't match client port, so ignore it. */ + return; + } + } + + /* Ignore line if client port is not in the matching addr range. */ + if (!rangeSockAddr(&port->raddr.addr, &addr, &mask)) + return; + /* Read the rest of the line. */ line = lnext(line); if (!line) @@ -712,16 +740,6 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) parse_hba_auth(line, &port->auth_method, &port->auth_arg, error_p); if (*error_p) goto hba_syntax; - - /* Must meet network restrictions */ - if (!rangeSockAddr(&port->raddr.addr, - (struct sockaddr_storage *) file_ip_addr->ai_addr, - mask)) - goto hba_freeaddr; - - freeaddrinfo_all(hints.ai_family, file_ip_addr); - if (file_ip_mask) - freeaddrinfo_all(hints.ai_family, file_ip_mask); } else goto hba_syntax; @@ -748,12 +766,6 @@ hba_syntax: line_number))); *error_p = true; - -hba_freeaddr: - if (file_ip_addr) - freeaddrinfo_all(hints.ai_family, file_ip_addr); - if (file_ip_mask) - freeaddrinfo_all(hints.ai_family, file_ip_mask); } @@ -1292,7 +1304,7 @@ ident_inet(const SockAddr remote_addr, { ereport(LOG, (errcode_for_socket_access(), - errmsg("could not connect to IDENT server at address \"%s\", port %s): %m", + errmsg("could not connect to IDENT server at address \"%s\", port %s: %m", remote_addr_s, ident_port))); ident_return = false; goto ident_inet_done; @@ -1312,7 +1324,7 @@ ident_inet(const SockAddr remote_addr, { ereport(LOG, (errcode_for_socket_access(), - errmsg("could not send query to IDENT server at address \"%s\", port %s): %m", + errmsg("could not send query to IDENT server at address \"%s\", port %s: %m", remote_addr_s, ident_port))); ident_return = false; goto ident_inet_done; @@ -1327,7 +1339,7 @@ ident_inet(const SockAddr remote_addr, { ereport(LOG, (errcode_for_socket_access(), - errmsg("could not receive response from IDENT server at address \"%s\", port %s): %m", + errmsg("could not receive response from IDENT server at address \"%s\", port %s: %m", remote_addr_s, ident_port))); ident_return = false; goto ident_inet_done; diff --git a/src/backend/libpq/ip.c b/src/backend/libpq/ip.c index 8ae6c8f7848..1fefbebf14b 100644 --- a/src/backend/libpq/ip.c +++ b/src/backend/libpq/ip.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.19 2003/08/04 02:39:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.19.2.1 2003/09/07 04:36:48 momjian Exp $ * * This file and the IPV6 implementation were initially provided by * Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design @@ -34,7 +34,8 @@ #endif #include <arpa/inet.h> #include <sys/file.h> -#endif + +#endif /* !defined(_MSC_VER) && !defined(__BORLANDC__) */ #include "libpq/ip.h" @@ -265,9 +266,16 @@ getnameinfo_unix(const struct sockaddr_un * sa, int salen, return 0; } + #endif /* HAVE_UNIX_SOCKETS */ +/* + * rangeSockAddr - is addr within the subnet specified by netaddr/netmask ? + * + * Note: caller must already have verified that all three addresses are + * in the same address family; and AF_UNIX addresses are not supported. + */ int rangeSockAddr(const struct sockaddr_storage * addr, const struct sockaddr_storage * netaddr, @@ -287,19 +295,52 @@ rangeSockAddr(const struct sockaddr_storage * addr, return 0; } +static int +rangeSockAddrAF_INET(const struct sockaddr_in * addr, + const struct sockaddr_in * netaddr, + const struct sockaddr_in * netmask) +{ + if (((addr->sin_addr.s_addr ^ netaddr->sin_addr.s_addr) & + netmask->sin_addr.s_addr) == 0) + return 1; + else + return 0; +} + + +#ifdef HAVE_IPV6 +static int +rangeSockAddrAF_INET6(const struct sockaddr_in6 * addr, + const struct sockaddr_in6 * netaddr, + const struct sockaddr_in6 * netmask) +{ + int i; + + for (i = 0; i < 16; i++) + { + if (((addr->sin6_addr.s6_addr[i] ^ netaddr->sin6_addr.s6_addr[i]) & + netmask->sin6_addr.s6_addr[i]) != 0) + return 0; + } + + return 1; +} + +#endif + /* * SockAddr_cidr_mask - make a network mask of the appropriate family * and required number of significant bits * - * Note: Returns a static pointer for the mask, so it's not thread safe, - * and a second call will overwrite the data. + * The resulting mask is placed in *mask, which had better be big enough. + * + * Return value is 0 if okay, -1 if not. */ int -SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family) +SockAddr_cidr_mask(struct sockaddr_storage * mask, char *numbits, int family) { long bits; char *endptr; - static struct sockaddr_storage sock; struct sockaddr_in mask4; #ifdef HAVE_IPV6 @@ -318,15 +359,13 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family) ) return -1; - *mask = &sock; - switch (family) { case AF_INET: mask4.sin_addr.s_addr = htonl((0xffffffffUL << (32 - bits)) & 0xffffffffUL); - memcpy(&sock, &mask4, sizeof(mask4)); + memcpy(mask, &mask4, sizeof(mask4)); break; #ifdef HAVE_IPV6 case AF_INET6: @@ -346,7 +385,7 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family) } bits -= 8; } - memcpy(&sock, &mask6, sizeof(mask6)); + memcpy(mask, &mask6, sizeof(mask6)); break; } #endif @@ -354,38 +393,80 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family) return -1; } - sock.ss_family = family; + mask->ss_family = family; return 0; } -static int -rangeSockAddrAF_INET(const struct sockaddr_in * addr, const struct sockaddr_in * netaddr, - const struct sockaddr_in * netmask) + +#ifdef HAVE_IPV6 + +/* + * promote_v4_to_v6_addr --- convert an AF_INET addr to AF_INET6, using + * the standard convention for IPv4 addresses mapped into IPv6 world + * + * The passed addr is modified in place; be sure it is large enough to + * hold the result! Note that we only worry about setting the fields + * that rangeSockAddr will look at. + */ +void +promote_v4_to_v6_addr(struct sockaddr_storage * addr) { - if (((addr->sin_addr.s_addr ^ netaddr->sin_addr.s_addr) & - netmask->sin_addr.s_addr) == 0) - return 1; - else - return 0; -} + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + uint32 s_addr; + memcpy(&addr4, addr, sizeof(addr4)); + s_addr = ntohl(addr4.sin_addr.s_addr); -#ifdef HAVE_IPV6 -static int -rangeSockAddrAF_INET6(const struct sockaddr_in6 * addr, - const struct sockaddr_in6 * netaddr, - const struct sockaddr_in6 * netmask) + memset(&addr6, 0, sizeof(addr6)); + + addr6.sin6_family = AF_INET6; + + addr6.sin6_addr.s6_addr[10] = 0xff; + addr6.sin6_addr.s6_addr[11] = 0xff; + addr6.sin6_addr.s6_addr[12] = (s_addr >> 24) & 0xFF; + addr6.sin6_addr.s6_addr[13] = (s_addr >> 16) & 0xFF; + addr6.sin6_addr.s6_addr[14] = (s_addr >> 8) & 0xFF; + addr6.sin6_addr.s6_addr[15] = (s_addr) & 0xFF; + + memcpy(addr, &addr6, sizeof(addr6)); +} + +/* + * promote_v4_to_v6_mask --- convert an AF_INET netmask to AF_INET6, using + * the standard convention for IPv4 addresses mapped into IPv6 world + * + * This must be different from promote_v4_to_v6_addr because we want to + * set the high-order bits to 1's not 0's. + * + * The passed addr is modified in place; be sure it is large enough to + * hold the result! Note that we only worry about setting the fields + * that rangeSockAddr will look at. + */ +void +promote_v4_to_v6_mask(struct sockaddr_storage * addr) { + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + uint32 s_addr; int i; - for (i = 0; i < 16; i++) - { - if (((addr->sin6_addr.s6_addr[i] ^ netaddr->sin6_addr.s6_addr[i]) & - netmask->sin6_addr.s6_addr[i]) != 0) - return 0; - } + memcpy(&addr4, addr, sizeof(addr4)); + s_addr = ntohl(addr4.sin_addr.s_addr); - return 1; + memset(&addr6, 0, sizeof(addr6)); + + addr6.sin6_family = AF_INET6; + + for (i = 0; i < 12; i++) + addr6.sin6_addr.s6_addr[i] = 0xff; + + addr6.sin6_addr.s6_addr[12] = (s_addr >> 24) & 0xFF; + addr6.sin6_addr.s6_addr[13] = (s_addr >> 16) & 0xFF; + addr6.sin6_addr.s6_addr[14] = (s_addr >> 8) & 0xFF; + addr6.sin6_addr.s6_addr[15] = (s_addr) & 0xFF; + + memcpy(addr, &addr6, sizeof(addr6)); } -#endif +#endif /* HAVE_IPV6 */ diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample index e5dba788c66..946e573ddc9 100644 --- a/src/backend/libpq/pg_hba.conf.sample +++ b/src/backend/libpq/pg_hba.conf.sample @@ -51,8 +51,7 @@ # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD local all all trust +# IPv4-style local connections: host all all 127.0.0.1 255.255.255.255 trust - -# uncomment these to support IPv6 localhost connections -# host all all ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff trust -# host all all ::ffff:127.0.0.1/128 trust +# IPv6-style local connections: +host all all ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff trust diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index fa1c567df0d..e77fee6417f 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.263 2003/08/08 21:41:43 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.263.2.1 2003/09/07 04:36:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -947,7 +947,7 @@ _copyArrayExpr(ArrayExpr *from) COPY_SCALAR_FIELD(array_typeid); COPY_SCALAR_FIELD(element_typeid); COPY_NODE_FIELD(elements); - COPY_SCALAR_FIELD(ndims); + COPY_SCALAR_FIELD(multidims); return newnode; } @@ -1402,11 +1402,12 @@ _copyTypeName(TypeName *from) return newnode; } -static SortGroupBy * -_copySortGroupBy(SortGroupBy *from) +static SortBy * +_copySortBy(SortBy *from) { - SortGroupBy *newnode = makeNode(SortGroupBy); + SortBy *newnode = makeNode(SortBy); + COPY_SCALAR_FIELD(sortby_kind); COPY_NODE_FIELD(useOp); COPY_NODE_FIELD(node); @@ -2924,8 +2925,8 @@ copyObject(void *from) case T_TypeCast: retval = _copyTypeCast(from); break; - case T_SortGroupBy: - retval = _copySortGroupBy(from); + case T_SortBy: + retval = _copySortBy(from); break; case T_RangeSubselect: retval = _copyRangeSubselect(from); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 5ad5dab1d3c..c10c5e45806 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -18,7 +18,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.207 2003/08/08 21:41:43 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.207.2.1 2003/09/07 04:36:49 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -409,7 +409,7 @@ _equalArrayExpr(ArrayExpr *a, ArrayExpr *b) COMPARE_SCALAR_FIELD(array_typeid); COMPARE_SCALAR_FIELD(element_typeid); COMPARE_NODE_FIELD(elements); - COMPARE_SCALAR_FIELD(ndims); + COMPARE_SCALAR_FIELD(multidims); return true; } @@ -1480,8 +1480,9 @@ _equalTypeCast(TypeCast *a, TypeCast *b) } static bool -_equalSortGroupBy(SortGroupBy *a, SortGroupBy *b) +_equalSortBy(SortBy *a, SortBy *b) { + COMPARE_SCALAR_FIELD(sortby_kind); COMPARE_NODE_FIELD(useOp); COMPARE_NODE_FIELD(node); @@ -2045,8 +2046,8 @@ equal(void *a, void *b) case T_TypeCast: retval = _equalTypeCast(a, b); break; - case T_SortGroupBy: - retval = _equalSortGroupBy(a, b); + case T_SortBy: + retval = _equalSortBy(a, b); break; case T_RangeSubselect: retval = _equalRangeSubselect(a, b); diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index b7c1a370695..6c715054b97 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.217 2003/08/08 21:41:44 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.217.2.1 2003/09/07 04:36:49 momjian Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -785,7 +785,7 @@ _outArrayExpr(StringInfo str, ArrayExpr *node) WRITE_OID_FIELD(array_typeid); WRITE_OID_FIELD(element_typeid); WRITE_NODE_FIELD(elements); - WRITE_INT_FIELD(ndims); + WRITE_BOOL_FIELD(multidims); } static void diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index d261ac7f862..2715202b343 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.161 2003/08/04 02:39:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.161.2.1 2003/09/07 04:36:49 momjian Exp $ * * NOTES * Path and Plan nodes do not have any readfuncs support, because we @@ -659,7 +659,7 @@ _readArrayExpr(void) READ_OID_FIELD(array_typeid); READ_OID_FIELD(element_typeid); READ_NODE_FIELD(elements); - READ_INT_FIELD(ndims); + READ_BOOL_FIELD(multidims); READ_DONE(); } diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 2f7fd02fb4b..3d076cb8457 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.154 2003/08/11 20:46:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.154.2.1 2003/09/07 04:36:49 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -629,8 +629,9 @@ create_unique_plan(Query *root, UniquePath *best_path) tle = get_tle_by_resno(my_tlist, groupColIdx[groupColPos]); Assert(tle != NULL); - sortList = addTargetToSortList(NULL, tle, sortList, - my_tlist, NIL, false); + sortList = addTargetToSortList(NULL, tle, + sortList, my_tlist, + SORTBY_ASC, NIL, false); } plan = (Plan *) make_sort_from_sortclauses(root, my_tlist, subplan, sortList); @@ -943,6 +944,10 @@ create_nestloop_plan(Query *root, otherclauses = NIL; } + /* Sort clauses into best execution order */ + joinclauses = order_qual_clauses(root, joinclauses); + otherclauses = order_qual_clauses(root, otherclauses); + join_plan = make_nestloop(tlist, joinclauses, otherclauses, @@ -994,6 +999,11 @@ create_mergejoin_plan(Query *root, mergeclauses = get_switched_clauses(best_path->path_mergeclauses, best_path->jpath.outerjoinpath->parent->relids); + /* Sort clauses into best execution order */ + /* NB: do NOT reorder the mergeclauses */ + joinclauses = order_qual_clauses(root, joinclauses); + otherclauses = order_qual_clauses(root, otherclauses); + /* * Create explicit sort nodes for the outer and inner join paths if * necessary. The sort cost was already accounted for in the path. @@ -1077,6 +1087,11 @@ create_hashjoin_plan(Query *root, hashclauses = get_switched_clauses(best_path->path_hashclauses, best_path->jpath.outerjoinpath->parent->relids); + /* Sort clauses into best execution order */ + joinclauses = order_qual_clauses(root, joinclauses); + otherclauses = order_qual_clauses(root, otherclauses); + hashclauses = order_qual_clauses(root, hashclauses); + /* * Extract the inner hash keys (right-hand operands of the * hashclauses) to put in the Hash node. diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 9eea1c8d20e..5bf6e061572 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.159 2003/08/04 02:40:01 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.159.2.1 2003/09/07 04:36:49 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1327,7 +1327,9 @@ hash_safe_grouping(Query *parse) Operator optup; bool oprcanhash; - optup = equality_oper(tle->resdom->restype, false); + optup = equality_oper(tle->resdom->restype, true); + if (!optup) + return false; oprcanhash = ((Form_pg_operator) GETSTRUCT(optup))->oprcanhash; ReleaseSysCache(optup); if (!oprcanhash) diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index b95002ef43e..35882c6024d 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.152 2003/08/08 21:41:55 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.152.2.1 2003/09/07 04:36:49 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -1515,7 +1515,7 @@ eval_const_expressions_mutator(Node *node, List *active_fns) newarray->array_typeid = arrayexpr->array_typeid; newarray->element_typeid = arrayexpr->element_typeid; newarray->elements = FastListValue(&newelems); - newarray->ndims = arrayexpr->ndims; + newarray->multidims = arrayexpr->multidims; if (all_const) return (Node *) evaluate_expr((Expr *) newarray, diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index d3060b76c7a..518bba71983 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.428 2003/08/04 02:40:01 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.428.2.1 2003/09/07 04:36:50 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -108,6 +108,7 @@ static void doNegateFloat(Value *v); DropBehavior dbehavior; OnCommitAction oncommit; List *list; + FastList fastlist; Node *node; Value *value; ColumnRef *columnref; @@ -115,7 +116,7 @@ static void doNegateFloat(Value *v); TypeName *typnam; DefElem *defelt; - SortGroupBy *sortgroupby; + SortBy *sortby; JoinExpr *jexpr; IndexElem *ielem; Alias *alias; @@ -189,7 +190,7 @@ static void doNegateFloat(Value *v); database_name access_method_clause access_method attr_name index_name name function_name file_name -%type <list> func_name handler_name qual_Op qual_all_Op OptUseOp +%type <list> func_name handler_name qual_Op qual_all_Op opt_class opt_validator %type <range> qualified_name OptConstrFromTable @@ -278,7 +279,7 @@ static void doNegateFloat(Value *v); %type <value> NumericOnly FloatOnly IntegerOnly %type <columnref> columnref %type <alias> alias_clause -%type <sortgroupby> sortby +%type <sortby> sortby %type <ielem> index_elem %type <node> table_ref %type <jexpr> joined_table @@ -293,7 +294,7 @@ static void doNegateFloat(Value *v); Bit ConstBit BitWithLength BitWithoutLength %type <str> character %type <str> extract_arg -%type <str> opt_charset opt_collate +%type <str> opt_charset %type <ival> opt_numeric opt_decimal %type <boolean> opt_varying opt_timezone @@ -440,7 +441,6 @@ static void doNegateFloat(Value *v); %right UMINUS %left '[' ']' %left '(' ')' -%left COLLATE %left TYPECAST %left '.' /* @@ -1460,19 +1460,13 @@ TableElement: | TableConstraint { $$ = $1; } ; -columnDef: ColId Typename ColQualList opt_collate +columnDef: ColId Typename ColQualList { ColumnDef *n = makeNode(ColumnDef); n->colname = $1; n->typename = $2; n->constraints = $3; n->is_local = true; - - if ($4 != NULL) - ereport(NOTICE, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("CREATE TABLE / COLLATE is not yet implemented; clause ignored"))); - $$ = (Node *)n; } ; @@ -3842,17 +3836,12 @@ DropdbStmt: DROP DATABASE database_name *****************************************************************************/ CreateDomainStmt: - CREATE DOMAIN_P any_name opt_as Typename ColQualList opt_collate + CREATE DOMAIN_P any_name opt_as Typename ColQualList { CreateDomainStmt *n = makeNode(CreateDomainStmt); n->domainname = $3; n->typename = $5; n->constraints = $6; - - if ($7 != NULL) - ereport(NOTICE, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("CREATE DOMAIN / COLLATE is not yet implemented; clause ignored"))); $$ = (Node *)n; } ; @@ -4577,21 +4566,34 @@ sortby_list: | sortby_list ',' sortby { $$ = lappend($1, $3); } ; -sortby: a_expr OptUseOp +sortby: a_expr USING qual_all_Op { - $$ = makeNode(SortGroupBy); + $$ = makeNode(SortBy); $$->node = $1; - $$->useOp = $2; + $$->sortby_kind = SORTBY_USING; + $$->useOp = $3; + } + | a_expr ASC + { + $$ = makeNode(SortBy); + $$->node = $1; + $$->sortby_kind = SORTBY_ASC; + $$->useOp = NIL; + } + | a_expr DESC + { + $$ = makeNode(SortBy); + $$->node = $1; + $$->sortby_kind = SORTBY_DESC; + $$->useOp = NIL; + } + | a_expr + { + $$ = makeNode(SortBy); + $$->node = $1; + $$->sortby_kind = SORTBY_ASC; /* default */ + $$->useOp = NIL; } - ; - -OptUseOp: USING qual_all_Op { $$ = $2; } - | ASC - { $$ = makeList1(makeString("<")); } - | DESC - { $$ = makeList1(makeString(">")); } - | /*EMPTY*/ - { $$ = makeList1(makeString("<")); /*default*/ } ; @@ -5449,11 +5451,6 @@ opt_charset: | /*EMPTY*/ { $$ = NULL; } ; -opt_collate: - COLLATE ColId { $$ = $2; } - | /*EMPTY*/ { $$ = NULL; } - ; - ConstDatetime: TIMESTAMP '(' Iconst ')' opt_timezone { @@ -5739,15 +5736,6 @@ qual_all_Op: a_expr: c_expr { $$ = $1; } | a_expr TYPECAST Typename { $$ = makeTypeCast($1, $3); } - | a_expr COLLATE ColId - { - FuncCall *n = makeNode(FuncCall); - n->funcname = SystemFuncName($3); - n->args = makeList1($1); - n->agg_star = FALSE; - n->agg_distinct = FALSE; - $$ = (Node *) n; - } | a_expr AT TIME ZONE c_expr { FuncCall *n = makeNode(FuncCall); @@ -6706,8 +6694,18 @@ opt_indirection: { $$ = NIL; } ; -expr_list: a_expr { $$ = makeList1($1); } - | expr_list ',' a_expr { $$ = lappend($1, $3); } +expr_list: a_expr + { + FastList *dst = (FastList *) &$$; + makeFastList1(dst, $1); + } + | expr_list ',' a_expr + { + FastList *dst = (FastList *) &$$; + FastList *src = (FastList *) &$1; + *dst = *src; + FastAppend(dst, $3); + } ; extract_list: diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index ebc3ed23eec..48d7788b09d 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.121 2003/08/07 19:20:22 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.121.2.1 2003/09/07 04:36:50 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1295,7 +1295,7 @@ transformSortClause(ParseState *pstate, foreach(olitem, orderlist) { - SortGroupBy *sortby = lfirst(olitem); + SortBy *sortby = lfirst(olitem); TargetEntry *tle; tle = findTargetlistEntry(pstate, sortby->node, @@ -1303,7 +1303,9 @@ transformSortClause(ParseState *pstate, sortlist = addTargetToSortList(pstate, tle, sortlist, targetlist, - sortby->useOp, resolveUnknown); + sortby->sortby_kind, + sortby->useOp, + resolveUnknown); } return sortlist; @@ -1409,7 +1411,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist, { *sortClause = addTargetToSortList(pstate, tle, *sortClause, targetlist, - NIL, true); + SORTBY_ASC, NIL, true); /* * Probably, the tle should always have been added at the @@ -1457,7 +1459,8 @@ addAllTargetsToSortList(ParseState *pstate, List *sortlist, if (!tle->resdom->resjunk) sortlist = addTargetToSortList(pstate, tle, sortlist, targetlist, - NIL, resolveUnknown); + SORTBY_ASC, NIL, + resolveUnknown); } return sortlist; } @@ -1478,7 +1481,8 @@ addAllTargetsToSortList(ParseState *pstate, List *sortlist, List * addTargetToSortList(ParseState *pstate, TargetEntry *tle, List *sortlist, List *targetlist, - List *opname, bool resolveUnknown) + int sortby_kind, List *sortby_opname, + bool resolveUnknown) { /* avoid making duplicate sortlist entries */ if (!targetIsInSortList(tle, sortlist)) @@ -1499,13 +1503,25 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle, sortcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist); - if (opname) - sortcl->sortop = compatible_oper_opid(opname, - restype, - restype, - false); - else - sortcl->sortop = ordering_oper_opid(restype); + switch (sortby_kind) + { + case SORTBY_ASC: + sortcl->sortop = ordering_oper_opid(restype); + break; + case SORTBY_DESC: + sortcl->sortop = reverse_ordering_oper_opid(restype); + break; + case SORTBY_USING: + Assert(sortby_opname != NIL); + sortcl->sortop = compatible_oper_opid(sortby_opname, + restype, + restype, + false); + break; + default: + elog(ERROR, "unrecognized sortby_kind: %d", sortby_kind); + break; + } sortlist = lappend(sortlist, sortcl); } diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 64718a48699..3838999b0a8 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.160 2003/08/04 02:40:01 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.160.2.1 2003/09/07 04:36:50 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -748,7 +748,6 @@ transformExpr(ParseState *pstate, Node *expr) List *element; Oid array_type; Oid element_type; - int ndims; /* Transform the element expressions */ foreach(element, a->elements) @@ -781,11 +780,13 @@ transformExpr(ParseState *pstate, Node *expr) if (array_type != InvalidOid) { /* Elements are presumably of scalar type */ - ndims = 1; + newa->multidims = false; } else { /* Must be nested array expressions */ + newa->multidims = true; + array_type = element_type; element_type = get_element_type(array_type); if (!OidIsValid(element_type)) @@ -793,47 +794,11 @@ transformExpr(ParseState *pstate, Node *expr) (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("could not find array type for datatype %s", format_type_be(array_type)))); - - /* - * make sure the element expressions all have the same - * number of dimensions - */ - ndims = 0; - foreach(element, newcoercedelems) - { - ArrayExpr *e = (ArrayExpr *) lfirst(element); - - if (!IsA(e, ArrayExpr)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multidimensional ARRAY[] must be built from nested array expressions"))); - if (ndims == 0) - ndims = e->ndims; - else if (e->ndims != ndims) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("nested array expressions must have common number of dimensions"))); - if (e->element_typeid != element_type) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("nested array expressions must have common element type"))); - - } - /* increment the number of dimensions */ - ndims++; - - /* make sure we don't have too many dimensions now */ - if (ndims > MAXDIM) - ereport(ERROR, - (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("number of array dimensions exceeds the maximum allowed, %d", - MAXDIM))); } newa->array_typeid = array_type; newa->element_typeid = element_type; newa->elements = newcoercedelems; - newa->ndims = ndims; result = (Node *) newa; break; diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c index e5d2ab2d05f..d0771920540 100644 --- a/src/backend/parser/parse_oper.c +++ b/src/backend/parser/parse_oper.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.73 2003/08/04 02:40:02 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.73.2.1 2003/09/07 04:36:50 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -26,6 +26,7 @@ #include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/syscache.h" +#include "utils/typcache.h" static Oid binary_oper_exact(Oid arg1, Oid arg2, @@ -135,52 +136,49 @@ LookupOperNameTypeNames(List *opername, TypeName *oprleft, Operator equality_oper(Oid argtype, bool noError) { + TypeCacheEntry *typentry; + Oid oproid; Operator optup; - Oid elem_type; + + /* + * Look for an "=" operator for the datatype. We require it to be + * an exact or binary-compatible match, since most callers are not + * prepared to cope with adding any run-time type coercion steps. + */ + typentry = lookup_type_cache(argtype, TYPECACHE_EQ_OPR); + oproid = typentry->eq_opr; /* * If the datatype is an array, then we can use array_eq ... but only - * if there is a suitable equality operator for the element type. (We - * must run this test first, since compatible_oper will find array_eq, - * but would not notice the lack of an element operator.) + * if there is a suitable equality operator for the element type. + * (This check is not in the raw typcache.c code ... should it be?) */ - elem_type = get_element_type(argtype); - if (OidIsValid(elem_type)) + if (oproid == ARRAY_EQ_OP) { - optup = equality_oper(elem_type, true); - if (optup != NULL) + Oid elem_type = get_element_type(argtype); + + if (OidIsValid(elem_type)) { - ReleaseSysCache(optup); - return SearchSysCache(OPEROID, - ObjectIdGetDatum(ARRAY_EQ_OP), - 0, 0, 0); + optup = equality_oper(elem_type, true); + if (optup != NULL) + ReleaseSysCache(optup); + else + oproid = InvalidOid; /* element type has no "=" */ } + else + oproid = InvalidOid; /* bogus array type? */ } - else - { - /* - * Look for an "=" operator for the datatype. We require it to be - * an exact or binary-compatible match, since most callers are not - * prepared to cope with adding any run-time type coercion steps. - */ - optup = compatible_oper(makeList1(makeString("=")), - argtype, argtype, true); - if (optup != NULL) - { - /* - * Only believe that it's equality if it's mergejoinable, - * hashjoinable, or uses eqsel() as oprrest. - */ - Form_pg_operator pgopform = (Form_pg_operator) GETSTRUCT(optup); - - if (OidIsValid(pgopform->oprlsortop) || - pgopform->oprcanhash || - pgopform->oprrest == F_EQSEL) - return optup; - ReleaseSysCache(optup); - } + if (OidIsValid(oproid)) + { + optup = SearchSysCache(OPEROID, + ObjectIdGetDatum(oproid), + 0, 0, 0); + if (optup == NULL) /* should not fail */ + elog(ERROR, "cache lookup failed for operator %u", oproid); + return optup; } + if (!noError) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), @@ -197,53 +195,119 @@ equality_oper(Oid argtype, bool noError) Operator ordering_oper(Oid argtype, bool noError) { + TypeCacheEntry *typentry; + Oid oproid; Operator optup; - Oid elem_type; + + /* + * Look for a "<" operator for the datatype. We require it to be + * an exact or binary-compatible match, since most callers are not + * prepared to cope with adding any run-time type coercion steps. + * + * Note: the search algorithm used by typcache.c ensures that if a "<" + * operator is returned, it will be consistent with the "=" operator + * returned by equality_oper. This is critical for sorting and grouping + * purposes. + */ + typentry = lookup_type_cache(argtype, TYPECACHE_LT_OPR); + oproid = typentry->lt_opr; /* * If the datatype is an array, then we can use array_lt ... but only - * if there is a suitable ordering operator for the element type. (We - * must run this test first, since the code below would find array_lt - * if there's an element = operator, but would not notice the lack of - * an element < operator.) + * if there is a suitable less-than operator for the element type. + * (This check is not in the raw typcache.c code ... should it be?) */ - elem_type = get_element_type(argtype); - if (OidIsValid(elem_type)) + if (oproid == ARRAY_LT_OP) { - optup = ordering_oper(elem_type, true); - if (optup != NULL) + Oid elem_type = get_element_type(argtype); + + if (OidIsValid(elem_type)) { - ReleaseSysCache(optup); - return SearchSysCache(OPEROID, - ObjectIdGetDatum(ARRAY_LT_OP), - 0, 0, 0); + optup = ordering_oper(elem_type, true); + if (optup != NULL) + ReleaseSysCache(optup); + else + oproid = InvalidOid; /* element type has no "<" */ } + else + oproid = InvalidOid; /* bogus array type? */ } - else + + if (OidIsValid(oproid)) { - /* - * Find the type's equality operator, and use its lsortop (it - * *must* be mergejoinable). We use this definition because for - * sorting and grouping purposes, it's important that the equality - * and ordering operators are consistent. - */ - optup = equality_oper(argtype, noError); - if (optup != NULL) - { - Oid lsortop; + optup = SearchSysCache(OPEROID, + ObjectIdGetDatum(oproid), + 0, 0, 0); + if (optup == NULL) /* should not fail */ + elog(ERROR, "cache lookup failed for operator %u", oproid); + return optup; + } - lsortop = ((Form_pg_operator) GETSTRUCT(optup))->oprlsortop; - ReleaseSysCache(optup); - if (OidIsValid(lsortop)) - { - optup = SearchSysCache(OPEROID, - ObjectIdGetDatum(lsortop), - 0, 0, 0); - if (optup != NULL) - return optup; - } + if (!noError) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("could not identify an ordering operator for type %s", + format_type_be(argtype)), + errhint("Use an explicit ordering operator or modify the query."))); + return NULL; +} + +/* + * reverse_ordering_oper - identify DESC sort operator (">") for a datatype + * + * On failure, return NULL if noError, else report a standard error + */ +Operator +reverse_ordering_oper(Oid argtype, bool noError) +{ + TypeCacheEntry *typentry; + Oid oproid; + Operator optup; + + /* + * Look for a ">" operator for the datatype. We require it to be + * an exact or binary-compatible match, since most callers are not + * prepared to cope with adding any run-time type coercion steps. + * + * Note: the search algorithm used by typcache.c ensures that if a ">" + * operator is returned, it will be consistent with the "=" operator + * returned by equality_oper. This is critical for sorting and grouping + * purposes. + */ + typentry = lookup_type_cache(argtype, TYPECACHE_GT_OPR); + oproid = typentry->gt_opr; + + /* + * If the datatype is an array, then we can use array_gt ... but only + * if there is a suitable greater-than operator for the element type. + * (This check is not in the raw typcache.c code ... should it be?) + */ + if (oproid == ARRAY_GT_OP) + { + Oid elem_type = get_element_type(argtype); + + if (OidIsValid(elem_type)) + { + optup = reverse_ordering_oper(elem_type, true); + if (optup != NULL) + ReleaseSysCache(optup); + else + oproid = InvalidOid; /* element type has no ">" */ } + else + oproid = InvalidOid; /* bogus array type? */ } + + if (OidIsValid(oproid)) + { + optup = SearchSysCache(OPEROID, + ObjectIdGetDatum(oproid), + 0, 0, 0); + if (optup == NULL) /* should not fail */ + elog(ERROR, "cache lookup failed for operator %u", oproid); + return optup; + } + if (!noError) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), @@ -286,16 +350,16 @@ ordering_oper_opid(Oid argtype) } /* - * ordering_oper_funcid - convenience routine for oprfuncid(ordering_oper()) + * reverse_ordering_oper_opid - convenience routine for oprid(reverse_ordering_oper()) */ Oid -ordering_oper_funcid(Oid argtype) +reverse_ordering_oper_opid(Oid argtype) { Operator optup; Oid result; - optup = ordering_oper(argtype, false); - result = oprfuncid(optup); + optup = reverse_ordering_oper(argtype, false); + result = oprid(optup); ReleaseSysCache(optup); return result; } diff --git a/src/backend/po/ru.po b/src/backend/po/ru.po index f9fca185eab..10edcd01087 100644 --- a/src/backend/po/ru.po +++ b/src/backend/po/ru.po @@ -1,9 +1,10 @@ # ru.po # POSTGRES Translated Messages into the Russian Language (KOI8-R) # -# $Header: /cvsroot/pgsql/src/backend/po/Attic/ru.po,v 1.11 2003/06/28 22:31:00 petere Exp $ +# $Header: /cvsroot/pgsql/src/backend/po/Attic/ru.po,v 1.11.2.1 2003/09/07 04:36:50 momjian Exp $ # -# Changelog: +# ChangeLog: +# - July - August 23, 2003: updates for 7.4.x; <mokhov@cs.concordia.ca> # - January 2, 2003: Fuzzy Fixes, Serguei A. Mokhov <mokhov@cs.concordia.ca> # - October 12, 2002: Post-7.3 beta 2, Fuzzy Fixes, Serguei A. Mokhov <mokhov@cs.concordia.ca> # - September 14, 2002: Post-7.3 beta 1, Take II, Serguei A. Mokhov <mokhov@cs.concordia.ca> @@ -12,8297 +13,5240 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 7.3.x\n" -"POT-Creation-Date: 2003-01-02 13:00-0500\n" -"PO-Revision-Date: 2003-01-02 13:33-0500\n" +"Project-Id-Version: PostgreSQL 7.4.x\n" +"POT-Creation-Date: 2003-07-26 04:18-0300\n" +"PO-Revision-Date: 2003-08-23 18:25-0500\n" "Last-Translator: Serguei A. Mokhov <mokhov@cs.concordia.ca>\n" "Language-Team: pgsql-rus <pgsql-rus@yahoogroups.com>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=koi8-r\n" "Content-Transfer-Encoding: 8bit\n" -#: access/common/heaptuple.c:179 -msgid "heap_attisnull: zero attnum disallowed" -msgstr "heap_attisnull: нулевой attnum не дозволен" - -#: access/common/heaptuple.c:182 -msgid "heap_attisnull: undefined negative attnum" -msgstr "heap_attisnull: отрицательный attnum не определён" - -#: access/common/heaptuple.c:460 -#, c-format -msgid "heap_getsysattr: invalid attnum %d" -msgstr "heap_getsysattr: неверный attnum: %d" - -#: access/common/heaptuple.c:584 -#, c-format -msgid "heap_formtuple: numberOfAttributes %d exceeds limit %d" -msgstr "" -"heap_formtuple: numberOfAttributes (число атрибутов) %d превышает лимит %d" - -#: access/common/heaptuple.c:687 -#, c-format -msgid "heap_modifytuple: repl is \\%3d" -msgstr "heap_modifytuple: значение repl: \\%3d" - -#: access/common/indextuple.c:55 -#, c-format -msgid "index_formtuple: numberOfAttributes %d > %d" -msgstr "index_formtuple: numberOfAttributes (число атрибутов) для %d > %d" - -#: access/common/indextuple.c:161 -#, c-format -msgid "index_formtuple: data takes %lu bytes, max is %d" -msgstr "index_formtuple: данные занимают %lu байт(ов), при максимуме: %d" - -#: access/common/tupdesc.c:420 -#, c-format -msgid "Unable to look up type id %u" -msgstr "Тип с ID %u не найден" - -#: access/common/tupdesc.c:646 executor/nodeFunctionscan.c:204 -#: parser/parse_relation.c:931 parser/parse_relation.c:1286 -#: parser/parse_relation.c:1596 -#, c-format -msgid "Invalid typrelid for complex type %u" -msgstr "Неверный typrelid для сложного типа %u" - -#: access/common/tupdesc.c:660 access/common/tupdesc.c:683 -msgid "TypeGetTupleDesc: number of aliases does not match number of attributes" -msgstr "TypeGetTupleDesc: число алиасов не совпадает с числом атрибутов" - -#: access/common/tupdesc.c:679 -msgid "TypeGetTupleDesc: no column alias was provided" -msgstr "TypeGetTupleDesc: алиасы колонок не указаны" - -#: access/common/tupdesc.c:698 -msgid "Unable to determine tuple description for function returning \"record\"" -msgstr "" -"Не в состоянии определить описание строки для функции возпращающей тип " -"\"record\"" - -#: access/common/tupdesc.c:700 catalog/pg_proc.c:463 -#: executor/nodeFunctionscan.c:234 parser/parse_relation.c:1383 -#: parser/parse_relation.c:1637 -msgid "Unknown kind of return type specified for function" -msgstr "Указан неизвестный тип возвращаемого значения для фунции" - -#: access/gist/gist.c:171 access/hash/hash.c:72 access/nbtree/nbtree.c:129 -#: access/rtree/rtree.c:128 -#, c-format -msgid "%s already contains data" -msgstr "%s уже содержит данные" - -#: access/gist/gist.c:399 access/gist/gist.c:606 -#, c-format -msgid "gist: failed to add index item to %s" -msgstr "gist: не получилось добавить элемент индекса к %s" - -#: access/gist/gist.c:1666 -#, c-format -msgid "initGISTstate: numberOfAttributes %d > %d" -msgstr "initGISTstate: numberOfAttributes для %d > %d" - -#: access/gist/gist.c:1928 +#: access/common/indextuple.c:57 #, c-format -msgid "%sPage: %d %s blk: %d maxoff: %d free: %d" -msgstr "%sСтр.: %d %s блк: %d макс для: %d свободно: %d" - -#: access/gist/gist.c:1938 -#, c-format -msgid "%s Tuple. blk: %d size: %d" -msgstr "%s Запись. блк: %d размер: %d" - -#: access/gist/gist.c:1953 -msgid "gist_redo: unimplemented" -msgstr "gist_redo: не поддерживается" - -#: access/gist/gist.c:1959 -msgid "gist_undo: unimplemented" -msgstr "gist_undo: не поддерживается" - -#: access/gist/gistscan.c:254 -#, c-format -msgid "GiST scan list corrupted -- cannot find 0x%p" -msgstr "" - -#: access/gist/gistscan.c:390 -#, c-format -msgid "Bad operation in GiST scan adjust: %d" -msgstr "" - -#: access/hash/hash.c:504 -msgid "hash_redo: unimplemented" -msgstr "hash_redo: ещё не сделано" - -#: access/hash/hash.c:510 -msgid "hash_undo: unimplemented" -msgstr "hash_undo: ещё не сделано" - -#: access/hash/hashinsert.c:51 -msgid "Hash indices valid for only one index key." -msgstr "" - -#: access/hash/hashinsert.c:166 -msgid "hash item too large" -msgstr "" - -#: access/hash/hashinsert.c:231 -#, c-format -msgid "_hash_pgaddtup: failed to add index item to %s" -msgstr "_hash_pgaddtup: не удалось добавить элемент индекса к %s" - -#: access/hash/hashovfl.c:61 -msgid "_hash_addovflpage: problem with _hash_getovfladdr." -msgstr "_hash_addovflpage: проблема с _hash_getovfladdr." - -#: access/hash/hashovfl.c:196 -msgid "overflow_page: problem with _hash_initbitmap." -msgstr "overflow_page: проблема с _hash_initbitmap." - -#: access/hash/hashovfl.c:568 -#, c-format -msgid "_hash_squeezebucket: failed to add index item to %s" -msgstr "_hash_squeezebucket: не удалось добавить элемент индекса к %s" - -#: access/hash/hashpage.c:93 -#, c-format -msgid "Cannot initialize non-empty hash table %s" -msgstr "" - -#: access/hash/hashpage.c:151 -msgid "Problem with _hash_initbitmap." -msgstr "Проблема с _hash_initbitmap." - -#: access/hash/hashpage.c:196 -msgid "_hash_getbuf: internal error: hash AM does not use P_NEW" -msgstr "" +msgid "number of index attributes %d exceeds limit, %d" +msgstr "число идексированных атрибутов: %d превышает лимит: %d" -#: access/hash/hashpage.c:204 +#: access/common/indextuple.c:165 #, c-format -msgid "_hash_getbuf: invalid access (%d) on new blk: %s" -msgstr "" - -#: access/hash/hashpage.c:231 -#, c-format -msgid "_hash_relbuf: invalid access (%d) on blk %x: %s" -msgstr "" - -#: access/hash/hashpage.c:290 -#, c-format -msgid "_hash_chgbufaccess: invalid access (%d) on blk %x: %s" -msgstr "" - -#: access/hash/hashpage.c:325 -#, c-format -msgid "_hash_setpagelock: invalid access (%d) on blk %x: %s" -msgstr "" - -#: access/hash/hashpage.c:349 -#, c-format -msgid "_hash_unsetpagelock: invalid access (%d) on blk %x: %s" -msgstr "" - -#: access/hash/hashpage.c:537 access/hash/hashpage.c:674 -#, c-format -msgid "_hash_splitpage: empty overflow page %d" -msgstr "" - -#: access/hash/hashpage.c:576 -#, c-format -msgid "_hash_splitpage: empty ovfl page %d!" -msgstr "" - -#: access/hash/hashpage.c:629 -#, c-format -msgid "_hash_splitpage: failed to add index item to %s" -msgstr "" - -#: access/hash/hashscan.c:105 -#, c-format -msgid "hash scan list trashed; can't find 0x%p" -msgstr "" - -#: access/hash/hashutil.c:81 -msgid "hash indices cannot include null keys" -msgstr "" - -#: access/heap/tuptoaster.c:899 -msgid "Failed to build TOAST tuple" -msgstr "" - -#: access/heap/tuptoaster.c:915 -msgid "Failed to insert index entry for TOAST tuple" -msgstr "" - -#: access/heap/tuptoaster.c:1074 access/heap/tuptoaster.c:1254 -#, c-format -msgid "unexpected chunk number %d (expected %d) for toast value %u" -msgstr "" - -#: access/heap/tuptoaster.c:1080 access/heap/tuptoaster.c:1087 -#: access/heap/tuptoaster.c:1260 access/heap/tuptoaster.c:1267 -#, c-format -msgid "unexpected chunk size %d in chunk %d for toast value %u" -msgstr "" - -#: access/heap/tuptoaster.c:1092 -#, c-format -msgid "unexpected chunk number %d for toast value %u" -msgstr "" - -#: access/heap/tuptoaster.c:1110 access/heap/tuptoaster.c:1294 -#, c-format -msgid "missing chunk number %d for toast value %u" -msgstr "" - -#: access/heap/heapam.c:144 -#, c-format -msgid "heapgettup(%s, tid=0x%x[%d,%d], dir=%d, ...)" -msgstr "" - -#: access/heap/heapam.c:150 -#, c-format -msgid "heapgettup(%s, tid=0x%x, dir=%d, ...)" -msgstr "" - -#: access/heap/heapam.c:153 -#, c-format -msgid "heapgettup(..., b=0x%x, nkeys=%d, key=0x%x" -msgstr "" - -#: access/heap/heapam.c:155 -#, c-format -msgid "heapgettup: relation(%c)=`%s', %p" -msgstr "" - -#: access/heap/heapam.c:203 access/heap/heapam.c:238 access/heap/heapam.c:278 -#: access/heap/heapam.c:372 -msgid "heapgettup: failed ReadBuffer" -msgstr "heapgettup: ReadBuffer не удался" +msgid "index tuple requires %lu bytes, maximum size is %lu" +msgstr "строка индекса требуеи байт: %lu, при максимуме: %lu" -#: access/heap/heapam.c:474 -#, c-format -msgid "Relation %u does not exist" -msgstr "" - -#: access/heap/heapam.c:553 catalog/namespace.c:189 tcop/utility.c:154 -#, c-format -msgid "Relation \"%s\" does not exist" -msgstr "" - -#: access/heap/heapam.c:605 access/heap/heapam.c:634 access/heap/heapam.c:663 -#, c-format -msgid "%s is an index relation" -msgstr "" - -#: access/heap/heapam.c:608 access/heap/heapam.c:637 access/heap/heapam.c:666 -#, c-format -msgid "%s is a special relation" -msgstr "" - -#: access/heap/heapam.c:611 access/heap/heapam.c:640 access/heap/heapam.c:669 -#, c-format -msgid "%s is a composite type" -msgstr "" - -#: access/heap/heapam.c:698 -msgid "heap_beginscan: !RelationIsValid(relation)" -msgstr "" - -#: access/heap/heapam.c:812 -#, c-format -msgid "heap_getnext([%s,nkeys=%d],dir=%d) called" -msgstr "" - -#: access/heap/heapam.c:816 -msgid "heap_getnext returning EOS" -msgstr "heap_getnext возращает EOS" - -#: access/heap/heapam.c:819 -msgid "heap_getnext returning tuple" -msgstr "" - -#: access/heap/heapam.c:842 -msgid "heap_getnext: NULL relscan" -msgstr "" - -#: access/heap/heapam.c:932 -#, c-format -msgid "heap_fetch: ReadBuffer(%s, %lu) failed" -msgstr "heap_fetch: ReadBuffer(%s, %lu) не удался" - -#: access/heap/heapam.c:1042 -#, c-format -msgid "heap_get_latest_tid: %s relation: ReadBuffer(%lx) failed" -msgstr "" - -#: access/heap/heapam.c:1284 -msgid "heap_delete: failed ReadBuffer" -msgstr "heap_delete: ReadBuffer не удался" - -#: access/heap/heapam.c:1303 -msgid "heap_delete: (am)invalid tid" -msgstr "" - -#: access/heap/heapam.c:1436 -msgid "simple_heap_delete: tuple already updated by self" -msgstr "" - -#: access/heap/heapam.c:1444 -msgid "simple_heap_delete: tuple concurrently updated" -msgstr "" - -#: access/heap/heapam.c:1448 executor/execMain.c:1324 -#, c-format -msgid "Unknown status %u from heap_delete" -msgstr "" - -#: access/heap/heapam.c:1482 -msgid "heap_update: failed ReadBuffer" -msgstr "heap_update: ReadBuffer не удался" - -#: access/heap/heapam.c:1507 -msgid "heap_update: (am)invalid tid" -msgstr "" - -#: access/heap/heapam.c:1770 -msgid "simple_heap_update: tuple already updated by self" -msgstr "" - -#: access/heap/heapam.c:1778 -msgid "simple_heap_update: tuple concurrently updated" -msgstr "" - -#: access/heap/heapam.c:1782 executor/execMain.c:1462 -#, c-format -msgid "Unknown status %u from heap_update" -msgstr "" - -#: access/heap/heapam.c:1806 -msgid "heap_mark4update: failed ReadBuffer" -msgstr "heap_mark4update: ReadBuffer не удался" - -#: access/heap/heapam.c:1823 -msgid "heap_mark4update: (am)invalid tid" -msgstr "" - -#: access/heap/heapam.c:2123 -msgid "heap_clean_redo: no block" -msgstr "" - -#: access/heap/heapam.c:2127 -msgid "heap_clean_redo: uninitialized page" -msgstr "" - -#: access/heap/heapam.c:2185 -#, c-format -msgid "heap_delete_%sdo: no block" -msgstr "" - -#: access/heap/heapam.c:2189 -#, c-format -msgid "heap_delete_%sdo: uninitialized page" -msgstr "" - -#: access/heap/heapam.c:2201 -msgid "heap_delete_undo: bad page LSN" -msgstr "" - -#: access/heap/heapam.c:2208 -#, c-format -msgid "heap_delete_%sdo: invalid lp" -msgstr "heap_delete_%sdo: не верный lp" - -#: access/heap/heapam.c:2228 -msgid "heap_delete_undo: unimplemented" -msgstr "" - -#: access/heap/heapam.c:2256 -#, c-format -msgid "heap_insert_%sdo: uninitialized page" -msgstr "" - -#: access/heap/heapam.c:2280 -msgid "heap_insert_redo: invalid max offset number" -msgstr "" - -#: access/heap/heapam.c:2304 -msgid "heap_insert_redo: failed to add tuple" -msgstr "" - -#: access/heap/heapam.c:2314 -msgid "heap_insert_undo: bad page LSN" -msgstr "" - -#: access/heap/heapam.c:2316 -msgid "heap_insert_undo: unimplemented" -msgstr "" - -#: access/heap/heapam.c:2347 -#, c-format -msgid "heap_update_%sdo: no block" -msgstr "heap_update_%sdo: нет блока" - -#: access/heap/heapam.c:2351 -#, c-format -msgid "heap_update_%sdo: uninitialized old page" -msgstr "" - -#: access/heap/heapam.c:2365 -msgid "heap_update_undo: bad old tuple page LSN" -msgstr "" - -#: access/heap/heapam.c:2372 -#, c-format -msgid "heap_update_%sdo: invalid lp" -msgstr "" - -#: access/heap/heapam.c:2407 access/heap/heapam.c:2507 -msgid "heap_update_undo: unimplemented" -msgstr "" - -#: access/heap/heapam.c:2428 -#, c-format -msgid "heap_update_%sdo: uninitialized page" -msgstr "" - -#: access/heap/heapam.c:2452 -msgid "heap_update_redo: invalid max offset number" -msgstr "" - -#: access/heap/heapam.c:2496 -msgid "heap_update_redo: failed to add tuple" -msgstr "" - -#: access/heap/heapam.c:2505 -msgid "heap_update_undo: bad new tuple page LSN" -msgstr "" - -#: access/heap/heapam.c:2523 -msgid "_heap_unlock_tuple: can't open relation" -msgstr "" - -#: access/heap/heapam.c:2528 -msgid "_heap_unlock_tuple: can't read buffer" -msgstr "" - -#: access/heap/heapam.c:2532 -msgid "_heap_unlock_tuple: uninitialized page" -msgstr "" - -#: access/heap/heapam.c:2536 -msgid "_heap_unlock_tuple: invalid itemid" -msgstr "" - -#: access/heap/heapam.c:2540 -msgid "_heap_unlock_tuple: unused/deleted tuple in rollback" -msgstr "" - -#: access/heap/heapam.c:2545 -msgid "_heap_unlock_tuple: invalid xmax in rollback" -msgstr "" - -#: access/heap/heapam.c:2569 -#, c-format -msgid "heap_redo: unknown op code %u" -msgstr "" - -#: access/heap/heapam.c:2589 -#, c-format -msgid "heap_undo: unknown op code %u" -msgstr "" - -#: access/heap/hio.c:53 -msgid "RelationPutHeapTuple: failed to add tuple" -msgstr "" - -#: access/heap/hio.c:113 -#, c-format -msgid "Tuple is too big: size %lu, max size %ld" -msgstr "" - -#: access/heap/hio.c:277 -#, c-format -msgid "Tuple is too big: size %lu" -msgstr "" - -#: access/index/indexam.c:91 access/index/indexam.c:100 -#, c-format -msgid "index_%s: invalid %s regproc" -msgstr "" - -#: access/index/indexam.c:131 access/index/indexam.c:154 -#: access/index/indexam.c:177 -#, c-format -msgid "%s is not an index relation" -msgstr "" - -#: access/index/indexam.c:652 -#, c-format -msgid "Missing support function %d for attribute %d of index %s" -msgstr "" - -#: access/index/genam.c:74 -msgid "RelationGetIndexScan: relation invalid" -msgstr "" - -#: access/index/genam.c:136 -msgid "IndexScanEnd: invalid scan" -msgstr "" - -#: access/index/istrat.c:238 -#, c-format -msgid "StrategyTermEvaluate: impossible case %d" -msgstr "" - -#: access/index/istrat.c:313 -#, c-format -msgid "RelationGetStrategy: impossible case %d" -msgstr "" - -#: access/index/istrat.c:319 -msgid "RelationGetStrategy: corrupted evaluation" -msgstr "" - -#: access/index/istrat.c:438 -#, c-format -msgid "RelationInvokeStrategy: cannot evaluate strategy %d" -msgstr "" - -#: access/nbtree/nbtinsert.c:250 -#, c-format -msgid "Cannot insert a duplicate key into unique index %s" -msgstr "Не возможно вставить повторный ключ в уникальный индекс %s" - -#: access/nbtree/nbtinsert.c:389 -#, c-format -msgid "btree: index item size %lu exceeds maximum %lu" -msgstr "" - -#: access/nbtree/nbtinsert.c:525 -msgid "btree: concurrent ROOT page split" -msgstr "" - -#: access/nbtree/nbtinsert.c:535 -#, c-format -msgid "bt_insertonpg[%s]: no root page found" -msgstr "" - -#: access/nbtree/nbtinsert.c:538 -#, c-format -msgid "bt_insertonpg[%s]: root page unfound - fixing upper levels" -msgstr "" - -#: access/nbtree/nbtinsert.c:585 -#, c-format -msgid "" -"_bt_getstackbuf: my bits moved right off the end of the world!\n" -"\tRecreate index %s." -msgstr "" -"_bt_getstackbuf: моя крыша съехала и рассыпалась на битики!\n" -"\tПересоздайте индекс %s." - -#: access/nbtree/nbtinsert.c:588 -#, c-format -msgid "bt_insertonpg[%s]: parent page unfound - fixing branch" -msgstr "" - -#: access/nbtree/nbtinsert.c:756 -msgid "btree: failed to add hikey to the right sibling" -msgstr "" - -#: access/nbtree/nbtinsert.c:782 -msgid "btree: failed to add hikey to the left sibling" -msgstr "" - -#: access/nbtree/nbtinsert.c:1112 -#, c-format -msgid "_bt_findsplitloc: can't find a feasible split point for %s" -msgstr "" - -#: access/nbtree/nbtinsert.c:1339 -msgid "btree: failed to add leftkey to new root page" -msgstr "" - -#: access/nbtree/nbtinsert.c:1356 -msgid "btree: failed to add rightkey to new root page" -msgstr "" - -#: access/nbtree/nbtinsert.c:1442 -msgid "bt_fixroot: not valid old root page" -msgstr "" - -#: access/nbtree/nbtinsert.c:1573 -#, c-format -msgid "bt_fixtree[%s]: invalid start page (need to recreate index)" -msgstr "" - -#: access/nbtree/nbtinsert.c:1599 -#, c-format -msgid "bt_fixtree[%s]: fixing root page" -msgstr "" - -#: access/nbtree/nbtinsert.c:1647 -#, c-format -msgid "bt_fixlevel[%s]: invalid maxoff on start page (need to recreate index)" -msgstr "" - -#: access/nbtree/nbtinsert.c:1654 -#, c-format -msgid "" -"bt_fixtlevel[%s]: non-leftmost child page of leftmost parent (need to " -"recreate index)" -msgstr "" - -#: access/nbtree/nbtinsert.c:1657 -#, c-format -msgid "bt_fixtlevel[%s]: invalid start child (need to recreate index)" -msgstr "" - -#: access/nbtree/nbtinsert.c:1683 -#, c-format -msgid "bt_fixlevel[%s]: invalid item order(1) (need to recreate index)" -msgstr "" - -#: access/nbtree/nbtinsert.c:1715 -#, c-format -msgid "bt_fixlevel[%s]: pointer disappeared (need to recreate index)" -msgstr "" - -#: access/nbtree/nbtinsert.c:1734 -#, c-format -msgid "bt_fixlevel[%s]: invalid item order(2) (need to recreate index)" -msgstr "" - -#: access/nbtree/nbtinsert.c:1748 -#, c-format -msgid "bt_fixlevel[%s]: invalid item order(3) (need to recreate index)" -msgstr "" - -#: access/nbtree/nbtinsert.c:1878 -#, c-format -msgid "bt_fixbranch[%s]: left pointer unfound (need to recreate index)" -msgstr "" - -#: access/nbtree/nbtinsert.c:1885 -#, c-format -msgid "bt_fixbranch[%s]: invalid item order (need to recreate index)" -msgstr "" - -#: access/nbtree/nbtinsert.c:1894 -#, c-format -msgid "bt_fixbranch[%s]: right pointer unfound(1) (need to recreate index)" -msgstr "" - -#: access/nbtree/nbtinsert.c:1902 -#, c-format -msgid "bt_fixbranch[%s]: right pointer unfound(2) (need to recreate index)" -msgstr "" - -#: access/nbtree/nbtinsert.c:1950 -#, c-format -msgid "bt_fixbranch[%s]: fixing upper levels" -msgstr "" - -#: access/nbtree/nbtinsert.c:1981 -#, c-format -msgid "bt_fixup[%s]: checking/fixing upper levels" -msgstr "" - -#: access/nbtree/nbtinsert.c:1996 -#, c-format -msgid "bt_fixup[%s]: fixing root page" -msgstr "" - -#: access/nbtree/nbtinsert.c:2059 -#, c-format -msgid "btree: failed to add item to the %s for %s" -msgstr "" - -#: access/nbtree/nbtpage.c:66 -#, c-format -msgid "Cannot initialize non-empty btree %s" -msgstr "" - -#: access/nbtree/nbtpage.c:127 -#, c-format -msgid "Index %s is not a btree" -msgstr "" - -#: access/nbtree/nbtpage.c:131 -#, c-format -msgid "Version mismatch on %s: version %d file, version %d code" -msgstr "" - -#: access/nbtree/nbtpage.c:258 -#, c-format -msgid "bt_getroot[%s]: fixing root page" -msgstr "" - -#: access/nbtree/nbtree.c:806 -#, c-format -msgid "" -"_bt_restscan: my bits moved right off the end of the world!\n" -"\tRecreate index %s." -msgstr "" - -#: access/nbtree/nbtree.c:836 -msgid "_bt_restore_page: can't add item to page" -msgstr "" - -#: access/nbtree/nbtree.c:859 -msgid "btree_delete_redo: block unfound" -msgstr "" - -#: access/nbtree/nbtree.c:862 -msgid "btree_delete_redo: uninitialized page" -msgstr "" - -#: access/nbtree/nbtree.c:898 -#, c-format -msgid "btree_insert_%sdo: block unfound" -msgstr "" - -#: access/nbtree/nbtree.c:901 -#, c-format -msgid "btree_insert_%sdo: uninitialized page" -msgstr "" - -#: access/nbtree/nbtree.c:915 -msgid "btree_insert_redo: failed to add item" -msgstr "" - -#: access/nbtree/nbtree.c:924 -msgid "btree_insert_undo: bad page LSN" -msgstr "" - -#: access/nbtree/nbtree.c:932 -msgid "btree_insert_undo: unimplemented" -msgstr "" - -#: access/nbtree/nbtree.c:959 -#, c-format -msgid "btree_split_%s: lost left sibling" -msgstr "" - -#: access/nbtree/nbtree.c:965 -msgid "btree_split_undo: uninitialized left sibling" -msgstr "" - -#: access/nbtree/nbtree.c:988 -msgid "btree_split_undo: bad left sibling LSN" -msgstr "" - -#: access/nbtree/nbtree.c:989 access/nbtree/nbtree.c:1028 -msgid "btree_split_undo: unimplemented" -msgstr "" - -#: access/nbtree/nbtree.c:997 -#, c-format -msgid "btree_split_%s: lost right sibling" -msgstr "" - -#: access/nbtree/nbtree.c:1003 -msgid "btree_split_undo: uninitialized right sibling" -msgstr "" - -#: access/nbtree/nbtree.c:1027 -msgid "btree_split_undo: bad right sibling LSN" -msgstr "" - -#: access/nbtree/nbtree.c:1041 -msgid "btree_split_redo: lost next right page" -msgstr "" - -#: access/nbtree/nbtree.c:1045 -msgid "btree_split_redo: uninitialized next right page" -msgstr "" - -#: access/nbtree/nbtree.c:1082 -msgid "btree_newroot_redo: no root page" -msgstr "" - -#: access/nbtree/nbtree.c:1085 -msgid "btree_newroot_redo: no metapage" -msgstr "" - -#: access/nbtree/nbtree.c:1139 -#, c-format -msgid "btree_redo: unknown op code %u" -msgstr "" - -#: access/nbtree/nbtree.c:1159 -#, c-format -msgid "btree_undo: unknown op code %u" -msgstr "" - -#: access/nbtree/nbtsearch.c:545 -msgid "_bt_first: btree doesn't support is(not)null, yet" -msgstr "" - -#: access/nbtree/nbtsearch.c:693 -msgid "_bt_first: equal items disappeared?" -msgstr "" - -#: access/nbtree/nbtsearch.c:1004 +#: access/common/heaptuple.c:584 #, c-format -msgid "Illegal scan direction %d" -msgstr "" - -#: access/nbtree/nbtsort.c:288 -msgid "btree: failed to add item to the page in _bt_sort" -msgstr "" +msgid "number of attributes %d exceeds limit, %d" +msgstr "число атрибутов: %d превышает лимит: %d" -#: access/nbtree/nbtsort.c:353 +#: access/common/printtup.c:279 +#: tcop/fastpath.c:187 +#: tcop/fastpath.c:517 +#: tcop/postgres.c:1430 #, c-format -msgid "btree: index item size %lu exceeds maximum %ld" -msgstr "" +msgid "unsupported format code: %d" +msgstr "неподдерживаемый код формата: %d" -#: access/nbtree/nbtutils.c:230 -msgid "_bt_orderkeys: key(s) for attribute 1 missed" -msgstr "" +#: access/common/tupdesc.c:660 +#: access/common/tupdesc.c:687 +msgid "number of aliases does not match number of attributes" +msgstr "число алиасов не совпадает с числом атрибутов" -#: access/nbtree/nbtutils.c:308 -#, c-format -msgid "_bt_orderkeys: key(s) for attribute %d missed" -msgstr "" - -#: access/nbtree/nbtutils.c:465 -#, c-format -msgid "_bt_getstrategynumber: unable to identify operator %u" -msgstr "" +#: access/common/tupdesc.c:681 +msgid "no column alias was provided" +msgstr "алиас колонки не указан" -#: access/rtree/rtree.c:331 -#, c-format -msgid "rtdoinsert: failed to add index item to %s" -msgstr "" +#: access/common/tupdesc.c:704 +msgid "could not determine tuple description for function returning record" +msgstr "не в состоянии определить описание строки для функции возпращающей запись" -#: access/rtree/rtree.c:523 access/rtree/rtree.c:547 +#: access/hash/hashovfl.c:166 +#: access/hash/hashovfl.c:185 +#: access/hash/hashovfl.c:208 +#: access/hash/hashovfl.c:254 #, c-format -msgid "rtdosplit: failed to add index item to %s" +msgid "out of overflow pages in hash index \"%s\"" msgstr "" -#: access/rtree/rtree.c:643 -msgid "Variable-length rtree keys are not supported." +#: access/hash/hashutil.c:83 +msgid "hash indexes cannot include null keys" msgstr "" -#: access/rtree/rtree.c:663 +#: access/heap/heapam.c:580 +#: access/heap/heapam.c:615 +#: access/heap/heapam.c:650 #, c-format -msgid "rtintinsert: failed to add index item to %s" -msgstr "" - -#: access/rtree/rtree.c:689 access/rtree/rtree.c:694 -#, c-format -msgid "rtnewroot: failed to add index item to %s" -msgstr "" +msgid "\"%s\" is an index relation" +msgstr "\"%s\" является индексом" -#: access/rtree/rtree.c:781 +#: access/heap/heapam.c:585 +#: access/heap/heapam.c:620 +#: access/heap/heapam.c:655 #, c-format -msgid "rtree: index item size %lu exceeds maximum %lu" -msgstr "" - -#: access/rtree/rtree.c:1068 -msgid "rtpicksplit: failed to find a workable page split" -msgstr "" - -#: access/rtree/rtree.c:1347 -msgid "rtree_redo: unimplemented" -msgstr "" - -#: access/rtree/rtree.c:1353 -msgid "rtree_undo: unimplemented" -msgstr "" +msgid "\"%s\" is a special relation" +msgstr "\"%s\" является специальной связью" -#: access/rtree/rtscan.c:255 +#: access/heap/heapam.c:590 +#: access/heap/heapam.c:625 +#: access/heap/heapam.c:660 #, c-format -msgid "rtree scan list corrupted -- cannot find 0x%p" -msgstr "" +msgid "\"%s\" is a composite type" +msgstr "\"%s\" являтся сложным типом" -#: access/rtree/rtscan.c:391 +#: access/heap/hio.c:109 #, c-format -msgid "Bad operation in rtree scan adjust: %d" +msgid "tuple is too big: size %lu, maximum size %lu" msgstr "" -#: access/transam/clog.c:546 access/transam/clog.c:598 +#: access/index/indexam.c:134 +#: access/index/indexam.c:159 +#: access/index/indexam.c:184 #, c-format -msgid "open of %s failed: %m" -msgstr "не удалось открыть %s: %m" +msgid "\"%s\" is not an index relation" +msgstr "\"%s\" не является индексом" -#: access/transam/clog.c:547 +#: access/nbtree/nbtinsert.c:242 #, c-format -msgid "clog file %s doesn't exist, reading as zeroes" +msgid "duplicate key violates UNIQUE constraint \"%s\"" msgstr "" -#: access/transam/clog.c:553 access/transam/clog.c:606 +#: access/nbtree/nbtinsert.c:394 +#: access/nbtree/nbtsort.c:402 #, c-format -msgid "lseek of clog file %u, offset %u failed: %m" +msgid "index tuple size %lu exceeds btree maximum, %lu" msgstr "" -#: access/transam/clog.c:558 +#: access/nbtree/nbtpage.c:150 +#: access/nbtree/nbtpage.c:329 #, c-format -msgid "read of clog file %u, offset %u failed: %m" -msgstr "" +msgid "index \"%s\" is not a btree" +msgstr "индекс \"%s\" не является b-деревом" -#: access/transam/clog.c:602 access/transam/xlog.c:1378 +#: access/nbtree/nbtpage.c:156 +#: access/nbtree/nbtpage.c:335 #, c-format -msgid "creation of file %s failed: %m" +msgid "version mismatch in \"%s\": file version %d, code version %d" msgstr "" -#: access/transam/clog.c:615 -#, c-format -msgid "write of clog file %u, offset %u failed: %m" +#: access/rtree/rtree.c:645 +msgid "variable-length rtree keys are not supported" msgstr "" -#: access/transam/clog.c:834 -msgid "unable to truncate commit log: apparent wraparound" -msgstr "" - -#: access/transam/clog.c:889 +#: access/rtree/rtree.c:785 #, c-format -msgid "could not open transaction-commit log directory (%s): %m" +msgid "index tuple size %lu exceeds rtree maximum, %lu" msgstr "" -#: access/transam/clog.c:905 -#, c-format -msgid "removing commit log file %s" -msgstr "удаление commit-лог-файла %s" - -#: access/transam/clog.c:914 -#, c-format -msgid "could not read transaction-commit log directory (%s): %m" -msgstr "" - -#: access/transam/xact.c:412 -msgid "You may only have 2^32-1 commands per transaction" -msgstr "Вы можете иметь до 2^32-1 команд в одной транзакции" - -#: access/transam/xact.c:702 -#, c-format -msgid "RecordTransactionAbort: xact %u already committed" -msgstr "" - -#: access/transam/xact.c:917 -msgid "CommitTransaction and not in in-progress state" -msgstr "" - -#: access/transam/xact.c:1058 -msgid "AbortTransaction and not in in-progress state" -msgstr "" - -#: access/transam/xact.c:1143 -msgid "CleanupTransaction and not in abort state" -msgstr "" - -#: access/transam/xact.c:1175 -msgid "StartTransactionCommand: can't prevent chain" -msgstr "StartTransactionCommand: не в состоянии предотвратить цепочку" - -#: access/transam/xact.c:1194 -msgid "StartTransactionCommand: unexpected TBLOCK_BEGIN" -msgstr "StartTransactionCommand: неожиданный TBLOCK_BEGIN" - -#: access/transam/xact.c:1215 -msgid "StartTransactionCommand: unexpected TBLOCK_END" -msgstr "StartTransactionCommand: неожиданный TBLOCK_END" - -#: access/transam/xact.c:1238 -msgid "StartTransactionCommand: unexpected TBLOCK_ENDABORT" -msgstr "StartTransactionCommand: неожиданный TBLOCK_ENDABORT" +#: access/transam/xact.c:405 +msgid "cannot have more than 2^32-1 commands in a transaction" +msgstr "нелтьзя иметь более 2^32-1 команд в одной транзакции" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:1454 +#: access/transam/xact.c:1374 #, c-format msgid "%s cannot run inside a transaction block" msgstr "%s не может выполняться внутри транзакционного блока" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:1464 +#: access/transam/xact.c:1386 #, c-format msgid "%s cannot be executed from a function" msgstr "%s не может выполняться внутри функции" -#: access/transam/xact.c:1468 -msgid "PreventTransactionChain: can't prevent chain" -msgstr "PreventTransactionChain: не в состоянии предотвратить цепочку" - -#. translator: %s represents an SQL statement name -#: access/transam/xact.c:1475 -#, c-format -msgid "%s will be committed automatically" -msgstr "" - #. translator: %s represents an SQL statement name -#: access/transam/xact.c:1519 +#: access/transam/xact.c:1429 #, c-format -msgid "%s may only be used in begin/end transaction blocks" -msgstr "" - -#: access/transam/xact.c:1541 -msgid "BEGIN: already a transaction in progress" -msgstr "BEGIN: транзакция уже в процессе выполнения" +msgid "%s may only be used in BEGIN/END transaction blocks" +msgstr "%s может выполняться только внутри транзакционного блока BEGIN/END" -#: access/transam/xact.c:1605 -msgid "COMMIT: no transaction in progress" -msgstr "COMMIT: нет транзакции в процессе выполнения" +#: access/transam/xact.c:1452 +msgid "there is already a transaction in progress" +msgstr "транзакция уже в процессе выполнения" -#: access/transam/xact.c:1642 access/transam/xact.c:1689 -msgid "ROLLBACK: no transaction in progress" -msgstr "ROLLBACK: нет транзакции в процессе выполнения" +#: access/transam/xact.c:1514 +#: access/transam/xact.c:1552 +#: access/transam/xact.c:1600 +msgid "there is no transaction in progress" +msgstr "нет транзакции в процессе выполнения" -#: access/transam/xact.c:1768 access/transam/xact.c:1779 +#: access/transam/slru.c:492 #, c-format -msgid "xact_redo: unknown op code %u" -msgstr "xact_redo: неизвестный код операции: %u" - -#: access/transam/xact.c:1777 -msgid "xact_undo: can't undo committed xaction" -msgstr "" +msgid "file \"%s\" doesn't exist, reading as zeroes" +msgstr "файл \"%s\" не существует, читается как нули" -#: access/transam/xact.c:1814 -msgid "XactPushRollback: already installed" +#: access/transam/slru.c:613 +#: access/transam/slru.c:620 +#: access/transam/slru.c:627 +#: access/transam/slru.c:634 +#: access/transam/slru.c:641 +#, c-format +msgid "could not access status of transaction %u" msgstr "" -#: access/transam/xlog.c:505 +#: access/transam/slru.c:614 #, c-format -msgid "XLogInsert: invalid info mask %02X" -msgstr "" +msgid "open of file \"%s\" failed: %m" +msgstr "не удалось открыть \"%s\": %m" -#: access/transam/xlog.c:610 +#: access/transam/slru.c:621 +#: access/transam/xlog.c:1387 #, c-format -msgid "XLogInsert: can backup %d blocks at most" -msgstr "" +msgid "creation of file \"%s\" failed: %m" +msgstr "не удалось создать файл \"%s\": %m" -#: access/transam/xlog.c:628 +#: access/transam/slru.c:628 #, c-format -msgid "XLogInsert: invalid record length %u" -msgstr "" +msgid "lseek of file \"%s\", offset %u failed: %m" +msgstr "не удалось выполнить lseek() для файла \"%s\", смещение %u: %m" -#: access/transam/xlog.c:785 access/transam/xlog.c:2625 scan.l:36 -#: utils/adt/name.c:52 utils/adt/varchar.c:83 utils/adt/varchar.c:357 -#: utils/adt/varlena.c:226 +#: access/transam/slru.c:635 #, c-format -msgid "%s" -msgstr "%s" +msgid "read of file \"%s\", offset %u failed: %m" +msgstr "не удалось считать файл \"%s\", смещение %u: %m" -#: access/transam/xlog.c:1029 +#: access/transam/slru.c:642 #, c-format -msgid "XLogWrite: write request %X/%X is past end of log %X/%X" -msgstr "" +msgid "write of file \"%s\", offset %u failed: %m" +msgstr "не удалось записать файл \"%s\", смещение %u: %m" -#: access/transam/xlog.c:1046 access/transam/xlog.c:1156 -#: access/transam/xlog.c:3329 +#: access/transam/slru.c:820 #, c-format -msgid "close of log file %u, segment %u failed: %m" +msgid "could not truncate \"%s\": apparent wraparound" msgstr "" -#: access/transam/xlog.c:1081 -msgid "XLogWrite: time for a checkpoint, signaling postmaster" -msgstr "" +#: access/transam/slru.c:879 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не получилось отктрыть директорию \"%s\": %m" -#: access/transam/xlog.c:1100 +#: access/transam/slru.c:895 #, c-format -msgid "lseek of log file %u, segment %u, offset %u failed: %m" -msgstr "" +msgid "removing file \"%s/%s\"" +msgstr "удаление файла \"%s/%s\"" -#: access/transam/xlog.c:1112 +#: access/transam/slru.c:907 #, c-format -msgid "write of log file %u, segment %u, offset %u failed: %m" -msgstr "" +msgid "could not read directory \"%s\": %m" +msgstr "не получилось cчитать директорию \"%s\": %m" -#: access/transam/xlog.c:1208 +#: access/transam/xlog.c:1049 +#: access/transam/xlog.c:1165 +#: access/transam/xlog.c:3555 #, c-format -msgid "XLogFlush%s%s: request %X/%X; write %X/%X; flush %X/%X" +msgid "close of log file %u, segment %u failed: %m" msgstr "" -#: access/transam/xlog.c:1313 +#: access/transam/xlog.c:1105 +#: access/transam/xlog.c:1867 #, c-format -msgid "XLogFlush: request %X/%X is not satisfied --- flushed only to %X/%X" +msgid "lseek of log file %u, segment %u, offset %u failed: %m" msgstr "" -#: access/transam/xlog.c:1356 access/transam/xlog.c:1437 -#: access/transam/xlog.c:1547 access/transam/xlog.c:1551 +#: access/transam/xlog.c:1119 #, c-format -msgid "open of %s (log file %u, segment %u) failed: %m" -msgstr "не удалось открыть %s (лог-файл: %u, сегмент: %u): %m" +msgid "write of log file %u, segment %u, offset %u failed: %m" +msgstr "" -#: access/transam/xlog.c:1405 +#: access/transam/xlog.c:1363 +#: access/transam/xlog.c:1452 +#: access/transam/xlog.c:1566 +#: access/transam/xlog.c:1572 #, c-format -msgid "ZeroFill failed to write %s: %m" -msgstr "" +msgid "open of \"%s\" (log file %u, segment %u) failed: %m" +msgstr "не удалось открыть \"%s\" (лог-файл: %u, сегмент: %u): %m" -#: access/transam/xlog.c:1410 +#: access/transam/xlog.c:1416 #, c-format -msgid "fsync of file %s failed: %m" -msgstr "" +msgid "failed to write \"%s\": %m" +msgstr "не удалось записать \"%s\": %m" -#: access/transam/xlog.c:1515 +#: access/transam/xlog.c:1423 #, c-format -msgid "" -"link from %s to %s (initialization of log file %u, segment %u) failed: %m" -msgstr "" +msgid "fsync of file \"%s\" failed: %m" +msgstr "fsync файла \"%s\" не удался: %m" -#: access/transam/xlog.c:1520 +#: access/transam/xlog.c:1530 #, c-format -msgid "" -"rename from %s to %s (initialization of log file %u, segment %u) failed: %m" +msgid "link from \"%s\" to \"%s\" (initialization of log file %u, segment %u) failed: %m" msgstr "" -#: access/transam/xlog.c:1601 +#: access/transam/xlog.c:1537 #, c-format -msgid "could not open transaction log directory (%s): %m" -msgstr "" +msgid "rename from \"%s\" to \"%s\" (initialization of log file %u, segment %u) failed: %m" +msgstr "не удалось переименовать \"%s\" в \"%s\" (инициализация лог-файла: %u, сегмент: %u): %m" -#: access/transam/xlog.c:1616 +#: access/transam/xlog.c:1624 #, c-format -msgid "archiving transaction log file %s" +msgid "could not open transaction log directory \"%s\": %m" msgstr "" -#: access/transam/xlog.c:1618 -msgid "archiving log files is not implemented!" -msgstr "архивация логов не поддерживается!" - -#: access/transam/xlog.c:1632 +#: access/transam/xlog.c:1640 #, c-format -msgid "recycled transaction log file %s" -msgstr "" +msgid "archiving transaction log file \"%s\"" +msgstr "архивирование лога транзакций: \"%s\"" -#: access/transam/xlog.c:1638 +#: access/transam/xlog.c:1657 #, c-format -msgid "removing transaction log file %s" -msgstr "удаление лог-файла транзакций: %s" +msgid "recycled transaction log file \"%s\"" +msgstr "переиспользование лога транзакций: \"%s\"" -#: access/transam/xlog.c:1647 +#: access/transam/xlog.c:1664 #, c-format -msgid "could not read transaction log directory (%s): %m" -msgstr "" +msgid "removing transaction log file \"%s\"" +msgstr "удаление лога транзакций: \"%s\"" -#: access/transam/xlog.c:1720 +#: access/transam/xlog.c:1675 #, c-format -msgid "ReadRecord: bad resource manager data checksum in record at %X/%X" -msgstr "" +msgid "could not read transaction log directory \"%s\": %m" +msgstr "не получилось считать файл директорию лога транзакций \"%s\": %m" -#: access/transam/xlog.c:1742 +#: access/transam/xlog.c:1749 #, c-format -msgid "ReadRecord: bad checksum of backup block %d in record at %X/%X" +msgid "bad resource manager data checksum in record at %X/%X" msgstr "" -#: access/transam/xlog.c:1811 +#: access/transam/xlog.c:1772 #, c-format -msgid "ReadRecord: invalid record offset at %X/%X" +msgid "bad checksum of backup block %d in record at %X/%X" msgstr "" -#: access/transam/xlog.c:1834 +#: access/transam/xlog.c:1842 #, c-format -msgid "ReadRecord: lseek of log file %u, segment %u, offset %u failed: %m" +msgid "invalid record offset at %X/%X" msgstr "" -#: access/transam/xlog.c:1840 access/transam/xlog.c:1924 +#: access/transam/xlog.c:1875 +#: access/transam/xlog.c:1965 #, c-format -msgid "ReadRecord: read of log file %u, segment %u, offset %u failed: %m" +msgid "read of log file %u, segment %u, offset %u failed: %m" msgstr "" -#: access/transam/xlog.c:1850 +#: access/transam/xlog.c:1886 #, c-format -msgid "ReadRecord: contrecord is requested by %X/%X" +msgid "contrecord is requested by %X/%X" msgstr "" -#: access/transam/xlog.c:1864 +#: access/transam/xlog.c:1901 #, c-format -msgid "ReadRecord: record with zero length at %X/%X" +msgid "record with zero length at %X/%X" msgstr "" -#: access/transam/xlog.c:1888 +#: access/transam/xlog.c:1926 #, c-format -msgid "ReadRecord: record length %u at %X/%X too long" +msgid "record length %u at %X/%X too long" msgstr "" -#: access/transam/xlog.c:1894 +#: access/transam/xlog.c:1933 #, c-format -msgid "ReadRecord: invalid resource manager id %u at %X/%X" +msgid "invalid resource manager id %u at %X/%X" msgstr "" -#: access/transam/xlog.c:1932 +#: access/transam/xlog.c:1974 #, c-format -msgid "" -"ReadRecord: there is no ContRecord flag in log file %u, segment %u, offset %u" +msgid "there is no contrecord flag in log file %u, segment %u, offset %u" msgstr "" -#: access/transam/xlog.c:1940 +#: access/transam/xlog.c:1983 #, c-format -msgid "" -"ReadRecord: invalid ContRecord length %u in log file %u, segment %u, offset %" -"u" +msgid "invalid contrecord length %u in log file %u, segment %u, offset %u" msgstr "" -#: access/transam/xlog.c:2004 +#: access/transam/xlog.c:2049 #, c-format -msgid "" -"ReadRecord: invalid magic number %04X in log file %u, segment %u, offset %u" +msgid "invalid magic number %04X in log file %u, segment %u, offset %u" msgstr "" -#: access/transam/xlog.c:2010 +#: access/transam/xlog.c:2056 #, c-format -msgid "" -"ReadRecord: invalid info bits %04X in log file %u, segment %u, offset %u" +msgid "invalid info bits %04X in log file %u, segment %u, offset %u" msgstr "" -#: access/transam/xlog.c:2018 +#: access/transam/xlog.c:2065 #, c-format -msgid "" -"ReadRecord: unexpected pageaddr %X/%X in log file %u, segment %u, offset %u" +msgid "unexpected pageaddr %X/%X in log file %u, segment %u, offset %u" msgstr "" #. translator: SUI = startup id -#: access/transam/xlog.c:2040 +#: access/transam/xlog.c:2088 #, c-format -msgid "" -"ReadRecord: out-of-sequence SUI %u (after %u) in log file %u, segment %u, " -"offset %u" +msgid "out-of-sequence SUI %u (after %u) in log file %u, segment %u, offset %u" msgstr "" -#: access/transam/xlog.c:2099 +#: access/transam/xlog.c:2149 msgid "invalid LC_COLLATE setting" -msgstr "" +msgstr "неверное значение LC_COLLATE" -#: access/transam/xlog.c:2103 +#: access/transam/xlog.c:2154 msgid "invalid LC_CTYPE setting" -msgstr "" +msgstr "неверное значение LC_CTYPE" -#: access/transam/xlog.c:2121 +#: access/transam/xlog.c:2173 msgid "sizeof(ControlFileData) is larger than BLCKSZ; fix either one" msgstr "" -#: access/transam/xlog.c:2129 +#: access/transam/xlog.c:2183 #, c-format -msgid "WriteControlFile: could not create control file (%s): %m" +msgid "could not create control file \"%s\": %m" msgstr "" -#: access/transam/xlog.c:2138 +#: access/transam/xlog.c:2194 +#: access/transam/xlog.c:2371 #, c-format -msgid "WriteControlFile: write to control file failed: %m" +msgid "write to control file failed: %m" msgstr "" -#: access/transam/xlog.c:2142 +#: access/transam/xlog.c:2200 +#: access/transam/xlog.c:2377 #, c-format -msgid "WriteControlFile: fsync of control file failed: %m" +msgid "fsync of control file failed: %m" msgstr "" -#: access/transam/xlog.c:2158 access/transam/xlog.c:2281 +#: access/transam/xlog.c:2218 +#: access/transam/xlog.c:2360 #, c-format -msgid "could not open control file (%s): %m" -msgstr "" +msgid "could not open control file \"%s\": %m" +msgstr "не получилось отктрыть файл управления \"%s\": %m" -#: access/transam/xlog.c:2161 +#: access/transam/xlog.c:2224 #, c-format msgid "read from control file failed: %m" msgstr "" -#: access/transam/xlog.c:2173 +#: access/transam/xlog.c:2236 +#: access/transam/xlog.c:2266 +#: access/transam/xlog.c:2273 +#: access/transam/xlog.c:2280 +#: access/transam/xlog.c:2287 +#: access/transam/xlog.c:2294 +#: access/transam/xlog.c:2303 +#: access/transam/xlog.c:2310 +#: access/transam/xlog.c:2318 +#: utils/init/miscinit.c:793 +msgid "database files are incompatible with server" +msgstr "" + +#: access/transam/xlog.c:2237 #, c-format -msgid "" -"The database cluster was initialized with PG_CONTROL_VERSION %d,\n" -"\tbut the server was compiled with PG_CONTROL_VERSION %d.\n" -"\tIt looks like you need to initdb." +msgid "The database cluster was initialized with PG_CONTROL_VERSION %d, but the server was compiled with PG_CONTROL_VERSION %d." msgstr "" -#: access/transam/xlog.c:2186 +#: access/transam/xlog.c:2240 +#: access/transam/xlog.c:2270 +msgid "It looks like you need to initdb." +msgstr "" + +#: access/transam/xlog.c:2250 msgid "invalid checksum in control file" msgstr "" -#: access/transam/xlog.c:2202 +#: access/transam/xlog.c:2267 #, c-format -msgid "" -"The database cluster was initialized with CATALOG_VERSION_NO %d,\n" -"\tbut the backend was compiled with CATALOG_VERSION_NO %d.\n" -"\tIt looks like you need to initdb." +msgid "The database cluster was initialized with CATALOG_VERSION_NO %d, but the server was compiled with CATALOG_VERSION_NO %d." msgstr "" -#: access/transam/xlog.c:2208 +#: access/transam/xlog.c:2274 #, c-format -msgid "" -"The database cluster was initialized with BLCKSZ %d,\n" -"\tbut the backend was compiled with BLCKSZ %d.\n" -"\tIt looks like you need to initdb." +msgid "The database cluster was initialized with BLCKSZ %d, but the server was compiled with BLCKSZ %d." msgstr "" -#: access/transam/xlog.c:2214 +#: access/transam/xlog.c:2277 +#: access/transam/xlog.c:2284 +#: access/transam/xlog.c:2291 +#: access/transam/xlog.c:2298 +#: access/transam/xlog.c:2306 +#: access/transam/xlog.c:2313 +#: access/transam/xlog.c:2322 +msgid "It looks like you need to recompile or initdb." +msgstr "" + +#: access/transam/xlog.c:2281 #, c-format -msgid "" -"The database cluster was initialized with RELSEG_SIZE %d,\n" -"\tbut the backend was compiled with RELSEG_SIZE %d.\n" -"\tIt looks like you need to recompile or initdb." +msgid "The database cluster was initialized with RELSEG_SIZE %d, but the server was compiled with RELSEG_SIZE %d." msgstr "" -#: access/transam/xlog.c:2221 +#: access/transam/xlog.c:2288 #, c-format -msgid "" -"The database cluster was initialized with NAMEDATALEN %d,\n" -"\tbut the backend was compiled with NAMEDATALEN %d.\n" -"\tIt looks like you need to recompile or initdb." +msgid "The database cluster was initialized with NAMEDATALEN %d, but the server was compiled with NAMEDATALEN %d." msgstr "" -#: access/transam/xlog.c:2228 +#: access/transam/xlog.c:2295 #, c-format -msgid "" -"The database cluster was initialized with FUNC_MAX_ARGS %d,\n" -"\tbut the backend was compiled with FUNC_MAX_ARGS %d.\n" -"\tIt looks like you need to recompile or initdb." +msgid "The database cluster was initialized with FUNC_MAX_ARGS %d, but the server was compiled with FUNC_MAX_ARGS %d." msgstr "" -#: access/transam/xlog.c:2236 -msgid "" -"The database cluster was initialized without HAVE_INT64_TIMESTAMP\n" -"\tbut the backend was compiled with HAVE_INT64_TIMESTAMP.\n" -"\tIt looks like you need to recompile or initdb." +#: access/transam/xlog.c:2304 +msgid "The database cluster was initialized without HAVE_INT64_TIMESTAMP but the server was compiled with HAVE_INT64_TIMESTAMP." msgstr "" -#: access/transam/xlog.c:2242 -msgid "" -"The database cluster was initialized with HAVE_INT64_TIMESTAMP\n" -"\tbut the backend was compiled without HAVE_INT64_TIMESTAMP.\n" -"\tIt looks like you need to recompile or initdb." +#: access/transam/xlog.c:2311 +msgid "The database cluster was initialized with HAVE_INT64_TIMESTAMP but the server was compiled without HAVE_INT64_TIMESTAMP." msgstr "" -#: access/transam/xlog.c:2249 +#: access/transam/xlog.c:2319 #, c-format -msgid "" -"The database cluster was initialized with LOCALE_NAME_BUFLEN %d,\n" -"\tbut the backend was compiled with LOCALE_NAME_BUFLEN %d.\n" -"\tIt looks like you need to initdb." +msgid "The database cluster was initialized with LOCALE_NAME_BUFLEN %d, but the server was compiled with LOCALE_NAME_BUFLEN %d." msgstr "" -#: access/transam/xlog.c:2256 -#, c-format -msgid "" -"The database cluster was initialized with LC_COLLATE '%s',\n" -"\twhich is not recognized by setlocale().\n" -"\tIt looks like you need to initdb." +#: access/transam/xlog.c:2325 +#: access/transam/xlog.c:2332 +msgid "database files are incompatible with operating system" msgstr "" -#: access/transam/xlog.c:2262 +#: access/transam/xlog.c:2326 #, c-format -msgid "" -"The database cluster was initialized with LC_CTYPE '%s',\n" -"\twhich is not recognized by setlocale().\n" -"\tIt looks like you need to initdb." +msgid "The database cluster was initialized with LC_COLLATE \"%s\", which is not recognized by setlocale()." msgstr "" -#: access/transam/xlog.c:2289 -#, c-format -msgid "write to control file failed: %m" +#: access/transam/xlog.c:2329 +#: access/transam/xlog.c:2336 +msgid "It looks like you need to initdb or install locale support." msgstr "" -#: access/transam/xlog.c:2293 +#: access/transam/xlog.c:2333 #, c-format -msgid "fsync of control file failed: %m" +msgid "The database cluster was initialized with LC_CTYPE \"%s\", which is not recognized by setlocale()." msgstr "" -#: access/transam/xlog.c:2433 +#: access/transam/xlog.c:2519 #, c-format -msgid "BootStrapXLOG failed to write log file: %m" +msgid "failed to write bootstrap xlog file: %m" msgstr "" -#: access/transam/xlog.c:2437 +#: access/transam/xlog.c:2525 #, c-format -msgid "BootStrapXLOG failed to fsync log file: %m" +msgid "failed to fsync bootstrap xlog file: %m" msgstr "" -#: access/transam/xlog.c:2503 -msgid "control file context is broken" +#: access/transam/xlog.c:2593 +msgid "control file contains invalid data" msgstr "" -#: access/transam/xlog.c:2506 +#: access/transam/xlog.c:2597 #, c-format msgid "database system was shut down at %s" msgstr "система была отключена: %s" -#: access/transam/xlog.c:2509 +#: access/transam/xlog.c:2601 #, c-format msgid "database system shutdown was interrupted at %s" msgstr "отключение системы было прервано: %s" -#: access/transam/xlog.c:2512 +#: access/transam/xlog.c:2605 #, c-format -msgid "" -"database system was interrupted being in recovery at %s\n" -"\tThis probably means that some data blocks are corrupted\n" -"\tand you will have to use the last backup for recovery." +msgid "database system was interrupted while in recovery at %s" +msgstr "система была прервана во время восстановления на %s" + +#: access/transam/xlog.c:2607 +msgid "This probably means that some data is corrupted and you will have to use the last backup for recovery." msgstr "" -#: access/transam/xlog.c:2517 +#: access/transam/xlog.c:2611 #, c-format msgid "database system was interrupted at %s" msgstr "система была прервана: %s" -#: access/transam/xlog.c:2528 +#: access/transam/xlog.c:2629 #, c-format msgid "checkpoint record is at %X/%X" msgstr "контрольная точка: %X/%X" -#: access/transam/xlog.c:2537 +#: access/transam/xlog.c:2639 #, c-format msgid "using previous checkpoint record at %X/%X" msgstr "используется предыдущая контрольная точка: %X/%X" -#: access/transam/xlog.c:2542 -msgid "unable to locate a valid checkpoint record" -msgstr "не в состоянии найти корректную контрольную точку" +#: access/transam/xlog.c:2645 +msgid "could not locate a valid checkpoint record" +msgstr "не получилось найти корректную контрольную точку" -#: access/transam/xlog.c:2548 +#: access/transam/xlog.c:2652 #, c-format msgid "redo record is at %X/%X; undo record is at %X/%X; shutdown %s" msgstr "redo-запись: %X/%X; undo-запись: %X/%X; отключение: %s" -#: access/transam/xlog.c:2552 +#: access/transam/xlog.c:2657 #, c-format msgid "next transaction id: %u; next oid: %u" msgstr "id следующей транзакции: %u; следующий OID: %u" -#: access/transam/xlog.c:2555 +#: access/transam/xlog.c:2661 msgid "invalid next transaction id" msgstr "" -#: access/transam/xlog.c:2566 +#: access/transam/xlog.c:2685 msgid "invalid redo in checkpoint record" msgstr "" -#: access/transam/xlog.c:2574 +#: access/transam/xlog.c:2694 msgid "invalid redo/undo record in shutdown checkpoint" msgstr "" -#: access/transam/xlog.c:2583 -msgid "" -"database system was not properly shut down; automatic recovery in progress" +#: access/transam/xlog.c:2706 +msgid "database system was not properly shut down; automatic recovery in progress" msgstr "" -#: access/transam/xlog.c:2603 +#: access/transam/xlog.c:2734 #, c-format msgid "redo starts at %X/%X" msgstr "" -#: access/transam/xlog.c:2634 +#: access/transam/xlog.c:2766 #, c-format msgid "redo done at %X/%X" msgstr "" -#: access/transam/xlog.c:2640 +#: access/transam/xlog.c:2773 msgid "redo is not required" msgstr "" -#: access/transam/xlog.c:2722 +#: access/transam/xlog.c:2842 #, c-format msgid "undo starts at %X/%X" msgstr "" -#: access/transam/xlog.c:2732 +#: access/transam/xlog.c:2853 #, c-format msgid "undo done at %X/%X" msgstr "" -#: access/transam/xlog.c:2736 +#: access/transam/xlog.c:2858 msgid "undo is not required" msgstr "" -#: access/transam/xlog.c:2770 +#: access/transam/xlog.c:2948 msgid "database system is ready" msgstr "система готова к использованию" -#: access/transam/xlog.c:2898 -msgid "shutting down" -msgstr "отключение в процессе" - -#: access/transam/xlog.c:2911 -msgid "database system is shut down" -msgstr "система отключена" - -#: access/transam/xlog.c:2932 -msgid "CreateCheckPoint: cannot be called inside transaction block" +#. translator: %s is "primary" or "secondary" +#: access/transam/xlog.c:2981 +#, c-format +msgid "invalid %s checkpoint link in control file" msgstr "" -#: access/transam/xlog.c:3047 -msgid "active transaction while database system is shutting down" -msgstr "" +#: access/transam/xlog.c:2982 +#: access/transam/xlog.c:2993 +#: access/transam/xlog.c:3001 +#: access/transam/xlog.c:3010 +#: access/transam/xlog.c:3018 +msgid "primary" +msgstr "первичный" -#: access/transam/xlog.c:3093 -msgid "" -"concurrent transaction log activity while database system is shutting down" -msgstr "" +#: access/transam/xlog.c:2982 +#: access/transam/xlog.c:2993 +#: access/transam/xlog.c:3001 +#: access/transam/xlog.c:3010 +#: access/transam/xlog.c:3018 +msgid "secondary" +msgstr "двоичный" -#: access/transam/xlog.c:3324 access/transam/xlog.c:3352 +#. translator: %s is "primary" or "secondary" +#: access/transam/xlog.c:2992 #, c-format -msgid "fsync of log file %u, segment %u failed: %m" +msgid "invalid %s checkpoint record" +msgstr "неверная контрольная точка %s" + +#. translator: %s is "primary" or "secondary" +#: access/transam/xlog.c:3000 +#, c-format +msgid "invalid resource manager id in %s checkpoint record" msgstr "" -#: access/transam/xlog.c:3358 +#. translator: %s is "primary" or "secondary" +#: access/transam/xlog.c:3009 #, c-format -msgid "fdatasync of log file %u, segment %u failed: %m" +msgid "invalid xl_info in %s checkpoint record" msgstr "" -#: access/transam/xlog.c:3366 +#. translator: %s is "primary" or "secondary" +#: access/transam/xlog.c:3017 #, c-format -msgid "bogus wal_sync_method %d" +msgid "invalid length of %s checkpoint record" msgstr "" -#: access/transam/xlogutils.c:253 -msgid "_xl_remove_hash_entry: file was not found in cache" +#: access/transam/xlog.c:3082 +msgid "shutting down" +msgstr "отключение в процессе" + +#: access/transam/xlog.c:3096 +msgid "database system is shut down" +msgstr "система отключена" + +#: access/transam/xlog.c:3119 +msgid "checkpoint cannot be made inside transaction block" +msgstr "контрольная точка не может располагаться внутри транзакционного блока" + +#: access/transam/xlog.c:3307 +msgid "concurrent transaction log activity while database system is shutting down" msgstr "" -#: access/transam/xlogutils.c:350 -msgid "XLogOpenRelation: out of memory for cache" +#: access/transam/xlog.c:3548 +#: access/transam/xlog.c:3580 +#, c-format +msgid "fsync of log file %u, segment %u failed: %m" msgstr "" -#: access/transam/xlogutils.c:353 -msgid "XLogOpenRelation: file found on insert into cache" +#: access/transam/xlog.c:3588 +#, c-format +msgid "fdatasync of log file %u, segment %u failed: %m" msgstr "" -#: bootstrap/bootstrap.c:194 +#: bootstrap/bootstrap.c:196 msgid "" "Usage:\n" -" postgres -boot [-d level] [-D datadir] [-F] [-o file] [-x num] dbname\n" -" -d 1-5 debug mode\n" +" postgres -boot [OPTION]... DBNAME\n" +" -c NAME=VALUE set run-time parameter\n" +" -d 1-5 debug level\n" " -D datadir data directory\n" " -F turn off fsync\n" " -o file send debug output to file\n" " -x num internal use\n" msgstr "" "Использование:\n" -" postgres -boot [-d уровень] [-D дирданных] [-F] [-o файл] [-x номер] " -"имябд\n" -" -d 1-5 режим отладки\n" -" -D дирданных директория с данными\n" +" postgres -boot [ОПЦИЯ]... ИМЯБД\n" +" -c ИМЯ=ЗНАЧЕНИЕ set run-time parameter\n" +" -d 1-5 уровень отладки\n" +" -D ДИРДАННЫХ директория с данными\n" " -F выключить fsync\n" -" -o файл направить debug-вывод в файл\n" -" -x номер для внутреннего использования\n" +" -o ФАЙЛ направить вывод режима отладки в файл\n" +" -x НОМЕР для внутреннего использования\n" + +#: bootstrap/bootstrap.c:319 +#: postmaster/postmaster.c:567 +#: tcop/postgres.c:2407 +#, c-format +msgid "--%s requires a value" +msgstr "--%s требует параметр" + +#: bootstrap/bootstrap.c:324 +#: postmaster/postmaster.c:572 +#: tcop/postgres.c:2412 +#, c-format +msgid "-c %s requires a value" +msgstr "-c %s требует параметр" -#: bootstrap/bootstrap.c:308 postmaster/postmaster.c:309 +#: bootstrap/bootstrap.c:357 +#: postmaster/postmaster.c:314 +#: tcop/postgres.c:2482 #, c-format msgid "" "%s does not know where to find the database system data.\n" "You must specify the directory that contains the database system\n" "either by specifying the -D invocation option or by setting the\n" "PGDATA environment variable.\n" -"\n" msgstr "" "Модуль %s не в состоянии найти данные (базы и т.д.) системы.\n" "Вы должны указать директорию, которая содержит данные\n" "путём указания опции -D при запуске или установив переменную\n" "окружения PGDATA.\n" -"\n" - -#: bootstrap/bootstrap.c:408 -#, c-format -msgid "Unsupported XLOG op %d" -msgstr "" - -#: bootstrap/bootstrap.c:511 -#, c-format -msgid "open relation %s, attrsize %d" -msgstr "" - -#: bootstrap/bootstrap.c:527 -#, c-format -msgid "create attribute %d name %s len %d num %d type %u" -msgstr "" - -#: bootstrap/bootstrap.c:546 -#, c-format -msgid "closerel: close of '%s' when '%s' was expected" -msgstr "" - -#: bootstrap/bootstrap.c:550 -#, c-format -msgid "closerel: close of '%s' before any relation was opened" -msgstr "" -#: bootstrap/bootstrap.c:555 -msgid "no open relation to close" -msgstr "" - -#: bootstrap/bootstrap.c:558 +#: catalog/dependency.c:173 #, c-format -msgid "close relation %s" -msgstr "" - -#: bootstrap/bootstrap.c:582 -msgid "warning: no open relations allowed with 'create' command" +msgid "cannot drop %s because other objects depend on it" msgstr "" -#: bootstrap/bootstrap.c:591 -#, c-format -msgid "column %s %s" -msgstr "колонка %s %s" - -#: bootstrap/bootstrap.c:681 -#, c-format -msgid "inserting row oid %u, %d columns" +#: catalog/dependency.c:175 +msgid "Use DROP ... CASCADE to drop the dependent objects too." msgstr "" -#: bootstrap/bootstrap.c:693 -msgid "row inserted" -msgstr "запись добавлена" - -#: bootstrap/bootstrap.c:715 +#: catalog/dependency.c:233 #, c-format -msgid "inserting column %d value '%s'" +msgid "failed to drop all objects depending on %s" msgstr "" -#: bootstrap/bootstrap.c:721 -msgid "Typ != NULL" -msgstr "Typ != NULL" - -#: bootstrap/bootstrap.c:728 +#: catalog/dependency.c:330 +#: catalog/dependency.c:729 #, c-format -msgid "unable to find atttypid %u in Typ list" +msgid "cannot drop %s because it is required by the database system" msgstr "" -#: bootstrap/bootstrap.c:739 bootstrap/bootstrap.c:760 -#, c-format -msgid " -> %s" -msgstr " -> %s" - -#: bootstrap/bootstrap.c:750 +#: catalog/dependency.c:466 #, c-format -msgid "type oid %u not found" +msgid "cannot drop %s because %s requires it" msgstr "" -#: bootstrap/bootstrap.c:751 -#, c-format -msgid "Typ == NULL, typeindex = %u" -msgstr "Typ == NULL, typeindex = %u" - -#: bootstrap/bootstrap.c:763 -msgid "inserted" -msgstr "добавлено" - -#: bootstrap/bootstrap.c:773 +#: catalog/dependency.c:468 #, c-format -msgid "inserting column %d NULL" +msgid "You may drop %s instead." msgstr "" -#: bootstrap/bootstrap.c:820 -msgid "Memory manager fault: cleanup called twice.\n" -msgstr "" - -#: bootstrap/bootstrap.c:867 -#, c-format -msgid "external type: %s" -msgstr "внешний тип: %s" - -#: bootstrap/bootstrap.c:891 +#: catalog/dependency.c:536 +#: catalog/dependency.c:686 +#: catalog/dependency.c:714 #, c-format -msgid "Error: unknown type '%s'.\n" -msgstr "Ошибка: неизвестный тип '%s'.\n" - -#: bootstrap/bootstrap.c:907 -msgid "AllocateAttribute: malloc failed" -msgstr "AllocateAttribute: malloc не удался" - -#: bootstrap/bootstrap.c:1058 -msgid "" -"There are too many string constants and identifiers for the compiler to " -"handle." +msgid "drop auto-cascades to %s" msgstr "" -#: bootscanner.l:128 +#: catalog/dependency.c:541 +#: catalog/dependency.c:691 #, c-format -msgid "syntax error at line %d: unexpected character %s" -msgstr "ошибка синтаксиса в строке %d: неожидаемый символ %s" - -#: bootscanner.l:138 -#, c-format -msgid "syntax error at line %d: unexpected token %s" -msgstr "ошибка синтаксиса в строке %d: неожидаемый токен %s" - -#: bootparse.y:59 -msgid "start transaction" -msgstr "начало транзакции" - -#: bootparse.y:67 -msgid "commit transaction" -msgstr "подтверждение транзакции" - -#: bootparse.y:158 -#, c-format -msgid "creating%s%s relation %s..." -msgstr "" - -#: bootparse.y:179 -msgid "create bootstrap: warning, open relation exists, closing first" -msgstr "" - -#: bootparse.y:189 -msgid "bootstrap relation created" +msgid "%s depends on %s" msgstr "" -#: bootparse.y:202 -#, c-format -msgid "relation created with oid %u" -msgstr "создан объект с OID %u" - -#: bootparse.y:213 -#, c-format -msgid "inserting row with oid %u..." -msgstr "добавляется строка с OID %u..." - -#: bootparse.y:215 -msgid "inserting row..." -msgstr "добавляется строка..." - -#: bootparse.y:221 -#, c-format -msgid "incorrect number of columns in row (expected %d, got %d)" -msgstr "неверое число колонок в строке (ожидалось %d, получено %d)" - -#: bootparse.y:225 -msgid "relation not open" -msgstr "объект не открыт" - -#: bootparse.y:306 -msgid "too many columns" -msgstr "слишком много колонок" - -#: catalog/aclchk.c:60 -#, c-format -msgid "acl size = %d, # acls = %d" -msgstr "размер acl = %d, число acl'ов = %d" - -#: catalog/aclchk.c:64 -#, c-format -msgid "\tacl[%d]: %s" -msgstr "\tacl[%d]: %s" - -#: catalog/aclchk.c:153 +#: catalog/dependency.c:548 +#: catalog/dependency.c:698 #, c-format -msgid "bogus GrantStmt.objtype %d" +msgid "drop cascades to %s" msgstr "" -#: catalog/aclchk.c:173 -#, c-format -msgid "invalid privilege type %s for table object" +#: catalog/aclchk.c:127 +msgid "grant options can only be granted to individual users" msgstr "" -#: catalog/aclchk.c:202 +#: catalog/aclchk.c:194 #, c-format -msgid "relation %u not found" +msgid "invalid privilege type %s for table" msgstr "" -#: catalog/aclchk.c:209 +#: catalog/aclchk.c:235 #, c-format msgid "\"%s\" is an index" msgstr "\"%s\" является индексом" -#: catalog/aclchk.c:268 +#: catalog/aclchk.c:297 #, c-format -msgid "invalid privilege type %s for database object" +msgid "invalid privilege type %s for database" msgstr "" -#: catalog/aclchk.c:298 +#: catalog/aclchk.c:329 +#: commands/comment.c:440 +#: commands/dbcommands.c:481 +#: commands/dbcommands.c:602 +#: commands/dbcommands.c:691 +#: utils/adt/acl.c:1311 +#: utils/init/postinit.c:261 +#: utils/init/postinit.c:273 #, c-format -msgid "database \"%s\" not found" -msgstr "база \"%s\" не найдена" - -#: catalog/aclchk.c:302 catalog/aclchk.c:474 catalog/pg_conversion.c:146 -#: commands/dbcommands.c:535 commands/user.c:911 tcop/utility.c:861 -#: utils/init/miscinit.c:615 -msgid "permission denied" -msgstr "доступ запрещён" +msgid "database \"%s\" does not exist" +msgstr "база данных \"%s\" не существует" -#: catalog/aclchk.c:359 +#: catalog/aclchk.c:396 #, c-format -msgid "invalid privilege type %s for function object" +msgid "invalid privilege type %s for function" msgstr "" -#: catalog/aclchk.c:389 parser/parse_func.c:885 parser/parse_func.c:1332 -#, c-format -msgid "function %u not found" -msgstr "Функция %u не найдена" - -#: catalog/aclchk.c:452 +#: catalog/aclchk.c:493 #, c-format -msgid "invalid privilege type %s for language object" +msgid "invalid privilege type %s for language" msgstr "" -#: catalog/aclchk.c:481 +#: catalog/aclchk.c:521 +#: commands/functioncmds.c:440 +#: commands/proclang.c:200 +#: commands/proclang.c:255 +#: utils/adt/acl.c:1729 #, c-format -msgid "language \"%s\" not found" -msgstr "язык \"%s\" не найден" +msgid "language \"%s\" does not exist" +msgstr "язык \"%s\" не существует" # TO REVIEW -#: catalog/aclchk.c:485 +#: catalog/aclchk.c:527 #, c-format msgid "language \"%s\" is not trusted" msgstr "язык \"%s\" недоверямый" -#: catalog/aclchk.c:542 -#, c-format -msgid "invalid privilege type %s for namespace object" -msgstr "" - -#: catalog/aclchk.c:568 -#, c-format -msgid "namespace \"%s\" not found" -msgstr "" - -#: catalog/aclchk.c:644 -#, c-format -msgid "privilege_to_string: unrecognized privilege %d" -msgstr "" - -#: catalog/aclchk.c:666 -#, c-format -msgid "non-existent group \"%s\"" -msgstr "" - -#: catalog/aclchk.c:736 -#, c-format -msgid "in_group: group %u not found" -msgstr "" - -#: catalog/aclchk.c:764 -msgid "aclcheck: null ACL, returning OK" -msgstr "" - -#: catalog/aclchk.c:779 -msgid "aclcheck: zero-length ACL, returning OK" -msgstr "" - -#: catalog/aclchk.c:788 -msgid "aclcheck: first entry in ACL is not 'world' entry" -msgstr "" - -#: catalog/aclchk.c:792 +#: catalog/aclchk.c:593 #, c-format -msgid "aclcheck: using world=%d" +msgid "invalid privilege type %s for schema" msgstr "" -#: catalog/aclchk.c:808 +#: catalog/aclchk.c:621 +#: catalog/namespace.c:245 +#: catalog/namespace.c:1200 +#: catalog/namespace.c:1238 +#: catalog/namespace.c:1800 +#: commands/comment.c:490 +#: commands/schemacmds.c:181 +#: commands/schemacmds.c:247 +#: utils/adt/acl.c:1933 #, c-format -msgid "aclcheck: found user %u/%d" -msgstr "" +msgid "schema \"%s\" does not exist" +msgstr "схема \"%s\" не существует" -#: catalog/aclchk.c:825 catalog/aclchk.c:846 +#: catalog/aclchk.c:724 +#: commands/user.c:1454 +#: commands/user.c:1696 +#: commands/user.c:1731 +#: libpq/pqcomm.c:475 #, c-format -msgid "aclcheck: found group %u/%d" -msgstr "" +msgid "group \"%s\" does not exist" +msgstr "группа \"%s\" не существует" -#: catalog/aclchk.c:858 +#: catalog/aclchk.c:796 #, c-format -msgid "aclcheck: bogus ACL id type: %d" -msgstr "" +msgid "group with ID %u does not exist" +msgstr "группа с ID %u не существует" -#: catalog/aclchk.c:879 commands/user.c:1304 +#: catalog/aclchk.c:865 #, c-format -msgid "%s: permission denied" -msgstr "%s: нет доступа" +msgid "permission denied for relation %s" +msgstr "доступ запрещён для связи %s" -#: catalog/aclchk.c:882 +#: catalog/aclchk.c:867 #, c-format -msgid "%s: must be owner" -msgstr "" +msgid "permission denied for database %s" +msgstr "доступ запрещён для базы %s" -#: catalog/aclchk.c:885 +#: catalog/aclchk.c:869 #, c-format -msgid "%s: unexpected AclResult %d" -msgstr "" +msgid "permission denied for function %s" +msgstr "доступ запрещён для фунции %s" -#: catalog/aclchk.c:913 +#: catalog/aclchk.c:871 #, c-format -msgid "pg_class_aclcheck: invalid user id %u" -msgstr "" +msgid "permission denied for operator %s" +msgstr "доступ запрещён для оператора %s" -#: catalog/aclchk.c:928 +#: catalog/aclchk.c:873 #, c-format -msgid "pg_class_aclcheck: relation %u not found" -msgstr "" - -#: catalog/aclchk.c:941 -msgid "pg_class_aclcheck: catalog update: permission denied" -msgstr "" +msgid "permission denied for type %s" +msgstr "доступ запрещён для типа %s" -#: catalog/aclchk.c:953 +#: catalog/aclchk.c:875 #, c-format -msgid "pg_class_aclcheck: %u is superuser" -msgstr "" +msgid "permission denied for language %s" +msgstr "доступ запрещён для языка %s" -#: catalog/aclchk.c:1021 +#: catalog/aclchk.c:877 #, c-format -msgid "pg_database_aclcheck: database %u not found" -msgstr "" +msgid "permission denied for schema %s" +msgstr "доступ запрещён для схемы %s" -#: catalog/aclchk.c:1076 +#: catalog/aclchk.c:879 #, c-format -msgid "pg_proc_aclcheck: function %u not found" -msgstr "" +msgid "permission denied for operator class %s" +msgstr "доступ запрещён для класса операторов %s" -#: catalog/aclchk.c:1129 +#: catalog/aclchk.c:881 #, c-format -msgid "pg_language_aclcheck: language %u not found" -msgstr "" +msgid "permission denied for conversion %s" +msgstr "доступ запрещён для конверсии %s" -#: catalog/aclchk.c:1186 +#: catalog/aclchk.c:887 #, c-format -msgid "pg_namespace_aclcheck: namespace %u not found" -msgstr "" +msgid "must be owner of relation %s" +msgstr "нужно быть владельцем связи %s" -#: catalog/aclchk.c:1234 +#: catalog/aclchk.c:889 #, c-format -msgid "pg_class_ownercheck: relation %u not found" -msgstr "" +msgid "must be owner of database %s" +msgstr "нужно быть владельцем базы %s" -#: catalog/aclchk.c:1260 +#: catalog/aclchk.c:891 #, c-format -msgid "pg_type_ownercheck: type %u not found" -msgstr "pg_type_ownercheck: тип '%u не найден" +msgid "must be owner of function %s" +msgstr "нужно быть владельцем функции %s" -#: catalog/aclchk.c:1286 +#: catalog/aclchk.c:893 #, c-format -msgid "pg_oper_ownercheck: operator %u not found" -msgstr "" +msgid "must be owner of operator %s" +msgstr "нужно быть владельцем оператора %s" -#: catalog/aclchk.c:1312 +#: catalog/aclchk.c:895 #, c-format -msgid "pg_proc_ownercheck: function %u not found" -msgstr "" +msgid "must be owner of type %s" +msgstr "нужно быть владельцем типа %s" -#: catalog/aclchk.c:1338 +#: catalog/aclchk.c:897 #, c-format -msgid "pg_namespace_ownercheck: namespace %u not found" -msgstr "" +msgid "must be owner of language %s" +msgstr "нужно быть владельцем языка %s" -#: catalog/aclchk.c:1365 +#: catalog/aclchk.c:899 #, c-format -msgid "pg_opclass_ownercheck: operator class %u not found" -msgstr "" +msgid "must be owner of schema %s" +msgstr "нужно быть владельцем схемы %s" -#: catalog/dependency.c:163 +#: catalog/aclchk.c:901 #, c-format -msgid "" -"Cannot drop %s because other objects depend on it\n" -"\tUse DROP ... CASCADE to drop the dependent objects too" -msgstr "" +msgid "must be owner of operator class %s" +msgstr "нужно быть владельцем класса операторов %s" -#: catalog/dependency.c:253 catalog/dependency.c:572 +#: catalog/aclchk.c:903 #, c-format -msgid "Cannot drop %s because it is required by the database system" -msgstr "" +msgid "must be owner of conversion %s" +msgstr "нужно быть владельцем конверсии %s" -#: catalog/dependency.c:257 +#: catalog/aclchk.c:961 #, c-format -msgid "findAutoDeletableObjects: unknown dependency type '%c' for %s" -msgstr "" +msgid "user with ID %u does not exist" +msgstr "пользователь с ID %u не существует" -#: catalog/dependency.c:386 +#: catalog/aclchk.c:978 +#: catalog/aclchk.c:1294 #, c-format -msgid "" -"Cannot drop %s because %s requires it\n" -"\tYou may drop %s instead" -msgstr "" +msgid "relation with OID %u does not exist" +msgstr "связь с OID %u не существует" -#: catalog/dependency.c:412 +#: catalog/aclchk.c:1073 +#: catalog/aclchk.c:1473 #, c-format -msgid "recursiveDeletion: multiple INTERNAL dependencies for %s" -msgstr "" +msgid "database with OID %u does not exist" +msgstr "база данных с OID %u не существует" -#: catalog/dependency.c:424 +#: catalog/aclchk.c:1130 +#: catalog/aclchk.c:1378 +#: tcop/fastpath.c:231 #, c-format -msgid "recursiveDeletion: incorrect use of PIN dependency with %s" -msgstr "" +msgid "function with OID %u does not exist" +msgstr "функция с OID %u не существует" -#: catalog/dependency.c:428 catalog/dependency.c:576 +#: catalog/aclchk.c:1185 #, c-format -msgid "recursiveDeletion: unknown dependency type '%c' for %s" -msgstr "" +msgid "language with OID %u does not exist" +msgstr "язык с OID %u не существует" -#: catalog/dependency.c:454 catalog/dependency.c:532 catalog/dependency.c:558 +#: catalog/aclchk.c:1244 +#: catalog/aclchk.c:1406 #, c-format -msgid "Drop auto-cascades to %s" -msgstr "" +msgid "schema with OID %u does not exist" +msgstr "схема с OID %u не существует" -#: catalog/dependency.c:458 catalog/dependency.c:536 +#: catalog/aclchk.c:1322 #, c-format -msgid "%s depends on %s" -msgstr "" +msgid "type with OID %u does not exist" +msgstr "тип с OID %u не существует" -#: catalog/dependency.c:464 catalog/dependency.c:542 +#: catalog/aclchk.c:1350 #, c-format -msgid "Drop cascades to %s" -msgstr "" +msgid "operator with OID %u does not exist" +msgstr "оператро с OID %u не существует" -#: catalog/dependency.c:693 +#: catalog/aclchk.c:1434 #, c-format -msgid "doDeletion: Unsupported object class %u" -msgstr "" +msgid "operator class with OID %u does not exist" +msgstr "класс операторов с OID %u не существует" -#: catalog/dependency.c:776 -#, c-format -msgid "find_expr_references_walker: bogus varlevelsup %d" +#: catalog/pg_aggregate.c:80 +msgid "cannot determine transition datatype" msgstr "" -#: catalog/dependency.c:780 -#, c-format -msgid "find_expr_references_walker: bogus varno %d" +#: catalog/pg_aggregate.c:81 +msgid "An aggregate using ANYARRAY or ANYELEMENT as trans type must have one of them as its base type." msgstr "" -#: catalog/dependency.c:800 +#: catalog/pg_aggregate.c:110 #, c-format -msgid "find_expr_references_walker: bogus varattno %d" +msgid "return type of transition function %s is not %s" msgstr "" -#: catalog/dependency.c:844 -msgid "find_expr_references_walker: already-planned subqueries not supported" +#: catalog/pg_aggregate.c:132 +msgid "must not omit initval when transfn is strict and transtype is not compatible with input type" msgstr "" -#: catalog/dependency.c:1180 -#, c-format -msgid "getObjectClass: Unknown object class %u" +#: catalog/pg_aggregate.c:165 +#: catalog/pg_proc.c:112 +#: catalog/pg_proc.c:535 +msgid "cannot determine result datatype" msgstr "" -#: catalog/dependency.c:1237 -#, c-format -msgid "getObjectDescription: Cast %u does not exist" +#: catalog/pg_aggregate.c:166 +msgid "An aggregate returning ANYARRAY or ANYELEMENT must have one of them as its base type." msgstr "" -#: catalog/dependency.c:1271 +#: catalog/pg_aggregate.c:280 +#: commands/typecmds.c:896 +#: commands/typecmds.c:966 +#: commands/typecmds.c:998 +#: commands/typecmds.c:1030 +#: parser/parse_func.c:319 +#: parser/parse_func.c:1491 #, c-format -msgid "getObjectDescription: Constraint %u does not exist" -msgstr "" +msgid "function %s does not exist" +msgstr "функция %s не существует" -#: catalog/dependency.c:1301 +#: catalog/pg_aggregate.c:285 #, c-format -msgid "getObjectDescription: Conversion %u does not exist" +msgid "function %s returns a set" msgstr "" -#: catalog/dependency.c:1330 +#: catalog/pg_aggregate.c:316 +#: catalog/pg_aggregate.c:325 #, c-format -msgid "getObjectDescription: Default %u does not exist" +msgid "function %s requires run-time type coercion" msgstr "" -#: catalog/dependency.c:1355 -#, c-format -msgid "getObjectDescription: Language %u does not exist" -msgstr "getObjectDescription: Язык %u не существует" - -#: catalog/dependency.c:1380 -#, c-format -msgid "cache lookup of opclass %u failed" -msgstr "поиск в кзше опкласса %u не удался" - -#: catalog/dependency.c:1398 utils/adt/ruleutils.c:425 -#, c-format -msgid "syscache lookup for AM %u failed" -msgstr "поиск в системном кзше AM %u не удался" - -#: catalog/dependency.c:1430 -#, c-format -msgid "getObjectDescription: Rule %u does not exist" -msgstr "getObjectDescription: Првило %u не существует" - -#: catalog/dependency.c:1464 +#: catalog/heap.c:227 #, c-format -msgid "getObjectDescription: Trigger %u does not exist" -msgstr "getObjectDescription: Триггер %u не существует" +msgid "permission denied to create \"%s.%s\"" +msgstr "доступ запрещён по созданию \"%s.%s\"" -#: catalog/dependency.c:1484 -#, c-format -msgid "getObjectDescription: Schema %u does not exist" -msgstr "getObjectDescription: Схема %u не существует" - -#: catalog/dependency.c:1516 catalog/heap.c:1660 catalog/pg_constraint.c:470 -#: utils/adt/ruleutils.c:3121 -#, c-format -msgid "cache lookup of relation %u failed" +#: catalog/heap.c:229 +msgid "System catalog modifications are currently disallowed." msgstr "" -#: catalog/heap.c:156 catalog/heap.c:159 +#: catalog/heap.c:356 +#: commands/tablecmds.c:1843 #, c-format -msgid "SystemAttributeDefinition: invalid attribute number %d" -msgstr "SystemAttributeDefinition: неверный номер атрибута: %d" - -#: catalog/heap.c:226 -#, c-format -msgid "" -"cannot create %s.%s: system catalog modifications are currently disallowed" +msgid "tables can have at most %d columns" msgstr "" -#: catalog/heap.c:353 -#, c-format -msgid "Number of columns is out of range (0 to %d)" -msgstr "Число колонок вне диапазона (от 0 до %d)" - -#: catalog/heap.c:368 +#: catalog/heap.c:373 #, c-format -msgid "name of column \"%s\" conflicts with an existing system column" -msgstr "имя колонки \"%s\" конфликтует с существующей системной колонкой" +msgid "column name \"%s\" conflicts with a system column name" +msgstr "имя колонки \"%s\" конфликтует с системной колонкой" -#: catalog/heap.c:382 +#: catalog/heap.c:389 #, c-format msgid "column name \"%s\" is duplicated" msgstr "повторное имя колонки: \"%s\"" -#: catalog/heap.c:420 -#, c-format -msgid "" -"Attribute \"%s\" has an unknown type\n" -"\tProceeding with relation creation anyway" -msgstr "" - -#: catalog/heap.c:424 -#, c-format -msgid "Attribute \"%s\" has pseudo-type %s" -msgstr "Атрибут \"%s\" имеет псевдо-тип %s" - -#: catalog/heap.c:431 +#: catalog/heap.c:429 #, c-format -msgid "Attribute \"%s\" has composite type %s" -msgstr "Атрибут \"%s\" имеет сложный тип %s" +msgid "attribute \"%s\" has type UNKNOWN" +msgstr "атрибут \"%s\" имеет тип UNKNOWN" -#: catalog/heap.c:714 -#, c-format -msgid "Relation '%s' already exists" -msgstr "Объект '%s' уже существует" - -#: catalog/heap.c:871 -#, c-format -msgid "DeleteRelationTuple: cache lookup failed for relation %u" -msgstr "DeleteRelationTuple: поиск в кэше связи %u не удался" - -#: catalog/heap.c:950 -#, c-format -msgid "RemoveAttributeById: Failed to find attribute %d in relation %u" -msgstr "" - -#: catalog/heap.c:1029 -#, c-format -msgid "RemoveAttrDefault: no default found for rel %u attnum %d" +#: catalog/heap.c:430 +msgid "Proceeding with relation creation anyway." msgstr "" -#: catalog/heap.c:1065 +#: catalog/heap.c:437 #, c-format -msgid "RemoveAttrDefaultById: cache lookup failed for attrdef %u" -msgstr "RemoveAttrDefaultById: поиск в кэше attrdef %u не удался" +msgid "attribute \"%s\" has pseudo-type %s" +msgstr "арибут \"%s\" имеет псевдо-тип %s" -#: catalog/heap.c:1088 +#: catalog/heap.c:447 #, c-format -msgid "RemoveAttrDefaultById: cache lookup failed for rel %u attr %d" -msgstr "RemoveAttrDefaultById: поиск в кэше для связи %u и attr %d не удался" +msgid "attribute \"%s\" has composite type %s" +msgstr "атрибут \"%s\" имеет сложный тип %s" -#: catalog/heap.c:1143 +#: catalog/heap.c:734 +#: catalog/index.c:543 +#: commands/tablecmds.c:1378 #, c-format -msgid "heap_drop_with_catalog: FlushRelationBuffers returned %d" -msgstr "heap_drop_with_catalog: FlushRelationBuffers возвратила %d" +msgid "relation \"%s\" already exists" +msgstr "объект \"%s\" уже существует" -#: catalog/heap.c:1264 parser/parse_relation.c:1503 utils/adt/ruleutils.c:3278 +#: catalog/heap.c:1556 +#: commands/tablecmds.c:2892 +#: commands/tablecmds.c:2934 #, c-format -msgid "cache lookup of attribute %d in relation %u failed" -msgstr "" +msgid "constraint \"%s\" for relation \"%s\" already exists" +msgstr "констрейнт \"%s\" для связи \"%s\" уже существует" -#: catalog/heap.c:1522 commands/tablecmds.c:2634 commands/tablecmds.c:2672 +#: catalog/heap.c:1572 #, c-format -msgid "constraint \"%s\" already exists for relation \"%s\"" -msgstr "" - -#: catalog/heap.c:1536 commands/tablecmds.c:206 -#, c-format -msgid "Duplicate CHECK constraint name: '%s'" -msgstr "" +msgid "CHECK constraint \"%s\" already exists" +msgstr "CHECK-ограничение \"%s\" уже существует" -#: catalog/heap.c:1596 +#: catalog/heap.c:1634 #, c-format -msgid "Only relation \"%s\" can be referenced in CHECK constraint expression" +msgid "only relation \"%s\" can be referenced in CHECK constraint" msgstr "" -#: catalog/heap.c:1603 commands/tablecmds.c:2754 commands/typecmds.c:1588 -msgid "cannot use subselect in CHECK constraint expression" +#: catalog/heap.c:1643 +#: commands/tablecmds.c:3021 +#: commands/typecmds.c:1828 +msgid "cannot use sub-select in CHECK constraint" msgstr "" -#: catalog/heap.c:1605 commands/tablecmds.c:2756 commands/typecmds.c:1590 -msgid "cannot use aggregate function in CHECK constraint expression" +#: catalog/heap.c:1647 +#: commands/tablecmds.c:3025 +#: commands/typecmds.c:1832 +msgid "cannot use aggregate in CHECK constraint" msgstr "" -#: catalog/heap.c:1715 +#: catalog/heap.c:1754 msgid "cannot use column references in DEFAULT clause" msgstr "" -#: catalog/heap.c:1721 +#: catalog/heap.c:1762 msgid "DEFAULT clause must not return a set" msgstr "" -#: catalog/heap.c:1727 -msgid "cannot use subselects in DEFAULT clause" -msgstr "" - -#: catalog/heap.c:1729 -msgid "cannot use aggregate functions in DEFAULT clause" -msgstr "" - -#: catalog/heap.c:1750 rewrite/rewriteHandler.c:487 -#, c-format -msgid "" -"Column \"%s\" is of type %s but default expression is of type %s\n" -"\tYou will need to rewrite or cast the expression" -msgstr "" - -#: catalog/index.c:124 -#, c-format -msgid "Function %u does not exist" -msgstr "Функция %u не существует" - -#: catalog/index.c:143 catalog/index.c:280 -#, c-format -msgid "Opclass %u does not exist" -msgstr "Opclass %u не существует" - -#: catalog/index.c:157 catalog/index.c:293 -#, c-format -msgid "Type %u does not exist" -msgstr "Тип %u не существует" - -#: catalog/index.c:238 -#, c-format -msgid "cannot create index: column %d does not exist" -msgstr "нельзя создать индекс: колонка %d не существует" - -#: catalog/index.c:543 -msgid "must index at least one column" -msgstr "покрайней мере одна колонка должна быть индексирована" - -#: catalog/index.c:548 -msgid "User-defined indexes on system catalogs are not supported" -msgstr "Пользовательские индексы на системные каталоги не поддерживаются" - -#: catalog/index.c:558 -msgid "Shared indexes cannot be created after initdb" -msgstr "" - -#: catalog/index.c:561 -#, c-format -msgid "relation named \"%s\" already exists" -msgstr "объект с именем \"%s\" уже существует" - -#: catalog/index.c:674 -msgid "index_create: constraint must be PRIMARY or UNIQUE" -msgstr "" - -#: catalog/index.c:824 -#, c-format -msgid "index_drop: cache lookup failed for index %u" -msgstr "index_drop: поиск в кэше индекса %u не удался" - -#: catalog/index.c:837 -#, c-format -msgid "index_drop: FlushRelationBuffers returned %d" -msgstr "index_drop: FlushRelationBuffers возвратила %d" - -#: catalog/index.c:1039 -#, c-format -msgid "relation %s isn't an indexable relation" -msgstr "объект %s не является индексируемым" - -#: catalog/index.c:1110 -#, c-format -msgid "setRelhasindex: cannot find relation %u in pg_class" +#: catalog/heap.c:1770 +msgid "cannot use sub-select in DEFAULT clause" msgstr "" -#: catalog/index.c:1226 -#, c-format -msgid "setNewRelfilenode: cannot find relation %u in pg_class" +#: catalog/heap.c:1774 +msgid "cannot use aggregate in DEFAULT clause" msgstr "" -#: catalog/index.c:1338 +#: catalog/heap.c:1792 +#: rewrite/rewriteHandler.c:560 #, c-format -msgid "UpdateStats: cannot find relation %u in pg_class" +msgid "column \"%s\" is of type %s but default expression is of type %s" msgstr "" -#: catalog/index.c:1617 -msgid "IndexBuildHeapScan: concurrent insert in progress" +#: catalog/heap.c:1797 +#: parser/analyze.c:2788 +#: parser/parse_node.c:232 +#: parser/parse_target.c:425 +#: rewrite/rewriteHandler.c:565 +msgid "You will need to rewrite or cast the expression." msgstr "" -#: catalog/index.c:1632 -msgid "IndexBuildHeapScan: concurrent delete in progress" -msgstr "" +#: catalog/index.c:526 +msgid "user-defined indexes on system catalogs are not supported" +msgstr "пользовательские индексы на системные каталоги не поддерживаются" -#: catalog/index.c:1637 commands/vacuum.c:1207 commands/vacuumlazy.c:359 -#: commands/vacuumlazy.c:846 -msgid "Unexpected HeapTupleSatisfiesVacuum result" +#: catalog/index.c:538 +msgid "shared indexes cannot be created after initdb" msgstr "" -#: catalog/index.c:1725 +#: catalog/index.c:995 #, c-format -msgid "IndexGetRelation: can't find index id %u" -msgstr "IndexGetRelation: не получается найти индекс с id %u" - -#: catalog/index.c:1774 -msgid "reindex_index: can't open index relation" -msgstr "" - -#: catalog/index.c:1785 -msgid "reindex_index: can't open heap relation" -msgstr "" +msgid "relation \"%s\" isn't an indexable relation" +msgstr "связт \"%s\" не является индексируемым объектом" -#: catalog/index.c:1799 catalog/index.c:1922 +#: catalog/index.c:1755 +#: catalog/index.c:1882 #, c-format msgid "the target relation %u is shared" msgstr "" -#: catalog/index.c:1805 +#: catalog/index.c:1763 #, c-format msgid "the target relation %u is nailed" msgstr "" -#: catalog/namespace.c:168 catalog/namespace.c:215 catalog/namespace.c:1153 -#: parser/parse_expr.c:845 parser/parse_target.c:147 -msgid "Cross-database references are not implemented" -msgstr "" - -#: catalog/namespace.c:186 -#, c-format -msgid "Relation \"%s\".\"%s\" does not exist" -msgstr "Объект \"%s\".\"%s\" не существует" - -#: catalog/namespace.c:222 -msgid "TEMP tables may not specify a namespace" -msgstr "" - -#: catalog/namespace.c:236 catalog/namespace.c:1182 catalog/namespace.c:1217 -#: catalog/namespace.c:1802 -#, c-format -msgid "Namespace \"%s\" does not exist" -msgstr "" - -#: catalog/namespace.c:246 catalog/namespace.c:1227 -msgid "No namespace has been selected to create in" -msgstr "" - -#: catalog/namespace.c:298 -#, c-format -msgid "Cache lookup failed for relation %u" -msgstr "Поиск в кэше связи %u не удался" - -#: catalog/namespace.c:380 -#, c-format -msgid "Cache lookup failed for type %u" +#: catalog/namespace.c:167 +#: catalog/namespace.c:220 +#: catalog/namespace.c:1167 +#: parser/parse_expr.c:1117 +#: parser/parse_target.c:162 +msgid "cross-database references are not implemented" msgstr "" -#: catalog/namespace.c:581 -#, c-format -msgid "Cache lookup failed for procedure %u" -msgstr "" - -#: catalog/namespace.c:793 -#, c-format -msgid "Cache lookup failed for operator %u" -msgstr "Поиск в кэше операторы %u не удался" - -#: catalog/namespace.c:1006 -#, c-format -msgid "Cache lookup failed for opclass %u" -msgstr "Поиск в кэше опкласса %u не удался" - -#: catalog/namespace.c:1087 +#: catalog/namespace.c:187 #, c-format -msgid "Cache lookup failed for converions %u" -msgstr "Поиск в кэше конверсии %u не удался" - -#: catalog/namespace.c:1156 gram.y:2291 gram.y:6839 -#, c-format -msgid "Improper qualified name (too many dotted names): %s" -msgstr "" - -#: catalog/namespace.c:1260 -msgid "Improper relation name (too many dotted names)" -msgstr "" - -#: catalog/namespace.c:1472 -msgid "recomputeNamespacePath: invalid list syntax" -msgstr "" +msgid "relation \"%s.%s\" does not exist" +msgstr "связь \"%s.%s\" не существует" -#: catalog/namespace.c:1601 +#: catalog/namespace.c:192 #, c-format -msgid "%s: not authorized to create temp tables" -msgstr "" +msgid "relation \"%s\" does not exist" +msgstr "связь \"%s\" не существует" -#: catalog/pg_aggregate.c:62 -msgid "no aggregate name supplied" +#: catalog/namespace.c:229 +msgid "TEMP tables may not specify a schema name" msgstr "" -#: catalog/pg_aggregate.c:65 -msgid "aggregate must have a transition function" +#: catalog/namespace.c:257 +#: catalog/namespace.c:1249 +msgid "no schema has been selected to create in" msgstr "" -#: catalog/pg_aggregate.c:87 +#: catalog/namespace.c:1172 +#: parser/parse_expr.c:1149 +#: parser/parse_target.c:170 #, c-format -msgid "return type of transition function %s is not %s" -msgstr "" - -#: catalog/pg_aggregate.c:99 -msgid "" -"must not omit initval when transfn is strict and transtype is not compatible " -"with input type" +msgid "improper qualified name (too many dotted names): %s" msgstr "" -#: catalog/pg_constraint.c:437 +#: catalog/namespace.c:1284 #, c-format -msgid "RemoveConstraintById: constraint %u not found" +msgid "improper relation name (too many dotted names): %s" msgstr "" -#: catalog/pg_constraint.c:475 +#: catalog/namespace.c:1628 #, c-format -msgid "RemoveConstraintById: relation %s has relchecks = 0" -msgstr "" +msgid "permission denied to create temp tables in database \"%s\"" +msgstr "доступ запрещён по созданию временных таблиц в базе \"%s\"" -#: catalog/pg_constraint.c:502 +#: catalog/pg_largeobject.c:110 +#: storage/large_object/inv_api.c:128 +#: storage/large_object/inv_api.c:248 #, c-format -msgid "RemoveConstraintById: Constraint %u is not a known type" -msgstr "" - -#: catalog/pg_conversion.c:57 -msgid "no conversion name supplied" +msgid "large object %u does not exist" msgstr "" -#: catalog/pg_conversion.c:64 +#: catalog/pg_conversion.c:66 #, c-format -msgid "conversion name \"%s\" already exists" -msgstr "конверсия с именем \"%s\" уже существует" +msgid "conversion \"%s\" already exists" +msgstr "конверсия \"%s\" уже существует" -#: catalog/pg_conversion.c:75 +#: catalog/pg_conversion.c:79 #, c-format msgid "default conversion for %s to %s already exists" -msgstr "" - -#: catalog/pg_conversion.c:141 catalog/pg_conversion.c:308 -#, c-format -msgid "Conversion %u search from syscache failed" -msgstr "" - -#: catalog/pg_conversion.c:192 -#, c-format -msgid "conversion %u does not exist" -msgstr "конверсия %u не существует" +msgstr "конверсия по умолчанию для %s в %s уже существует" -#: catalog/pg_conversion.c:302 commands/conversioncmds.c:97 +#: catalog/pg_conversion.c:308 +#: commands/conversioncmds.c:109 +#: commands/conversioncmds.c:133 #, c-format -msgid "conversion %s not found" -msgstr "" - -#: catalog/pg_largeobject.c:108 -#, c-format -msgid "LargeObjectDrop: large object %u not found" -msgstr "LargeObjectDrop: большой объект %u не найден" - -#: catalog/pg_namespace.c:43 -msgid "no namespace name supplied" -msgstr "" +msgid "conversion \"%s\" does not exist" +msgstr "конверсия \"%s\" не существует" -#: catalog/pg_namespace.c:49 +#: catalog/pg_namespace.c:51 +#: commands/schemacmds.c:256 #, c-format -msgid "namespace \"%s\" already exists" -msgstr "" +msgid "schema \"%s\" already exists" +msgstr "схема \"%s\" уже существует" -#: catalog/pg_operator.c:215 catalog/pg_operator.c:401 +#: catalog/pg_operator.c:217 +#: catalog/pg_operator.c:406 #, c-format msgid "\"%s\" is not a valid operator name" msgstr "\"%s\" не является верным именем оператора" -#: catalog/pg_operator.c:404 +#: catalog/pg_operator.c:412 msgid "at least one of leftarg or rightarg must be specified" msgstr "" -#: catalog/pg_operator.c:410 +#: catalog/pg_operator.c:420 msgid "only binary operators can have commutators" msgstr "" -#: catalog/pg_operator.c:412 +#: catalog/pg_operator.c:424 msgid "only binary operators can have join selectivity" msgstr "" -#: catalog/pg_operator.c:414 +#: catalog/pg_operator.c:428 msgid "only binary operators can hash" msgstr "" -#: catalog/pg_operator.c:416 +#: catalog/pg_operator.c:432 msgid "only binary operators can mergejoin" msgstr "" -#: catalog/pg_operator.c:426 +#: catalog/pg_operator.c:444 #, c-format -msgid "OperatorDef: operator \"%s\" already defined" -msgstr "OperatorDef: оператор \"%s\" уже определён" - -#: catalog/pg_operator.c:623 -#, c-format -msgid "OperatorDef: operator %u not found" -msgstr "" +msgid "operator %s already exists" +msgstr "оператор %s уже существует" -#: catalog/pg_operator.c:711 +#: catalog/pg_operator.c:726 msgid "operator cannot be its own negator or sort operator" msgstr "" -#: catalog/pg_operator.c:728 -#, c-format -msgid "OperatorDef: can't create operator shell \"%s\"" -msgstr "" - -#: catalog/pg_proc.c:86 commands/functioncmds.c:140 parser/parse_func.c:1393 +#: catalog/pg_proc.c:88 +#: commands/functioncmds.c:150 +#: parser/parse_func.c:1514 #, c-format msgid "functions cannot have more than %d arguments" msgstr "функции не могут иметь число аргументов более %d" -#: catalog/pg_proc.c:127 -msgid "lookup for procedure by source needs fix (Jan)" +#: catalog/pg_proc.c:113 +#: catalog/pg_proc.c:536 +msgid "A function returning ANYARRAY or ANYELEMENT must have at least one argument of either type." msgstr "" -#: catalog/pg_proc.c:139 +#: catalog/pg_proc.c:168 #, c-format -msgid "method %s already an attribute of type %s" +msgid "\"%s\" is already an attribute of type %s" msgstr "" -#: catalog/pg_proc.c:189 +#: catalog/pg_proc.c:220 #, c-format -msgid "function %s already exists with same argument types" -msgstr "" +msgid "function \"%s\" already exists with same argument types" +msgstr "функция \"%s\" с таким набором аргументов уже существует" -#: catalog/pg_proc.c:192 -#, c-format -msgid "ProcedureCreate: you do not have permission to replace function %s" -msgstr "" +#: catalog/pg_proc.c:234 +msgid "cannot change return type of existing function" +msgstr "нельзя поменять тип возвращаемого значения для существующей фунции" -#: catalog/pg_proc.c:201 -msgid "" -"ProcedureCreate: cannot change return type of existing function.\n" -"\tUse DROP FUNCTION first." +#: catalog/pg_proc.c:235 +msgid "Use DROP FUNCTION first." msgstr "" -#: catalog/pg_proc.c:208 +#: catalog/pg_proc.c:243 #, c-format -msgid "function %s is an aggregate" -msgstr "функция %s не является агрегатом" +msgid "function \"%s\" is an aggregate" +msgstr "функция \"%s\" является агрегатом" -#: catalog/pg_proc.c:211 +#: catalog/pg_proc.c:248 #, c-format -msgid "function %s is not an aggregate" -msgstr "функция %s не является агрегатом" +msgid "function \"%s\" is not an aggregate" +msgstr "функция \"%s\" не является агрегатом" -#: catalog/pg_proc.c:323 +#: catalog/pg_proc.c:367 +#: catalog/pg_proc.c:388 +#: catalog/pg_proc.c:398 +#: catalog/pg_proc.c:422 +#: catalog/pg_proc.c:430 +#: catalog/pg_proc.c:482 +#: catalog/pg_proc.c:494 +#: catalog/pg_proc.c:514 #, c-format -msgid "function declared to return %s, but no SELECT provided" +msgid "return type mismatch in function declared to return %s" msgstr "" -#: catalog/pg_proc.c:341 -msgid "function declared to return void, but final statement is a SELECT" +#: catalog/pg_proc.c:369 +#: catalog/pg_proc.c:400 +msgid "Function's final statement must be a SELECT." msgstr "" -#: catalog/pg_proc.c:347 -#, c-format -msgid "function declared to return %s, but final statement is not a SELECT" +#: catalog/pg_proc.c:390 +msgid "Function's final statement must not be a SELECT." msgstr "" -#: catalog/pg_proc.c:368 -#, c-format -msgid "function declared to return %s returns multiple columns in final SELECT" +#: catalog/pg_proc.c:424 +msgid "Final SELECT must return exactly one column." msgstr "" -#: catalog/pg_proc.c:373 +#: catalog/pg_proc.c:432 #, c-format -msgid "return type mismatch in function: declared to return %s, returns %s" +msgid "Actual return type is %s." msgstr "" -#: catalog/pg_proc.c:421 catalog/pg_proc.c:447 -#, c-format -msgid "" -"function declared to return %s does not SELECT the right number of columns (%" -"d)" +#: catalog/pg_proc.c:484 +msgid "Final SELECT returns too many columns." msgstr "" -#: catalog/pg_proc.c:430 +#: catalog/pg_proc.c:496 #, c-format -msgid "function declared to return %s returns %s instead of %s at column %d" +msgid "Final SELECT returns %s instead of %s at column %d." msgstr "" -#: catalog/pg_proc.c:486 catalog/pg_proc.c:525 catalog/pg_proc.c:568 -#: commands/functioncmds.c:739 utils/adt/ruleutils.c:3163 -#, c-format -msgid "cache lookup of function %u failed" -msgstr "поиск в кзше функции %u не удался" +#: catalog/pg_proc.c:516 +msgid "Final SELECT returns too few columns." +msgstr "" -#: catalog/pg_proc.c:491 catalog/pg_proc.c:530 catalog/pg_proc.c:590 -msgid "null prosrc" -msgstr "null prosrc" +#: catalog/pg_proc.c:541 +#, c-format +msgid "return type %s is not supported for SQL functions" +msgstr "" -#: catalog/pg_proc.c:495 +#: catalog/pg_proc.c:578 #, c-format msgid "there is no built-in function named \"%s\"" msgstr "встроенной функции \"%s\" не существует" -#: catalog/pg_proc.c:535 -msgid "null probin" -msgstr "null probin" - -#: catalog/pg_proc.c:578 +#: catalog/pg_proc.c:671 #, c-format msgid "SQL functions cannot return type %s" msgstr "SQL-функции не могут возвращать тип %s" -#: catalog/pg_proc.c:584 +#: catalog/pg_proc.c:687 #, c-format msgid "SQL functions cannot have arguments of type %s" msgstr "SQL-функции не могут иметь аргументы типа %s" -#: catalog/pg_type.c:171 catalog/pg_type.c:175 +#: catalog/pg_type.c:195 +#: catalog/pg_type.c:201 #, c-format -msgid "TypeCreate: invalid type internal size %d" +msgid "invalid type internal size %d" msgstr "" -#: catalog/pg_type.c:180 -msgid "TypeCreate: fixed size types must have storage PLAIN" +#: catalog/pg_type.c:208 +msgid "fixed-size types must have storage PLAIN" msgstr "" -#: catalog/pg_type.c:257 +#: catalog/pg_type.c:289 +#: catalog/pg_type.c:511 #, c-format -msgid "type %s already exists" -msgstr "тип %s уже существует" +msgid "type \"%s\" already exists" +msgstr "тип \"%s\" уже существует" -#: catalog/pg_type.c:437 +#: catalog/pg_type.c:503 +#: commands/functioncmds.c:109 +#: commands/typecmds.c:407 +#: commands/typecmds.c:786 +#: commands/typecmds.c:1113 +#: commands/typecmds.c:1233 +#: commands/typecmds.c:1353 +#: commands/typecmds.c:1440 +#: commands/typecmds.c:2034 +#: parser/parse_func.c:1526 +#: parser/parse_type.c:201 +#: parser/parse_type.c:227 +#: tcop/utility.c:95 #, c-format -msgid "type %s does not exist" -msgstr "тип %s не существует" +msgid "type \"%s\" does not exist" +msgstr "тип \"%s\" не существует" -#: catalog/pg_type.c:443 +#: commands/aggregatecmds.c:97 #, c-format -msgid "type named %s already exists" -msgstr "тип %s уже существует" +msgid "aggregate attribute \"%s\" not recognized" +msgstr "агрегатный атрибут \"%s\" не распознан" -#: commands/analyze.c:199 -#, c-format -msgid "Skipping \"%s\" --- only table or database owner can ANALYZE it" +#: commands/aggregatecmds.c:107 +msgid "aggregate basetype must be specified" msgstr "" -#: commands/analyze.c:213 commands/vacuum.c:784 -#, c-format -msgid "" -"Skipping \"%s\" --- can not process indexes, views or special system tables" +#: commands/aggregatecmds.c:111 +msgid "aggregate stype must be specified" msgstr "" -"Пропускается \"%s\" --- индексы, виды илм специальные системные таблицы не " -"обрабатываются" - -#: commands/analyze.c:242 -#, c-format -msgid "Analyzing %s.%s" -msgstr "Анализируется %s.%s" -#: commands/analyze.c:431 utils/adt/ruleutils.c:2498 -#, c-format -msgid "cache lookup of type %u failed" +#: commands/aggregatecmds.c:115 +msgid "aggregate sfunc must be specified" msgstr "" -#: commands/analyze.c:638 -#, c-format -msgid "acquire_sample_rows: ReadBuffer(%s,%u) failed" -msgstr "acquire_sample_rows: ReadBuffer(%s,%u) не удался" - -#: commands/aggregatecmds.c:93 +#: commands/aggregatecmds.c:138 #, c-format -msgid "DefineAggregate: attribute \"%s\" not recognized" -msgstr "" - -#: commands/aggregatecmds.c:101 -msgid "Define: \"basetype\" unspecified" -msgstr "" - -#: commands/aggregatecmds.c:103 -msgid "Define: \"stype\" unspecified" -msgstr "" - -#: commands/aggregatecmds.c:105 -msgid "Define: \"sfunc\" unspecified" +msgid "aggregate transition datatype cannot be %s" msgstr "" -#: commands/aggregatecmds.c:123 +#: commands/aggregatecmds.c:259 #, c-format -msgid "Aggregate transition datatype cannot be %s" +msgid "function %s(*) already exists in schema \"%s\"" msgstr "" -#: commands/aggregatecmds.c:174 +#: commands/aggregatecmds.c:265 +#: commands/functioncmds.c:680 #, c-format -msgid "RemoveAggregate: couldn't find pg_proc tuple for %s" +msgid "function %s already exists in schema \"%s\"" msgstr "" -#: commands/async.c:153 -#, c-format -msgid "Async_Notify: %s" -msgstr "Async_Notify: %s" - -#: commands/async.c:201 -#, c-format -msgid "Async_Listen: %s" -msgstr "Async_Listen: %s" - -#: commands/async.c:224 +#: commands/analyze.c:200 #, c-format -msgid "Async_Listen: We are already listening on %s" +msgid "skipping \"%s\" --- only table or database owner can ANALYZE it" msgstr "" -#: commands/async.c:296 +#: commands/analyze.c:215 #, c-format -msgid "Async_Unlisten %s" -msgstr "Async_Unlisten %s" +msgid "skipping \"%s\" --- cannot ANALYZE indexes, views or special system tables" +msgstr "пропускается \"%s\" --- индексы, виды или специальные системные таблицы не анализируются" -#: commands/async.c:354 -msgid "Async_UnlistenAll" -msgstr "Async_UnlistenAll" - -#: commands/async.c:456 -msgid "AtCommit_Notify" -msgstr "AtCommit_Notify" - -#: commands/async.c:488 -msgid "AtCommit_Notify: notifying self" -msgstr "" - -#: commands/async.c:495 +#: commands/analyze.c:245 #, c-format -msgid "AtCommit_Notify: notifying pid %d" -msgstr "" - -#: commands/async.c:544 -msgid "AtCommit_Notify: done" -msgstr "AtCommit_Notify: завершено" - -#: commands/async.c:621 -msgid "Async_NotifyHandler: perform async notify" -msgstr "" - -#: commands/async.c:626 -msgid "Async_NotifyHandler: done" -msgstr "Async_NotifyHandler: завершено" +msgid "analyzing \"%s.%s\"" +msgstr "анализируется \"%s.%s\"" -#: commands/async.c:693 -msgid "EnableNotifyInterrupt: perform async notify" +#: commands/cluster.c:150 +#, c-format +msgid "there is no previously clustered index for table \"%s\"" msgstr "" -#: commands/async.c:698 -msgid "EnableNotifyInterrupt: done" -msgstr "EnableNotifyInterrupt: завершено" - -#: commands/async.c:749 -msgid "ProcessIncomingNotify" -msgstr "ProcessIncomingNotify" - -#: commands/async.c:785 +#: commands/cluster.c:164 +#: commands/tablecmds.c:3988 #, c-format -msgid "ProcessIncomingNotify: received %s from %d" -msgstr "ProcessIncomingNotify: получено %s от %d" - -#: commands/async.c:820 -msgid "ProcessIncomingNotify: done" -msgstr "ProcessIncomingNotify: завершено" +msgid "index \"%s\" for table \"%s\" does not exist" +msgstr "индекс \"%s\" для таблицы \"%s\" не существует" -#: commands/async.c:847 +#: commands/cluster.c:321 #, c-format -msgid "NOTIFY for %s" -msgstr "NOTIFY для %s" +msgid "\"%s\" is not an index for table \"%s\"" +msgstr "\"%s\" не является индексом для таблицы \"%s\"" -#: commands/cluster.c:119 -#, c-format -msgid "CLUSTER: You do not own relation %s" +#: commands/cluster.c:334 +msgid "cannot cluster on partial index" msgstr "" -#: commands/cluster.c:137 commands/cluster.c:541 commands/cluster.c:560 -#, c-format -msgid "Cache lookup failed for index %u" -msgstr "Поиск в кэше индекса %u не удался" - -#: commands/cluster.c:150 -#, c-format -msgid "CLUSTER: No previously clustered index found on table \"%s\"" +#: commands/cluster.c:352 +msgid "cannot cluster when index access method does not handle nulls" msgstr "" -#: commands/cluster.c:159 +#: commands/cluster.c:353 #, c-format -msgid "CLUSTER: cannot find index \"%s\" for table \"%s\"" +msgid "You may be able to work around this by marking column \"%s\" NOT NULL." msgstr "" -#: commands/cluster.c:312 -#, c-format -msgid "CLUSTER: \"%s\" is not an index for table \"%s\"" +#: commands/cluster.c:365 +msgid "cannot cluster on expressional index when index access method does not handle nulls" msgstr "" -#: commands/cluster.c:324 +#: commands/cluster.c:379 #, c-format -msgid "CLUSTER: cannot cluster system relation \"%s\"" -msgstr "" +msgid "\"%s\" is a system catalog" +msgstr "\"%s\" является системным каталогом" -#: commands/cluster.c:332 -msgid "CLUSTER cannot be used on temp tables of other processes" +#: commands/cluster.c:389 +msgid "cannot cluster temp tables of other processes" msgstr "" -#: commands/cluster.c:627 +#: commands/async.c:225 #, c-format -msgid "cache lookup failed for index %u" -msgstr "поиск в кэше индекса %u не удался" - -#: commands/cluster.c:679 commands/cluster.c:686 -#, c-format -msgid "CLUSTER: Cannot find tuple for relation %u" +msgid "already listening on \"%s\"" msgstr "" -#: commands/cluster.c:698 commands/cluster.c:704 +#: commands/conversioncmds.c:66 #, c-format -msgid "CLUSTER: FlushRelationBuffers returned %d" -msgstr "CLUSTER: FlushRelationBuffers возвратила %d" - -#: commands/cluster.c:766 -msgid "CLUSTER: expected both swapped tables to have TOAST tables" +msgid "source encoding \"%s\" does not exist" msgstr "" -#: commands/cluster.c:772 commands/cluster.c:777 +#: commands/conversioncmds.c:73 #, c-format -msgid "CLUSTER: expected one dependency record for TOAST table, found %ld" +msgid "destination encoding \"%s\" does not exist" msgstr "" -#: commands/comment.c:111 +#: commands/conversioncmds.c:151 #, c-format -msgid "An attempt was made to comment on a unknown type: %d" +msgid "conversion \"%s\" already exists in schema \"%s\"" msgstr "" -#: commands/comment.c:306 +#: commands/comment.c:309 +#: commands/indexcmds.c:583 +#: commands/indexcmds.c:617 #, c-format msgid "relation \"%s\" is not an index" msgstr "объект \"%s\" не является индексом" -#: commands/comment.c:311 +#: commands/comment.c:316 #, c-format msgid "relation \"%s\" is not a sequence" -msgstr "" +msgstr "связь \"%s\" не является последовательностью" -#: commands/comment.c:316 +#: commands/comment.c:323 +#: commands/indexcmds.c:109 +#: commands/indexcmds.c:669 #, c-format msgid "relation \"%s\" is not a table" msgstr "объект \"%s\" не является таблицей" -#: commands/comment.c:321 +#: commands/comment.c:330 #, c-format msgid "relation \"%s\" is not a view" msgstr "объект \"%s\" не является видом" -#: commands/comment.c:357 -msgid "CommentAttribute: must specify relation.attribute" -msgstr "" - -#: commands/comment.c:374 commands/tablecmds.c:1953 commands/tablecmds.c:2087 -#: commands/tablecmds.c:2205 commands/tablecmds.c:2422 -#: optimizer/prep/prepunion.c:802 parser/parse_func.c:1176 -#: parser/parse_relation.c:1551 parser/parse_relation.c:1614 -#: parser/parse_relation.c:1770 parser/parse_type.c:88 +#: commands/comment.c:386 +#: commands/tablecmds.c:2020 +#: commands/tablecmds.c:2164 +#: commands/tablecmds.c:2292 +#: commands/tablecmds.c:2456 +#: commands/tablecmds.c:2669 +#: parser/parse_func.c:1270 +#: parser/parse_relation.c:1583 +#: parser/parse_relation.c:1641 +#: parser/parse_relation.c:1820 +#: parser/parse_type.c:94 #, c-format -msgid "Relation \"%s\" has no column \"%s\"" -msgstr "Связь \"%s\" не имеет колонки \"%s\"" +msgid "attribute \"%s\" of relation \"%s\" does not exist" +msgstr "атрибут \"%s\" для связи \"%s\" не существует" -#: commands/comment.c:403 -msgid "CommentDatabase: database name may not be qualified" -msgstr "" - -#: commands/comment.c:409 commands/dbcommands.c:531 utils/adt/acl.c:1038 -#, c-format -msgid "database \"%s\" does not exist" -msgstr "база данных \"%s\" не существует" - -#: commands/comment.c:414 -#, c-format -msgid "you are not permitted to comment on database \"%s\"" +#: commands/comment.c:417 +msgid "database name may not be qualified" msgstr "" -#: commands/comment.c:419 -msgid "Database comments may only be applied to the current database" +#: commands/comment.c:449 +msgid "database comments may only be applied to the current database" msgstr "" -#: commands/comment.c:442 -msgid "CommentSchema: schema name may not be qualified" +#: commands/comment.c:481 +#: commands/schemacmds.c:172 +msgid "schema name may not be qualified" msgstr "" -#: commands/comment.c:449 -#, c-format -msgid "CommentSchema: Schema \"%s\" could not be found" -msgstr "CommentSchema: Схема \"%s\" не найдена" - -#: commands/comment.c:521 commands/comment.c:555 +#: commands/comment.c:564 #, c-format msgid "rule \"%s\" does not exist" msgstr "правило \"%s\" не существует" -#: commands/comment.c:527 +#: commands/comment.c:572 #, c-format -msgid "" -"There are multiple rules \"%s\"\n" -"\tPlease specify a relation name as well as a rule name" +msgid "there are multiple rules \"%s\"" msgstr "" -#: commands/comment.c:732 -msgid "CommentTrigger: must specify relation and trigger" +#: commands/comment.c:573 +msgid "Specify a relation name as well as a rule name." msgstr "" -#: commands/comment.c:765 +#: commands/comment.c:815 +#: commands/trigger.c:484 +#: commands/trigger.c:697 #, c-format msgid "trigger \"%s\" for relation \"%s\" does not exist" msgstr "триггер \"%s\" для связи \"%s\" не существует" -#: commands/comment.c:807 -msgid "CommentConstraint: must specify relation and constraint" -msgstr "" - -#: commands/comment.c:841 +#: commands/comment.c:894 #, c-format -msgid "Relation \"%s\" has multiple constraints named \"%s\"" +msgid "relation \"%s\" has multiple constraints named \"%s\"" msgstr "" -#: commands/comment.c:851 +#: commands/comment.c:906 #, c-format msgid "constraint \"%s\" for relation \"%s\" does not exist" msgstr "" -#: commands/conversioncmds.c:58 -#, c-format -msgid "Invalid for encoding name: %s" -msgstr "Невернаое имя исходной кодировки (for): %s" +#: commands/copy.c:684 +#: commands/copy.c:692 +#: commands/copy.c:700 +#: commands/copy.c:708 +#: commands/dbcommands.c:103 +#: commands/dbcommands.c:111 +#: commands/dbcommands.c:119 +#: commands/dbcommands.c:127 +#: commands/functioncmds.c:220 +#: commands/functioncmds.c:228 +#: commands/functioncmds.c:236 +#: commands/functioncmds.c:244 +#: commands/functioncmds.c:252 +#: commands/sequence.c:895 +#: commands/sequence.c:908 +#: commands/sequence.c:916 +#: commands/sequence.c:924 +#: commands/sequence.c:932 +#: commands/sequence.c:940 +#: commands/user.c:525 +#: commands/user.c:537 +#: commands/user.c:545 +#: commands/user.c:553 +#: commands/user.c:561 +#: commands/user.c:569 +#: commands/user.c:775 +#: commands/user.c:787 +#: commands/user.c:795 +#: commands/user.c:803 +#: commands/user.c:1275 +#: commands/user.c:1283 +msgid "conflicting or redundant options" +msgstr "" -#: commands/conversioncmds.c:62 +#: commands/dbcommands.c:153 #, c-format -msgid "Invalid to encoding name: %s" -msgstr "Неверное имя кодировки назначения (to): %s" +msgid "%d is not a valid encoding code" +msgstr "%d не является верным кодом кодировки" -#: commands/copy.c:128 +#: commands/dbcommands.c:162 #, c-format -msgid "CopySendData: %m" -msgstr "CopySendData: %m" - -#: commands/copy.c:303 -msgid "COPY: BINARY option appears more than once" -msgstr "" +msgid "%s is not a valid encoding name" +msgstr "%s не является верным именем кодировки" -#: commands/copy.c:310 -msgid "COPY: OIDS option appears more than once" -msgstr "" +#: commands/dbcommands.c:183 +msgid "permission denied to create database" +msgstr "доступ запрещён по созданию базы" -#: commands/copy.c:317 -msgid "COPY: DELIMITER string may only be defined once in query" +#: commands/dbcommands.c:192 +msgid "must be superuser to create database for another user" msgstr "" -#: commands/copy.c:324 -msgid "COPY: NULL representation may only be defined once in query" +#: commands/dbcommands.c:203 +msgid "cannot use an alternate location on this platform" msgstr "" -#: commands/copy.c:329 +#: commands/dbcommands.c:217 +#: commands/dbcommands.c:384 +#: commands/dbcommands.c:632 #, c-format -msgid "COPY: option \"%s\" not recognized" -msgstr "" - -#: commands/copy.c:334 -msgid "You can not specify the DELIMITER in BINARY mode." -msgstr "" - -#: commands/copy.c:337 -msgid "You can not specify NULL in BINARY mode." -msgstr "" - -#: commands/copy.c:357 -msgid "" -"You must have Postgres superuser privilege to do a COPY directly to or from " -"a file. Anyone can COPY to stdout or from stdin. Psql's \\copy command " -"also works for anyone." -msgstr "" - -#: commands/copy.c:366 -msgid "COPY BINARY is not supported to stdout or from stdin" -msgstr "" - -#: commands/copy.c:372 -msgid "COPY delimiter must be a single character" -msgstr "" +msgid "database \"%s\" already exists" +msgstr "база \"%s\" уже существует" -#: commands/copy.c:378 +#: commands/dbcommands.c:231 #, c-format -msgid "COPY: table \"%s\" does not have OIDs" -msgstr "COPY: таблица \"%s\" не содержит OIDs" +msgid "template \"%s\" does not exist" +msgstr "шаблон \"%s\" не существует" -#: commands/copy.c:399 commands/copy.c:444 +#: commands/dbcommands.c:242 #, c-format -msgid "You cannot copy view %s" -msgstr "Вы не можете копировать вид %s" +msgid "permission denied to copy database \"%s\"" +msgstr "доступ запрещён по копированию базы \"%s\"" -#: commands/copy.c:402 +#: commands/dbcommands.c:263 #, c-format -msgid "You cannot change sequence relation %s" +msgid "source database \"%s\" is being accessed by other users" msgstr "" -#: commands/copy.c:405 commands/copy.c:450 -#, c-format -msgid "You cannot copy object %s" -msgstr "Вы не можете копировать объект %s" - -#: commands/copy.c:425 +#: commands/dbcommands.c:274 #, c-format -msgid "" -"COPY command, running in backend with effective uid %d, could not open file " -"'%s' for reading. Errno = %s (%d)." +msgid "invalid backend encoding %d" msgstr "" -"Команда COPY, выполняющаяся в backendе с эффективным UID %d, не смогла " -"открыть файл '%s' для чтения. Errno = %s (%d)." - -#: commands/copy.c:434 commands/copy.c:490 -#, c-format -msgid "COPY: %s is a directory" -msgstr "COPY: %s является директорией" -#: commands/copy.c:447 -#, c-format -msgid "You cannot copy sequence %s" +#: commands/dbcommands.c:304 +#: commands/dbcommands.c:308 +#: commands/dbcommands.c:312 +msgid "database path may not contain single quotes" msgstr "" -#: commands/copy.c:474 -msgid "Relative path not allowed for server side COPY command" -msgstr "" +#: commands/dbcommands.c:337 +#, c-format +msgid "could not create database directory \"%s\": %m" +msgstr "не получилось создать директорию баз данных \"%s\": %m" -#: commands/copy.c:482 +#: commands/dbcommands.c:342 #, c-format -msgid "" -"COPY command, running in backend with effective uid %d, could not open file " -"'%s' for writing. Errno = %s (%d)." +msgid "could not remove temp directory \"%s\": %m" msgstr "" -"Команда COPY, выполняющаяся в backendе с эффективным UID %d, не смогла " -"открыть файл '%s' для записи. Errno = %s (%d)." -#: commands/copy.c:561 +#: commands/dbcommands.c:353 #, c-format -msgid "COPY: couldn't lookup info for type %u" +msgid "could not link \"%s\" to \"%s\": %m" msgstr "" -#: commands/copy.c:565 commands/copy.c:835 -msgid "COPY BINARY: cstring not supported" +#: commands/dbcommands.c:462 +msgid "cannot drop the currently open database" msgstr "" -#: commands/copy.c:906 -msgid "COPY BINARY: file signature not recognized" +#: commands/dbcommands.c:495 +msgid "cannot drop a template database" msgstr "" -#: commands/copy.c:910 -msgid "COPY BINARY: incompatible integer layout" +#: commands/dbcommands.c:506 +#: commands/dbcommands.c:622 +#, c-format +msgid "database \"%s\" is being accessed by other users" msgstr "" -#: commands/copy.c:914 -msgid "COPY BINARY: bogus file header (missing flags)" +#: commands/dbcommands.c:613 +msgid "current database may not be renamed" msgstr "" -#: commands/copy.c:918 -msgid "COPY BINARY: unrecognized critical flags in header" -msgstr "" +#: commands/dbcommands.c:644 +msgid "permission denied to rename database" +msgstr "доступ запрещён по переименованию базы" -#: commands/copy.c:922 -msgid "COPY BINARY: bogus file header (missing length)" +#: commands/dbcommands.c:863 +msgid "relative paths are not allowed as database locations" msgstr "" -#: commands/copy.c:928 -msgid "COPY BINARY: bogus file header (wrong length)" +#: commands/dbcommands.c:867 +msgid "absolute paths are not allowed as database locations" msgstr "" -#: commands/copy.c:979 -msgid "NULL Oid" -msgstr "NULL Oid" - -#: commands/copy.c:985 -msgid "Invalid Oid" -msgstr "Неверный Oid" - -#: commands/copy.c:1002 +#: commands/dbcommands.c:879 #, c-format -msgid "Missing data for column \"%s\"" -msgstr "Отсутствуют данные для колонки \"%s\"" - -#: commands/copy.c:1034 -msgid "Extra data after last expected column" +msgid "postmaster environment variable \"%s\" not found" msgstr "" -#: commands/copy.c:1058 +#: commands/dbcommands.c:884 #, c-format -msgid "COPY BINARY: tuple field count is %d, expected %d" +msgid "postmaster environment variable \"%s\" must be absolute path" msgstr "" -#: commands/copy.c:1065 commands/copy.c:1071 commands/copy.c:1086 -#: commands/copy.c:1100 commands/copy.c:1109 commands/copy.c:1121 -#: commands/copy.c:1136 -msgid "COPY BINARY: unexpected EOF" +#: commands/dbcommands.c:893 +msgid "alternate path is too long" msgstr "" -#: commands/copy.c:1067 +#: commands/dbcommands.c:924 #, c-format -msgid "COPY BINARY: sizeof(Oid) is %d, expected %d" -msgstr "" - -#: commands/copy.c:1073 -msgid "COPY BINARY: Invalid Oid" -msgstr "" +msgid "could not remove \"%s\": %m" +msgstr "не получилось удалить \"%s\": %m" -#: commands/copy.c:1090 +#: commands/dbcommands.c:939 #, c-format -msgid "COPY BINARY: sizeof(field %d) is %d, expected %d" +msgid "could not remove database directory \"%s\": %m" msgstr "" -#: commands/copy.c:1102 -msgid "COPY BINARY: bogus varlena length" +#: commands/copy.c:177 +#: commands/copy.c:189 +#: commands/copy.c:222 +#: commands/copy.c:232 +msgid "COPY BINARY is not supported to stdout or from stdin" msgstr "" -#: commands/copy.c:1284 +#: commands/copy.c:285 #, c-format -msgid "GetInputFunction: Cache lookup of type %u failed" +msgid "failed to write COPY file: %m" msgstr "" -#: commands/copy.c:1300 -#, c-format -msgid "GetTypeElement: Cache lookup of type %u failed" +#: commands/copy.c:293 +msgid "connection lost during COPY to stdout" msgstr "" -#: commands/copy.c:1442 -msgid "CopyReadAttribute: end of record marker corrupted" +#: commands/copy.c:376 +#: commands/copy.c:394 +#: commands/copy.c:398 +#: commands/copy.c:458 +#: commands/copy.c:507 +#: tcop/fastpath.c:292 +#: tcop/postgres.c:281 +#: tcop/postgres.c:304 +msgid "unexpected EOF on client connection" msgstr "" -#: commands/copy.c:1594 +#: commands/copy.c:410 #, c-format -msgid "Attribute \"%s\" specified more than once" -msgstr "Атрибут \"%s\" указан более одного раза" - -#: commands/dbcommands.c:99 commands/dbcommands.c:105 -#: commands/dbcommands.c:111 commands/dbcommands.c:117 -msgid "CREATE DATABASE: conflicting options" +msgid "COPY from stdin failed: %s" msgstr "" -#: commands/dbcommands.c:121 +#: commands/copy.c:425 #, c-format -msgid "CREATE DATABASE: option \"%s\" not recognized" +msgid "unexpected message type 0x%02X during COPY from stdin" msgstr "" -#: commands/dbcommands.c:141 -#, c-format -msgid "%d is not a valid encoding code" -msgstr "%d не является верным кодом кодировки" +#: commands/copy.c:719 +msgid "cannot specify DELIMITER in BINARY mode" +msgstr "" -#: commands/dbcommands.c:147 -#, c-format -msgid "%s is not a valid encoding name" -msgstr "%s не является верным именем кодировки" +#: commands/copy.c:724 +msgid "cannot specify NULL in BINARY mode" +msgstr "" -#: commands/dbcommands.c:151 -msgid "CREATE DATABASE: bogus encoding parameter" +#: commands/copy.c:742 +#: executor/execMain.c:462 +#: tcop/utility.c:260 +msgid "transaction is read-only" +msgstr "транзакция установлена \"только для чтения\"" + +#: commands/copy.c:753 +msgid "must be superuser to COPY to or from a file" msgstr "" -#: commands/dbcommands.c:164 commands/dbcommands.c:171 -msgid "CREATE DATABASE: permission denied" +#: commands/copy.c:754 +msgid "Anyone can COPY to stdout or from stdin. psql's \\copy command also works for anyone." msgstr "" -#: commands/dbcommands.c:186 commands/dbcommands.c:326 -#, c-format -msgid "CREATE DATABASE: database \"%s\" already exists" +#: commands/copy.c:763 +msgid "COPY delimiter must be a single character" msgstr "" -#: commands/dbcommands.c:198 +#: commands/copy.c:771 #, c-format -msgid "CREATE DATABASE: template \"%s\" does not exist" -msgstr "" +msgid "table \"%s\" does not have OIDs" +msgstr "таблица \"%s\" не содержит OIDs" -#: commands/dbcommands.c:208 +#: commands/copy.c:799 #, c-format -msgid "CREATE DATABASE: permission to copy \"%s\" denied" -msgstr "" +msgid "cannot copy to view \"%s\"" +msgstr "нельзя копировать в вид \"%s\"" -#: commands/dbcommands.c:227 +#: commands/copy.c:804 #, c-format -msgid "" -"CREATE DATABASE: source database \"%s\" is being accessed by other users" -msgstr "" +msgid "cannot copy to sequence \"%s\"" +msgstr "нельзя копировать в последовательность \"%s\"" -#: commands/dbcommands.c:235 -msgid "CREATE DATABASE: invalid backend encoding" -msgstr "" +#: commands/copy.c:809 +#, c-format +msgid "cannot copy to non-table relation \"%s\"" +msgstr "нельзя копировать в не-таблицу \"%s\"" -#: commands/dbcommands.c:263 commands/dbcommands.c:265 -#: commands/dbcommands.c:267 -msgid "database path may not contain single quotes" -msgstr "" +#: commands/copy.c:828 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "не получилось отктрыть файл \"%s\" для чтения: %m" -#: commands/dbcommands.c:290 +#: commands/copy.c:837 +#: commands/copy.c:899 #, c-format -msgid "CREATE DATABASE: unable to create database directory '%s': %m" -msgstr "" +msgid "\"%s\" is a directory" +msgstr "\"%s\" является директорией" -#: commands/dbcommands.c:293 +#: commands/copy.c:849 #, c-format -msgid "CREATE DATABASE: unable to remove temp directory '%s': %m" -msgstr "" +msgid "cannot copy from view \"%s\"" +msgstr "нельзя копировать из вида \"%s\"" -#: commands/dbcommands.c:300 +#: commands/copy.c:854 #, c-format -msgid "CREATE DATABASE: could not link '%s' to '%s': %m" -msgstr "" +msgid "cannot copy from sequence \"%s\"" +msgstr "нельзя копировать из последовательности \"%s\"" -#: commands/dbcommands.c:310 -msgid "CREATE DATABASE: could not initialize database directory" -msgstr "" +#: commands/copy.c:859 +#, c-format +msgid "cannot copy from non-table relation \"%s\"" +msgstr "нельзя копировать из не-таблицы \"%s\"" -#: commands/dbcommands.c:312 -msgid "" -"CREATE DATABASE: could not initialize database directory; delete failed as " -"well" +#: commands/copy.c:881 +msgid "relative path not allowed for COPY to file" msgstr "" -#: commands/dbcommands.c:402 -msgid "DROP DATABASE: cannot be executed on the currently open database" -msgstr "" +#: commands/copy.c:890 +#, c-format +msgid "could not open file \"%s\" for writing: %m" +msgstr "не получилось отктрыть файл \"%s\" для записи: %m" -#: commands/dbcommands.c:419 +#: commands/copy.c:1114 #, c-format -msgid "DROP DATABASE: database \"%s\" does not exist" -msgstr "" +msgid "COPY FROM, line %d" +msgstr "COPY FROM, строка %d" -#: commands/dbcommands.c:422 -msgid "DROP DATABASE: permission denied" +#: commands/copy.c:1282 +msgid "COPY file signature not recognized" msgstr "" -#: commands/dbcommands.c:430 -msgid "DROP DATABASE: database is marked as a template" +#: commands/copy.c:1288 +msgid "invalid COPY file header (missing flags)" msgstr "" -#: commands/dbcommands.c:439 -#, c-format -msgid "DROP DATABASE: database \"%s\" is being accessed by other users" +#: commands/copy.c:1294 +msgid "unrecognized critical flags in COPY file header" msgstr "" -#: commands/dbcommands.c:456 -#, c-format -msgid "" -"DROP DATABASE: Database \"%s\" doesn't exist despite earlier reports to the " -"contrary" +#: commands/copy.c:1300 +msgid "invalid COPY file header (missing length)" msgstr "" -#: commands/dbcommands.c:700 -msgid "Relative paths are not allowed as database locations" +#: commands/copy.c:1308 +msgid "invalid COPY file header (wrong length)" msgstr "" -#: commands/dbcommands.c:702 -msgid "Absolute paths are not allowed as database locations" +#: commands/copy.c:1376 +msgid "null OID in COPY data" msgstr "" -#: commands/dbcommands.c:712 -#, c-format -msgid "Postmaster environment variable '%s' not set" +#: commands/copy.c:1384 +#: commands/copy.c:1499 +msgid "invalid OID in COPY data" msgstr "" -#: commands/dbcommands.c:714 +#: commands/copy.c:1403 #, c-format -msgid "Postmaster environment variable '%s' must be absolute path" -msgstr "" +msgid "missing data for column \"%s\"" +msgstr "отсутствуют данные для колонки \"%s\"" -#: commands/dbcommands.c:720 -msgid "Alternate path is too long" +#: commands/copy.c:1449 +#: commands/copy.c:1460 +msgid "extra data after last expected column" msgstr "" -#: commands/dbcommands.c:749 +#: commands/copy.c:1486 #, c-format -msgid "could not remove '%s': %m" +msgid "row field count is %d, expected %d" msgstr "" -#: commands/dbcommands.c:758 -#, c-format -msgid "database directory '%s' could not be removed" +#: commands/copy.c:1691 +#: commands/copy.c:1709 +msgid "literal carriage return found in data" msgstr "" -#: commands/dbcommands.c:830 commands/vacuum.c:581 -#, c-format -msgid "database %u does not exist" +#: commands/copy.c:1692 +#: commands/copy.c:1710 +msgid "Use \"\\r\" to represent carriage return." msgstr "" -#: commands/define.c:68 commands/define.c:157 commands/define.c:185 -#: commands/define.c:215 -#, c-format -msgid "Define: \"%s\" requires a parameter" +#: commands/copy.c:1728 +msgid "literal newline found in data" msgstr "" -#: commands/define.c:93 commands/define.c:239 -#, c-format -msgid "Define: cannot interpret argument of \"%s\"" +#: commands/copy.c:1729 +msgid "" +"Use \"\\n" +"\" to represent newline." msgstr "" -#: commands/define.c:106 commands/define.c:115 commands/define.c:128 -#: commands/define.c:144 -#, c-format -msgid "Define: \"%s\" requires a numeric value" +#: commands/copy.c:1826 +#: commands/copy.c:1842 +msgid "end-of-copy marker does not match previous newline style" msgstr "" -#: commands/define.c:169 -#, c-format -msgid "Define: argument of \"%s\" must be a name" +#: commands/copy.c:1830 +#: commands/copy.c:1836 +msgid "end-of-copy marker corrupt" msgstr "" -#: commands/define.c:201 -#, c-format -msgid "Define: argument of \"%s\" must be a type name" +#: commands/copy.c:1911 +#: commands/copy.c:1933 +msgid "unexpected EOF in COPY data" msgstr "" -#: commands/define.c:222 +#: commands/copy.c:1920 #, c-format -msgid "Define: \"%s\" requires an integral value" +msgid "invalid size for field %d" msgstr "" -#: commands/define.c:242 +#: commands/copy.c:1947 #, c-format -msgid "Define: invalid argument for \"%s\": \"%s\"" -msgstr "Define: неверный аргумент для \"%s\": \"%s\"" +msgid "incorrect binary data format in field %d" +msgstr "" -#: commands/explain.c:890 +#: commands/copy.c:2067 +#: parser/parse_target.c:500 #, c-format -msgid "show_sort_keys: no tlist entry for key %d" -msgstr "" +msgid "attribute \"%s\" specified more than once" +msgstr "атрибут \"%s\" указан более одного раза" -#: commands/functioncmds.c:81 +#: commands/functioncmds.c:83 #, c-format -msgid "SQL function cannot return shell type \"%s\"" -msgstr "SQL-функции не могут возвращать тип shell \"%s\"" +msgid "SQL function cannot return shell type %s" +msgstr "SQL-функция не может возвращать тип оболочки %s" -#: commands/functioncmds.c:84 +#: commands/functioncmds.c:88 #, c-format -msgid "Return type \"%s\" is only a shell" +msgid "return type %s is only a shell" msgstr "" -#: commands/functioncmds.c:103 commands/functioncmds.c:159 -#: commands/typecmds.c:345 commands/typecmds.c:352 commands/typecmds.c:689 -#: commands/typecmds.c:933 commands/typecmds.c:1052 commands/typecmds.c:1177 -#: commands/typecmds.c:1264 parser/parse_func.c:1403 parser/parse_oper.c:98 -#: parser/parse_oper.c:107 parser/parse_type.c:191 parser/parse_type.c:213 -#: parser/parse_type.c:219 +#: commands/functioncmds.c:114 #, c-format -msgid "Type \"%s\" does not exist" -msgstr "Тип \"%s\" не существует" +msgid "type \"%s\" is not yet defined" +msgstr "тип \"%s\" ещё не определён" -#: commands/functioncmds.c:106 -#, c-format -msgid "ProcedureCreate: type %s is not yet defined" -msgstr "ProcedureCreate: тип %s ещё не определён" +#: commands/functioncmds.c:115 +msgid "Creating a shell type definition." +msgstr "" -#: commands/functioncmds.c:116 +#: commands/functioncmds.c:162 #, c-format -msgid "could not create type %s" -msgstr "не получилось создать тип %s" +msgid "SQL function cannot accept shell type %s" +msgstr "SQL-функция не может принимать значение типа оболочки %s" -#: commands/functioncmds.c:150 +#: commands/functioncmds.c:167 #, c-format -msgid "SQL function cannot accept shell type \"%s\"" -msgstr "SQL-функции не могут принимать значение типа shell \"%s\"" +msgid "argument type %s is only a shell" +msgstr "тип аргумента %s является только оболочкой" -#: commands/functioncmds.c:153 +#: commands/functioncmds.c:175 +#: parser/parse_oper.c:113 +#: parser/parse_oper.c:124 #, c-format -msgid "Argument type \"%s\" is only a shell" -msgstr "Тип аргумента \"%s\" только shell" - -#: commands/functioncmds.c:164 -msgid "Functions cannot accept set arguments" -msgstr "Функции не принимают аргументы-множества (set)" - -#: commands/functioncmds.c:200 commands/functioncmds.c:206 -#: commands/functioncmds.c:212 commands/functioncmds.c:218 -#: commands/functioncmds.c:224 -msgid "conflicting or redundant options" -msgstr "" +msgid "type %s does not exist" +msgstr "тип %s не существует" -#: commands/functioncmds.c:228 -msgid "invalid CREATE FUNCTION option" -msgstr "" +#: commands/functioncmds.c:182 +msgid "functions cannot accept set arguments" +msgstr "функции не принимают аргументы-множества (set)" -#: commands/functioncmds.c:234 +#: commands/functioncmds.c:265 msgid "no function body specified" msgstr "" -#: commands/functioncmds.c:239 +#: commands/functioncmds.c:272 msgid "no language specified" msgstr "язык не указан" -#: commands/functioncmds.c:250 -msgid "invalid volatility" -msgstr "" - -#: commands/functioncmds.c:297 -#, c-format -msgid "Unrecognized function attribute '%s' ignored" -msgstr "" - -#: commands/functioncmds.c:339 -#, c-format -msgid "CREATE FUNCTION: only one AS item needed for %s language" -msgstr "" - -#: commands/functioncmds.c:399 utils/adt/acl.c:1442 -#, c-format -msgid "language \"%s\" does not exist" -msgstr "язык \"%s\" не существует" - -#: commands/functioncmds.c:505 -#, c-format -msgid "RemoveFunction: couldn't find tuple for function %s" -msgstr "" - -#: commands/functioncmds.c:515 -#, c-format -msgid "" -"RemoveFunction: function '%s' is an aggregate\n" -"\tUse DROP AGGREGATE to remove it" -msgstr "" - -#: commands/functioncmds.c:522 +#: commands/functioncmds.c:333 #, c-format -msgid "Removing built-in function \"%s\"" +msgid "unrecognized function attribute \"%s\" ignored" msgstr "" -#: commands/functioncmds.c:560 +#: commands/functioncmds.c:377 #, c-format -msgid "RemoveFunctionById: couldn't find tuple for function %u" +msgid "only one AS item needed for language \"%s\"" msgstr "" -#: commands/functioncmds.c:582 +#: commands/functioncmds.c:559 +#: commands/functioncmds.c:665 #, c-format -msgid "RemoveFunctionById: couldn't find pg_aggregate tuple for %u" -msgstr "" - -#: commands/functioncmds.c:614 -#, c-format -msgid "SetFunctionReturnType: couldn't find tuple for function %u" -msgstr "" +msgid "\"%s\" is an aggregate function" +msgstr "функция \"%s\" является агрегатом" -#: commands/functioncmds.c:619 -#, c-format -msgid "SetFunctionReturnType: function %u doesn't return OPAQUE" +#: commands/functioncmds.c:561 +msgid "Use DROP AGGREGATE to drop aggregate functions." msgstr "" -#: commands/functioncmds.c:652 +#: commands/functioncmds.c:568 #, c-format -msgid "SetFunctionArgType: couldn't find tuple for function %u" -msgstr "" +msgid "removing built-in function \"%s\"" +msgstr "удаление встроенной функции \"%s\"" -#: commands/functioncmds.c:658 -#, c-format -msgid "SetFunctionArgType: function %u doesn't take OPAQUE" +#: commands/functioncmds.c:667 +msgid "Use ALTER AGGREGATE to rename aggregate functions." msgstr "" -#: commands/functioncmds.c:693 commands/functioncmds.c:884 +#: commands/functioncmds.c:805 +#: commands/functioncmds.c:1039 #, c-format msgid "source data type %s does not exist" msgstr "исходный тип данных %s не существует" -#: commands/functioncmds.c:698 commands/functioncmds.c:889 +#: commands/functioncmds.c:812 +#: commands/functioncmds.c:1046 #, c-format msgid "target data type %s does not exist" msgstr "тип данных назначения %s не существует" -#: commands/functioncmds.c:702 +#: commands/functioncmds.c:818 msgid "source data type and target data type are the same" msgstr "" -#: commands/functioncmds.c:706 +#: commands/functioncmds.c:824 #, c-format msgid "source data type %s is only a shell" msgstr "" -#: commands/functioncmds.c:710 +#: commands/functioncmds.c:830 #, c-format msgid "target data type %s is only a shell" msgstr "" -#: commands/functioncmds.c:714 +#: commands/functioncmds.c:836 #, c-format msgid "source data type %s is a pseudo-type" msgstr "" -#: commands/functioncmds.c:718 +#: commands/functioncmds.c:842 #, c-format msgid "target data type %s is a pseudo-type" msgstr "" -#: commands/functioncmds.c:723 commands/functioncmds.c:904 +#: commands/functioncmds.c:850 +#: commands/functioncmds.c:1065 #, c-format msgid "must be owner of type %s or type %s" msgstr "" -#: commands/functioncmds.c:743 -msgid "cast function must take 1 argument" +#: commands/functioncmds.c:872 +msgid "cast function must take one argument" msgstr "" -#: commands/functioncmds.c:745 +#: commands/functioncmds.c:876 msgid "argument of cast function must match source data type" msgstr "" -#: commands/functioncmds.c:747 +#: commands/functioncmds.c:880 msgid "return data type of cast function must match target data type" msgstr "" -#: commands/functioncmds.c:749 +#: commands/functioncmds.c:891 msgid "cast function must not be volatile" msgstr "" -#: commands/functioncmds.c:751 +#: commands/functioncmds.c:896 msgid "cast function must not be an aggregate function" msgstr "" -#: commands/functioncmds.c:753 +#: commands/functioncmds.c:900 msgid "cast function must not return a set" msgstr "" -#: commands/functioncmds.c:774 -msgid "Must be superuser to create a cast WITHOUT FUNCTION" +#: commands/functioncmds.c:923 +msgid "must be superuser to create a cast WITHOUT FUNCTION" msgstr "" -#: commands/functioncmds.c:787 +#: commands/functioncmds.c:938 msgid "source and target datatypes are not physically compatible" msgstr "" -#: commands/functioncmds.c:803 +#: commands/functioncmds.c:973 #, c-format -msgid "CreateCast: bogus CoercionContext %c" -msgstr "" - -#: commands/functioncmds.c:820 -#, c-format -msgid "cast from data type %s to data type %s already exists" -msgstr "" +msgid "cast from type %s to type %s already exists" +msgstr "конверсия типа %s в тип %s уже существует" -#: commands/functioncmds.c:897 +#: commands/functioncmds.c:1056 #, c-format msgid "cast from type %s to type %s does not exist" msgstr "конверсия типа %s в тип %s не существует" -#: commands/functioncmds.c:940 +#: commands/define.c:71 +#: commands/define.c:169 +#: commands/define.c:201 +#: commands/define.c:235 #, c-format -msgid "could not find tuple for cast %u" -msgstr "" +msgid "%s requires a parameter" +msgstr "%s требует параметр" -#: commands/indexcmds.c:92 -msgid "DefineIndex: must specify at least one attribute" -msgstr "" - -#: commands/indexcmds.c:94 +#: commands/define.c:110 +#: commands/define.c:121 +#: commands/define.c:136 +#: commands/define.c:154 #, c-format -msgid "Cannot use more than %d attributes in an index" -msgstr "" +msgid "%s requires a numeric value" +msgstr "%s требует цифровое значение" -#: commands/indexcmds.c:105 +#: commands/define.c:183 #, c-format -msgid "DefineIndex: relation \"%s\" is not a table" +msgid "argument of %s must be a name" msgstr "" -#: commands/indexcmds.c:114 -msgid "Existing indexes are inactive. REINDEX first" -msgstr "" - -#: commands/indexcmds.c:142 +#: commands/define.c:219 #, c-format -msgid "DefineIndex: access method \"%s\" not found" +msgid "argument of %s must be a type name" msgstr "" -#: commands/indexcmds.c:148 +#: commands/define.c:244 #, c-format -msgid "DefineIndex: access method \"%s\" does not support UNIQUE indexes" -msgstr "" +msgid "%s requires an integer value" +msgstr "%s требует целое значение" -#: commands/indexcmds.c:151 +#: commands/define.c:265 #, c-format -msgid "DefineIndex: access method \"%s\" does not support multi-column indexes" -msgstr "" +msgid "invalid argument for %s: \"%s\"" +msgstr "неверный аргумент для %s: \"%s\"" -#: commands/indexcmds.c:185 -msgid "Functional index can only have one attribute" -msgstr "" - -#: commands/indexcmds.c:189 +#: commands/indexcmds.c:152 +#: commands/opclasscmds.c:91 +#: commands/opclasscmds.c:497 +#: commands/opclasscmds.c:647 #, c-format -msgid "Index function can take at most %d arguments" -msgstr "" - -#: commands/indexcmds.c:244 -msgid "Partial-index predicates may refer only to the base relation" -msgstr "" - -#: commands/indexcmds.c:252 -msgid "Cannot use subselect in index predicate" +msgid "access method \"%s\" does not exist" msgstr "" -#: commands/indexcmds.c:254 -msgid "Cannot use aggregate in index predicate" +#: commands/opclasscmds.c:112 +msgid "must be superuser to create an operator class" msgstr "" -#: commands/indexcmds.c:261 -msgid "Functions in index predicate must be marked isImmutable" -msgstr "" - -#: commands/indexcmds.c:299 commands/indexcmds.c:389 +#: commands/opclasscmds.c:154 #, c-format -msgid "DefineIndex: attribute \"%s\" not found" -msgstr "" - -#: commands/indexcmds.c:324 -msgid "DefineIndex: functional index may not use an aggregate function" +msgid "invalid operator number %d, must be between 1 and %d" msgstr "" -#: commands/indexcmds.c:326 -msgid "" -"DefineIndex: functional index must use a real function, not a type coercion\n" -"\tTry specifying the index opclass you want to use, instead" -msgstr "" - -#: commands/indexcmds.c:334 -msgid "DefineIndex: cannot index on a function returning a set" -msgstr "" - -#: commands/indexcmds.c:350 -msgid "DefineIndex: index function must be marked isImmutable" -msgstr "" - -#: commands/indexcmds.c:385 -msgid "missing attribute for define index" -msgstr "" - -#: commands/indexcmds.c:418 +#: commands/opclasscmds.c:160 #, c-format -msgid "" -"data type %s has no default operator class for access method \"%s\"\n" -"\tYou must specify an operator class for the index or define a\n" -"\tdefault operator class for the data type" -msgstr "" +msgid "operator number %d appears more than once" +msgstr "номер оператора %d указан больше одного раза" -#: commands/indexcmds.c:449 commands/indexcmds.c:457 +#: commands/opclasscmds.c:192 #, c-format -msgid "" -"DefineIndex: operator class \"%s\" not supported by access method \"%s\"" +msgid "invalid procedure number %d, must be between 1 and %d" msgstr "" -#: commands/indexcmds.c:468 +#: commands/opclasscmds.c:198 #, c-format -msgid "operator class \"%s\" does not accept data type %s" +msgid "DefineOpClass: procedure number %d appears more than once" msgstr "" -#: commands/indexcmds.c:522 -#, c-format -msgid "pg_opclass contains multiple default opclasses for data type %s" +#: commands/opclasscmds.c:214 +msgid "storage type specified more than once" msgstr "" -#: commands/indexcmds.c:544 commands/indexcmds.c:576 commands/indexcmds.c:619 +#: commands/opclasscmds.c:241 #, c-format -msgid "relation \"%s\" is of type \"%c\"" +msgid "storage type may not be different from datatype for access method \"%s\"" msgstr "" -#: commands/indexcmds.c:573 +#: commands/opclasscmds.c:259 #, c-format -msgid "index \"%s\" does not exist" +msgid "operator class \"%s\" for access method \"%s\" already exists" msgstr "" -#: commands/indexcmds.c:584 +#: commands/opclasscmds.c:287 #, c-format -msgid "" -"\"%s\" is a system index. call REINDEX under standalone postgres with -O -P " -"options" +msgid "could not make class \"%s\" be default for type %s" msgstr "" -#: commands/indexcmds.c:587 +#: commands/opclasscmds.c:290 #, c-format -msgid "" -"\"%s\" is a system index. call REINDEX under standalone postgres with -P -O " -"options" +msgid "Class \"%s\" already is the default." msgstr "" -#: commands/indexcmds.c:602 +#: commands/indexcmds.c:479 +#: commands/indexcmds.c:489 +#: commands/opclasscmds.c:526 +#: commands/opclasscmds.c:536 +#: commands/opclasscmds.c:669 +#: commands/opclasscmds.c:680 #, c-format -msgid "index \"%s\" wasn't reindexed" +msgid "operator class \"%s\" does not exist for access method \"%s\"" msgstr "" -#: commands/indexcmds.c:634 +#: commands/opclasscmds.c:701 #, c-format -msgid "table \"%s\" wasn't reindexed" +msgid "operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"" msgstr "" -#: commands/indexcmds.c:658 -msgid "REINDEX DATABASE: Can be executed only on the currently open database." +#: commands/indexcmds.c:92 +msgid "must specify at least one attribute" msgstr "" -#: commands/indexcmds.c:661 -msgid "REINDEX DATABASE: Permission denied." +#: commands/indexcmds.c:96 +#, c-format +msgid "cannot use more than %d attributes in an index" msgstr "" -#: commands/indexcmds.c:664 -msgid "must be called under standalone postgres with -O -P options" +#: commands/indexcmds.c:120 +msgid "existing indexes are inactive" msgstr "" -#: commands/indexcmds.c:666 -msgid "must be called under standalone postgres with -P -O options" +#: commands/indexcmds.c:121 +msgid "REINDEX the table first." msgstr "" -#: commands/indexcmds.c:732 +#: commands/indexcmds.c:160 #, c-format -msgid "relation %u was reindexed" +msgid "access method \"%s\" does not support UNIQUE indexes" msgstr "" -#: commands/lockcmds.c:65 +#: commands/indexcmds.c:165 #, c-format -msgid "LOCK TABLE: %s is not a table" +msgid "access method \"%s\" does not support multi-column indexes" msgstr "" -#: commands/opclasscmds.c:88 -#, c-format -msgid "DefineOpClass: access method \"%s\" not found" +#: commands/indexcmds.c:179 +msgid "index expressions and predicates may refer only to the base relation" msgstr "" -#: commands/opclasscmds.c:107 -msgid "Must be superuser to create an operator class" +#: commands/indexcmds.c:210 +msgid "primary keys cannot be expressions" msgstr "" -#: commands/opclasscmds.c:146 +#: commands/indexcmds.c:240 +#: parser/analyze.c:1442 #, c-format -msgid "DefineOpClass: invalid operator number %d, must be between 1 and %d" +msgid "column \"%s\" named in key does not exist" msgstr "" -#: commands/opclasscmds.c:150 -#, c-format -msgid "DefineOpClass: operator number %d appears more than once" +#: commands/indexcmds.c:299 +msgid "cannot use sub-select in index predicate" msgstr "" -#: commands/opclasscmds.c:167 -#, c-format -msgid "DefineOpClass: Operator '%s' for types '%s' and '%s' does not exist" +#: commands/indexcmds.c:303 +msgid "cannot use aggregate in index predicate" msgstr "" -#: commands/opclasscmds.c:183 -#, c-format -msgid "DefineOpClass: invalid procedure number %d, must be between 1 and %d" +#: commands/indexcmds.c:312 +msgid "functions in index predicate must be marked IMMUTABLE" msgstr "" -#: commands/opclasscmds.c:187 +#: commands/indexcmds.c:345 +#: commands/tablecmds.c:1205 #, c-format -msgid "DefineOpClass: procedure number %d appears more than once" -msgstr "" +msgid "attribute \"%s\" does not exist" +msgstr "атрибут \"%s\" не существует" -#: commands/opclasscmds.c:200 -msgid "DefineOpClass: storage type specified more than once" +#: commands/indexcmds.c:377 +msgid "cannot use sub-select in index expression" msgstr "" -#: commands/opclasscmds.c:204 -#, c-format -msgid "DefineOpClass: bogus item type %d" +#: commands/indexcmds.c:381 +msgid "cannot use aggregate in index expression" msgstr "" -#: commands/opclasscmds.c:226 -#, c-format -msgid "Storage type may not be different from datatype for access method %s" +#: commands/indexcmds.c:392 +msgid "functions in index expression must be marked IMMUTABLE" msgstr "" -#: commands/opclasscmds.c:242 +#: commands/indexcmds.c:447 #, c-format -msgid "Operator class \"%s\" already exists for access method \"%s\"" +msgid "data type %s has no default operator class for access method \"%s\"" msgstr "" -#: commands/opclasscmds.c:266 -#, c-format -msgid "" -"Can't add class \"%s\" as default for type %s\n" -"\tclass \"%s\" already is the default" +#: commands/indexcmds.c:449 +msgid "You must specify an operator class for the index or define a default operator class for the data type." msgstr "" -#: commands/opclasscmds.c:474 +#: commands/indexcmds.c:502 #, c-format -msgid "RemoveOpClass: access method \"%s\" not found" +msgid "operator class \"%s\" does not accept data type %s" msgstr "" -#: commands/opclasscmds.c:501 commands/opclasscmds.c:509 +#: commands/indexcmds.c:559 +#: utils/cache/typcache.c:286 #, c-format -msgid "" -"RemoveOpClass: operator class \"%s\" not supported by access method \"%s\"" +msgid "there are multiple default operator classes for data type %s" msgstr "" -#: commands/opclasscmds.c:553 +#: commands/indexcmds.c:626 +#: commands/indexcmds.c:632 #, c-format -msgid "RemoveOpClassById: couldn't find pg_class entry %u" -msgstr "" - -#: commands/operatorcmds.c:103 -msgid "setof type not implemented for leftarg" -msgstr "" +msgid "permission denied: \"%s\" is a system index" +msgstr "доступ запрещён: \"%s\" является системным индексом" -#: commands/operatorcmds.c:109 -msgid "setof type not implemented for rightarg" -msgstr "" - -#: commands/operatorcmds.c:135 -#, c-format -msgid "DefineOperator: attribute \"%s\" not recognized" +#: commands/indexcmds.c:628 +msgid "Do REINDEX in standalone postgres with -O -P options." msgstr "" -#: commands/operatorcmds.c:144 -msgid "Define: \"procedure\" unspecified" -msgstr "" - -#: commands/operatorcmds.c:215 -#, c-format -msgid "RemoveOperator: failed to find tuple for operator '%s'" +#: commands/indexcmds.c:634 +msgid "Do REINDEX in standalone postgres with -P -O options." msgstr "" -#: commands/operatorcmds.c:251 +#: commands/indexcmds.c:649 #, c-format -msgid "RemoveOperatorById: failed to find tuple for operator %u" +msgid "index \"%s\" wasn't reindexed" msgstr "" -#: commands/portalcmds.c:88 -msgid "PerformPortalFetch: missing portal name" -msgstr "PerformPortalFetch: отсутствует имя портала" - -#: commands/portalcmds.c:98 +#: commands/indexcmds.c:685 #, c-format -msgid "PerformPortalFetch: portal \"%s\" not found" +msgid "table \"%s\" wasn't reindexed" msgstr "" -#: commands/portalcmds.c:243 -msgid "PerformPortalClose: missing portal name" -msgstr "PerformPortalClose: отсутствует имя портала" - -#: commands/portalcmds.c:253 -#, c-format -msgid "PerformPortalClose: portal \"%s\" not found" +#: commands/indexcmds.c:712 +msgid "can only reindex the currently open database" msgstr "" -#: commands/prepare.c:65 -msgid "No statement name given" -msgstr "Не указано имя команды" - -#: commands/prepare.c:68 -msgid "Utility statements cannot be prepared" +#: commands/indexcmds.c:721 +msgid "REINDEX DATABASE must be done in standalone postgres with -O -P options" msgstr "" -#: commands/prepare.c:122 -msgid "ExecuteQuery: wrong number of arguments" -msgstr "ExecuteQuery: неверное число аргументов" - -#: commands/prepare.c:172 -msgid "INTO clause specified for non-SELECT query" +#: commands/indexcmds.c:725 +msgid "REINDEX DATABASE must be done in standalone postgres with -P -O options" msgstr "" -#: commands/prepare.c:223 -msgid "InitQueryHashTable: unable to create hash table" +#: commands/indexcmds.c:793 +#, c-format +msgid "relation %u was reindexed" msgstr "" -# [SM]: TO REVIEW -#: commands/prepare.c:253 +#: commands/lockcmds.c:68 +#: commands/tablecmds.c:382 +#: commands/tablecmds.c:1679 +#: commands/tablecmds.c:1970 +#: commands/tablecmds.c:2114 +#: commands/tablecmds.c:2348 +#: commands/tablecmds.c:2514 +#: commands/tablecmds.c:2648 +#: commands/tablecmds.c:2829 +#: commands/tablecmds.c:3816 +#: commands/tablecmds.c:4085 +#: commands/trigger.c:144 +#: commands/trigger.c:546 +#: tcop/utility.c:76 #, c-format -msgid "Prepared statement with name \"%s\" already exists" -msgstr "Заготовленная команда с именем \"%s\" уже существует" +msgid "\"%s\" is not a table" +msgstr "\"%s\" не является таблицей" -#: commands/prepare.c:283 -#, c-format -msgid "Unable to store prepared statement \"%s\"!" +#: commands/operatorcmds.c:106 +#: commands/operatorcmds.c:114 +msgid "setof type not allowed for operator argument" msgstr "" -# [SM]: TO REVIEW -#: commands/prepare.c:309 commands/prepare.c:326 commands/prepare.c:364 -#: commands/prepare.c:388 +#: commands/operatorcmds.c:141 #, c-format -msgid "Prepared statement with name \"%s\" does not exist" -msgstr "Заготовленная команда с именем \"%s\" не существует" +msgid "operator attribute \"%s\" not recognized" +msgstr "атрибут оператора \"%s\" не распознан" -#: commands/proclang.c:61 -msgid "" -"Only users with superuser privilege are permitted to create procedural " -"languages" +#: commands/operatorcmds.c:151 +msgid "operator procedure must be specified" msgstr "" -#: commands/proclang.c:73 -#, c-format -msgid "Language %s already exists" +#: commands/portalcmds.c:54 +#: commands/portalcmds.c:165 +#: commands/portalcmds.c:213 +msgid "invalid cursor name: must not be empty" msgstr "" -#: commands/proclang.c:82 -#, c-format -msgid "function %s() doesn't exist" -msgstr "функция %s() не существует" +#: commands/portalcmds.c:80 +msgid "DECLARE CURSOR may not specify INTO" +msgstr "DECLARE CURSOR не может указывать INTO" -#: commands/proclang.c:94 -#, c-format -msgid "" -"CreateProceduralLanguage: changing return type of function %s() from OPAQUE " -"to LANGUAGE_HANDLER" +#: commands/portalcmds.c:84 +msgid "DECLARE CURSOR ... FOR UPDATE is not supported" msgstr "" -#: commands/proclang.c:99 -#, c-format -msgid "CreateProceduralLanguage: function %s() must return LANGUAGE_HANDLER" +#: commands/portalcmds.c:85 +msgid "Cursors must be READ ONLY." msgstr "" -#: commands/proclang.c:109 +#: commands/portalcmds.c:174 +#: commands/portalcmds.c:223 +#: tcop/postgres.c:1506 +#: tcop/postgres.c:1704 #, c-format -msgid "function %s(oid) doesn't exist" -msgstr "функция %s(oid) не существует" +msgid "portal \"%s\" does not exist" +msgstr "портал \"%s\" не существует" -#: commands/proclang.c:183 -msgid "" -"Only users with superuser privilege are permitted to drop procedural " -"languages" -msgstr "" - -#: commands/proclang.c:196 +#: commands/portalcmds.c:313 +#: tcop/pquery.c:419 +#: tcop/pquery.c:931 #, c-format -msgid "Language %s doesn't exist" -msgstr "Язык %s не существует" +msgid "portal \"%s\" already active" +msgstr "портал \"%s\" уже активен" -#: commands/proclang.c:225 -#, c-format -msgid "DropProceduralLanguageById: language %u not found" +#: commands/portalcmds.c:369 +msgid "could not reposition held cursor" msgstr "" -#: commands/schemacmds.c:79 -#, c-format -msgid "" -"CREATE SCHEMA: permission denied\n" -"\t\"%s\" is not a superuser, so cannot create a schema for \"%s\"" +#: commands/prepare.c:61 +msgid "invalid statement name: must not be empty" msgstr "" -#: commands/schemacmds.c:92 -#, c-format -msgid "" -"CREATE SCHEMA: Illegal schema name: \"%s\" -- pg_ is reserved for system " -"schemas" +#: commands/prepare.c:80 +msgid "utility statements cannot be prepared" msgstr "" -#: commands/schemacmds.c:162 -msgid "Schema name may not be qualified" -msgstr "" +# [SM]: TO REVIEW +#: commands/prepare.c:168 +#: commands/prepare.c:173 +#: commands/prepare.c:536 +msgid "prepared statement is not a SELECT" +msgstr "заготовленная команда не является SELECTом" -#: commands/schemacmds.c:169 +# [SM]: TO REVIEW +#: commands/prepare.c:308 #, c-format -msgid "Schema \"%s\" does not exist" -msgstr "Схема \"%s\" не существует" +msgid "prepared statement \"%s\" already exists" +msgstr "заготовленная команда \"%s\" уже существует" -#: commands/schemacmds.c:206 +# [SM]: TO REVIEW +#: commands/prepare.c:388 #, c-format -msgid "RemoveSchemaById: schema %u not found" -msgstr "" +msgid "prepared statement \"%s\" does not exist" +msgstr "заготовленная команда \"%s\" не существует" -#: commands/sequence.c:208 -msgid "DefineSequence: ReadBuffer failed" -msgstr "" - -#: commands/sequence.c:335 +#: commands/sequence.c:421 +#: commands/sequence.c:613 +#: commands/sequence.c:656 #, c-format -msgid "%s.nextval: you don't have permissions to set sequence %s" -msgstr "" +msgid "permission denied for sequence %s" +msgstr "доступ запрещён для последовательности %s" -#: commands/sequence.c:410 +#: commands/sequence.c:498 #, c-format msgid "%s.nextval: reached MAXVALUE (%s)" msgstr "" -#: commands/sequence.c:431 -#, c-format -msgid "%s.nextval: reached MINVALUE (%s)" -msgstr "" - #: commands/sequence.c:521 #, c-format -msgid "%s.currval: you don't have permissions to read sequence %s" +msgid "%s.nextval: reached MINVALUE (%s)" msgstr "" -#: commands/sequence.c:525 +#: commands/sequence.c:619 #, c-format msgid "%s.currval is not yet defined in this session" msgstr "" -#: commands/sequence.c:560 -#, c-format -msgid "%s.setval: you don't have permissions to set sequence %s" -msgstr "" - -#: commands/sequence.c:575 -#, c-format -msgid "%s.setval: value %s is out of bounds (%s,%s)" -msgstr "" - -#: commands/sequence.c:701 -#, c-format -msgid "%s.%s: %s is not a sequence" -msgstr "" - -#: commands/sequence.c:719 -msgid "Memory exhausted in init_sequence" -msgstr "" - -#: commands/sequence.c:747 -#, c-format -msgid "%s.%s: invalid number of blocks in sequence" -msgstr "" +#: commands/sequence.c:673 +#, c-format +msgid "%s.setval: value %s is out of bounds (%s..%s)" +msgstr "" + +#: commands/sequence.c:800 +#: tcop/utility.c:81 +#, c-format +msgid "\"%s\" is not a sequence" +msgstr "\"%s\" не является последовательностью" + +#: commands/sequence.c:820 +#: executor/execGrouping.c:328 +#: executor/execGrouping.c:388 +#: executor/nodeIndexscan.c:1041 +#: executor/spi.c:83 +#: executor/spi.c:165 +#: lib/dllist.c:43 +#: lib/dllist.c:88 +#: libpq/auth.c:634 +#: postmaster/pgstat.c:828 +#: postmaster/pgstat.c:845 +#: postmaster/pgstat.c:2255 +#: postmaster/pgstat.c:2318 +#: postmaster/pgstat.c:2363 +#: postmaster/pgstat.c:2414 +#: postmaster/postmaster.c:1556 +#: postmaster/postmaster.c:2153 +#: postmaster/postmaster.c:2916 +#: storage/buffer/localbuf.c:129 +#: storage/file/fd.c:523 +#: storage/file/fd.c:556 +#: storage/file/fd.c:701 +#: storage/ipc/shmem.c:163 +#: storage/ipc/shmem.c:222 +#: storage/ipc/shmem.c:342 +#: storage/ipc/sinval.c:342 +#: storage/lmgr/lock.c:479 +#: storage/lmgr/lock.c:527 +#: storage/lmgr/proc.c:154 +#: storage/lmgr/proc.c:170 +#: storage/smgr/mm.c:191 +#: utils/adt/cash.c:297 +#: utils/adt/cash.c:312 +#: utils/adt/regexp.c:189 +#: utils/adt/ri_triggers.c:3266 +#: utils/cache/relcache.c:172 +#: utils/cache/relcache.c:182 +#: utils/cache/relcache.c:196 +#: utils/cache/relcache.c:1219 +#: utils/cache/typcache.c:121 +#: utils/fmgr/dfmgr.c:118 +#: utils/init/miscinit.c:126 +#: utils/init/miscinit.c:147 +#: utils/init/miscinit.c:157 +#: utils/misc/guc.c:1664 +#: utils/misc/guc.c:1861 +#: utils/misc/guc.c:2834 +#: utils/misc/guc.c:2881 +#: utils/misc/guc.c:3767 +#: utils/misc/guc.c:3903 +#: utils/misc/guc.c:3969 +#: utils/misc/guc.c:3977 +#: utils/misc/guc.c:3986 +#: utils/mmgr/aset.c:335 +#: utils/mmgr/aset.c:501 +#: utils/mmgr/aset.c:701 +#: utils/mmgr/aset.c:894 +#: utils/mmgr/portalmem.c:75 +msgid "out of memory" +msgstr "не хватает памяти" -#: commands/sequence.c:752 -#, c-format -msgid "%s.%s: ReadBuffer failed" +#: commands/sequence.c:958 +msgid "cannot increment by zero" msgstr "" -#: commands/sequence.c:761 +#: commands/sequence.c:994 #, c-format -msgid "%s.%s: bad magic (%08X)" +msgid "MINVALUE (%s) must be less than MAXVALUE (%s)" msgstr "" -#: commands/sequence.c:804 +#: commands/sequence.c:1018 #, c-format -msgid "DefineSequence: option \"%s\" not recognized" +msgid "START value (%s) can't be less than MINVALUE (%s)" msgstr "" -#: commands/sequence.c:811 -msgid "DefineSequence: can't INCREMENT by 0" -msgstr "" - -#: commands/sequence.c:840 +#: commands/sequence.c:1030 #, c-format -msgid "DefineSequence: MINVALUE (%s) must be less than MAXVALUE (%s)" +msgid "START value (%s) can't be greater than MAXVALUE (%s)" msgstr "" -#: commands/sequence.c:861 +#: commands/sequence.c:1044 #, c-format -msgid "DefineSequence: START value (%s) can't be less than MINVALUE (%s)" +msgid "CACHE (%s) must be greater than zero" msgstr "" -#: commands/sequence.c:871 -#, c-format -msgid "DefineSequence: START value (%s) can't be greater than MAXVALUE (%s)" +#: commands/proclang.c:63 +msgid "must be superuser to create procedural language" msgstr "" -#: commands/sequence.c:882 +#: commands/proclang.c:76 +#: commands/proclang.c:263 #, c-format -msgid "DefineSequence: CACHE (%s) can't be <= 0" -msgstr "" +msgid "language \"%s\" already exists" +msgstr "язык \"%s\" уже существует" -#: commands/sequence.c:902 +#: commands/proclang.c:96 #, c-format -msgid "seq_redo: unknown op code %u" +msgid "changing return type of function %s() from OPAQUE to LANGUAGE_HANDLER" msgstr "" -#: commands/sequence.c:910 +#: commands/proclang.c:103 #, c-format -msgid "seq_redo: can't read block of %u/%u" -msgstr "" - -#: commands/sequence.c:926 -msgid "seq_redo: failed to add item to page" -msgstr "" +msgid "function %s() must return LANGUAGE_HANDLER" +msgstr "функция %s() должна возвращать LANGUAGE_HANDLER" -#: commands/tablecmds.c:149 -msgid "ON COMMIT can only be used on TEMP tables" +#: commands/proclang.c:186 +msgid "must be superuser to drop procedural language" msgstr "" -#: commands/tablecmds.c:379 -#, c-format -msgid "TRUNCATE cannot be used on sequences. '%s' is a sequence" +#: commands/proclang.c:269 +msgid "must be superuser to rename procedural language" msgstr "" -#: commands/tablecmds.c:382 -#, c-format -msgid "TRUNCATE cannot be used on views. '%s' is a view" -msgstr "" - -#: commands/tablecmds.c:385 -#, c-format -msgid "TRUNCATE can only be used on tables. '%s' is not a table" -msgstr "" +#: commands/schemacmds.c:84 +#: commands/user.c:832 +#: commands/user.c:967 +msgid "permission denied" +msgstr "доступ запрещён" -#: commands/tablecmds.c:391 +#: commands/schemacmds.c:85 #, c-format -msgid "TRUNCATE cannot be used on system tables. '%s' is a system table" +msgid "\"%s\" is not a superuser, so cannot create a schema for \"%s\"" msgstr "" -#: commands/tablecmds.c:402 -msgid "TRUNCATE cannot be used on temp tables of other processes" -msgstr "" - -#: commands/tablecmds.c:426 +#: commands/schemacmds.c:100 +#: commands/schemacmds.c:272 #, c-format -msgid "" -"TRUNCATE cannot be used as table %s references this one via foreign key " -"constraint %s" +msgid "unacceptable schema name \"%s\"" msgstr "" -#: commands/tablecmds.c:537 -#, c-format -msgid "CREATE TABLE: attribute \"%s\" duplicated" +#: commands/schemacmds.c:101 +#: commands/schemacmds.c:273 +msgid "The prefix \"pg_\" is reserved for system schemas." msgstr "" -#: commands/tablecmds.c:560 -#, c-format -msgid "CREATE TABLE: inherited relation \"%s\" is not a table" +#: commands/tablecmds.c:150 +msgid "ON COMMIT can only be used on TEMP tables" msgstr "" -#: commands/tablecmds.c:564 +#: commands/tablecmds.c:210 #, c-format -msgid "CREATE TABLE: cannot inherit from temp relation \"%s\"" +msgid "duplicate CHECK constraint name \"%s\"" msgstr "" -#: commands/tablecmds.c:579 +#: commands/tablecmds.c:393 +#: commands/tablecmds.c:1150 +#: commands/tablecmds.c:1357 +#: commands/tablecmds.c:1695 +#: commands/tablecmds.c:1981 +#: commands/tablecmds.c:2125 +#: commands/tablecmds.c:2253 +#: commands/tablecmds.c:2362 +#: commands/tablecmds.c:2525 +#: commands/tablecmds.c:2659 +#: commands/tablecmds.c:2840 +#: commands/tablecmds.c:3139 +#: commands/tablecmds.c:3827 +#: commands/trigger.c:150 +#: commands/trigger.c:552 +#: tcop/utility.c:162 +#: tcop/utility.c:197 #, c-format -msgid "CREATE TABLE: inherited relation \"%s\" duplicated" -msgstr "" +msgid "permission denied: \"%s\" is a system catalog" +msgstr "доступ запрещён: \"%s\" является системным каталогом" -#: commands/tablecmds.c:631 -#, c-format -msgid "" -"CREATE TABLE: merging multiple inherited definitions of attribute \"%s\"" +#: commands/tablecmds.c:403 +msgid "cannot truncate temp tables of other processes" msgstr "" -#: commands/tablecmds.c:636 -#, c-format -msgid "CREATE TABLE: inherited attribute \"%s\" type conflict (%s and %s)" +#: commands/tablecmds.c:429 +msgid "cannot truncate a table referenced in a foreign key constraint" msgstr "" -#: commands/tablecmds.c:782 +#: commands/tablecmds.c:430 #, c-format -msgid "CREATE TABLE: merging attribute \"%s\" with inherited definition" +msgid "Table \"%s\" references this one via foreign key constraint \"%s\"." msgstr "" -#: commands/tablecmds.c:787 +#: commands/tablecmds.c:543 #, c-format -msgid "CREATE TABLE: attribute \"%s\" type conflict (%s and %s)" -msgstr "" +msgid "attribute \"%s\" duplicated" +msgstr "повторное имя атрибута: \"%s\"" -#: commands/tablecmds.c:825 +#: commands/tablecmds.c:568 +#: parser/analyze.c:1188 #, c-format -msgid "" -"CREATE TABLE: attribute \"%s\" inherits conflicting default values\n" -"\tTo resolve the conflict, specify a default explicitly" +msgid "inherited relation \"%s\" is not a table" msgstr "" -#: commands/tablecmds.c:1069 +#: commands/tablecmds.c:574 #, c-format -msgid "setRelhassubclassInRelation: cache lookup failed for relation %u" +msgid "cannot inherit from temporary relation \"%s\"" msgstr "" -#: commands/tablecmds.c:1124 +#: commands/tablecmds.c:591 #, c-format -msgid "renameatt: class \"%s\" is a system catalog" +msgid "inherited relation \"%s\" duplicated" msgstr "" -#: commands/tablecmds.c:1170 +#: commands/tablecmds.c:645 #, c-format -msgid "Inherited attribute \"%s\" must be renamed in child tables too" +msgid "merging multiple inherited definitions of attribute \"%s\"" msgstr "" -#: commands/tablecmds.c:1178 +#: commands/tablecmds.c:652 #, c-format -msgid "renameatt: attribute \"%s\" does not exist" +msgid "inherited attribute \"%s\" has a type conflict" msgstr "" -#: commands/tablecmds.c:1183 +#: commands/tablecmds.c:654 +#: commands/tablecmds.c:809 +#: parser/parse_coerce.c:255 +#: parser/parse_coerce.c:901 +#: parser/parse_coerce.c:918 +#: parser/parse_coerce.c:956 #, c-format -msgid "renameatt: system attribute \"%s\" may not be renamed" -msgstr "" +msgid "%s versus %s" +msgstr "%s против %s" -#: commands/tablecmds.c:1191 +#: commands/tablecmds.c:800 #, c-format -msgid "renameatt: inherited attribute \"%s\" may not be renamed" +msgid "merging attribute \"%s\" with inherited definition" msgstr "" -#: commands/tablecmds.c:1200 +#: commands/tablecmds.c:807 #, c-format -msgid "renameatt: attribute \"%s\" exists" +msgid "attribute \"%s\" has a type conflict" msgstr "" -#: commands/tablecmds.c:1230 +#: commands/tablecmds.c:848 #, c-format -msgid "renameatt: can't find index id %u" +msgid "attribute \"%s\" inherits conflicting default values" msgstr "" -#: commands/tablecmds.c:1315 -#, c-format -msgid "renamerel: system relation \"%s\" may not be renamed" +#: commands/tablecmds.c:850 +msgid "To resolve the conflict, specify a default explicitly." msgstr "" -#: commands/tablecmds.c:1331 +#: commands/tablecmds.c:1195 #, c-format -msgid "renamerel: relation \"%s\" does not exist" +msgid "inherited attribute \"%s\" must be renamed in child tables too" msgstr "" -#: commands/tablecmds.c:1335 +#: commands/tablecmds.c:1213 #, c-format -msgid "renamerel: relation \"%s\" exists" -msgstr "" +msgid "cannot rename system attribute \"%s\"" +msgstr "нельзя переименовать системный атрибут \"%s\"" -#: commands/tablecmds.c:1633 commands/tablecmds.c:1908 -#: commands/tablecmds.c:2042 commands/tablecmds.c:2257 -#: commands/tablecmds.c:2406 commands/tablecmds.c:2576 -#: commands/tablecmds.c:3535 commands/tablecmds.c:3710 +#: commands/tablecmds.c:1223 #, c-format -msgid "ALTER TABLE: relation \"%s\" is not a table" -msgstr "" +msgid "cannot rename inherited attribute \"%s\"" +msgstr "нельзя переименовать наследованный атрибут \"%s\"" -#: commands/tablecmds.c:1644 commands/tablecmds.c:1913 -#: commands/tablecmds.c:2047 commands/tablecmds.c:2165 -#: commands/tablecmds.c:2264 commands/tablecmds.c:2411 -#: commands/tablecmds.c:2581 commands/tablecmds.c:3540 +#: commands/tablecmds.c:1234 +#: commands/tablecmds.c:1835 #, c-format -msgid "ALTER TABLE: relation \"%s\" is a system catalog" -msgstr "" +msgid "attribute \"%s\" of relation \"%s\" already exists" +msgstr "атрибут \"%s\" для связи \"%s\" уже существует" -#: commands/tablecmds.c:1697 +#: commands/tablecmds.c:1748 #, c-format -msgid "ALTER TABLE: child table \"%s\" has different type for column \"%s\"" +msgid "child table \"%s\" has different type for column \"%s\"" msgstr "" -#: commands/tablecmds.c:1705 +#: commands/tablecmds.c:1756 #, c-format -msgid "ALTER TABLE: merging definition of column \"%s\" for child %s" +msgid "merging definition of column \"%s\" for child \"%s\"" msgstr "" -#: commands/tablecmds.c:1735 -msgid "Attribute must be added to child tables too" +#: commands/tablecmds.c:1788 +msgid "attribute must be added to child tables too" msgstr "" -#: commands/tablecmds.c:1752 -msgid "" -"Adding columns with defaults is not implemented.\n" -"\tAdd the column, then use ALTER TABLE SET DEFAULT." +#: commands/tablecmds.c:1807 +msgid "adding columns with defaults is not implemented" msgstr "" -#: commands/tablecmds.c:1756 -msgid "" -"Adding NOT NULL columns is not implemented.\n" -"\tAdd the column, then use ALTER TABLE ... SET NOT NULL." +#: commands/tablecmds.c:1808 +msgid "Add the column, then use ALTER TABLE SET DEFAULT." msgstr "" -#: commands/tablecmds.c:1765 commands/tablecmds.c:3852 -#, c-format -msgid "ALTER TABLE: relation \"%s\" not found" +#: commands/tablecmds.c:1813 +msgid "adding NOT NULL columns is not implemented" msgstr "" -#: commands/tablecmds.c:1777 -#, c-format -msgid "ALTER TABLE: column name \"%s\" already exists in table \"%s\"" +#: commands/tablecmds.c:1814 +msgid "Add the column, then use ALTER TABLE SET NOT NULL." msgstr "" -#: commands/tablecmds.c:1783 +#: commands/tablecmds.c:2027 +#: commands/tablecmds.c:2171 +#: commands/tablecmds.c:2299 +#: commands/tablecmds.c:2463 #, c-format -msgid "ALTER TABLE: relations limited to %d columns" -msgstr "" +msgid "cannot alter system attribute \"%s\"" +msgstr "нельзя поменять системный атрибут \"%s\"" -#: commands/tablecmds.c:1958 commands/tablecmds.c:2092 -#: commands/tablecmds.c:2210 +#: commands/tablecmds.c:2063 #, c-format -msgid "ALTER TABLE: Cannot alter system attribute \"%s\"" +msgid "attribute \"%s\" is in a primary key" msgstr "" -#: commands/tablecmds.c:1979 +#: commands/tablecmds.c:2192 #, c-format -msgid "ALTER TABLE: Index %u not found" -msgstr "ALTER TABLE: Индекс %u не найден" - -#: commands/tablecmds.c:1994 -#, c-format -msgid "ALTER TABLE: Attribute \"%s\" is in a primary key" +msgid "attribute \"%s\" contains NULL values" msgstr "" -#: commands/tablecmds.c:2010 commands/tablecmds.c:2124 -#: commands/tablecmds.c:2352 +#: commands/tablecmds.c:2242 #, c-format -msgid "ALTER TABLE: relation \"%s\" has no column \"%s\"" -msgstr "" +msgid "\"%s\" is not a table or view" +msgstr "\"%s\" не является таблицей или видом" -#: commands/tablecmds.c:2111 +#: commands/tablecmds.c:2381 #, c-format -msgid "ALTER TABLE: Attribute \"%s\" contains NULL values" +msgid "statistics target %d is too low" msgstr "" -#: commands/tablecmds.c:2160 +#: commands/tablecmds.c:2389 #, c-format -msgid "ALTER TABLE: relation \"%s\" is not a table or view" +msgid "lowering statistics target to %d" msgstr "" -#: commands/tablecmds.c:2284 +#: commands/tablecmds.c:2412 #, c-format -msgid "ALTER TABLE: statistics target %d is too low" +msgid "invalid storage type \"%s\"" msgstr "" -#: commands/tablecmds.c:2289 -msgid "ALTER TABLE: lowering statistics target to 1000" -msgstr "" - -# [SM]: TO REVIEW -#: commands/tablecmds.c:2310 -#, c-format -msgid "ALTER TABLE: \"%s\" storage not recognized" -msgstr "ALTER TABLE: \"%s\" медия не распознана" - -#: commands/tablecmds.c:2315 +#: commands/tablecmds.c:2482 #, c-format -msgid "ALTER TABLE: Invalid column flag: %c" +msgid "column datatype %s can only have storage \"plain\"" msgstr "" -#: commands/tablecmds.c:2357 -#, c-format -msgid "ALTER TABLE: cannot change system attribute \"%s\"" -msgstr "ALTER TABLE: нельзя поменять системный атрибут \"%s\"" - -#: commands/tablecmds.c:2374 +#: commands/tablecmds.c:2572 #, c-format -msgid "ALTER TABLE: Column datatype %s can only have storage \"plain\"" +msgid "table \"%s\" is already WITH OIDS" msgstr "" -#: commands/tablecmds.c:2428 +#: commands/tablecmds.c:2576 #, c-format -msgid "ALTER TABLE: Cannot drop system attribute \"%s\"" +msgid "table \"%s\" is already WITHOUT OIDS" msgstr "" -#: commands/tablecmds.c:2434 -#, c-format -msgid "ALTER TABLE: Cannot drop inherited column \"%s\"" +#: commands/tablecmds.c:2596 +msgid "ALTER TABLE WITH OIDS is not yet implemented" msgstr "" -#: commands/tablecmds.c:2463 commands/tablecmds.c:2514 +#: commands/tablecmds.c:2677 #, c-format -msgid "ALTER TABLE: relation %u has no column \"%s\"" -msgstr "ALTER TABLE: у связи %u нет колонки \"%s\"" +msgid "cannot drop system attribute \"%s\"" +msgstr "нельзя удалить системный атрибут \"%s\"" -#: commands/tablecmds.c:2468 commands/tablecmds.c:2519 +#: commands/tablecmds.c:2685 #, c-format -msgid "ALTER TABLE: relation %u has non-inherited column \"%s\"" -msgstr "ALTER TABLE: у связи %u нет ненаследованной колонки \"%s\"" - -#: commands/tablecmds.c:2655 -msgid "" -"ALTER TABLE / ADD CONSTRAINT is not implemented for that constraint type." -msgstr "" +msgid "cannot drop inherited attribute \"%s\"" +msgstr "нельзя удалить наследованный атрибут \"%s\"" -#: commands/tablecmds.c:2687 -msgid "" -"ALTER TABLE / ADD CONSTRAINT unable to determine type of constraint passed" -msgstr "" - -#: commands/tablecmds.c:2747 +#: commands/tablecmds.c:3012 #, c-format -msgid "Only relation '%s' can be referenced in CHECK" +msgid "CHECK constraint may only reference relation \"%s\"" msgstr "" -#: commands/tablecmds.c:2802 +#: commands/tablecmds.c:3076 #, c-format -msgid "AlterTableAddConstraint: rejected due to CHECK constraint %s" +msgid "CHECK constraint \"%s\" is violated at some row(s)" msgstr "" -#: commands/tablecmds.c:2858 +#: commands/tablecmds.c:3127 #, c-format msgid "referenced relation \"%s\" is not a table" msgstr "" -#: commands/tablecmds.c:2863 -#, c-format -msgid "%s: relation \"%s\" is a system catalog" -msgstr "%s: объект \"%s\" является системным каталогом" - -#: commands/tablecmds.c:2878 -#, c-format -msgid "%s: Unable to reference temporary table from permanent table constraint" -msgstr "" - -#: commands/tablecmds.c:2920 -#, c-format -msgid "" -"%s: number of referencing and referenced attributes for foreign key disagree" +#: commands/tablecmds.c:3152 +msgid "cannot reference temporary table from permanent table constraint" msgstr "" -#: commands/tablecmds.c:3001 -#, c-format -msgid "%s: column \"%s\" referenced in foreign key constraint does not exist" -msgstr "" - -#: commands/tablecmds.c:3004 -#, c-format -msgid "Can only have %d keys in a foreign key" +#: commands/tablecmds.c:3193 +#: commands/tablecmds.c:3622 +msgid "number of referencing and referenced attributes for foreign key disagree" msgstr "" -#: commands/tablecmds.c:3048 +#: commands/tablecmds.c:3275 #, c-format -msgid "transformFkeyGetPrimaryKey: index %u not found" +msgid "column \"%s\" referenced in foreign key constraint does not exist" msgstr "" -#: commands/tablecmds.c:3066 +#: commands/tablecmds.c:3280 #, c-format -msgid "PRIMARY KEY for referenced table \"%s\" not found" +msgid "cannot have more than %d keys in a foreign key" msgstr "" -#: commands/tablecmds.c:3122 +#: commands/tablecmds.c:3343 #, c-format -msgid "transformFkeyCheckAttrs: index %u not found" +msgid "there is no PRIMARY KEY for referenced table \"%s\"" msgstr "" -#: commands/tablecmds.c:3180 +#: commands/tablecmds.c:3457 #, c-format -msgid "" -"UNIQUE constraint matching given keys for referenced table \"%s\" not found" +msgid "there is no UNIQUE constraint matching given keys for referenced table \"%s\"" msgstr "" -#: commands/tablecmds.c:3343 +#: commands/tablecmds.c:3872 +#: commands/trigger.c:2312 #, c-format -msgid "" -"number of key attributes in referenced table must be equal to foreign key\n" -"\tIllegal FOREIGN KEY definition references \"%s\"" -msgstr "" - -#: commands/tablecmds.c:3399 -msgid "Unrecognized ON DELETE action for FOREIGN KEY constraint" -msgstr "" - -#: commands/tablecmds.c:3465 -msgid "Unrecognized ON UPDATE action for FOREIGN KEY constraint" +msgid "constraint \"%s\" does not exist" msgstr "" -#: commands/tablecmds.c:3510 +#: commands/tablecmds.c:3877 #, c-format -msgid "fkMatchTypeToString: Unknown MATCH TYPE '%c'" +msgid "multiple constraints named \"%s\" were dropped" msgstr "" -#: commands/tablecmds.c:3586 +#: commands/tablecmds.c:3919 #, c-format -msgid "ALTER TABLE / DROP CONSTRAINT: %s does not exist" -msgstr "" - -#: commands/tablecmds.c:3590 -msgid "Multiple constraints dropped" +msgid "\"%s\" is not a table, TOAST table, index, view, or sequence" msgstr "" -#: commands/tablecmds.c:3615 +#: commands/tablecmds.c:4005 #, c-format -msgid "ALTER TABLE: relation %u not found" -msgstr "ALTER TABLE: связь %u не найдена" - -#: commands/tablecmds.c:3677 -#, c-format -msgid "" -"ALTER TABLE: relation \"%s\" is not a table, TOAST table, index, view, or " -"sequence" -msgstr "" - -#: commands/tablecmds.c:3727 -msgid "Shared relations cannot be toasted after initdb" +msgid "table \"%s\" is already being clustered on index \"%s\"" msgstr "" -#: commands/tablecmds.c:3740 -#, c-format -msgid "ALTER TABLE: relation \"%s\" already has a toast table" +#: commands/tablecmds.c:4106 +msgid "shared relations cannot be toasted after initdb" msgstr "" -#: commands/tablecmds.c:3755 +#: commands/tablecmds.c:4121 #, c-format -msgid "ALTER TABLE: relation \"%s\" does not need a toast table" +msgid "relation \"%s\" already has a toast table" msgstr "" -#: commands/trigger.c:132 +#: commands/tablecmds.c:4138 #, c-format -msgid "Unable to find table for constraint \"%s\"" +msgid "relation \"%s\" does not need a toast table" msgstr "" #: commands/trigger.c:137 #, c-format -msgid "CreateTrigger: relation \"%s\" is not a table" -msgstr "" - -#: commands/trigger.c:141 -#, c-format -msgid "CreateTrigger: can't create trigger for system relation %s" -msgstr "" - -#: commands/trigger.c:208 -msgid "CreateTrigger: double INSERT event specified" -msgstr "" - -#: commands/trigger.c:213 -msgid "CreateTrigger: double DELETE event specified" -msgstr "" - -#: commands/trigger.c:218 -msgid "CreateTrigger: double UPDATE event specified" +msgid "could not determine referenced table for constraint \"%s\"" msgstr "" #: commands/trigger.c:222 -msgid "CreateTrigger: unknown event specified" -msgstr "" - -#: commands/trigger.c:248 -#, c-format -msgid "CreateTrigger: trigger %s already defined on relation %s" +msgid "double INSERT event specified" msgstr "" -#: commands/trigger.c:260 -#, c-format -msgid "CreateTrigger: function %s() does not exist" +#: commands/trigger.c:229 +msgid "double DELETE event specified" msgstr "" -#: commands/trigger.c:271 -#, c-format -msgid "" -"CreateTrigger: changing return type of function %s() from OPAQUE to TRIGGER" +#: commands/trigger.c:236 +msgid "double UPDATE event specified" msgstr "" -#: commands/trigger.c:276 +#: commands/trigger.c:269 +#: commands/trigger.c:654 #, c-format -msgid "CreateTrigger: function %s() must return TRIGGER" -msgstr "" - -#: commands/trigger.c:376 -#, c-format -msgid "CreateTrigger: relation %s not found in pg_class" -msgstr "" +msgid "trigger \"%s\" for relation \"%s\" already exists" +msgstr "триггер \"%s\" для связи \"%s\" уже существует" -#: commands/trigger.c:461 +#: commands/trigger.c:290 #, c-format -msgid "DropTrigger: there is no trigger %s on relation %s" +msgid "changing return type of function %s() from OPAQUE to TRIGGER" msgstr "" -#: commands/trigger.c:510 +#: commands/trigger.c:297 #, c-format -msgid "RemoveTriggerById: Trigger %u does not exist" -msgstr "RemoveTriggerById: Триггер %u не существует" +msgid "function %s() must return TRIGGER" +msgstr "функция %s() должна возвращать TRIGGER" -#: commands/trigger.c:521 +#: commands/trigger.c:1161 #, c-format -msgid "DropTrigger: relation \"%s\" is not a table" +msgid "trigger function %u returned NULL" msgstr "" -#: commands/trigger.c:525 -#, c-format -msgid "DropTrigger: can't drop trigger for system relation %s" +#: commands/trigger.c:1213 +#: commands/trigger.c:1326 +#: commands/trigger.c:1455 +msgid "BEFORE STATEMENT trigger cannot return a value" msgstr "" -#: commands/trigger.c:550 -#, c-format -msgid "DropTrigger: relation %s not found in pg_class" +#: commands/trigger.c:1582 +#: executor/execMain.c:1124 +#: executor/execMain.c:1423 +#: executor/execMain.c:1557 +msgid "could not serialize access due to concurrent update" msgstr "" -#: commands/trigger.c:555 -#, c-format -msgid "DropTrigger: relation %s has reltriggers = 0" -msgstr "" - -#: commands/trigger.c:626 -#, c-format -msgid "renametrig: trigger %s already defined on relation %s" +#: commands/trigger.c:2263 +msgid "unnamed constraints cannot be set explicitly" msgstr "" -#: commands/trigger.c:667 +#: commands/trigger.c:2296 #, c-format -msgid "renametrig: trigger %s not defined on relation %s" +msgid "constraint \"%s\" is not deferrable" msgstr "" -#: commands/trigger.c:730 +#: commands/typecmds.c:135 #, c-format -msgid "RelationBuildTriggers: unexpected record found for rel %s" +msgid "type names must be %d characters or less" msgstr "" -#: commands/trigger.c:758 +#: commands/typecmds.c:167 #, c-format -msgid "RelationBuildTriggers: tgargs IS NULL for rel %s" +msgid "array element type cannot be %s" msgstr "" -#: commands/trigger.c:778 +#: commands/typecmds.c:200 #, c-format -msgid "RelationBuildTriggers: %d record(s) not found for rel %s" +msgid "alignment \"%s\" not recognized" msgstr "" -#: commands/trigger.c:1129 +#: commands/typecmds.c:217 #, c-format -msgid "ExecCallTriggerFunc: function %u returned NULL" +msgid "storage \"%s\" not recognized" msgstr "" -#: commands/trigger.c:1179 commands/trigger.c:1290 commands/trigger.c:1414 -msgid "BEFORE STATEMENT trigger cannot return a value." -msgstr "" - -#: commands/trigger.c:1534 executor/execMain.c:1015 executor/execMain.c:1308 -#: executor/execMain.c:1442 -msgid "Can't serialize access due to concurrent update" -msgstr "" - -#: commands/trigger.c:1557 executor/execMain.c:1036 +#: commands/typecmds.c:222 #, c-format -msgid "Unknown status %u from heap_mark4update" -msgstr "" - -#: commands/trigger.c:1569 -msgid "GetTupleForTrigger: failed ReadBuffer" -msgstr "" +msgid "type attribute \"%s\" not recognized" +msgstr "Атрибут типа \"%s\" не распознан" -#: commands/trigger.c:1757 -msgid "DeferredTriggerExecute: failed to fetch old tuple" +#: commands/typecmds.c:232 +msgid "type input function must be specified" msgstr "" -#: commands/trigger.c:1764 -msgid "DeferredTriggerExecute: failed to fetch new tuple" +#: commands/typecmds.c:236 +msgid "type output function must be specified" msgstr "" -#: commands/trigger.c:1785 +#: commands/typecmds.c:275 #, c-format -msgid "DeferredTriggerExecute: can't find trigger %u" +msgid "changing return type of function %s from OPAQUE to %s" msgstr "" -#: commands/trigger.c:1931 +#: commands/typecmds.c:282 #, c-format -msgid "deferredTriggerInvokeEvents: relation %u has no triggers" +msgid "type input function %s must return %s" msgstr "" -#: commands/trigger.c:2036 -msgid "DeferredTriggerBeginXact() called while inside transaction" -msgstr "" - -#: commands/trigger.c:2211 -msgid "unnamed constraints cannot be set explicitly" -msgstr "" - -#: commands/trigger.c:2242 -#, c-format -msgid "Constraint '%s' is not deferrable" -msgstr "" - -#: commands/trigger.c:2256 +#: commands/typecmds.c:292 #, c-format -msgid "Constraint '%s' does not exist" -msgstr "" - -#: commands/trigger.c:2332 -msgid "DeferredTriggerSaveEvent() called outside of transaction" +msgid "changing return type of function %s from OPAQUE to CSTRING" msgstr "" -#: commands/typecmds.c:117 +#: commands/typecmds.c:299 #, c-format -msgid "DefineType: type names must be %d characters or less" +msgid "type output function %s must return cstring" msgstr "" -#: commands/typecmds.c:147 +#: commands/typecmds.c:308 #, c-format -msgid "Array element type cannot be %s" +msgid "type receive function %s must return %s" msgstr "" -#: commands/typecmds.c:178 +#: commands/typecmds.c:317 #, c-format -msgid "DefineType: \"%s\" alignment not recognized" +msgid "type send function %s must return bytea" msgstr "" -#: commands/typecmds.c:194 +#: commands/typecmds.c:520 #, c-format -msgid "DefineType: \"%s\" storage not recognized" +msgid "domain names must be %d characters or less" msgstr "" -#: commands/typecmds.c:199 +#: commands/typecmds.c:541 #, c-format -msgid "DefineType: attribute \"%s\" not recognized" -msgstr "" +msgid "\"%s\" is not a valid base type for a domain" +msgstr "\"%s\" не является верным базовым типом для домена" -#: commands/typecmds.c:208 -msgid "Define: \"input\" unspecified" -msgstr "" +#: commands/typecmds.c:598 +#: commands/typecmds.c:1457 +msgid "FOREIGN KEY constraints not supported for domains" +msgstr "FOREIGN KEY констрейнты не поддерживаются для доменов" -#: commands/typecmds.c:210 -msgid "Define: \"output\" unspecified" +#: commands/typecmds.c:618 +msgid "multiple DEFAULT expressions" msgstr "" -#: commands/typecmds.c:243 -#, c-format -msgid "TypeCreate: changing return type of function %s from OPAQUE to %s" +#: commands/typecmds.c:648 +#: commands/typecmds.c:657 +msgid "conflicting NULL/NOT NULL constraints" msgstr "" -#: commands/typecmds.c:248 -#, c-format -msgid "Type input function %s must return %s" -msgstr "" +#: commands/typecmds.c:676 +#: commands/typecmds.c:1488 +msgid "UNIQUE constraints not supported for domains" +msgstr "UNIQUE констрейнты не поддерживаются для доменов" -#: commands/typecmds.c:256 -#, c-format -msgid "TypeCreate: changing return type of function %s from OPAQUE to CSTRING" -msgstr "" +#: commands/typecmds.c:682 +#: commands/typecmds.c:1494 +msgid "PRIMARY KEY constraints not supported for domains" +msgstr "PRIMARY KEY констрэйнты не поддерживаются для доменов" -#: commands/typecmds.c:261 -#, c-format -msgid "Type output function %s must return cstring" +#: commands/typecmds.c:691 +#: commands/typecmds.c:1503 +msgid "deferrability constraints not supported for domains" msgstr "" -#: commands/typecmds.c:389 +#: commands/typecmds.c:808 +#: commands/typecmds.c:1737 +#: commands/typecmds.c:2048 #, c-format -msgid "RemoveTypeById: type %u not found" -msgstr "RemoveTypeById: тип %u не найден" +msgid "\"%s\" is not a domain" +msgstr "\"%s\" не является доменом" -#: commands/typecmds.c:450 +#: commands/typecmds.c:878 #, c-format -msgid "CREATE DOMAIN: domain names must be %d characters or less" +msgid "changing argument type of function %s from OPAQUE to CSTRING" msgstr "" -#: commands/typecmds.c:469 +#: commands/typecmds.c:948 #, c-format -msgid "DefineDomain: %s is not a basetype" -msgstr "" - -#: commands/typecmds.c:522 -msgid "CREATE DOMAIN / FOREIGN KEY constraints not supported" -msgstr "CREATE DOMAIN / FOREIGN KEY: коистрэйты не поддерживаются" - -#: commands/typecmds.c:526 -msgid "DefineDomain: unexpected constraint node type" -msgstr "" - -#: commands/typecmds.c:538 -msgid "CREATE DOMAIN has multiple DEFAULT expressions" -msgstr "" - -#: commands/typecmds.c:565 commands/typecmds.c:572 -msgid "CREATE DOMAIN has conflicting NULL / NOT NULL constraint" -msgstr "" - -#: commands/typecmds.c:588 -msgid "CREATE DOMAIN / UNIQUE not supported" -msgstr "CREATE DOMAIN / UNIQUE не поддерживаются" - -#: commands/typecmds.c:592 -msgid "CREATE DOMAIN / PRIMARY KEY not supported" -msgstr "CREATE DOMAIN / PRIMARY KEY не поддерживаются" - -#: commands/typecmds.c:599 -msgid "" -"CREATE DOMAIN: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not " -"supported" +msgid "changing argument type of function %s from OPAQUE to %s" msgstr "" -#: commands/typecmds.c:604 -msgid "DefineDomain: unrecognized constraint subtype" +#: commands/typecmds.c:1059 +msgid "composite type must have at least one attribute" msgstr "" -#: commands/typecmds.c:696 -#, c-format -msgid "RemoveDomain: type \"%s\" does not exist" -msgstr "RemoveDomain: тип \"%s\" не существует" - -#: commands/typecmds.c:709 commands/typecmds.c:1507 +#: commands/typecmds.c:1250 #, c-format -msgid "%s is not a domain" -msgstr "%s не является доменом" - -#: commands/typecmds.c:778 -#, c-format -msgid "TypeCreate: changing argument type of function %s from OPAQUE to %s" +msgid "\"%s\" is already set to %s" msgstr "" -#: commands/typecmds.c:837 +#: commands/typecmds.c:1294 #, c-format -msgid "" -"TypeCreate: changing argument type of function %s from OPAQUE to CSTRING" +msgid "relation \"%s\" attribute \"%s\" contains NULL values" msgstr "" -#: commands/typecmds.c:880 -msgid "attempted to define composite type relation with no attrs" +#: commands/typecmds.c:1471 +msgid "use ALTER DOMAIN .. SET DEFAULT instead" msgstr "" -#: commands/typecmds.c:941 commands/typecmds.c:1060 commands/typecmds.c:1185 -#: commands/typecmds.c:1272 -#, c-format -msgid "AlterDomain: type \"%s\" does not exist" -msgstr "AlterDomain: тип \"%s\" не существует" - -#: commands/typecmds.c:1070 -#, c-format -msgid "AlterDomain: %s is already set to %s" +#: commands/typecmds.c:1478 +msgid "use ALTER DOMAIN .. [ SET | DROP ] NOT NULL instead" msgstr "" -#: commands/typecmds.c:1111 +#: commands/typecmds.c:1574 #, c-format -msgid "ALTER DOMAIN: Relation \"%s\" Attribute \"%s\" contains NULL values" +msgid "relation \"%s\" attribute \"%s\" contains values that violate the new constraint" msgstr "" -#: commands/typecmds.c:1282 -msgid "ALTER DOMAIN / FOREIGN KEY constraints not supported" -msgstr "ALTER DOMAIN / FOREIGN KEY: констрэйнты не поддерживаются" - -#: commands/typecmds.c:1286 -msgid "AlterDomainAddConstraint: unexpected constraint node type" -msgstr "" - -#: commands/typecmds.c:1293 -msgid "Use ALTER DOMAIN .. SET DEFAULT instead" -msgstr "" - -#: commands/typecmds.c:1298 -msgid "Use ALTER DOMAIN .. [ SET | DROP ] NOT NULL instead" -msgstr "" - -#: commands/typecmds.c:1306 -msgid "ALTER DOMAIN / UNIQUE indexes not supported" -msgstr "ALTER DOMAIN / UNIQUE: индексы не поддерживаются" - -#: commands/typecmds.c:1310 -msgid "ALTER DOMAIN / PRIMARY KEY indexes not supported" -msgstr "ALTER DOMAIN / PRIMARY KEY: индексы не поддерживаются" - -#: commands/typecmds.c:1317 -msgid "" -"ALTER DOMAIN: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not " -"supported" -msgstr "" - -#: commands/typecmds.c:1322 -msgid "AlterDomainAddConstraint: unrecognized constraint node type" -msgstr "" - -#: commands/typecmds.c:1387 +#: commands/typecmds.c:1771 #, c-format -msgid "AlterDomainAddConstraint: Domain %s constraint %s failed" -msgstr "" - -#: commands/typecmds.c:1535 -#, c-format -msgid "constraint \"%s\" already exists for domain \"%s\"" -msgstr "констрэйт \"%s\" уже существует для домена \"%s\"" - -#: commands/typecmds.c:1575 -msgid "Relations cannot be referenced in domain CHECK constraint" +msgid "constraint \"%s\" for domain \"%s\" already exists" msgstr "" -#: commands/typecmds.c:1582 -msgid "cannot use column references in domain CHECK clause" +#: commands/typecmds.c:1811 +#: commands/typecmds.c:1820 +msgid "cannot use table references in domain CHECK constraint" msgstr "" -#: commands/user.c:147 +#: commands/user.c:149 +#: commands/user.c:248 +#: commands/user.c:297 +#: commands/user.c:379 #, c-format -msgid "write_group_file: unable to write %s: %m" +msgid "could not write temp file \"%s\": %m" msgstr "" -#: commands/user.c:181 +#: commands/user.c:184 #, c-format -msgid "Invalid group name '%s'" -msgstr "Неверное имя группы '%s'" +msgid "invalid group name \"%s\"" +msgstr "неверное имя группы \"%s\"" -#: commands/user.c:211 commands/user.c:335 +#: commands/user.c:215 +#: commands/user.c:347 #, c-format -msgid "Invalid user name '%s'" -msgstr "Неверное имя пользователя '%s'" +msgid "invalid user name \"%s\"" +msgstr "неверное имя пользователя \"%s\"" -#: commands/user.c:242 commands/user.c:364 +#: commands/user.c:258 +#: commands/user.c:389 #, c-format -msgid "%s: %m" -msgstr "%s: %m" +msgid "could not rename \"%s\" to \"%s\": %m" +msgstr "не получилось переименовать \"%s\" в \"%s\": %m" -#: commands/user.c:250 commands/user.c:372 +#: commands/user.c:354 #, c-format -msgid "rename %s to %s: %m" -msgstr "RENAME %s TO %s: %m" +msgid "invalid user password \"%s\"" +msgstr "неверный пароль \"%s\"" -#: commands/user.c:286 -#, c-format -msgid "write_user_file: unable to write %s: %m" -msgstr "write_user_file: не удалось записать %s: %m" - -#: commands/user.c:341 -#, c-format -msgid "Invalid user password '%s'" -msgstr "Неверный пароль '%s'" - -#: commands/user.c:505 commands/user.c:515 commands/user.c:521 -#: commands/user.c:527 commands/user.c:533 commands/user.c:539 -msgid "CREATE USER: conflicting options" -msgstr "" - -#: commands/user.c:543 -#, c-format -msgid "CREATE USER: option \"%s\" not recognized" -msgstr "" - -#: commands/user.c:555 +#: commands/user.c:587 msgid "user id must be positive" msgstr "" -#: commands/user.c:570 -msgid "CREATE USER: permission denied" +#: commands/user.c:604 +msgid "must be superuser to create users" msgstr "" -#: commands/user.c:573 +#: commands/user.c:609 #, c-format -msgid "CREATE USER: user name \"%s\" is reserved" +msgid "user name \"%s\" is reserved" msgstr "" -#: commands/user.c:608 +#: commands/user.c:646 +#: commands/user.c:1191 #, c-format -msgid "CREATE USER: user name \"%s\" already exists" -msgstr "" - -#: commands/user.c:611 -#, c-format -msgid "CREATE USER: sysid %d is already assigned" -msgstr "" - -#: commands/user.c:642 commands/user.c:843 -msgid "CREATE USER: password encryption failed" -msgstr "" - -#: commands/user.c:733 commands/user.c:743 commands/user.c:749 -#: commands/user.c:755 -msgid "ALTER USER: conflicting options" -msgstr "" +msgid "user \"%s\" already exists" +msgstr "пользователь \"%s\" уже существует" -#: commands/user.c:759 +#: commands/user.c:651 +#: commands/user.c:1357 #, c-format -msgid "ALTER USER: option \"%s\" not recognized" +msgid "sysid %d is already assigned" msgstr "" -#: commands/user.c:782 -msgid "ALTER USER: permission denied" -msgstr "ALTER USER: нет доступа" - -#: commands/user.c:796 -#, c-format -msgid "ALTER USER: user \"%s\" does not exist" -msgstr "ALTER USER: пользователь \"%s\" не существует" - -#: commands/user.c:907 commands/variable.c:549 utils/cache/lsyscache.c:1543 -#: utils/init/miscinit.c:555 +#: commands/user.c:848 +#: commands/user.c:961 +#: commands/user.c:1053 +#: commands/user.c:1172 +#: commands/variable.c:778 +#: utils/cache/lsyscache.c:1989 +#: utils/init/miscinit.c:259 #, c-format msgid "user \"%s\" does not exist" msgstr "пользователь \"%s\" не существует" -#: commands/user.c:968 -msgid "DROP USER: permission denied" -msgstr "DROP USER: нед доступа" - -#: commands/user.c:995 -#, c-format -msgid "DROP USER: user \"%s\" does not exist (no users removed)" +#: commands/user.c:1026 +msgid "must be superuser to drop users" msgstr "" -"DROP USER: пользователь \"%s\" не существует (никто из поользователей не " -"удалён)" - -#: commands/user.c:997 -#, c-format -msgid "DROP USER: user \"%s\" does not exist" -msgstr "DROP USER: пользователь \"%s\" не существует" -#: commands/user.c:1003 +#: commands/user.c:1060 msgid "current user cannot be dropped" msgstr "" -#: commands/user.c:1005 +#: commands/user.c:1064 msgid "session user cannot be dropped" msgstr "" -#: commands/user.c:1029 -#, c-format -msgid "DROP USER: user \"%s\" owns database \"%s\", cannot be removed%s" -msgstr "" - -#: commands/user.c:1109 -#, c-format -msgid "CheckPgUserAclNotNull: \"%s\" not found" -msgstr "" - -#: commands/user.c:1114 -#, c-format -msgid "" -"To use passwords, you have to revoke permissions on %s so normal users " -"cannot read the passwords. Try 'REVOKE ALL ON \"%s\" FROM PUBLIC'." -msgstr "" -"Для использования паролей требуется отнять права на %s так чтобы обычные " -"пользователи не смогли их читать. Попробуйте 'REVOKE ALL ON \"%s\" FROM " -"PUBLIC'." - -#: commands/user.c:1156 commands/user.c:1162 -msgid "CREATE GROUP: conflicting options" -msgstr "CREATE GROUP: конфликт опций" - -#: commands/user.c:1166 -#, c-format -msgid "CREATE GROUP: option \"%s\" not recognized" -msgstr "CREATE GROUP: опция \"%s\" не распознана" - -#: commands/user.c:1174 -msgid "group id must be positive" -msgstr "" - -#: commands/user.c:1185 -msgid "CREATE GROUP: permission denied" -msgstr "CREATE GROUP: нет доступа" - -#: commands/user.c:1188 -#, c-format -msgid "CREATE GROUP: group name \"%s\" is reserved" -msgstr "" - -#: commands/user.c:1223 -#, c-format -msgid "CREATE GROUP: group name \"%s\" already exists" -msgstr "" - -#: commands/user.c:1226 -#, c-format -msgid "CREATE GROUP: group sysid %d is already assigned" -msgstr "" - -#: commands/user.c:1319 -#, c-format -msgid "%s: group \"%s\" does not exist" -msgstr "" - -#: commands/user.c:1360 -#, c-format -msgid "AlterGroup: unknown tag %s" -msgstr "" - -#: commands/user.c:1372 +#: commands/user.c:1090 #, c-format -msgid "%s: user \"%s\" is already in group \"%s\"" -msgstr "" - -#: commands/user.c:1387 -#, c-format -msgid "ALTER GROUP: group \"%s\" does not have any members" -msgstr "" - -#: commands/user.c:1412 -#, c-format -msgid "ALTER GROUP: user \"%s\" is not in group \"%s\"" -msgstr "" - -#: commands/user.c:1541 -msgid "DROP GROUP: permission denied" -msgstr "" - -#: commands/user.c:1554 -#, c-format -msgid "DROP GROUP: group \"%s\" does not exist" -msgstr "" - -#: commands/vacuum.c:459 -msgid "" -"oldest Xmin is far in the past --- close open transactions soon to avoid " -"wraparound problems" +msgid "user \"%s\" cannot be dropped" msgstr "" -#: commands/vacuum.c:505 commands/vacuum.c:512 +#: commands/user.c:1091 #, c-format -msgid "pg_class entry for relid %u vanished during vacuuming" +msgid "The user owns database \"%s\"." msgstr "" -#: commands/vacuum.c:665 -msgid "" -"Some databases have not been vacuumed in over 2 billion transactions.\n" -"\tYou may have already suffered transaction-wraparound data loss." +#: commands/user.c:1183 +msgid "session user may not be renamed" msgstr "" -#: commands/vacuum.c:676 -msgid "" -"Some databases have not been vacuumed in over 1 billion transactions.\n" -"\tBetter vacuum them soon, or you may have a wraparound failure." +#: commands/user.c:1197 +msgid "must be superuser to rename users" msgstr "" -#: commands/vacuum.c:683 +#: commands/user.c:1230 #, c-format -msgid "" -"Some databases have not been vacuumed in %d transactions.\n" -"\tBetter vacuum them within %d transactions,\n" -"\tor you may have a wraparound failure." +msgid "before using passwords you must revoke permissions on %s" msgstr "" -#: commands/vacuum.c:771 -#, c-format -msgid "Skipping \"%s\" --- only table or database owner can VACUUM it" +#: commands/user.c:1232 +msgid "This restriction is to prevent unprivileged users from reading the passwords." msgstr "" -#: commands/vacuum.c:977 +#: commands/user.c:1233 #, c-format -msgid "VACUUM (full_vacuum_rel): FlushRelationBuffers returned %d" +msgid "Try 'REVOKE ALL ON \"%s\" FROM PUBLIC'." msgstr "" -#: commands/vacuum.c:1044 commands/vacuumlazy.c:210 -#, c-format -msgid "--Relation %s.%s--" +#: commands/user.c:1297 +msgid "group id must be positive" msgstr "" -#: commands/vacuum.c:1078 commands/vacuumlazy.c:268 -#, c-format -msgid "Rel %s: Uninitialized page %u - fixing" +#: commands/user.c:1310 +msgid "must be superuser to create groups" msgstr "" -#: commands/vacuum.c:1192 +#: commands/user.c:1315 #, c-format -msgid "" -"Rel %s: TID %u/%u: InsertTransactionInProgress %u - can't shrink relation" +msgid "group name \"%s\" is reserved" msgstr "" -#: commands/vacuum.c:1202 +#: commands/user.c:1352 +#: commands/user.c:1739 #, c-format -msgid "" -"Rel %s: TID %u/%u: DeleteTransactionInProgress %u - can't shrink relation" -msgstr "" +msgid "group \"%s\" already exists" +msgstr "группа \"%s\" уже существует" -#: commands/vacuum.c:1220 commands/vacuumlazy.c:372 -#, c-format -msgid "Rel %s: TID %u/%u: OID IS INVALID. TUPGONE %d." +#: commands/user.c:1437 +msgid "must be superuser to alter groups" msgstr "" -#: commands/vacuum.c:1358 +#: commands/user.c:1504 #, c-format -msgid "" -"Pages %u: Changed %u, reaped %u, Empty %u, New %u; Tup %.0f: Vac %.0f, Keep/" -"VTL %.0f/%u, UnUsed %.0f, MinLen %lu, MaxLen %lu; Re-using: Free/Avail. " -"Space %.0f/%.0f; EndEmpty/Avail. Pages %u/%u.\n" -"\t%s" -msgstr "" - -#: commands/vacuum.c:1582 -msgid "HEAP_MOVED_IN was not expected" +msgid "user \"%s\" is already in group \"%s\"" msgstr "" -#: commands/vacuum.c:1592 -msgid "Invalid XVAC in tuple header" -msgstr "" - -#: commands/vacuum.c:1617 -msgid "HEAP_MOVED_OFF was expected" -msgstr "" - -#: commands/vacuum.c:1671 commands/vacuum.c:1793 -msgid "Parent item in update-chain not found - can't continue repair_frag" -msgstr "" - -#: commands/vacuum.c:1708 -msgid "" -"Child itemid in update-chain marked as unused - can't continue repair_frag" -msgstr "" - -#: commands/vacuum.c:1805 -msgid "Parent itemid marked as unused" -msgstr "" - -#: commands/vacuum.c:1829 -msgid "Too old parent tuple found - can't continue repair_frag" -msgstr "" - -#: commands/vacuum.c:1958 +#: commands/user.c:1521 #, c-format -msgid "moving chain: failed to add item with len = %lu to page %u" +msgid "group \"%s\" does not have any members" msgstr "" -#: commands/vacuum.c:2102 +#: commands/user.c:1549 #, c-format -msgid "" -"failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %" -"u)" -msgstr "" +msgid "user \"%s\" is not in group \"%s\"" +msgstr "пользователь \"%s\" не принадлежит группе \"%s\"" -#: commands/vacuum.c:2191 -msgid "HEAP_MOVED_IN was not expected (2)" +#: commands/user.c:1681 +msgid "must be superuser to drop groups" msgstr "" -#: commands/vacuum.c:2195 -msgid "Invalid XVAC in tuple header (4)" +#: commands/user.c:1745 +msgid "must be superuser to rename groups" msgstr "" -#: commands/vacuum.c:2220 -msgid "HEAP_MOVED_OFF was expected (2)" +#: commands/vacuum.c:466 +msgid "oldest Xmin is far in the past" msgstr "" -#: commands/vacuum.c:2331 -msgid "HEAP_MOVED_OFF/HEAP_MOVED_IN was expected" +#: commands/vacuum.c:467 +msgid "Close open transactions soon to avoid wraparound problems." msgstr "" -#: commands/vacuum.c:2333 -msgid "Invalid XVAC in tuple header (2)" +#: commands/vacuum.c:674 +msgid "some databases have not been vacuumed in over 2 billion transactions" msgstr "" -#: commands/vacuum.c:2351 -#, c-format -msgid "" -"Rel %s: Pages: %u --> %u; Tuple(s) moved: %u.\n" -"\t%s" +#: commands/vacuum.c:675 +msgid "You may have already suffered transaction-wraparound data loss." msgstr "" -#: commands/vacuum.c:2413 -msgid "Invalid XVAC in tuple header (3)" +#: commands/vacuum.c:686 +msgid "some databases have not been vacuumed in over 1 billion transactions" msgstr "" -#: commands/vacuum.c:2418 -msgid "HEAP_MOVED_OFF was expected (3)" +#: commands/vacuum.c:687 +msgid "Better vacuum them soon, or you may have a wraparound failure." msgstr "" -#: commands/vacuum.c:2468 +#: commands/vacuum.c:694 #, c-format -msgid "VACUUM (repair_frag): FlushRelationBuffers returned %d" +msgid "some databases have not been vacuumed in %d transactions" msgstr "" -#: commands/vacuum.c:2534 +#: commands/vacuum.c:696 #, c-format -msgid "VACUUM (vacuum_heap): FlushRelationBuffers returned %d" +msgid "Better vacuum them within %d transactions, or you may have a wraparound failure." msgstr "" -#: commands/vacuum.c:2540 +#: commands/vacuum.c:785 #, c-format -msgid "Rel %s: Pages: %u --> %u." +msgid "skipping \"%s\" --- only table or database owner can VACUUM it" msgstr "" -#: commands/vacuum.c:2625 commands/vacuumlazy.c:599 +#: commands/vacuum.c:799 #, c-format -msgid "" -"Index %s: Pages %u; Tuples %.0f.\n" -"\t%s" +msgid "skipping \"%s\" --- cannot VACUUM indexes, views or special system tables" msgstr "" -#: commands/vacuum.c:2638 commands/vacuum.c:2692 +#: commands/vacuum.c:1058 +#: commands/vacuumlazy.c:205 #, c-format -msgid "" -"Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\n" -"\tRecreate the index." +msgid "vacuuming \"%s.%s\"" msgstr "" -#: commands/vacuum.c:2679 commands/vacuumlazy.c:646 +#: commands/vacuum.c:1093 +#: commands/vacuumlazy.c:263 #, c-format -msgid "" -"Index %s: Pages %u; Tuples %.0f: Deleted %.0f.\n" -"\t%s" +msgid "relation \"%s\" page %u is uninitialized --- fixing" msgstr "" -#: commands/vacuumlazy.c:434 +#: commands/vacuum.c:1210 #, c-format -msgid "" -"Pages %u: Changed %u, Empty %u; Tup %.0f: Vac %.0f, Keep %.0f, UnUsed %.0f.\n" -"\tTotal %s" +msgid "relation \"%s\" TID %u/%u: InsertTransactionInProgress %u --- can't shrink relation" msgstr "" -#: commands/vacuumlazy.c:484 +#: commands/vacuum.c:1223 #, c-format -msgid "" -"Removed %d tuples in %d pages.\n" -"\t%s" +msgid "relation \"%s\" TID %u/%u: DeleteTransactionInProgress %u --- can't shrink relation" msgstr "" -#: commands/vacuumlazy.c:720 +#: commands/vacuum.c:1385 +#: commands/vacuumlazy.c:428 #, c-format -msgid "VACUUM (lazy_truncate_heap): FlushRelationBuffers returned %d" +msgid "\"%s\": found %.0f removable, %.0f nonremovable tuples in %u pages" msgstr "" -#: commands/vacuumlazy.c:755 +#: commands/vacuum.c:1388 #, c-format msgid "" -"Truncated %u --> %u pages.\n" -"\t%s" -msgstr "" - -#: commands/variable.c:62 -msgid "SET DATESTYLE: invalid list syntax" +"%.0f dead tuples cannot be removed yet.\n" +"Nonremovable tuples range from %lu to %lu bytes long.\n" +"There were %.0f unused item pointers.\n" +"Total free space (including removable tuples) is %.0f bytes.\n" +"%u pages are or will become empty, including %u at the end of the table.\n" +"%u pages containing %.0f free bytes are potential move destinations.\n" +"%s" msgstr "" -#: commands/variable.c:141 +#: commands/vacuum.c:2391 #, c-format -msgid "SET DATESTYLE: unrecognized keyword %s" -msgstr "" - -#: commands/variable.c:156 -msgid "SET DATESTYLE: conflicting specifications" -msgstr "" - -#: commands/variable.c:288 -msgid "SET TIME ZONE: illegal INTERVAL; month not allowed" -msgstr "" - -#: commands/variable.c:331 -msgid "Unable to clear TZ environment variable" -msgstr "" - -#: commands/variable.c:351 -msgid "assign_timezone: putenv failed" -msgstr "" - -#: commands/variable.c:420 -msgid "SET TRANSACTION ISOLATION LEVEL must be called before any query" +msgid "\"%s\": moved %u tuples, truncated %u to %u pages" msgstr "" -#: commands/variable.c:495 +#: commands/vacuum.c:2394 +#: commands/vacuumlazy.c:489 +#: commands/vacuumlazy.c:774 +#: nodes/print.c:87 +#: storage/lmgr/deadlock.c:888 +#: tcop/postgres.c:3191 #, c-format -msgid "Conversion between %s and %s is not supported" -msgstr "" - -#: commands/variable.c:507 -msgid "SET SERVER_ENCODING is not supported" -msgstr "SET SERVER_ENCODING не поддерживается" - -#: commands/view.c:87 -msgid "attempted to define virtual relation with no attrs" -msgstr "" +msgid "%s" +msgstr "%s" -#: commands/view.c:109 +#: commands/vacuum.c:2578 +#: commands/vacuumlazy.c:771 #, c-format -msgid "%s is not a view" -msgstr "%s не является видом" - -#: commands/view.c:162 commands/view.c:172 -msgid "Cannot change number of columns in view" +msgid "\"%s\": truncated %u to %u pages" msgstr "" -#: commands/view.c:175 +#: commands/vacuum.c:2670 +#: commands/vacuum.c:2737 +#: commands/vacuumlazy.c:597 +#: commands/vacuumlazy.c:657 #, c-format -msgid "Cannot change name of view column \"%s\"" +msgid "index \"%s\" now contains %.0f tuples in %u pages" msgstr "" -#: commands/view.c:180 +#: commands/vacuum.c:2674 +#: commands/vacuumlazy.c:601 #, c-format -msgid "Cannot change datatype of view column \"%s\"" +msgid "" +"%u index pages have been deleted, %u are currently reusable.\n" +"%s" msgstr "" -#: executor/execAmi.c:163 +#: commands/vacuum.c:2688 +#: commands/vacuum.c:2757 #, c-format -msgid "ExecReScan: node type %d not supported" +msgid "index \"%s\" contains %.0f tuples, but table contains %.0f tuples" msgstr "" -#: executor/execAmi.c:211 -#, c-format -msgid "ExecMarkPos: node type %d not supported" +#: commands/vacuum.c:2691 +#: commands/vacuum.c:2760 +msgid "Rebuild the index with REINDEX." msgstr "" -#: executor/execAmi.c:252 +#: commands/vacuum.c:2741 +#: commands/vacuumlazy.c:661 #, c-format -msgid "ExecRestrPos: node type %d not supported" +msgid "" +"%.0f index tuples were removed.\n" +"%u index pages have been deleted, %u are currently reusable.\n" +"%s" msgstr "" -#: executor/execMain.c:369 +#: commands/vacuumlazy.c:431 #, c-format -msgid "ExecCheckRTEPerms: bogus operation %d" +msgid "" +"%.0f dead tuples cannot be removed yet.\n" +"There were %.0f unused item pointers.\n" +"%u pages are entirely empty.\n" +"%s" msgstr "" -#: executor/execMain.c:741 +#: commands/vacuumlazy.c:486 #, c-format -msgid "You can't change sequence relation %s" +msgid "\"%s\": removed %d tuples in %d pages" msgstr "" -#: executor/execMain.c:745 -#, c-format -msgid "You can't change toast relation %s" +#: commands/variable.c:75 +msgid "invalid list syntax for datestyle" msgstr "" -#: executor/execMain.c:749 +#: commands/variable.c:161 #, c-format -msgid "You can't change view relation %s" +msgid "unrecognized datestyle keyword: \"%s\"" msgstr "" -#: executor/execMain.c:963 -msgid "ExecutePlan: NO (junk) `ctid' was found!" +#: commands/variable.c:179 +msgid "conflicting datestyle specifications" msgstr "" -#: executor/execMain.c:967 -msgid "ExecutePlan: (junk) `ctid' is NULL!" +#: commands/variable.c:450 +msgid "invalid INTERVAL for time zone: month not allowed" msgstr "" -#: executor/execMain.c:992 +#: commands/variable.c:557 #, c-format -msgid "ExecutePlan: NO (junk) `%s' was found!" +msgid "unrecognized timezone name: \"%s\"" msgstr "" -#: executor/execMain.c:997 +#: commands/variable.c:565 #, c-format -msgid "ExecutePlan: (junk) `%s' is NULL!" +msgid "timezone \"%s\" appears to use leap seconds" msgstr "" -#: executor/execMain.c:1086 -msgid "ExecutePlan: unknown operation in queryDesc" +#: commands/variable.c:567 +msgid "PostgreSQL does not support leap seconds" msgstr "" -#: executor/execMain.c:1372 -msgid "ExecUpdate: UPDATE can't run without transactions" +#: commands/variable.c:636 +msgid "SET TRANSACTION ISOLATION LEVEL must be called before any query" msgstr "" -#: executor/execMain.c:1572 +#: commands/variable.c:713 +#: utils/mb/mbutils.c:188 #, c-format -msgid "%s: Fail to add null value in not null attribute %s" +msgid "conversion between %s and %s is not supported" msgstr "" -#: executor/execMain.c:1582 -#, c-format -msgid "%s: rejected due to CHECK constraint \"%s\" on \"%s\"" +#: commands/view.c:89 +msgid "view must have at least one attribute" msgstr "" -#: executor/execMain.c:1625 +#: commands/view.c:113 +#: tcop/utility.c:86 #, c-format -msgid "EvalPlanQual: can't find RTE %d" -msgstr "" +msgid "\"%s\" is not a view" +msgstr "\"%s\" не является видом" -#: executor/execMain.c:1643 -msgid "EvalPlanQual: t_xmin is uncommitted ?!" +#: commands/view.c:169 +#: commands/view.c:181 +msgid "cannot change number of columns in view" msgstr "" -#: executor/execProcnode.c:218 +#: commands/view.c:186 #, c-format -msgid "ExecInitNode: node type %d unsupported" +msgid "cannot change name of view column \"%s\"" msgstr "" -#: executor/execProcnode.c:378 +#: commands/view.c:193 #, c-format -msgid "ExecProcNode: node type %d unsupported" +msgid "cannot change datatype of view column \"%s\"" msgstr "" -#: executor/execProcnode.c:471 +#: executor/execMain.c:844 #, c-format -msgid "ExecCountSlotsNode: node type %d unsupported" +msgid "cannot change sequence relation \"%s\"" msgstr "" -#: executor/execProcnode.c:600 +#: executor/execMain.c:850 #, c-format -msgid "ExecEndNode: node type %d unsupported" +msgid "cannot change toast relation \"%s\"" msgstr "" -#: executor/execProcnode.c:776 +#: executor/execMain.c:856 #, c-format -msgid "ExecGetTupType: node type %d unsupported" +msgid "cannot change view relation \"%s\"" msgstr "" -#: executor/execQual.c:167 executor/execQual.c:189 +#: executor/execMain.c:1689 #, c-format -msgid "ExecEvalArrayRef: can only handle %d dimensions" -msgstr "" - -#: executor/execQual.c:211 -msgid "ExecEvalArrayRef: upper and lower indices mismatch" -msgstr "" - -#: executor/execQual.c:292 -msgid "ExecEvalAggref: no aggregates in this expression context" +msgid "null value for attribute \"%s\" violates NOT NULL constraint" msgstr "" -#: executor/execQual.c:470 +#: executor/execMain.c:1701 #, c-format -msgid "ExecEvalParam: invalid paramkind %d" +msgid "new row for relation \"%s\" violates CHECK constraint \"%s\"" msgstr "" -#: executor/execQual.c:482 +#: executor/execQual.c:180 +#: executor/execQual.c:204 +#: executor/execQual.c:1719 +#: utils/adt/array_userfuncs.c:362 +#: utils/adt/arrayfuncs.c:212 +#: utils/adt/arrayfuncs.c:378 +#: utils/adt/arrayfuncs.c:897 +#: utils/adt/arrayfuncs.c:2237 #, c-format -msgid "ExecEvalParam: Unknown value for parameter %s" +msgid "number of array dimensions exceeds the maximum allowed, %d" msgstr "" -#: executor/execQual.c:485 +#: executor/execQual.c:500 #, c-format -msgid "ExecEvalParam: Unknown value for parameter %d" -msgstr "" - -#: executor/execQual.c:517 -msgid "GetAttributeByNum: Invalid attribute number" -msgstr "" - -#: executor/execQual.c:520 -msgid "GetAttributeByNum: cannot access system attributes here" +msgid "no value found for parameter \"%s\"" msgstr "" -#: executor/execQual.c:523 -msgid "GetAttributeByNum: a NULL isNull flag was passed" -msgstr "" - -#: executor/execQual.c:551 -msgid "GetAttributeByName: Invalid attribute name" -msgstr "" - -#: executor/execQual.c:554 -msgid "GetAttributeByName: a NULL isNull flag was passed" -msgstr "" - -#: executor/execQual.c:576 +#: executor/execQual.c:505 #, c-format -msgid "GetAttributeByName: attribute %s not found" +msgid "no value found for parameter %d" msgstr "" -#: executor/execQual.c:603 -msgid "init_fcache: too many arguments" -msgstr "" +#: executor/execQual.c:665 +msgid "functions and operators can take at most one set argument" +msgstr "функции и операторы принимают только один аргумент-множество (set)" -#: executor/execQual.c:645 -msgid "Functions and operators can take only one set argument" +#: executor/execQual.c:717 +#: executor/execQual.c:761 +#: executor/execQual.c:948 +#: executor/execQual.c:2959 +#: executor/functions.c:578 +#: executor/functions.c:617 +#: utils/adt/pgstatfuncs.c:191 +#: utils/adt/sets.c:207 +#: utils/fmgr/funcapi.c:38 +msgid "set-valued function called in context that cannot accept a set" msgstr "" -#: executor/execQual.c:695 executor/execQual.c:737 executor/execQual.c:922 -#: executor/execQual.c:2427 executor/functions.c:524 executor/functions.c:559 -#: utils/adt/sets.c:204 -msgid "Set-valued function called in context that cannot accept a set" +#: executor/execQual.c:1059 +#: executor/execQual.c:1100 +msgid "function returning tuple cannot return NULL" msgstr "" -#: executor/execQual.c:1033 executor/execQual.c:1068 -msgid "" -"ExecMakeTableFunctionResult: Invalid result from function returning tuple" +#: executor/execQual.c:1064 +msgid "function returning tuple did not return a valid tuple slot" msgstr "" -#: executor/execQual.c:1093 -msgid "ExecMakeTableFunctionResult: Materialize-mode protocol not followed" +#: executor/execQual.c:1127 +msgid "table-function protocol for materialize mode was not followed" msgstr "" -#: executor/execQual.c:1098 +#: executor/execQual.c:1134 #, c-format -msgid "ExecMakeTableFunctionResult: unknown returnMode %d" +msgid "unrecognized table-function returnMode: %d" msgstr "" -#: executor/execQual.c:1218 +#: executor/execQual.c:1247 msgid "IS DISTINCT FROM does not support set arguments" msgstr "" -#: executor/execQual.c:1470 -#, c-format -msgid "ExecEvalNullTest: unexpected nulltesttype %d" +#: executor/execQual.c:1315 +msgid "op ANY/ALL (array) does not support set arguments" msgstr "" -#: executor/execQual.c:1555 -#, c-format -msgid "ExecEvalBooleanTest: unexpected booltesttype %d" +#: executor/execQual.c:1705 +msgid "cannot merge incompatible arrays" msgstr "" -#: executor/execQual.c:1584 +#: executor/execQual.c:1706 #, c-format -msgid "Domain %s does not allow NULL values" +msgid "Array with element type %s cannot be included in ARRAY construct with element type %s." msgstr "" -#: executor/execQual.c:1611 -#, c-format -msgid "ExecEvalConstraintTest: Domain %s constraint %s failed" +#: executor/execQual.c:1739 +msgid "multidimensional arrays must have array expressions with matching dimensions" msgstr "" -#: executor/execQual.c:1619 -msgid "ExecEvalConstraintTest: Constraint type unknown" -msgstr "" - -#: executor/execQual.c:1791 -#, c-format -msgid "ExecEvalExpr: unknown boolop %d" +#: executor/execQual.c:1849 +msgid "NULLIF does not support set arguments" msgstr "" -#: executor/execQual.c:1845 +#: executor/execQual.c:2030 #, c-format -msgid "ExecEvalExpr: unknown expression type %d" +msgid "domain %s does not allow NULL values" msgstr "" -#: executor/execQual.c:1944 optimizer/util/clauses.c:422 -msgid "Aggregate function calls may not be nested" -msgstr "" - -#: executor/execQual.c:1947 -msgid "ExecInitExpr: Aggref not expected here" -msgstr "" - -#: executor/execQual.c:2016 executor/execQual.c:2153 -msgid "ExecInitExpr: SubPlan not expected here" -msgstr "" - -#: executor/execQual.c:2129 +#: executor/execQual.c:2060 #, c-format -msgid "ExecInitExpr: unknown expression type %d" +msgid "value for domain %s violates CHECK constraint \"%s\"" msgstr "" -#: executor/execTuples.c:259 -msgid "" -"Plan requires more slots than are available\n" -"\tsend mail to your local executor guru to fix this" +#: executor/execQual.c:2417 +#: optimizer/util/clauses.c:411 +#: parser/parse_agg.c:74 +msgid "aggregate function calls may not be nested" msgstr "" -#: executor/functions.c:154 +#: executor/functions.c:183 #, c-format -msgid "init_sql_fcache: Cache lookup failed for procedure %u" +msgid "could not determine actual result type for function declared %s" msgstr "" -#: executor/functions.c:166 +#: executor/functions.c:254 #, c-format -msgid "init_sql_fcache: Cache lookup failed for type %u" +msgid "could not determine actual type of argument declared %s" msgstr "" -#: executor/functions.c:228 +#: executor/functions.c:673 #, c-format -msgid "init_sql_fcache: null prosrc for procedure %u" -msgstr "" - -#: executor/instrument.c:40 -msgid "InstrStartTimer called twice in a row" -msgstr "" +msgid "SQL function \"%s\" query %d" +msgstr "SQL-функция \"%s\" запрос %d" -#: executor/instrument.c:56 -msgid "InstrStopNode without start" -msgstr "" - -#: executor/nodeAgg.c:1253 +#: executor/functions.c:686 #, c-format -msgid "ExecAgg: cache lookup failed for aggregate %u" -msgstr "ExecAgg: поиск в кэше агрегата %u не удался" +msgid "SQL function \"%s\"" +msgstr "SQL-функция \"%s\"" -#: executor/nodeAgg.c:1308 +#: executor/functions.c:692 #, c-format -msgid "Aggregate %u needs to have compatible input type and transition type" -msgstr "" +msgid "SQL function \"%s\" during startup" +msgstr "SQL-функция \"%s\" при старте" -#: executor/nodeAgg.c:1357 +#: executor/nodeAgg.c:1314 #, c-format -msgid "" -"GetAggInitVal: cache lookup failed on aggregate transition function return " -"type %u" +msgid "aggregate %u needs to have compatible input type and transition type" msgstr "" -#: executor/nodeAgg.c:1465 +#: executor/nodeIndexscan.c:970 #, c-format -msgid "Aggregate function %u called as normal function" +msgid "indexes of relation %u were deactivated" msgstr "" -#: executor/nodeFunctionscan.c:91 -msgid "" -"Query-specified return tuple and actual function return tuple do not match" +#: executor/nodeFunctionscan.c:93 +msgid "query-specified return tuple and actual function return tuple do not match" msgstr "" -#: executor/nodeHash.c:705 -#, c-format -msgid "ComputeHashFunc: Invalid typLen %d" -msgstr "ComputeHashFunc: Не верный typLen %d" - -#: executor/nodeHashjoin.c:363 +#: executor/nodeHashjoin.c:561 +#: executor/nodeHashjoin.c:571 #, c-format -msgid "ExecInitHashJoin: unsupported join type %d" -msgstr "" - -#: executor/nodeHashjoin.c:541 executor/nodeHashjoin.c:549 -msgid "Read from hashjoin temp file failed" -msgstr "" - -#: executor/nodeHashjoin.c:605 executor/nodeHashjoin.c:610 -msgid "Failed to rewind hash temp file" +msgid "read from hashjoin temp file failed: %m" msgstr "" -#: executor/nodeHashjoin.c:659 executor/nodeHashjoin.c:662 -msgid "Write to hashjoin temp file failed" -msgstr "" - -#: executor/nodeIndexscan.c:675 -msgid "ExecInitIndexScan: indxqual not an opclause!" -msgstr "" - -#: executor/nodeIndexscan.c:777 executor/nodeIndexscan.c:814 +#: executor/nodeHashjoin.c:629 +#: executor/nodeHashjoin.c:636 #, c-format -msgid "ExecInitIndexScan: %s" -msgstr "ExecInitIndexScan: %s" - -#: executor/nodeIndexscan.c:887 -#, c-format -msgid "indexes of the relation %u was inactivated" -msgstr "" - -#: executor/nodeLimit.c:152 executor/nodeLimit.c:167 -msgid "ExecLimit: subplan failed to run backwards" +msgid "failed to rewind hashjoin temp file: %m" msgstr "" -#: executor/nodeLimit.c:198 +#: executor/nodeHashjoin.c:687 +#: executor/nodeHashjoin.c:692 #, c-format -msgid "ExecLimit: impossible state %d" +msgid "write to hashjoin temp file failed: %m" msgstr "" -#: executor/nodeMergejoin.c:132 -msgid "MJFormSkipQuals: op not an OpExpr!" +#: executor/spi.c:725 +msgid "cannot open multi-query plan as cursor" msgstr "" -#: executor/nodeMergejoin.c:400 -#, c-format -msgid "ExecMergeJoin: unsupported join type %d" +#: executor/spi.c:732 +msgid "cannot open non-SELECT query as cursor" msgstr "" -#: executor/nodeMergejoin.c:1384 -#, c-format -msgid "ExecMergeJoin: invalid join state %d, aborting" +#: executor/spi.c:736 +msgid "cannot open SELECT INTO query as cursor" msgstr "" -#: executor/nodeMergejoin.c:1471 +#: executor/nodeMergejoin.c:1479 msgid "RIGHT JOIN is only supported with mergejoinable join conditions" msgstr "" -#: executor/nodeMergejoin.c:1486 optimizer/path/joinpath.c:904 +#: executor/nodeMergejoin.c:1496 +#: optimizer/path/joinpath.c:821 msgid "FULL JOIN is only supported with mergejoinable join conditions" msgstr "" -#: executor/nodeMergejoin.c:1489 -#, c-format -msgid "ExecInitMergeJoin: unsupported join type %d" -msgstr "" - -#: executor/nodeNestloop.c:322 -#, c-format -msgid "ExecInitNestLoop: unsupported join type %d" -msgstr "" - -#: executor/nodeSetOp.c:173 -#, c-format -msgid "ExecSetOp: bogus command code %d" -msgstr "" - -#: executor/nodeSort.c:52 -msgid "ExtractSortKeys: keycount <= 0" -msgstr "" - -#: executor/nodeSubplan.c:56 -msgid "ExecSubPlan: can't set parent params from subquery" -msgstr "" - -#: executor/nodeSubplan.c:125 executor/nodeSubplan.c:150 -#: executor/nodeSubplan.c:427 -msgid "More than one tuple returned by a subselect used as an expression." -msgstr "" - -#: executor/nodeSubplan.c:193 -msgid "ExecSubPlan: failed to find placeholder for subplan result" -msgstr "" - -#: executor/nodeSubplan.c:400 -msgid "ExecSetParamPlan: ANY/ALL subselect unsupported" +#: executor/nodeSubplan.c:290 +#: executor/nodeSubplan.c:332 +#: executor/nodeSubplan.c:966 +msgid "more than one tuple returned by a subselect used as an expression" msgstr "" -#: executor/nodeSubplan.c:516 -msgid "ExecReScanSetParamPlan: direct correlated subquery unsupported, yet" -msgstr "" - -#: executor/nodeSubplan.c:518 -msgid "ExecReScanSetParamPlan: setParam list is NULL" -msgstr "" - -#: executor/nodeSubplan.c:520 -msgid "ExecReScanSetParamPlan: extParam list of plan is NULL" -msgstr "" - -#: executor/spi.c:70 -msgid "SPI_connect: no connection(s) expected" -msgstr "" - -#: executor/spi.c:76 -msgid "SPI_connect: some connection(s) expected" -msgstr "" - -#: executor/spi.c:82 -msgid "Memory exhausted in SPI_connect" -msgstr "" - -#: executor/spi.c:148 -msgid "Memory exhausted in SPI_finish" -msgstr "" - -#: executor/spi.c:310 executor/spi.c:337 executor/spi.c:366 executor/spi.c:404 -#: executor/spi.c:648 executor/spi.c:1418 -msgid "SPI: stack corrupted" -msgstr "" - -#: executor/spi.c:714 -msgid "cannot open multi-query plan as cursor" -msgstr "" - -#: executor/spi.c:719 -msgid "plan in SPI_cursor_open() is not a SELECT" -msgstr "" - -#: executor/spi.c:721 -msgid "plan in SPI_cursor_open() must NOT be a DECLARE already" -msgstr "" - -#: executor/spi.c:723 -msgid "plan in SPI_cursor_open() must NOT be a SELECT INTO" -msgstr "" - -#: executor/spi.c:754 -#, c-format -msgid "cursor \"%s\" already in use" -msgstr "" - -#: executor/spi.c:760 +#: libpq/be-fsstubs.c:124 +#: libpq/be-fsstubs.c:162 +#: libpq/be-fsstubs.c:186 +#: libpq/be-fsstubs.c:214 +#: libpq/be-fsstubs.c:271 #, c-format -msgid "failed to create portal \"%s\"" +msgid "invalid large-object descriptor: %d" msgstr "" -#: executor/spi.c:869 executor/spi.c:1324 -msgid "invalid portal in SPI cursor operation" +#: libpq/be-fsstubs.c:375 +msgid "must be superuser to use server-side lo_import()" msgstr "" -#: executor/spi.c:894 -msgid "SPI: improper call to spi_printtup" +#: libpq/be-fsstubs.c:376 +msgid "Anyone can use the client-side lo_import() provided by libpq." msgstr "" -#: executor/spi.c:896 -msgid "SPI: stack corrupted in spi_printtup" -msgstr "" - -#: executor/spi.c:1275 -msgid "SPI_select: retrieve into portal not implemented" -msgstr "" - -#: executor/spi.c:1285 -msgid "SPI_select: # of processed tuples check failed" -msgstr "" - -#: executor/spi.c:1384 -msgid "SPI_fetch: # of processed tuples check failed" -msgstr "" - -#: lib/dllist.c:41 -msgid "Memory exhausted in DLNewList" -msgstr "" - -#: lib/dllist.c:84 -msgid "Memory exhausted in DLNewElem" -msgstr "" - -#: libpq/auth.c:106 -#, c-format -msgid "pg_krb4_recvauth: kerberos error: %s" -msgstr "" - -#: libpq/auth.c:112 +#: libpq/be-fsstubs.c:391 #, c-format -msgid "pg_krb4_recvauth: protocol version \"%s\" != \"%s\"" -msgstr "" +msgid "could not open server file \"%s\": %m" +msgstr "не получилось отктрыть файл сервера \"%s\": %m" -#: libpq/auth.c:118 +#: libpq/be-fsstubs.c:412 #, c-format -msgid "pg_krb4_recvauth: name \"%s\" != \"%s\"" -msgstr "" +msgid "could not read server file \"%s\": %m" +msgstr "не получилось считать файл сервера \"%s\": %m" -#: libpq/auth.c:130 -msgid "pg_krb4_recvauth: Kerberos not implemented on this server" +#: libpq/be-fsstubs.c:442 +msgid "must be superuser to use server-side lo_export()" msgstr "" -#: libpq/auth.c:190 -#, c-format -msgid "pg_krb5_init: krb5_init_context returned Kerberos error %d" +#: libpq/be-fsstubs.c:443 +msgid "Anyone can use the client-side lo_export() provided by libpq." msgstr "" -#: libpq/auth.c:199 +#: libpq/be-fsstubs.c:469 #, c-format -msgid "pg_krb5_init: krb5_kt_resolve returned Kerberos error %d" -msgstr "" +msgid "could not create server file \"%s\": %m" +msgstr "не получилось создать файл сервера \"%s\": %m" -#: libpq/auth.c:211 +#: libpq/be-fsstubs.c:481 #, c-format -msgid "pg_krb5_init: krb5_sname_to_principal returned Kerberos error %d" -msgstr "" +msgid "could not write server file \"%s\": %m" +msgstr "не получилось записать файл сервера \"%s\": %m" -#: libpq/auth.c:255 +#: libpq/auth.c:113 #, c-format -msgid "pg_krb5_recvauth: krb5_recvauth returned Kerberos error %d" -msgstr "" +msgid "kerberos error: %s" +msgstr "ошибка kerberos: %s" -#: libpq/auth.c:279 +#: libpq/auth.c:119 #, c-format -msgid "pg_krb5_recvauth: krb5_unparse_name returned Kerberos error %d" +msgid "kerberos protocol version \"%s\" != \"%s\"" msgstr "" -#: libpq/auth.c:290 +#: libpq/auth.c:126 +#: libpq/auth.c:306 #, c-format -msgid "pg_krb5_recvauth: user name \"%s\" != krb5 name \"%s\"" +msgid "kerberos user name \"%s\" != \"%s\"" msgstr "" -#: libpq/auth.c:309 -msgid "pg_krb5_recvauth: Kerberos not implemented on this server" +#: libpq/auth.c:140 +msgid "kerberos v4 not implemented on this server" msgstr "" -#: libpq/auth.c:374 +#: libpq/auth.c:201 #, c-format -msgid "%s authentication failed for user \"%s\"" -msgstr "" - -#: libpq/auth.c:396 -msgid "Missing or erroneous pg_hba.conf file, see postmaster log for details" +msgid "kerberos init returned error %d" msgstr "" -#: libpq/auth.c:417 +#: libpq/auth.c:211 #, c-format -msgid "No pg_hba.conf entry for host %s, user %s, database %s" +msgid "kerberos keytab resolve returned error %d" msgstr "" -#: libpq/auth.c:452 +#: libpq/auth.c:224 #, c-format -msgid "pg_local_sendauth: can't do setsockopt: %m" +msgid "kerberos sname_to_principal(\"%s\") returned error %d" msgstr "" -#: libpq/auth.c:541 +#: libpq/auth.c:269 #, c-format -msgid "pam_passwd_conv_proc: Error from underlying PAM layer: '%s'" +msgid "kerberos recvauth returned error %d" msgstr "" -#: libpq/auth.c:545 +#: libpq/auth.c:294 #, c-format -msgid "pam_passwd_conv_proc: Unexpected PAM conversation %d/'%s'" -msgstr "" - -#: libpq/auth.c:575 -msgid "received PAM packet" +msgid "kerberos unparse_name returned error %d" msgstr "" -#: libpq/auth.c:579 -msgid "pam_passwd_conv_proc: no password" +#: libpq/auth.c:327 +msgid "kerberos v5 not implemented on this server" msgstr "" -#: libpq/auth.c:592 -msgid "pam_passwd_conv_proc: Out of memory!" -msgstr "" - -#: libpq/auth.c:636 +#: libpq/auth.c:394 #, c-format -msgid "CheckPAMAuth: Failed to create PAM authenticator: '%s'" +msgid "%s authentication failed for user \"%s\"" msgstr "" -#: libpq/auth.c:646 -#, c-format -msgid "CheckPAMAuth: pam_set_item(PAM_USER) failed: '%s'" +#: libpq/auth.c:418 +msgid "missing or erroneous pg_hba.conf file" msgstr "" -#: libpq/auth.c:656 -#, c-format -msgid "CheckPAMAuth: pam_set_item(PAM_CONV) failed: '%s'" +#: libpq/auth.c:419 +msgid "See postmaster log for details." msgstr "" -#: libpq/auth.c:666 +#: libpq/auth.c:445 #, c-format -msgid "CheckPAMAuth: pam_authenticate failed: '%s'" +msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s" msgstr "" -#: libpq/auth.c:676 -#, c-format -msgid "CheckPAMAuth: pam_acct_mgmt failed: '%s'" -msgstr "" +#: libpq/auth.c:447 +msgid "SSL on" +msgstr "SSL вкл." -#: libpq/auth.c:686 -#, c-format -msgid "CheckPAMAuth: Failed to release PAM authenticator: '%s'" -msgstr "" +#: libpq/auth.c:447 +msgid "SSL off" +msgstr "SSL выкл." -#: libpq/auth.c:726 +#: libpq/auth.c:451 #, c-format -msgid "unexpected password packet size: read %d, expected %d" +msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"" msgstr "" -#: libpq/auth.c:730 -msgid "received password packet" +#: libpq/auth.c:463 +msgid "kerberos 4 only supports IPv4 connections" msgstr "" -#: libpq/be-fsstubs.c:84 +#: libpq/auth.c:495 #, c-format -msgid "lo_open(%u,%d)" +msgid "failed to enable credential receipt: %m" msgstr "" -#: libpq/be-fsstubs.c:102 +#: libpq/auth.c:582 #, c-format -msgid "cannot open large object %u" +msgid "error from underlying PAM layer: %s" msgstr "" -#: libpq/be-fsstubs.c:122 +#: libpq/auth.c:587 #, c-format -msgid "lo_close: invalid large obj descriptor (%d)" +msgid "unsupported PAM conversation %d/%s" msgstr "" -#: libpq/be-fsstubs.c:126 -#, c-format -msgid "lo_close(%d)" +#: libpq/auth.c:619 +msgid "empty password returned by client" msgstr "" -#: libpq/be-fsstubs.c:158 +#: libpq/auth.c:679 #, c-format -msgid "lo_read: invalid large obj descriptor (%d)" +msgid "Failed to create PAM authenticator: %s" msgstr "" -#: libpq/be-fsstubs.c:180 +#: libpq/auth.c:690 #, c-format -msgid "lo_write: invalid large obj descriptor (%d)" +msgid "pam_set_item(PAM_USER) failed: %s" msgstr "" -#: libpq/be-fsstubs.c:206 +#: libpq/auth.c:701 #, c-format -msgid "lo_lseek: invalid large obj descriptor (%d)" +msgid "pam_set_item(PAM_CONV) failed: %s" < |
