├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── problem-installing-psycopg2.md │ └── problem-using-psycopg2.md ├── dependabot.yml └── workflows │ ├── docs.yml │ ├── packages.yml │ └── tests.yml ├── .gitignore ├── AUTHORS ├── INSTALL ├── LICENSE ├── MANIFEST.in ├── Makefile ├── NEWS ├── README.rst ├── doc ├── .gitignore ├── COPYING.LESSER ├── Makefile ├── README.rst ├── SUCCESS ├── pep-0249.txt ├── release.rst ├── requirements.in ├── requirements.txt └── src │ ├── Makefile │ ├── _static │ └── psycopg.css │ ├── _templates │ └── searchbox.html │ ├── advanced.rst │ ├── conf.py │ ├── connection.rst │ ├── cursor.rst │ ├── errorcodes.rst │ ├── errors.rst │ ├── extensions.rst │ ├── extras.rst │ ├── faq.rst │ ├── index.rst │ ├── install.rst │ ├── license.rst │ ├── module.rst │ ├── news.rst │ ├── pool.rst │ ├── sql.rst │ ├── tools │ ├── lib │ │ ├── dbapi_extension.py │ │ ├── sql_role.py │ │ └── ticket_role.py │ └── make_sqlstate_docs.py │ ├── tz.rst │ └── usage.rst ├── lib ├── __init__.py ├── _ipaddress.py ├── _json.py ├── _range.py ├── errorcodes.py ├── errors.py ├── extensions.py ├── extras.py ├── pool.py ├── sql.py └── tz.py ├── psycopg ├── _psycopg.vc9.amd64.manifest ├── _psycopg.vc9.x86.manifest ├── adapter_asis.c ├── adapter_asis.h ├── adapter_binary.c ├── adapter_binary.h ├── adapter_datetime.c ├── adapter_datetime.h ├── adapter_list.c ├── adapter_list.h ├── adapter_pboolean.c ├── adapter_pboolean.h ├── adapter_pdecimal.c ├── adapter_pdecimal.h ├── adapter_pfloat.c ├── adapter_pfloat.h ├── adapter_pint.c ├── adapter_pint.h ├── adapter_qstring.c ├── adapter_qstring.h ├── aix_support.c ├── aix_support.h ├── bytes_format.c ├── column.h ├── column_type.c ├── config.h ├── connection.h ├── connection_int.c ├── connection_type.c ├── conninfo.h ├── conninfo_type.c ├── cursor.h ├── cursor_int.c ├── cursor_type.c ├── diagnostics.h ├── diagnostics_type.c ├── error.h ├── error_type.c ├── green.c ├── green.h ├── libpq_support.c ├── libpq_support.h ├── lobject.h ├── lobject_int.c ├── lobject_type.c ├── microprotocols.c ├── microprotocols.h ├── microprotocols_proto.c ├── microprotocols_proto.h ├── notify.h ├── notify_type.c ├── pgtypes.h ├── pqpath.c ├── pqpath.h ├── psycopg.h ├── psycopgmodule.c ├── python.h ├── replication_connection.h ├── replication_connection_type.c ├── replication_cursor.h ├── replication_cursor_type.c ├── replication_message.h ├── replication_message_type.c ├── solaris_support.c ├── solaris_support.h ├── sqlstate_errors.h ├── typecast.c ├── typecast.h ├── typecast_array.c ├── typecast_basic.c ├── typecast_binary.c ├── typecast_binary.h ├── typecast_builtins.c ├── typecast_datetime.c ├── utils.c ├── utils.h ├── win32_support.c ├── win32_support.h ├── xid.h └── xid_type.c ├── psycopg2.cproj ├── scripts ├── build │ ├── build_libpq.sh │ ├── build_macos_arm64.sh │ ├── build_sdist.sh │ ├── pg_config_vcpkg_stub │ │ ├── pg_config_vcpkg_stub │ │ │ └── __init__.py │ │ └── pyproject.toml │ ├── print_so_versions.sh │ ├── run_build_macos_arm64.sh │ ├── scaleway_m1.sh │ ├── strip_wheel.sh │ ├── wheel_linux_before_all.sh │ ├── wheel_macos_before_all.sh │ └── wheel_win32_before_build.bat ├── make_errorcodes.py ├── make_errors.py └── refcounter.py ├── setup.cfg ├── setup.py ├── tests ├── __init__.py ├── dbapi20.py ├── dbapi20_tpc.py ├── test_async.py ├── test_bugX000.py ├── test_bug_gc.py ├── test_cancel.py ├── test_connection.py ├── test_copy.py ├── test_cursor.py ├── test_dates.py ├── test_errcodes.py ├── test_errors.py ├── test_extras_dictcursor.py ├── test_fast_executemany.py ├── test_green.py ├── test_ipaddress.py ├── test_lobject.py ├── test_module.py ├── test_notify.py ├── test_psycopg2_dbapi20.py ├── test_quote.py ├── test_replication.py ├── test_sql.py ├── test_transaction.py ├── test_types_basic.py ├── test_types_extras.py ├── test_with.py ├── testconfig.py └── testutils.py └── tox.ini /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: 2 | - dvarrazzo 3 | custom: 4 | - "https://www.paypal.me/dvarrazzo" 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/problem-installing-psycopg2.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Problem installing psycopg2 3 | about: Report a case in which psycopg2 failed to install on your platform 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **This is a bug tracker** 11 | If you have a question, such has "how do you do X with Python/PostgreSQL/psycopg2" please [write to the mailing list](https://lists.postgresql.org/manage/) or [open a question](https://github.com/psycopg/psycopg2/discussions) instead. 12 | 13 | **Before opening this ticket, please confirm that:** 14 | - [ ] I am running the latest version of pip, i.e. typing ``pip --version`` you get [this version](https://pypi.org/project/pip/). 15 | - [ ] I have read the [installation documentation](https://www.psycopg.org/docs/install.html) and the [frequently asked questions](https://www.psycopg.org/docs/faq.html) 16 | - [ ] If install failed, I typed `pg_config` on the command line and I obtained an output instead of an error. 17 | 18 | **Please complete the following information:** 19 | - OS: 20 | - Psycopg version: 21 | - Python version: 22 | - PostgreSQL version: 23 | - pip version 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/problem-using-psycopg2.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Problem using psycopg2 3 | about: Report a case in which psycopg2 is not working as expected 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **This is a bug tracker** 11 | If you have a question, such has "how do you do X with Python/PostgreSQL/psycopg2" please [write to the mailing list](https://lists.postgresql.org/manage/) or [open a question](https://github.com/psycopg/psycopg2/discussions) instead. 12 | 13 | **Please complete the following information:** 14 | - OS: 15 | - Psycopg version: 16 | - Python version: 17 | - PostgreSQL version: 18 | - pip version 19 | 20 | **Describe the bug** 21 | Please let us know: 22 | 23 | 1: what you did 24 | 2: what you expected to happen 25 | 3: what happened instead 26 | 27 | If possible, provide a script reproducing the issue. 28 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Build documentation 2 | 3 | on: 4 | push: 5 | branches: 6 | # This should match the DOC_BRANCH value in the psycopg-website Makefile 7 | - master 8 | 9 | jobs: 10 | docs: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Trigger docs build 14 | uses: peter-evans/repository-dispatch@v3 15 | with: 16 | repository: psycopg/psycopg-website 17 | event-type: psycopg2-commit 18 | token: ${{ secrets.ACCESS_TOKEN }} 19 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | env: 4 | PIP_BREAK_SYSTEM_PACKAGES: "1" 5 | 6 | on: 7 | push: 8 | pull_request: 9 | 10 | jobs: 11 | linux: 12 | runs-on: ubuntu-latest 13 | if: true 14 | 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | include: 19 | - {python: "3.8", postgres: "12"} 20 | - {python: "3.9", postgres: "13"} 21 | - {python: "3.10", postgres: "14"} 22 | - {python: "3.11", postgres: "15"} 23 | - {python: "3.12", postgres: "16"} 24 | - {python: "3.13", postgres: "17"} 25 | 26 | # Opposite extremes of the supported Py/PG range, other architecture 27 | - {python: "3.8", postgres: "17", architecture: "x86"} 28 | - {python: "3.9", postgres: "16", architecture: "x86"} 29 | - {python: "3.10", postgres: "15", architecture: "x86"} 30 | - {python: "3.11", postgres: "14", architecture: "x86"} 31 | - {python: "3.12", postgres: "13", architecture: "x86"} 32 | - {python: "3.13", postgres: "12", architecture: "x86"} 33 | 34 | env: 35 | PSYCOPG2_TESTDB: postgres 36 | PSYCOPG2_TESTDB_HOST: 127.0.0.1 37 | PSYCOPG2_TESTDB_USER: postgres 38 | PSYCOPG2_TESTDB_PASSWORD: password 39 | 40 | services: 41 | postgresql: 42 | image: postgres:${{ matrix.postgres }} 43 | env: 44 | POSTGRES_PASSWORD: password 45 | ports: 46 | - 5432:5432 47 | # Set health checks to wait until postgres has started 48 | options: >- 49 | --health-cmd pg_isready 50 | --health-interval 10s 51 | --health-timeout 5s 52 | --health-retries 5 53 | 54 | steps: 55 | - uses: actions/checkout@v4 56 | 57 | # Can enable to test an unreleased libpq version. 58 | - name: install libpq 16 59 | if: false 60 | run: | 61 | set -x 62 | rel=$(lsb_release -c -s) 63 | echo "deb http://apt.postgresql.org/pub/repos/apt ${rel}-pgdg main 16" \ 64 | | sudo tee -a /etc/apt/sources.list.d/pgdg.list 65 | sudo apt-get -qq update 66 | pqver=$(apt-cache show libpq5 | grep ^Version: | head -1 \ 67 | | awk '{print $2}') 68 | sudo apt-get -qq -y install "libpq-dev=${pqver}" "libpq5=${pqver}" 69 | 70 | - name: Install tox 71 | run: pip install "tox < 4" 72 | - uses: actions/setup-python@v5 73 | with: 74 | python-version: ${{ matrix.python }} 75 | - name: Run tests 76 | env: 77 | MATRIX_PYTHON: ${{ matrix.python }} 78 | run: tox -e ${MATRIX_PYTHON%-dev} 79 | timeout-minutes: 5 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | MANIFEST 2 | *~ 3 | *.userprefs 4 | *.pidb 5 | *.pyc 6 | *.sw[po] 7 | *.egg-info/ 8 | dist/* 9 | /build 10 | env 11 | env? 12 | .idea 13 | .tox 14 | .vscode/ 15 | /rel 16 | /wheels 17 | /packages 18 | /wheelhouse 19 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Main authors: 2 | Federico Di Gregorio 3 | Daniele Varrazzo 4 | 5 | For the win32 port: 6 | Jason Erickson 7 | 8 | Additional Help: 9 | 10 | Peter Fein contributed a logging connection/cursor class that even if it 11 | was not used directly heavily influenced the implementation currently in 12 | psycopg2.extras. 13 | 14 | Jan Urbański (re)started the work on asynchronous queries and contributed 15 | both on that and on other parts of psycopg2. 16 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation instructions are included in the docs. 2 | 3 | Please check the 'doc/src/install.rst' file or online at 4 | . 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | psycopg2 and the LGPL 2 | --------------------- 3 | 4 | psycopg2 is free software: you can redistribute it and/or modify it 5 | under the terms of the GNU Lesser General Public License as published 6 | by the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | psycopg2 is distributed in the hope that it will be useful, but WITHOUT 10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 12 | License for more details. 13 | 14 | In addition, as a special exception, the copyright holders give 15 | permission to link this program with the OpenSSL library (or with 16 | modified versions of OpenSSL that use the same license as OpenSSL), 17 | and distribute linked combinations including the two. 18 | 19 | You must obey the GNU Lesser General Public License in all respects for 20 | all of the code used other than OpenSSL. If you modify file(s) with this 21 | exception, you may extend this exception to your version of the file(s), 22 | but you are not obligated to do so. If you do not wish to do so, delete 23 | this exception statement from your version. If you delete this exception 24 | statement from all source files in the program, then also delete it here. 25 | 26 | You should have received a copy of the GNU Lesser General Public License 27 | along with psycopg2 (see the doc/ directory.) 28 | If not, see . 29 | 30 | 31 | Alternative licenses 32 | -------------------- 33 | 34 | The following BSD-like license applies (at your option) to the files following 35 | the pattern ``psycopg/adapter*.{h,c}`` and ``psycopg/microprotocol*.{h,c}``: 36 | 37 | Permission is granted to anyone to use this software for any purpose, 38 | including commercial applications, and to alter it and redistribute it 39 | freely, subject to the following restrictions: 40 | 41 | 1. The origin of this software must not be misrepresented; you must not 42 | claim that you wrote the original software. If you use this 43 | software in a product, an acknowledgment in the product documentation 44 | would be appreciated but is not required. 45 | 46 | 2. Altered source versions must be plainly marked as such, and must not 47 | be misrepresented as being the original software. 48 | 49 | 3. This notice may not be removed or altered from any source distribution. 50 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include psycopg *.c *.h *.manifest 2 | recursive-include lib *.py 3 | recursive-include tests *.py 4 | include doc/README.rst doc/SUCCESS doc/COPYING.LESSER doc/pep-0249.txt 5 | include doc/Makefile doc/requirements.txt 6 | recursive-include doc/src *.rst *.py *.css Makefile 7 | recursive-include scripts *.py *.sh 8 | include AUTHORS README.rst INSTALL LICENSE NEWS 9 | include MANIFEST.in setup.py setup.cfg Makefile 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for psycopg2. Do you want to... 2 | # 3 | # Build the library:: 4 | # 5 | # make 6 | # 7 | # Build the documentation:: 8 | # 9 | # make env (once) 10 | # make docs 11 | # 12 | # Create a source package:: 13 | # 14 | # make sdist 15 | # 16 | # Run the test:: 17 | # 18 | # make check # this requires setting up a test database with the correct user 19 | 20 | PYTHON := python$(PYTHON_VERSION) 21 | PYTHON_VERSION ?= $(shell $(PYTHON) -c 'import sys; print ("%d.%d" % sys.version_info[:2])') 22 | BUILD_DIR = $(shell pwd)/build/lib.$(PYTHON_VERSION) 23 | 24 | SOURCE_C := $(wildcard psycopg/*.c psycopg/*.h) 25 | SOURCE_PY := $(wildcard lib/*.py) 26 | SOURCE_TESTS := $(wildcard tests/*.py) 27 | SOURCE_DOC := $(wildcard doc/src/*.rst) 28 | SOURCE := $(SOURCE_C) $(SOURCE_PY) $(SOURCE_TESTS) $(SOURCE_DOC) 29 | 30 | PACKAGE := $(BUILD_DIR)/psycopg2 31 | PLATLIB := $(PACKAGE)/_psycopg.so 32 | PURELIB := $(patsubst lib/%,$(PACKAGE)/%,$(SOURCE_PY)) 33 | 34 | BUILD_OPT := --build-lib=$(BUILD_DIR) 35 | BUILD_EXT_OPT := --build-lib=$(BUILD_DIR) 36 | SDIST_OPT := --formats=gztar 37 | 38 | ifdef PG_CONFIG 39 | BUILD_EXT_OPT += --pg-config=$(PG_CONFIG) 40 | endif 41 | 42 | VERSION := $(shell grep PSYCOPG_VERSION setup.py | head -1 | sed -e "s/.*'\(.*\)'/\1/") 43 | SDIST := dist/psycopg2-$(VERSION).tar.gz 44 | 45 | .PHONY: check clean 46 | 47 | default: package 48 | 49 | all: package sdist 50 | 51 | package: $(PLATLIB) $(PURELIB) 52 | 53 | docs: docs-html 54 | 55 | docs-html: doc/html/genindex.html 56 | 57 | # for PyPI documentation 58 | docs-zip: doc/docs.zip 59 | 60 | sdist: $(SDIST) 61 | 62 | env: 63 | $(MAKE) -C doc $@ 64 | 65 | check: 66 | PYTHONPATH=$(BUILD_DIR) $(PYTHON) -c "import tests; tests.unittest.main(defaultTest='tests.test_suite')" --verbose 67 | 68 | testdb: 69 | @echo "* Creating $(TESTDB)" 70 | @if psql -l | grep -q " $(TESTDB) "; then \ 71 | dropdb $(TESTDB) >/dev/null; \ 72 | fi 73 | createdb $(TESTDB) 74 | # Note to packagers: this requires the postgres user running the test 75 | # to be a superuser. You may change this line to use the superuser only 76 | # to install the contrib. Feel free to suggest a better way to set up the 77 | # testing environment (as the current is enough for development). 78 | psql -f `pg_config --sharedir`/contrib/hstore.sql $(TESTDB) 79 | 80 | 81 | $(PLATLIB): $(SOURCE_C) 82 | $(PYTHON) setup.py build_ext $(BUILD_EXT_OPT) 83 | 84 | $(PACKAGE)/%.py: lib/%.py 85 | $(PYTHON) setup.py build_py $(BUILD_OPT) 86 | touch $@ 87 | 88 | $(PACKAGE)/tests/%.py: tests/%.py 89 | $(PYTHON) setup.py build_py $(BUILD_OPT) 90 | touch $@ 91 | 92 | $(SDIST): $(SOURCE) 93 | $(PYTHON) setup.py sdist $(SDIST_OPT) 94 | 95 | # docs depend on the build as it partly use introspection. 96 | doc/html/genindex.html: $(PLATLIB) $(PURELIB) $(SOURCE_DOC) 97 | $(MAKE) -C doc html 98 | 99 | doc/docs.zip: doc/html/genindex.html 100 | (cd doc/html && zip -r ../docs.zip *) 101 | 102 | clean: 103 | rm -rf build 104 | $(MAKE) -C doc clean 105 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | psycopg2 - Python-PostgreSQL Database Adapter 2 | ============================================= 3 | 4 | Psycopg is the most popular PostgreSQL database adapter for the Python 5 | programming language. Its main features are the complete implementation of 6 | the Python DB API 2.0 specification and the thread safety (several threads can 7 | share the same connection). It was designed for heavily multi-threaded 8 | applications that create and destroy lots of cursors and make a large number 9 | of concurrent "INSERT"s or "UPDATE"s. 10 | 11 | Psycopg 2 is mostly implemented in C as a libpq wrapper, resulting in being 12 | both efficient and secure. It features client-side and server-side cursors, 13 | asynchronous communication and notifications, "COPY TO/COPY FROM" support. 14 | Many Python types are supported out-of-the-box and adapted to matching 15 | PostgreSQL data types; adaptation can be extended and customized thanks to a 16 | flexible objects adaptation system. 17 | 18 | Psycopg 2 is both Unicode and Python 3 friendly. 19 | 20 | .. Note:: 21 | 22 | The psycopg2 package is still widely used and actively maintained, but it 23 | is not expected to receive new features. 24 | 25 | `Psycopg 3`__ is the evolution of psycopg2 and is where `new features are 26 | being developed`__: if you are starting a new project you should probably 27 | start from 3! 28 | 29 | .. __: https://pypi.org/project/psycopg/ 30 | .. __: https://www.psycopg.org/psycopg3/docs/index.html 31 | 32 | 33 | Documentation 34 | ------------- 35 | 36 | Documentation is included in the ``doc`` directory and is `available online`__. 37 | 38 | .. __: https://www.psycopg.org/docs/ 39 | 40 | For any other resource (source code repository, bug tracker, mailing list) 41 | please check the `project homepage`__. 42 | 43 | .. __: https://psycopg.org/ 44 | 45 | 46 | Installation 47 | ------------ 48 | 49 | Building Psycopg requires a few prerequisites (a C compiler, some development 50 | packages): please check the install_ and the faq_ documents in the ``doc`` dir 51 | or online for the details. 52 | 53 | If prerequisites are met, you can install psycopg like any other Python 54 | package, using ``pip`` to download it from PyPI_:: 55 | 56 | $ pip install psycopg2 57 | 58 | or using ``setup.py`` if you have downloaded the source package locally:: 59 | 60 | $ python setup.py build 61 | $ sudo python setup.py install 62 | 63 | You can also obtain a stand-alone package, not requiring a compiler or 64 | external libraries, by installing the `psycopg2-binary`_ package from PyPI:: 65 | 66 | $ pip install psycopg2-binary 67 | 68 | The binary package is a practical choice for development and testing but in 69 | production it is advised to use the package built from sources. 70 | 71 | .. _PyPI: https://pypi.org/project/psycopg2/ 72 | .. _psycopg2-binary: https://pypi.org/project/psycopg2-binary/ 73 | .. _install: https://www.psycopg.org/docs/install.html#install-from-source 74 | .. _faq: https://www.psycopg.org/docs/faq.html#faq-compile 75 | 76 | :Build status: |gh-actions| 77 | 78 | .. |gh-actions| image:: https://github.com/psycopg/psycopg2/actions/workflows/tests.yml/badge.svg 79 | :target: https://github.com/psycopg/psycopg2/actions/workflows/tests.yml 80 | :alt: Build status 81 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | env 2 | src/_build/* 3 | html/* 4 | psycopg2.txt 5 | src/sqlstate_errors.rst 6 | 7 | # Added by psycopg-website to customize published docs 8 | src/_templates/layout.html 9 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: env help clean html package doctest 2 | 3 | docs: html 4 | 5 | check: doctest 6 | 7 | # The environment is currently required to build the documentation. 8 | # It is not clean by 'make clean' 9 | 10 | PYTHON := python$(PYTHON_VERSION) 11 | PYTHON_VERSION ?= $(shell $(PYTHON) -c 'import sys; print("%d.%d" % sys.version_info[:2])') 12 | BUILD_DIR = $(shell pwd)/../build/lib.$(PYTHON_VERSION) 13 | 14 | SPHINXBUILD ?= $$(pwd)/env/bin/sphinx-build 15 | SPHOPTS = SPHINXBUILD=$(SPHINXBUILD) 16 | 17 | html: package src/sqlstate_errors.rst 18 | $(MAKE) $(SPHOPTS) -C src $@ 19 | cp -r src/_build/html . 20 | 21 | src/sqlstate_errors.rst: ../psycopg/sqlstate_errors.h $(BUILD_DIR) 22 | ./env/bin/python src/tools/make_sqlstate_docs.py $< > $@ 23 | 24 | $(BUILD_DIR): 25 | $(MAKE) PYTHON=$(PYTHON) -C .. package 26 | 27 | doctest: 28 | $(MAKE) PYTHON=$(PYTHON) -C .. package 29 | $(MAKE) $(SPHOPTS) -C src $@ 30 | 31 | clean: 32 | $(MAKE) $(SPHOPTS) -C src $@ 33 | rm -rf html src/sqlstate_errors.rst 34 | 35 | env: requirements.txt 36 | $(PYTHON) -m venv env 37 | ./env/bin/pip install -r requirements.txt 38 | echo "$$(pwd)/../build/lib.$(PYTHON_VERSION)" \ 39 | > env/lib/python$(PYTHON_VERSION)/site-packages/psycopg.pth 40 | -------------------------------------------------------------------------------- /doc/README.rst: -------------------------------------------------------------------------------- 1 | How to build psycopg documentation 2 | ---------------------------------- 3 | 4 | Building the documentation usually requires building the library too for 5 | introspection, so you will need the same prerequisites_. The only extra 6 | prerequisite is virtualenv_: the packages needed to build the docs will be 7 | installed when building the env. 8 | 9 | .. _prerequisites: https://www.psycopg.org/docs/install.html#install-from-source 10 | .. _virtualenv: https://virtualenv.pypa.io/en/latest/ 11 | 12 | Build the env once with:: 13 | 14 | make env 15 | 16 | Then you can build the documentation with:: 17 | 18 | make 19 | 20 | You should find the rendered documentation in the ``html`` directory. 21 | -------------------------------------------------------------------------------- /doc/SUCCESS: -------------------------------------------------------------------------------- 1 | From: Jack Moffitt 2 | To: Psycopg Mailing List 3 | Subject: Re: [Psycopg] preparing for 1.0 4 | Date: 22 Oct 2001 11:16:21 -0600 5 | 6 | www.vorbis.com is serving from 5-10k pages per day with psycopg serving 7 | data for most of that. 8 | 9 | I plan to use it for several of our other sites, so that number will 10 | increase. 11 | 12 | I've never had a single problem (that wasn't my fault) besides those 13 | segfaults, and those are now gone as well, and I've been using psycopg 14 | since June (around 0.99.2?). 15 | 16 | jack. 17 | 18 | 19 | From: Yury Don 20 | To: Psycopg Mailing List 21 | Subject: Re: [Psycopg] preparing for 1.0 22 | Date: 23 Oct 2001 09:53:11 +0600 23 | 24 | We use psycopg and psycopg zope adapter since fisrt public 25 | release (it seems version 0.4). Now it works on 3 our sites and in intranet 26 | applications. We had few problems, but all problems were quickly 27 | solved. The strong side of psycopg is that it's code is well organized 28 | and easy to understand. When I found a problem with non-ISO datestyle in first 29 | version of psycopg, it took for me 15 or 20 minutes to learn code and 30 | to solve the problem, even thouth my knowledge of c were poor. 31 | 32 | BTW, segfault with dictfetchall on particular data set (see [Psycopg] 33 | dictfetchXXX() problems) disappeared in 0.99.8pre2. 34 | 35 | -- 36 | Best regards, 37 | Yury Don 38 | 39 | 40 | From: Tom Jenkins 41 | To: Federico Di Gregorio 42 | Cc: Psycopg Mailing List 43 | Subject: Re: [Psycopg] preparing for 1.0 44 | Date: 23 Oct 2001 08:25:52 -0400 45 | 46 | The US Govt Department of Labor's Office of Disability Employment 47 | Policy's DisabilityDirect website is run on zope and zpsycopg. 48 | 49 | 50 | From: Scott Leerssen 51 | To: Federico Di Gregorio 52 | Subject: Re: [Psycopg] preparing for 1.0 53 | Date: 23 Oct 2001 09:56:10 -0400 54 | 55 | Racemi's load management software infrastructure uses psycopg to handle 56 | complex server allocation decisions, plus storage and access of 57 | environmental conditions and accounting records for potentially 58 | thousands of servers. Psycopg has, to this point, been the only 59 | Python/PostGreSQL interface that could handle the scaling required for 60 | our multithreaded applications. 61 | 62 | Scott 63 | 64 | 65 | From: Andre Schubert 66 | To: Federico Di Gregorio 67 | Cc: Psycopg Mailing List 68 | Subject: Re: [Psycopg] preparing for 1.0 69 | Date: 23 Oct 2001 11:46:07 +0200 70 | 71 | i have changed the psycopg version to 0.99.8pre2 on all devel-machines 72 | and all segfaults are gone. after my holiday i wil change to 0.99.8pre2 73 | or 1.0 on our production-server. 74 | this server contains several web-sites which are all connected to 75 | postgres over ZPsycopgDA. 76 | 77 | thanks as 78 | 79 | 80 | From: Fred Wilson Horch 81 | To: 82 | Subject: [Psycopg] Success story for psycopg 83 | Date: 23 Oct 2001 10:59:17 -0400 84 | 85 | Due to various quirks of PyGreSQL and PoPy, EcoAccess has been looking for 86 | a reliable, fast and relatively bug-free Python-PostgreSQL interface for 87 | our project. 88 | 89 | Binary support in psycopg, along with the umlimited tuple size in 90 | PostgreSQL 7.1, allowed us to quickly prototype a database-backed file 91 | storage web application, which we're using for file sharing among our 92 | staff and volunteers. Using a database backend instead of a file system 93 | allows us to easily enrich the meta-information associated with each file 94 | and simplifies our data handling routines. 95 | 96 | We've been impressed by the responsiveness of the psycopg team to bug 97 | reports and feature requests, and we're looking forward to using psycopg 98 | as the Python interface for additional database-backed web applications. 99 | 100 | Keep up the good work! 101 | -- 102 | Fred Wilson Horch mailto:fhorch@ecoaccess.org 103 | Executive Director, EcoAccess http://ecoaccess.org/ 104 | 105 | 106 | From: Damon Fasching 107 | To: Michele Comitini 108 | Cc: fog@debian.org 109 | Subject: Re: How does one create a database within Python using psycopg? 110 | Date: 25 Feb 2002 17:39:41 -0800 111 | 112 | [snip] 113 | btw I checked out 4 different Python-PostgreSQL packages. psycopg is the 114 | only one which built and imported w/o any trouble! (At least for me.) 115 | -------------------------------------------------------------------------------- /doc/release.rst: -------------------------------------------------------------------------------- 1 | How to make a psycopg2 release 2 | ============================== 3 | 4 | - Edit ``setup.py`` and set a stable version release. Use PEP 440 to choose 5 | version numbers, e.g. 6 | 7 | - ``2.7``: a new major release, new features 8 | - ``2.7.1``: a bugfix release 9 | - ``2.7.1.1``: a release to fix packaging problems 10 | - ``2.7.2.dev0``: version held during development, non-public test packages... 11 | - ``2.8b1``: a beta for public tests 12 | 13 | In the rest of this document we assume you have exported the version number 14 | into an environment variable, e.g.:: 15 | 16 | $ export VERSION=2.8.4 17 | 18 | - Push psycopg2 to master or to the maint branch. Make sure tests on `GitHub 19 | Actions`__. 20 | 21 | .. __: https://github.com/psycopg/psycopg2/actions/workflows/tests.yml 22 | 23 | - Create a signed tag with the content of the relevant NEWS bit and push it. 24 | E.g.:: 25 | 26 | # Tag name will be 2_8_4 27 | $ git tag -a -s ${VERSION//\./_} 28 | 29 | Psycopg 2.8.4 released 30 | 31 | What's new in psycopg 2.8.4 32 | --------------------------- 33 | 34 | New features: 35 | 36 | - Fixed bug blah (:ticket:`#42`). 37 | ... 38 | 39 | - Create the packages: 40 | 41 | - On GitHub Actions run manually a `package build workflow`__. 42 | 43 | .. __: https://github.com/psycopg/psycopg2/actions/workflows/packages.yml 44 | 45 | - When the workflows have finished download the packages from the job 46 | artifacts. 47 | 48 | - Only for stable packages: upload the signed packages on PyPI:: 49 | 50 | $ twine upload -s wheelhouse/psycopg2-${VERSION}/* 51 | 52 | - Create a release and release notes in the psycopg website, announce to 53 | psycopg and pgsql-announce mailing lists. 54 | 55 | - Edit ``setup.py`` changing the version again (e.g. go to ``2.8.5.dev0``). 56 | 57 | 58 | Releasing test packages 59 | ----------------------- 60 | 61 | Test packages may be uploaded on the `PyPI testing site`__ using:: 62 | 63 | $ twine upload -s -r testpypi wheelhouse/psycopg2-${VERSION}/* 64 | 65 | assuming `proper configuration`__ of ``~/.pypirc``. 66 | 67 | .. __: https://test.pypi.org/project/psycopg2/ 68 | .. __: https://wiki.python.org/moin/TestPyPI 69 | -------------------------------------------------------------------------------- /doc/requirements.in: -------------------------------------------------------------------------------- 1 | Sphinx 2 | sphinx-better-theme 3 | -------------------------------------------------------------------------------- /doc/requirements.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with Python 3.10 3 | # by the following command: 4 | # 5 | # pip-compile requirements.in 6 | # 7 | alabaster==0.7.13 8 | # via sphinx 9 | babel==2.12.1 10 | # via sphinx 11 | certifi>=2023.7.22 12 | # via requests 13 | charset-normalizer==3.1.0 14 | # via requests 15 | docutils==0.19 16 | # via sphinx 17 | idna==3.4 18 | # via requests 19 | imagesize==1.4.1 20 | # via sphinx 21 | jinja2==3.1.2 22 | # via sphinx 23 | markupsafe==2.1.2 24 | # via jinja2 25 | packaging==23.1 26 | # via sphinx 27 | pygments==2.15.0 28 | # via sphinx 29 | requests==2.31.0 30 | # via sphinx 31 | snowballstemmer==2.2.0 32 | # via sphinx 33 | sphinx==6.1.3 34 | # via -r requirements.in 35 | sphinx-better-theme==0.1.5 36 | # via -r requirements.in 37 | sphinxcontrib-applehelp==1.0.4 38 | # via sphinx 39 | sphinxcontrib-devhelp==1.0.2 40 | # via sphinx 41 | sphinxcontrib-htmlhelp==2.0.1 42 | # via sphinx 43 | sphinxcontrib-jsmath==1.0.1 44 | # via sphinx 45 | sphinxcontrib-qthelp==1.0.3 46 | # via sphinx 47 | sphinxcontrib-serializinghtml==1.1.5 48 | # via sphinx 49 | urllib3==1.26.17 50 | # via requests 51 | -------------------------------------------------------------------------------- /doc/src/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # DSN for the doctest database 11 | PSYCOPG2_DSN="user=postgres dbname=test" 12 | 13 | # Internal variables. 14 | PAPEROPT_a4 = -D latex_paper_size=a4 15 | PAPEROPT_letter = -D latex_paper_size=letter 16 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 17 | 18 | .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest 19 | 20 | help: 21 | @echo "Please use \`make ' where is one of" 22 | @echo " html to make standalone HTML files" 23 | @echo " dirhtml to make HTML files named index.html in directories" 24 | @echo " pickle to make pickle files" 25 | @echo " json to make JSON files" 26 | @echo " htmlhelp to make HTML files and a HTML help project" 27 | @echo " qthelp to make HTML files and a qthelp project" 28 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 29 | @echo " changes to make an overview of all changed/added/deprecated items" 30 | @echo " linkcheck to check all external links for integrity" 31 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 32 | 33 | clean: 34 | -rm -rf $(BUILDDIR)/* 35 | -rm -rf ./html/* 36 | 37 | html: 38 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 39 | @echo 40 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 41 | 42 | dirhtml: 43 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 44 | @echo 45 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 46 | 47 | text: 48 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 49 | @echo 50 | @echo "Build finished. The text pages are in $(BUILDDIR)/text." 51 | 52 | pickle: 53 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 54 | @echo 55 | @echo "Build finished; now you can process the pickle files." 56 | 57 | json: 58 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 59 | @echo 60 | @echo "Build finished; now you can process the JSON files." 61 | 62 | htmlhelp: 63 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 64 | @echo 65 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 66 | ".hhp project file in $(BUILDDIR)/htmlhelp." 67 | 68 | qthelp: 69 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 70 | @echo 71 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 72 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 73 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/psycopg.qhcp" 74 | @echo "To view the help file:" 75 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/psycopg.qhc" 76 | 77 | latex: 78 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 79 | @echo 80 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 81 | @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ 82 | "run these through (pdf)latex." 83 | 84 | changes: 85 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 86 | @echo 87 | @echo "The overview file is in $(BUILDDIR)/changes." 88 | 89 | linkcheck: 90 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 91 | @echo 92 | @echo "Link check complete; look for any errors in the above output " \ 93 | "or in $(BUILDDIR)/linkcheck/output.txt." 94 | 95 | doctest: 96 | PSYCOPG2_DSN=$(PSYCOPG2_DSN) \ 97 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 98 | @echo "Testing of doctests in the sources finished, look at the " \ 99 | "results in $(BUILDDIR)/doctest/output.txt." 100 | -------------------------------------------------------------------------------- /doc/src/_static/psycopg.css: -------------------------------------------------------------------------------- 1 | blockquote { 2 | font-style: italic; 3 | } 4 | 5 | div.admonition-todo { 6 | background-color: #ffa; 7 | border: 1px solid #ee2; 8 | } 9 | 10 | div.dbapi-extension { 11 | background-color: #eef; 12 | border: 1px solid #aaf; 13 | } 14 | 15 | code.sql, 16 | tt.sql { 17 | font-size: 1em; 18 | background-color: transparent; 19 | } 20 | 21 | a > code.sql, 22 | a > tt.sql { 23 | font-weight: normal; 24 | } 25 | 26 | a > code.sql:hover, 27 | a > tt.sql:hover { 28 | text-decoration: underline; 29 | } 30 | 31 | dl.faq dt { 32 | font-weight: bold; 33 | } 34 | 35 | table.data-types div.line-block { 36 | margin-bottom: 0; 37 | } 38 | 39 | 40 | /* better theme customisation */ 41 | 42 | body { 43 | background-color: #216464; 44 | } 45 | 46 | header, .related, .document, footer { 47 | background-color: white; 48 | } 49 | 50 | header h1 { 51 | font-size: 150%; 52 | margin-bottom: 0; 53 | padding: 0.5rem 10px 0.5rem 10px; 54 | } 55 | 56 | h1, h2, h3 { 57 | font-weight: normal; 58 | } 59 | 60 | .body h1, .body h2, .body h3 { 61 | color: #074848; 62 | } 63 | 64 | h1 { 65 | font-size: 200%; 66 | } 67 | 68 | h2 { 69 | font-size: 160%; 70 | } 71 | 72 | h3 { 73 | font-size: 140%; 74 | } 75 | 76 | footer#pagefooter { 77 | margin-bottom: 1rem; 78 | font-size: 85%; 79 | color: #444; 80 | } 81 | 82 | #rellinks, #breadcrumbs { 83 | padding-right: 10px; 84 | padding-left: 10px; 85 | } 86 | 87 | .sphinxsidebar { 88 | padding-left: 10px; 89 | } 90 | 91 | .bodywrapper { 92 | padding-right: 10px; 93 | } 94 | 95 | div.body h1, div.body h2, div.body h3 { 96 | background-color: #f2f2f2; 97 | border-bottom: 1px solid #d0d0d0; 98 | } 99 | 100 | div.body p.rubric { 101 | border-bottom: 1px solid #d0d0d0; 102 | } 103 | 104 | body .sphinxsidebar .search { 105 | margin-top: 0; 106 | } 107 | 108 | html pre { 109 | background-color: #efc; 110 | border: 1px solid #ac9; 111 | border-left: none; 112 | border-right: none; 113 | } 114 | 115 | a, a:visited { 116 | color: #0b6868; 117 | } 118 | 119 | th { 120 | background-color: #ede; 121 | } 122 | 123 | code.xref, a code { 124 | font-weight: bold; 125 | } 126 | 127 | code.descname { 128 | font-weight: bold; 129 | font-size: 120%; 130 | } 131 | 132 | @media (max-width: 820px) { 133 | body { 134 | background-color: white; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /doc/src/_templates/searchbox.html: -------------------------------------------------------------------------------- 1 | {# Add a title over the search box #} 2 | 3 | {%- if pagename != "search" %} 4 |

Quick search

5 | {%- include "!searchbox.html" %} 6 | {%- endif %} 7 | -------------------------------------------------------------------------------- /doc/src/errorcodes.rst: -------------------------------------------------------------------------------- 1 | `psycopg2.errorcodes` -- Error codes defined by PostgreSQL 2 | =============================================================== 3 | 4 | .. sectionauthor:: Daniele Varrazzo 5 | 6 | .. index:: 7 | single: Error; Codes 8 | 9 | .. module:: psycopg2.errorcodes 10 | 11 | .. testsetup:: * 12 | 13 | from psycopg2 import errorcodes 14 | 15 | .. versionadded:: 2.0.6 16 | 17 | This module contains symbolic names for all PostgreSQL error codes and error 18 | classes codes. Subclasses of `~psycopg2.Error` make the PostgreSQL error 19 | code available in the `~psycopg2.Error.pgcode` attribute. 20 | 21 | From PostgreSQL documentation: 22 | 23 | All messages emitted by the PostgreSQL server are assigned five-character 24 | error codes that follow the SQL standard's conventions for :sql:`SQLSTATE` 25 | codes. Applications that need to know which error condition has occurred 26 | should usually test the error code, rather than looking at the textual 27 | error message. The error codes are less likely to change across 28 | PostgreSQL releases, and also are not subject to change due to 29 | localization of error messages. Note that some, but not all, of the error 30 | codes produced by PostgreSQL are defined by the SQL standard; some 31 | additional error codes for conditions not defined by the standard have 32 | been invented or borrowed from other databases. 33 | 34 | According to the standard, the first two characters of an error code 35 | denote a class of errors, while the last three characters indicate a 36 | specific condition within that class. Thus, an application that does not 37 | recognize the specific error code can still be able to infer what to do 38 | from the error class. 39 | 40 | .. seealso:: `PostgreSQL Error Codes table`__ 41 | 42 | .. __: https://www.postgresql.org/docs/current/static/errcodes-appendix.html#ERRCODES-TABLE 43 | 44 | 45 | An example of the available constants defined in the module: 46 | 47 | >>> errorcodes.CLASS_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION 48 | '42' 49 | >>> errorcodes.UNDEFINED_TABLE 50 | '42P01' 51 | 52 | Constants representing all the error values defined by PostgreSQL versions 53 | between 8.1 and 15 are included in the module. 54 | 55 | 56 | .. autofunction:: lookup(code) 57 | 58 | .. doctest:: 59 | 60 | >>> try: 61 | ... cur.execute("SELECT ouch FROM aargh;") 62 | ... except Exception as e: 63 | ... pass 64 | ... 65 | >>> errorcodes.lookup(e.pgcode[:2]) 66 | 'CLASS_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION' 67 | >>> errorcodes.lookup(e.pgcode) 68 | 'UNDEFINED_TABLE' 69 | 70 | .. versionadded:: 2.0.14 71 | 72 | 73 | .. testcode:: 74 | :hide: 75 | 76 | conn.rollback() 77 | -------------------------------------------------------------------------------- /doc/src/errors.rst: -------------------------------------------------------------------------------- 1 | `psycopg2.errors` -- Exception classes mapping PostgreSQL errors 2 | ================================================================ 3 | 4 | .. sectionauthor:: Daniele Varrazzo 5 | 6 | .. index:: 7 | single: Error; Class 8 | 9 | .. module:: psycopg2.errors 10 | 11 | .. versionadded:: 2.8 12 | 13 | .. versionchanged:: 2.8.4 added errors introduced in PostgreSQL 12 14 | 15 | .. versionchanged:: 2.8.6 added errors introduced in PostgreSQL 13 16 | 17 | .. versionchanged:: 2.9.2 added errors introduced in PostgreSQL 14 18 | 19 | .. versionchanged:: 2.9.4 added errors introduced in PostgreSQL 15 20 | 21 | .. versionchanged:: 2.9.10 added errors introduced in PostgreSQL 17 22 | 23 | This module exposes the classes psycopg raises upon receiving an error from 24 | the database with a :sql:`SQLSTATE` value attached (available in the 25 | `~psycopg2.Error.pgcode` attribute). The content of the module is generated 26 | from the PostgreSQL source code and includes classes for every error defined 27 | by PostgreSQL in versions between 9.1 and 15. 28 | 29 | Every class in the module is named after what referred as "condition name" `in 30 | the documentation`__, converted to CamelCase: e.g. the error 22012, 31 | ``division_by_zero`` is exposed by this module as the class `!DivisionByZero`. 32 | 33 | .. __: https://www.postgresql.org/docs/current/static/errcodes-appendix.html#ERRCODES-TABLE 34 | 35 | Every exception class is a subclass of one of the :ref:`standard DB-API 36 | exception ` and expose the `~psycopg2.Error` interface. 37 | Each class' superclass is what used to be raised by psycopg in versions before 38 | the introduction of this module, so everything should be compatible with 39 | previously written code catching one the DB-API class: if your code used to 40 | catch `!IntegrityError` to detect a duplicate entry, it will keep on working 41 | even if a more specialised subclass such as `UniqueViolation` is raised. 42 | 43 | The new classes allow a more idiomatic way to check and process a specific 44 | error among the many the database may return. For instance, in order to check 45 | that a table is locked, the following code could have been used previously: 46 | 47 | .. code-block:: python 48 | 49 | try: 50 | cur.execute("LOCK TABLE mytable IN ACCESS EXCLUSIVE MODE NOWAIT") 51 | except psycopg2.OperationalError as e: 52 | if e.pgcode == psycopg2.errorcodes.LOCK_NOT_AVAILABLE: 53 | locked = True 54 | else: 55 | raise 56 | 57 | While this method is still available, the specialised class allows for a more 58 | idiomatic error handler: 59 | 60 | .. code-block:: python 61 | 62 | try: 63 | cur.execute("LOCK TABLE mytable IN ACCESS EXCLUSIVE MODE NOWAIT") 64 | except psycopg2.errors.LockNotAvailable: 65 | locked = True 66 | 67 | 68 | .. autofunction:: lookup 69 | 70 | .. code-block:: python 71 | 72 | try: 73 | cur.execute("LOCK TABLE mytable IN ACCESS EXCLUSIVE MODE NOWAIT") 74 | except psycopg2.errors.lookup("55P03"): 75 | locked = True 76 | 77 | 78 | SQLSTATE exception classes 79 | -------------------------- 80 | 81 | The following table contains the list of all the SQLSTATE classes exposed by 82 | the module. 83 | 84 | Note that, for completeness, the module also exposes all the 85 | :ref:`DB-API-defined exceptions ` and :ref:`a few 86 | psycopg-specific ones ` exposed by the `!extensions` 87 | module, which are not listed here. 88 | 89 | .. include:: sqlstate_errors.rst 90 | -------------------------------------------------------------------------------- /doc/src/index.rst: -------------------------------------------------------------------------------- 1 | ================================================= 2 | Psycopg -- PostgreSQL database adapter for Python 3 | ================================================= 4 | 5 | .. sectionauthor:: Daniele Varrazzo 6 | 7 | Psycopg_ is the most popular PostgreSQL_ database adapter for the Python_ 8 | programming language. Its main features are the complete implementation of 9 | the Python |DBAPI|_ specification and the thread safety (several threads can 10 | share the same connection). It was designed for heavily multi-threaded 11 | applications that create and destroy lots of cursors and make a large number 12 | of concurrent :sql:`INSERT`\s or :sql:`UPDATE`\s. 13 | 14 | Psycopg 2 is mostly implemented in C as a libpq_ wrapper, resulting in being 15 | both efficient and secure. It features client-side and :ref:`server-side 16 | ` cursors, :ref:`asynchronous communication 17 | ` and :ref:`notifications `, :ref:`COPY ` 18 | support. Many Python types are supported out-of-the-box and :ref:`adapted to 19 | matching PostgreSQL data types `; adaptation can be 20 | extended and customized thanks to a flexible :ref:`objects adaptation system 21 | `. 22 | 23 | Psycopg 2 is both Unicode and Python 3 friendly. 24 | 25 | 26 | .. _Psycopg: https://psycopg.org/ 27 | .. _PostgreSQL: https://www.postgresql.org/ 28 | .. _Python: https://www.python.org/ 29 | .. _libpq: https://www.postgresql.org/docs/current/static/libpq.html 30 | 31 | 32 | .. rubric:: Contents 33 | 34 | .. toctree:: 35 | :maxdepth: 2 36 | 37 | install 38 | usage 39 | module 40 | connection 41 | cursor 42 | advanced 43 | extensions 44 | extras 45 | errors 46 | sql 47 | tz 48 | pool 49 | errorcodes 50 | faq 51 | news 52 | license 53 | 54 | 55 | .. ifconfig:: builder != 'text' 56 | 57 | .. rubric:: Indices and tables 58 | 59 | * :ref:`genindex` 60 | * :ref:`modindex` 61 | * :ref:`search` 62 | 63 | 64 | .. ifconfig:: todo_include_todos 65 | 66 | .. note:: 67 | 68 | **To Do items in the documentation** 69 | 70 | .. todolist:: 71 | -------------------------------------------------------------------------------- /doc/src/license.rst: -------------------------------------------------------------------------------- 1 | .. index:: 2 | single: License 3 | 4 | License 5 | ======= 6 | 7 | .. include:: ../../LICENSE 8 | -------------------------------------------------------------------------------- /doc/src/news.rst: -------------------------------------------------------------------------------- 1 | .. index:: 2 | single: Release notes 3 | single: News 4 | 5 | .. _news: 6 | 7 | Release notes 8 | ============= 9 | 10 | .. include:: ../../NEWS 11 | -------------------------------------------------------------------------------- /doc/src/pool.rst: -------------------------------------------------------------------------------- 1 | `psycopg2.pool` -- Connections pooling 2 | ====================================== 3 | 4 | .. sectionauthor:: Daniele Varrazzo 5 | 6 | .. index:: 7 | pair: Connection; Pooling 8 | 9 | .. module:: psycopg2.pool 10 | 11 | Creating new PostgreSQL connections can be an expensive operation. This 12 | module offers a few pure Python classes implementing simple connection pooling 13 | directly in the client application. 14 | 15 | .. class:: AbstractConnectionPool(minconn, maxconn, \*args, \*\*kwargs) 16 | 17 | Base class implementing generic key-based pooling code. 18 | 19 | New *minconn* connections are created automatically. The pool will support 20 | a maximum of about *maxconn* connections. *\*args* and *\*\*kwargs* are 21 | passed to the `~psycopg2.connect()` function. 22 | 23 | The following methods are expected to be implemented by subclasses: 24 | 25 | .. method:: getconn(key=None) 26 | 27 | Get a free connection from the pool. 28 | 29 | The *key* parameter is optional: if used, the connection will be 30 | associated to the key and calling `!getconn()` with the same key again 31 | will return the same connection. 32 | 33 | .. method:: putconn(conn, key=None, close=False) 34 | 35 | Put away a connection. 36 | 37 | If *close* is `!True`, discard the connection from the pool. 38 | *key* should be used consistently with `getconn()`. 39 | 40 | .. method:: closeall 41 | 42 | Close all the connections handled by the pool. 43 | 44 | Note that all the connections are closed, including ones 45 | eventually in use by the application. 46 | 47 | 48 | The following classes are `AbstractConnectionPool` subclasses ready to 49 | be used. 50 | 51 | .. autoclass:: SimpleConnectionPool 52 | 53 | .. note:: This pool class is useful only for single-threaded applications. 54 | 55 | 56 | .. index:: Multithread; Connection pooling 57 | 58 | .. autoclass:: ThreadedConnectionPool 59 | 60 | .. note:: This pool class can be safely used in multi-threaded applications. 61 | -------------------------------------------------------------------------------- /doc/src/tools/lib/dbapi_extension.py: -------------------------------------------------------------------------------- 1 | """ 2 | extension 3 | ~~~~~~~~~ 4 | 5 | A directive to create a box warning that a certain bit of Psycopg is an 6 | extension to the DBAPI 2.0. 7 | 8 | :copyright: Copyright 2010 by Daniele Varrazzo. 9 | """ 10 | 11 | from docutils import nodes 12 | 13 | from sphinx.locale import _ 14 | from docutils.parsers.rst import Directive 15 | 16 | class extension_node(nodes.Admonition, nodes.Element): pass 17 | 18 | 19 | class Extension(Directive): 20 | """ 21 | An extension entry, displayed as an admonition. 22 | """ 23 | 24 | has_content = True 25 | required_arguments = 0 26 | optional_arguments = 0 27 | final_argument_whitespace = False 28 | option_spec = {} 29 | 30 | def run(self): 31 | node = extension_node('\n'.join(self.content)) 32 | node += nodes.title(_('DB API extension'), _('DB API extension')) 33 | self.state.nested_parse(self.content, self.content_offset, node) 34 | node['classes'].append('dbapi-extension') 35 | return [node] 36 | 37 | 38 | def visit_extension_node(self, node): 39 | self.visit_admonition(node) 40 | 41 | def depart_extension_node(self, node): 42 | self.depart_admonition(node) 43 | 44 | def setup(app): 45 | app.add_node(extension_node, 46 | html=(visit_extension_node, depart_extension_node), 47 | latex=(visit_extension_node, depart_extension_node), 48 | text=(visit_extension_node, depart_extension_node)) 49 | 50 | app.add_directive('extension', Extension) 51 | -------------------------------------------------------------------------------- /doc/src/tools/lib/sql_role.py: -------------------------------------------------------------------------------- 1 | """ 2 | sql role 3 | ~~~~~~~~ 4 | 5 | An interpreted text role to style SQL syntax in Psycopg documentation. 6 | 7 | :copyright: Copyright 2010 by Daniele Varrazzo. 8 | """ 9 | 10 | from docutils import nodes, utils 11 | from docutils.parsers.rst import roles 12 | 13 | def sql_role(name, rawtext, text, lineno, inliner, options={}, content=[]): 14 | text = utils.unescape(text) 15 | options['classes'] = ['sql'] 16 | return [nodes.literal(rawtext, text, **options)], [] 17 | 18 | def setup(app): 19 | roles.register_local_role('sql', sql_role) 20 | -------------------------------------------------------------------------------- /doc/src/tools/lib/ticket_role.py: -------------------------------------------------------------------------------- 1 | """ 2 | ticket role 3 | ~~~~~~~~~~~ 4 | 5 | An interpreted text role to link docs to tickets issues. 6 | 7 | :copyright: Copyright 2013 by Daniele Varrazzo. 8 | """ 9 | 10 | import re 11 | from docutils import nodes, utils 12 | from docutils.parsers.rst import roles 13 | 14 | def ticket_role(name, rawtext, text, lineno, inliner, options={}, content=[]): 15 | cfg = inliner.document.settings.env.app.config 16 | if cfg.ticket_url is None: 17 | msg = inliner.reporter.warning( 18 | "ticket not configured: please configure ticket_url in conf.py") 19 | prb = inliner.problematic(rawtext, rawtext, msg) 20 | return [prb], [msg] 21 | 22 | rv = [nodes.Text(name + ' ')] 23 | tokens = re.findall(r'(#?\d+)|([^\d#]+)', text) 24 | for ticket, noise in tokens: 25 | if ticket: 26 | num = int(ticket.replace('#', '')) 27 | 28 | # Push numbers of the oldel tickets ahead. 29 | # We moved the tickets from a different tracker to GitHub and the 30 | # latter already had a few ticket numbers taken (as merge 31 | # requests). 32 | remap_until = cfg.ticket_remap_until 33 | remap_offset = cfg.ticket_remap_offset 34 | if remap_until and remap_offset: 35 | if num <= remap_until: 36 | num += remap_offset 37 | 38 | url = cfg.ticket_url % num 39 | roles.set_classes(options) 40 | node = nodes.reference(ticket, utils.unescape(ticket), 41 | refuri=url, **options) 42 | 43 | rv.append(node) 44 | 45 | else: 46 | assert noise 47 | rv.append(nodes.Text(noise)) 48 | 49 | return rv, [] 50 | 51 | 52 | def setup(app): 53 | app.add_config_value('ticket_url', None, 'env') 54 | app.add_config_value('ticket_remap_until', None, 'env') 55 | app.add_config_value('ticket_remap_offset', None, 'env') 56 | app.add_role('ticket', ticket_role) 57 | app.add_role('tickets', ticket_role) 58 | -------------------------------------------------------------------------------- /doc/src/tools/make_sqlstate_docs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Create the docs table of the sqlstate errors. 3 | """ 4 | 5 | 6 | import re 7 | import sys 8 | from collections import namedtuple 9 | 10 | from psycopg2._psycopg import sqlstate_errors 11 | 12 | 13 | def main(): 14 | sqlclasses = {} 15 | clsfile = sys.argv[1] 16 | with open(clsfile) as f: 17 | for l in f: 18 | m = re.match(r'/\* Class (..) - (.+) \*/', l) 19 | if m is not None: 20 | sqlclasses[m.group(1)] = m.group(2) 21 | 22 | Line = namedtuple('Line', 'colstate colexc colbase sqlstate') 23 | 24 | lines = [Line('SQLSTATE', 'Exception', 'Base exception', None)] 25 | for k in sorted(sqlstate_errors): 26 | exc = sqlstate_errors[k] 27 | lines.append(Line( 28 | f"``{k}``", f"`!{exc.__name__}`", 29 | f"`!{get_base_exception(exc).__name__}`", k)) 30 | 31 | widths = [max(len(l[c]) for l in lines) for c in range(3)] 32 | h = Line(*(['=' * w for w in widths] + [None])) 33 | lines.insert(0, h) 34 | lines.insert(2, h) 35 | lines.append(h) 36 | 37 | h1 = '-' * (sum(widths) + len(widths) - 1) 38 | sqlclass = None 39 | for l in lines: 40 | cls = l.sqlstate[:2] if l.sqlstate else None 41 | if cls and cls != sqlclass: 42 | print(f"**Class {cls}**: {sqlclasses[cls]}") 43 | print(h1) 44 | sqlclass = cls 45 | 46 | print("%-*s %-*s %-*s" % ( 47 | widths[0], l.colstate, widths[1], l.colexc, widths[2], l.colbase)) 48 | 49 | 50 | def get_base_exception(exc): 51 | for cls in exc.__mro__: 52 | if cls.__module__ == 'psycopg2': 53 | return cls 54 | 55 | 56 | if __name__ == '__main__': 57 | sys.exit(main()) 58 | -------------------------------------------------------------------------------- /doc/src/tz.rst: -------------------------------------------------------------------------------- 1 | `psycopg2.tz` -- ``tzinfo`` implementations for Psycopg 2 2 | =============================================================== 3 | 4 | .. sectionauthor:: Daniele Varrazzo 5 | 6 | .. module:: psycopg2.tz 7 | 8 | .. deprecated:: 2.9 9 | The module will be dropped in psycopg 2.10. Use `datetime.timezone` 10 | instead. 11 | 12 | This module holds two different tzinfo implementations that can be used as the 13 | `tzinfo` argument to `~datetime.datetime` constructors, directly passed to 14 | Psycopg functions or used to set the `cursor.tzinfo_factory` attribute in 15 | cursors. 16 | 17 | .. autoclass:: psycopg2.tz.FixedOffsetTimezone 18 | 19 | .. autoclass:: psycopg2.tz.LocalTimezone 20 | -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- 1 | """A Python driver for PostgreSQL 2 | 3 | psycopg is a PostgreSQL_ database adapter for the Python_ programming 4 | language. This is version 2, a complete rewrite of the original code to 5 | provide new-style classes for connection and cursor objects and other sweet 6 | candies. Like the original, psycopg 2 was written with the aim of being very 7 | small and fast, and stable as a rock. 8 | 9 | Homepage: https://psycopg.org/ 10 | 11 | .. _PostgreSQL: https://www.postgresql.org/ 12 | .. _Python: https://www.python.org/ 13 | 14 | :Groups: 15 | * `Connections creation`: connect 16 | * `Value objects constructors`: Binary, Date, DateFromTicks, Time, 17 | TimeFromTicks, Timestamp, TimestampFromTicks 18 | """ 19 | # psycopg/__init__.py - initialization of the psycopg module 20 | # 21 | # Copyright (C) 2003-2019 Federico Di Gregorio 22 | # Copyright (C) 2020-2021 The Psycopg Team 23 | # 24 | # psycopg2 is free software: you can redistribute it and/or modify it 25 | # under the terms of the GNU Lesser General Public License as published 26 | # by the Free Software Foundation, either version 3 of the License, or 27 | # (at your option) any later version. 28 | # 29 | # In addition, as a special exception, the copyright holders give 30 | # permission to link this program with the OpenSSL library (or with 31 | # modified versions of OpenSSL that use the same license as OpenSSL), 32 | # and distribute linked combinations including the two. 33 | # 34 | # You must obey the GNU Lesser General Public License in all respects for 35 | # all of the code used other than OpenSSL. 36 | # 37 | # psycopg2 is distributed in the hope that it will be useful, but WITHOUT 38 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 39 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 40 | # License for more details. 41 | 42 | # Import modules needed by _psycopg to allow tools like py2exe to do 43 | # their work without bothering about the module dependencies. 44 | 45 | # Note: the first internal import should be _psycopg, otherwise the real cause 46 | # of a failed loading of the C module may get hidden, see 47 | # https://archives.postgresql.org/psycopg/2011-02/msg00044.php 48 | 49 | # Import the DBAPI-2.0 stuff into top-level module. 50 | 51 | from psycopg2._psycopg import ( # noqa 52 | BINARY, NUMBER, STRING, DATETIME, ROWID, 53 | 54 | Binary, Date, Time, Timestamp, 55 | DateFromTicks, TimeFromTicks, TimestampFromTicks, 56 | 57 | Error, Warning, DataError, DatabaseError, ProgrammingError, IntegrityError, 58 | InterfaceError, InternalError, NotSupportedError, OperationalError, 59 | 60 | _connect, apilevel, threadsafety, paramstyle, 61 | __version__, __libpq_version__, 62 | ) 63 | 64 | 65 | # Register default adapters. 66 | 67 | from psycopg2 import extensions as _ext 68 | _ext.register_adapter(tuple, _ext.SQL_IN) 69 | _ext.register_adapter(type(None), _ext.NoneAdapter) 70 | 71 | # Register the Decimal adapter here instead of in the C layer. 72 | # This way a new class is registered for each sub-interpreter. 73 | # See ticket #52 74 | from decimal import Decimal # noqa 75 | from psycopg2._psycopg import Decimal as Adapter # noqa 76 | _ext.register_adapter(Decimal, Adapter) 77 | del Decimal, Adapter 78 | 79 | 80 | def connect(dsn=None, connection_factory=None, cursor_factory=None, **kwargs): 81 | """ 82 | Create a new database connection. 83 | 84 | The connection parameters can be specified as a string: 85 | 86 | conn = psycopg2.connect("dbname=test user=postgres password=secret") 87 | 88 | or using a set of keyword arguments: 89 | 90 | conn = psycopg2.connect(database="test", user="postgres", password="secret") 91 | 92 | Or as a mix of both. The basic connection parameters are: 93 | 94 | - *dbname*: the database name 95 | - *database*: the database name (only as keyword argument) 96 | - *user*: user name used to authenticate 97 | - *password*: password used to authenticate 98 | - *host*: database host address (defaults to UNIX socket if not provided) 99 | - *port*: connection port number (defaults to 5432 if not provided) 100 | 101 | Using the *connection_factory* parameter a different class or connections 102 | factory can be specified. It should be a callable object taking a dsn 103 | argument. 104 | 105 | Using the *cursor_factory* parameter, a new default cursor factory will be 106 | used by cursor(). 107 | 108 | Using *async*=True an asynchronous connection will be created. *async_* is 109 | a valid alias (for Python versions where ``async`` is a keyword). 110 | 111 | Any other keyword parameter will be passed to the underlying client 112 | library: the list of supported parameters depends on the library version. 113 | 114 | """ 115 | kwasync = {} 116 | if 'async' in kwargs: 117 | kwasync['async'] = kwargs.pop('async') 118 | if 'async_' in kwargs: 119 | kwasync['async_'] = kwargs.pop('async_') 120 | 121 | dsn = _ext.make_dsn(dsn, **kwargs) 122 | conn = _connect(dsn, connection_factory=connection_factory, **kwasync) 123 | if cursor_factory is not None: 124 | conn.cursor_factory = cursor_factory 125 | 126 | return conn 127 | -------------------------------------------------------------------------------- /lib/_ipaddress.py: -------------------------------------------------------------------------------- 1 | """Implementation of the ipaddres-based network types adaptation 2 | """ 3 | 4 | # psycopg/_ipaddress.py - Ipaddres-based network types adaptation 5 | # 6 | # Copyright (C) 2016-2019 Daniele Varrazzo 7 | # Copyright (C) 2020-2021 The Psycopg Team 8 | # 9 | # psycopg2 is free software: you can redistribute it and/or modify it 10 | # under the terms of the GNU Lesser General Public License as published 11 | # by the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # In addition, as a special exception, the copyright holders give 15 | # permission to link this program with the OpenSSL library (or with 16 | # modified versions of OpenSSL that use the same license as OpenSSL), 17 | # and distribute linked combinations including the two. 18 | # 19 | # You must obey the GNU Lesser General Public License in all respects for 20 | # all of the code used other than OpenSSL. 21 | # 22 | # psycopg2 is distributed in the hope that it will be useful, but WITHOUT 23 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 24 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 25 | # License for more details. 26 | 27 | from psycopg2.extensions import ( 28 | new_type, new_array_type, register_type, register_adapter, QuotedString) 29 | 30 | # The module is imported on register_ipaddress 31 | ipaddress = None 32 | 33 | # The typecasters are created only once 34 | _casters = None 35 | 36 | 37 | def register_ipaddress(conn_or_curs=None): 38 | """ 39 | Register conversion support between `ipaddress` objects and `network types`__. 40 | 41 | :param conn_or_curs: the scope where to register the type casters. 42 | If `!None` register them globally. 43 | 44 | After the function is called, PostgreSQL :sql:`inet` values will be 45 | converted into `~ipaddress.IPv4Interface` or `~ipaddress.IPv6Interface` 46 | objects, :sql:`cidr` values into into `~ipaddress.IPv4Network` or 47 | `~ipaddress.IPv6Network`. 48 | 49 | .. __: https://www.postgresql.org/docs/current/static/datatype-net-types.html 50 | """ 51 | global ipaddress 52 | import ipaddress 53 | 54 | global _casters 55 | if _casters is None: 56 | _casters = _make_casters() 57 | 58 | for c in _casters: 59 | register_type(c, conn_or_curs) 60 | 61 | for t in [ipaddress.IPv4Interface, ipaddress.IPv6Interface, 62 | ipaddress.IPv4Network, ipaddress.IPv6Network]: 63 | register_adapter(t, adapt_ipaddress) 64 | 65 | 66 | def _make_casters(): 67 | inet = new_type((869,), 'INET', cast_interface) 68 | ainet = new_array_type((1041,), 'INET[]', inet) 69 | 70 | cidr = new_type((650,), 'CIDR', cast_network) 71 | acidr = new_array_type((651,), 'CIDR[]', cidr) 72 | 73 | return [inet, ainet, cidr, acidr] 74 | 75 | 76 | def cast_interface(s, cur=None): 77 | if s is None: 78 | return None 79 | # Py2 version force the use of unicode. meh. 80 | return ipaddress.ip_interface(str(s)) 81 | 82 | 83 | def cast_network(s, cur=None): 84 | if s is None: 85 | return None 86 | return ipaddress.ip_network(str(s)) 87 | 88 | 89 | def adapt_ipaddress(obj): 90 | return QuotedString(str(obj)) 91 | -------------------------------------------------------------------------------- /lib/errors.py: -------------------------------------------------------------------------------- 1 | """Error classes for PostgreSQL error codes 2 | """ 3 | 4 | # psycopg/errors.py - SQLSTATE and DB-API exceptions 5 | # 6 | # Copyright (C) 2018-2019 Daniele Varrazzo 7 | # Copyright (C) 2020-2021 The Psycopg Team 8 | # 9 | # psycopg2 is free software: you can redistribute it and/or modify it 10 | # under the terms of the GNU Lesser General Public License as published 11 | # by the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # In addition, as a special exception, the copyright holders give 15 | # permission to link this program with the OpenSSL library (or with 16 | # modified versions of OpenSSL that use the same license as OpenSSL), 17 | # and distribute linked combinations including the two. 18 | # 19 | # You must obey the GNU Lesser General Public License in all respects for 20 | # all of the code used other than OpenSSL. 21 | # 22 | # psycopg2 is distributed in the hope that it will be useful, but WITHOUT 23 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 24 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 25 | # License for more details. 26 | 27 | # 28 | # NOTE: the exceptions are injected into this module by the C extention. 29 | # 30 | 31 | 32 | def lookup(code): 33 | """Lookup an error code and return its exception class. 34 | 35 | Raise `!KeyError` if the code is not found. 36 | """ 37 | from psycopg2._psycopg import sqlstate_errors # avoid circular import 38 | return sqlstate_errors[code] 39 | -------------------------------------------------------------------------------- /psycopg/_psycopg.vc9.amd64.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /psycopg/_psycopg.vc9.x86.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /psycopg/adapter_asis.h: -------------------------------------------------------------------------------- 1 | /* adapter_asis.h - definition for the psycopg AsIs type wrapper 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_ASIS_H 28 | #define PSYCOPG_ASIS_H 1 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | extern HIDDEN PyTypeObject asisType; 35 | 36 | typedef struct { 37 | PyObject_HEAD 38 | 39 | /* this is the real object we wrap */ 40 | PyObject *wrapped; 41 | 42 | } asisObject; 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif /* !defined(PSYCOPG_ASIS_H) */ 49 | -------------------------------------------------------------------------------- /psycopg/adapter_binary.h: -------------------------------------------------------------------------------- 1 | /* adapter_binary.h - definition for the Binary type 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_BINARY_H 28 | #define PSYCOPG_BINARY_H 1 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | extern HIDDEN PyTypeObject binaryType; 35 | 36 | typedef struct { 37 | PyObject_HEAD 38 | 39 | PyObject *wrapped; 40 | PyObject *buffer; 41 | PyObject *conn; 42 | } binaryObject; 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif /* !defined(PSYCOPG_BINARY_H) */ 49 | -------------------------------------------------------------------------------- /psycopg/adapter_datetime.h: -------------------------------------------------------------------------------- 1 | /* adapter_datetime.h - definition for the python date/time types 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_DATETIME_H 28 | #define PSYCOPG_DATETIME_H 1 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | extern HIDDEN PyTypeObject pydatetimeType; 35 | 36 | typedef struct { 37 | PyObject_HEAD 38 | 39 | PyObject *wrapped; 40 | int type; 41 | #define PSYCO_DATETIME_TIME 0 42 | #define PSYCO_DATETIME_DATE 1 43 | #define PSYCO_DATETIME_TIMESTAMP 2 44 | #define PSYCO_DATETIME_INTERVAL 3 45 | 46 | } pydatetimeObject; 47 | 48 | 49 | RAISES_NEG HIDDEN int adapter_datetime_init(void); 50 | 51 | HIDDEN PyObject *psyco_Date(PyObject *module, PyObject *args); 52 | #define psyco_Date_doc \ 53 | "Date(year, month, day) -> new date\n\n" \ 54 | "Build an object holding a date value." 55 | 56 | HIDDEN PyObject *psyco_Time(PyObject *module, PyObject *args); 57 | #define psyco_Time_doc \ 58 | "Time(hour, minutes, seconds, tzinfo=None) -> new time\n\n" \ 59 | "Build an object holding a time value." 60 | 61 | HIDDEN PyObject *psyco_Timestamp(PyObject *module, PyObject *args); 62 | #define psyco_Timestamp_doc \ 63 | "Timestamp(year, month, day, hour, minutes, seconds, tzinfo=None) -> new timestamp\n\n" \ 64 | "Build an object holding a timestamp value." 65 | 66 | HIDDEN PyObject *psyco_DateFromTicks(PyObject *module, PyObject *args); 67 | #define psyco_DateFromTicks_doc \ 68 | "DateFromTicks(ticks) -> new date\n\n" \ 69 | "Build an object holding a date value from the given ticks value.\n\n" \ 70 | "Ticks are the number of seconds since the epoch; see the documentation " \ 71 | "of the standard Python time module for details)." 72 | 73 | HIDDEN PyObject *psyco_TimeFromTicks(PyObject *module, PyObject *args); 74 | #define psyco_TimeFromTicks_doc \ 75 | "TimeFromTicks(ticks) -> new time\n\n" \ 76 | "Build an object holding a time value from the given ticks value.\n\n" \ 77 | "Ticks are the number of seconds since the epoch; see the documentation " \ 78 | "of the standard Python time module for details)." 79 | 80 | HIDDEN PyObject *psyco_TimestampFromTicks(PyObject *module, PyObject *args); 81 | #define psyco_TimestampFromTicks_doc \ 82 | "TimestampFromTicks(ticks) -> new timestamp\n\n" \ 83 | "Build an object holding a timestamp value from the given ticks value.\n\n" \ 84 | "Ticks are the number of seconds since the epoch; see the documentation " \ 85 | "of the standard Python time module for details)." 86 | 87 | HIDDEN PyObject *psyco_DateFromPy(PyObject *module, PyObject *args); 88 | #define psyco_DateFromPy_doc \ 89 | "DateFromPy(datetime.date) -> new wrapper" 90 | 91 | HIDDEN PyObject *psyco_TimeFromPy(PyObject *module, PyObject *args); 92 | #define psyco_TimeFromPy_doc \ 93 | "TimeFromPy(datetime.time) -> new wrapper" 94 | 95 | HIDDEN PyObject *psyco_TimestampFromPy(PyObject *module, PyObject *args); 96 | #define psyco_TimestampFromPy_doc \ 97 | "TimestampFromPy(datetime.datetime) -> new wrapper" 98 | 99 | HIDDEN PyObject *psyco_IntervalFromPy(PyObject *module, PyObject *args); 100 | #define psyco_IntervalFromPy_doc \ 101 | "IntervalFromPy(datetime.timedelta) -> new wrapper" 102 | 103 | #ifdef __cplusplus 104 | } 105 | #endif 106 | 107 | #endif /* !defined(PSYCOPG_DATETIME_H) */ 108 | -------------------------------------------------------------------------------- /psycopg/adapter_list.h: -------------------------------------------------------------------------------- 1 | /* adapter_list.h - definition for the python list types 2 | * 3 | * Copyright (C) 2004-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_LIST_H 28 | #define PSYCOPG_LIST_H 1 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | extern HIDDEN PyTypeObject listType; 35 | 36 | typedef struct { 37 | PyObject_HEAD 38 | 39 | PyObject *wrapped; 40 | PyObject *connection; 41 | } listObject; 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif /* !defined(PSYCOPG_LIST_H) */ 48 | -------------------------------------------------------------------------------- /psycopg/adapter_pboolean.h: -------------------------------------------------------------------------------- 1 | /* adapter_pboolean.h - definition for the psycopg boolean type wrapper 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_PBOOLEAN_H 28 | #define PSYCOPG_PBOOLEAN_H 1 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | extern HIDDEN PyTypeObject pbooleanType; 35 | 36 | typedef struct { 37 | PyObject_HEAD 38 | 39 | /* this is the real object we wrap */ 40 | PyObject *wrapped; 41 | 42 | } pbooleanObject; 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif /* !defined(PSYCOPG_PBOOLEAN_H) */ 49 | -------------------------------------------------------------------------------- /psycopg/adapter_pdecimal.h: -------------------------------------------------------------------------------- 1 | /* adapter_pdecimal.h - definition for the psycopg Decimal type wrapper 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_PDECIMAL_H 28 | #define PSYCOPG_PDECIMAL_H 1 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | extern HIDDEN PyTypeObject pdecimalType; 35 | 36 | typedef struct { 37 | PyObject_HEAD 38 | 39 | /* this is the real object we wrap */ 40 | PyObject *wrapped; 41 | 42 | } pdecimalObject; 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif /* !defined(PSYCOPG_PDECIMAL_H) */ 49 | -------------------------------------------------------------------------------- /psycopg/adapter_pfloat.h: -------------------------------------------------------------------------------- 1 | /* adapter_pfloat.h - definition for the psycopg float type wrapper 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_PFLOAT_H 28 | #define PSYCOPG_PFLOAT_H 1 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | extern HIDDEN PyTypeObject pfloatType; 35 | 36 | typedef struct { 37 | PyObject_HEAD 38 | 39 | /* this is the real object we wrap */ 40 | PyObject *wrapped; 41 | 42 | } pfloatObject; 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif /* !defined(PSYCOPG_PFLOAT_H) */ 49 | -------------------------------------------------------------------------------- /psycopg/adapter_pint.h: -------------------------------------------------------------------------------- 1 | /* adapter_pint.h - definition for the psycopg int type wrapper 2 | * 3 | * Copyright (C) 2011-2019 Daniele Varrazzo 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_PINT_H 28 | #define PSYCOPG_PINT_H 1 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | extern HIDDEN PyTypeObject pintType; 35 | 36 | typedef struct { 37 | PyObject_HEAD 38 | 39 | /* this is the real object we wrap */ 40 | PyObject *wrapped; 41 | 42 | } pintObject; 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif /* !defined(PSYCOPG_PINT_H) */ 49 | -------------------------------------------------------------------------------- /psycopg/adapter_qstring.h: -------------------------------------------------------------------------------- 1 | /* adapter_qstring.h - definition for the QuotedString type 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_QSTRING_H 28 | #define PSYCOPG_QSTRING_H 1 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | extern HIDDEN PyTypeObject qstringType; 35 | 36 | typedef struct { 37 | PyObject_HEAD 38 | 39 | PyObject *wrapped; 40 | PyObject *buffer; 41 | 42 | connectionObject *conn; 43 | 44 | const char *encoding; 45 | 46 | } qstringObject; 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* !defined(PSYCOPG_QSTRING_H) */ 53 | -------------------------------------------------------------------------------- /psycopg/aix_support.c: -------------------------------------------------------------------------------- 1 | /* aix_support.c - emulate functions missing on AIX 2 | * 3 | * Copyright (C) 2017 My Karlsson 4 | * Copyright (c) 2018, Joyent, Inc. 5 | * Copyright (C) 2020-2021 The Psycopg Team 6 | * 7 | * This file is part of psycopg. 8 | * 9 | * psycopg2 is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * In addition, as a special exception, the copyright holders give 15 | * permission to link this program with the OpenSSL library (or with 16 | * modified versions of OpenSSL that use the same license as OpenSSL), 17 | * and distribute linked combinations including the two. 18 | * 19 | * You must obey the GNU Lesser General Public License in all respects for 20 | * all of the code used other than OpenSSL. 21 | * 22 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 23 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 24 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 25 | * License for more details. 26 | */ 27 | 28 | #define PSYCOPG_MODULE 29 | #include "psycopg/psycopg.h" 30 | #include "psycopg/aix_support.h" 31 | 32 | #if defined(_AIX) 33 | /* timeradd is missing on AIX */ 34 | #ifndef timeradd 35 | void 36 | timeradd(struct timeval *a, struct timeval *b, struct timeval *c) 37 | { 38 | c->tv_sec = a->tv_sec + b->tv_sec; 39 | c->tv_usec = a->tv_usec + b->tv_usec; 40 | if (c->tv_usec >= 1000000) { 41 | c->tv_usec -= 1000000; 42 | c->tv_sec += 1; 43 | } 44 | } 45 | 46 | /* timersub is missing on AIX */ 47 | void 48 | timersub(struct timeval *a, struct timeval *b, struct timeval *c) 49 | { 50 | c->tv_sec = a->tv_sec - b->tv_sec; 51 | c->tv_usec = a->tv_usec - b->tv_usec; 52 | if (c->tv_usec < 0) { 53 | c->tv_usec += 1000000; 54 | c->tv_sec -= 1; 55 | } 56 | } 57 | #endif /* timeradd */ 58 | #endif /* defined(_AIX)*/ 59 | -------------------------------------------------------------------------------- /psycopg/aix_support.h: -------------------------------------------------------------------------------- 1 | /* aix_support.h - definitions for aix_support.c 2 | * 3 | * Copyright (C) 2017 My Karlsson 4 | * Copyright (c) 2018-2019, Joyent, Inc. 5 | * Copyright (C) 2020-2021 The Psycopg Team 6 | * 7 | * This file is part of psycopg. 8 | * 9 | * psycopg2 is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * In addition, as a special exception, the copyright holders give 15 | * permission to link this program with the OpenSSL library (or with 16 | * modified versions of OpenSSL that use the same license as OpenSSL), 17 | * and distribute linked combinations including the two. 18 | * 19 | * You must obey the GNU Lesser General Public License in all respects for 20 | * all of the code used other than OpenSSL. 21 | * 22 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 23 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 24 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 25 | * License for more details. 26 | */ 27 | #ifndef PSYCOPG_AIX_SUPPORT_H 28 | #define PSYCOPG_AIX_SUPPORT_H 29 | 30 | #include "psycopg/config.h" 31 | 32 | #ifdef _AIX 33 | #include 34 | 35 | #ifndef timeradd 36 | extern HIDDEN void timeradd(struct timeval *a, struct timeval *b, struct timeval *c); 37 | extern HIDDEN void timersub(struct timeval *a, struct timeval *b, struct timeval *c); 38 | #endif 39 | 40 | #ifndef timercmp 41 | #define timercmp(a, b, cmp) \ 42 | (((a)->tv_sec == (b)->tv_sec) ? \ 43 | ((a)->tv_usec cmp (b)->tv_usec) : \ 44 | ((a)->tv_sec cmp (b)->tv_sec)) 45 | #endif 46 | #endif 47 | 48 | #endif /* !defined(PSYCOPG_AIX_SUPPORT_H) */ 49 | -------------------------------------------------------------------------------- /psycopg/column.h: -------------------------------------------------------------------------------- 1 | /* column.h - definition for a column in cursor.description type 2 | * 3 | * Copyright (C) 2018-2019 Daniele Varrazzo 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_COLUMN_H 28 | #define PSYCOPG_COLUMN_H 1 29 | 30 | extern HIDDEN PyTypeObject columnType; 31 | 32 | typedef struct { 33 | PyObject_HEAD 34 | 35 | PyObject *name; 36 | PyObject *type_code; 37 | PyObject *display_size; 38 | PyObject *internal_size; 39 | PyObject *precision; 40 | PyObject *scale; 41 | PyObject *null_ok; 42 | 43 | /* Extensions to the DBAPI */ 44 | PyObject *table_oid; 45 | PyObject *table_column; 46 | 47 | } columnObject; 48 | 49 | #endif /* PSYCOPG_COLUMN_H */ 50 | -------------------------------------------------------------------------------- /psycopg/conninfo.h: -------------------------------------------------------------------------------- 1 | /* connection.h - definition for the psycopg ConnectionInfo type 2 | * 3 | * Copyright (C) 2018-2019 Daniele Varrazzo 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_CONNINFO_H 28 | #define PSYCOPG_CONNINFO_H 1 29 | 30 | #include "psycopg/connection.h" 31 | 32 | extern HIDDEN PyTypeObject connInfoType; 33 | 34 | typedef struct { 35 | PyObject_HEAD 36 | 37 | connectionObject *conn; 38 | 39 | } connInfoObject; 40 | 41 | #endif /* PSYCOPG_CONNINFO_H */ 42 | -------------------------------------------------------------------------------- /psycopg/diagnostics.h: -------------------------------------------------------------------------------- 1 | /* diagnostics.c - definition for the psycopg Diagnostics type 2 | * 3 | * Copyright (C) 2013-2019 Matthew Woodcraft 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_DIAGNOSTICS_H 28 | #define PSYCOPG_DIAGNOSTICS_H 1 29 | 30 | #include "psycopg/error.h" 31 | 32 | extern HIDDEN PyTypeObject diagnosticsType; 33 | 34 | typedef struct { 35 | PyObject_HEAD 36 | 37 | errorObject *err; /* exception to retrieve the diagnostics from */ 38 | 39 | } diagnosticsObject; 40 | 41 | #endif /* PSYCOPG_DIAGNOSTICS_H */ 42 | -------------------------------------------------------------------------------- /psycopg/error.h: -------------------------------------------------------------------------------- 1 | /* error.h - definition for the psycopg base Error type 2 | * 3 | * Copyright (C) 2013-2019 Daniele Varrazzo 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_ERROR_H 28 | #define PSYCOPG_ERROR_H 1 29 | 30 | extern HIDDEN PyTypeObject errorType; 31 | 32 | typedef struct { 33 | PyBaseExceptionObject exc; 34 | 35 | PyObject *pgerror; 36 | PyObject *pgcode; 37 | cursorObject *cursor; 38 | PyObject *pydecoder; 39 | PGresult *pgres; 40 | } errorObject; 41 | 42 | HIDDEN PyObject *error_text_from_chars(errorObject *self, const char *str); 43 | HIDDEN BORROWED PyObject *exception_from_sqlstate(const char *sqlstate); 44 | HIDDEN BORROWED PyObject *base_exception_from_sqlstate(const char *sqlstate); 45 | 46 | #endif /* PSYCOPG_ERROR_H */ 47 | -------------------------------------------------------------------------------- /psycopg/green.h: -------------------------------------------------------------------------------- 1 | /* green.c - cooperation with coroutine libraries. 2 | * 3 | * Copyright (C) 2010-2019 Daniele Varrazzo 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_GREEN_H 28 | #define PSYCOPG_GREEN_H 1 29 | 30 | #include 31 | #include "psycopg/connection.h" 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | #define psyco_set_wait_callback_doc \ 38 | "Register a callback function to block waiting for data.\n" \ 39 | "\n" \ 40 | "The callback should have signature :samp:`fun({conn})` and\n" \ 41 | "is called to wait for data available whenever a blocking function from the\n" \ 42 | "libpq is called. Use `!set_wait_callback(None)` to revert to the\n" \ 43 | "original behaviour (i.e. using blocking libpq functions).\n" \ 44 | "\n" \ 45 | "The function is an hook to allow coroutine-based libraries (such as\n" \ 46 | "Eventlet_ or gevent_) to switch when Psycopg is blocked, allowing\n" \ 47 | "other coroutines to run concurrently.\n" \ 48 | "\n" \ 49 | "See `~psycopg2.extras.wait_select()` for an example of a wait callback\n" \ 50 | "implementation.\n" \ 51 | "\n" \ 52 | ".. _Eventlet: https://eventlet.net/\n" \ 53 | ".. _gevent: http://www.gevent.org/\n" 54 | HIDDEN PyObject *psyco_set_wait_callback(PyObject *self, PyObject *obj); 55 | 56 | #define psyco_get_wait_callback_doc \ 57 | "Return the currently registered wait callback.\n" \ 58 | "\n" \ 59 | "Return `!None` if no callback is currently registered.\n" 60 | HIDDEN PyObject *psyco_get_wait_callback(PyObject *self, PyObject *obj); 61 | 62 | HIDDEN int psyco_green(void); 63 | HIDDEN int psyco_wait(connectionObject *conn); 64 | HIDDEN PGresult *psyco_exec_green(connectionObject *conn, const char *command); 65 | 66 | #define EXC_IF_GREEN(cmd) \ 67 | if (psyco_green()) { \ 68 | PyErr_SetString(ProgrammingError, #cmd " cannot be used " \ 69 | "with an asynchronous callback."); \ 70 | return NULL; } 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif /* !defined(PSYCOPG_GREEN_H) */ 77 | -------------------------------------------------------------------------------- /psycopg/libpq_support.c: -------------------------------------------------------------------------------- 1 | /* libpq_support.c - functions not provided by libpq, but which are 2 | * required for advanced communication with the server, such as 3 | * streaming replication 4 | * 5 | * Copyright (C) 2003-2019 Federico Di Gregorio 6 | * Copyright (C) 2020-2021 The Psycopg Team 7 | * 8 | * This file is part of psycopg. 9 | * 10 | * psycopg2 is free software: you can redistribute it and/or modify it 11 | * under the terms of the GNU Lesser General Public License as published 12 | * by the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * In addition, as a special exception, the copyright holders give 16 | * permission to link this program with the OpenSSL library (or with 17 | * modified versions of OpenSSL that use the same license as OpenSSL), 18 | * and distribute linked combinations including the two. 19 | * 20 | * You must obey the GNU Lesser General Public License in all respects for 21 | * all of the code used other than OpenSSL. 22 | * 23 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 24 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 25 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 26 | * License for more details. 27 | */ 28 | 29 | #define PSYCOPG_MODULE 30 | #include "psycopg/psycopg.h" 31 | 32 | #include "psycopg/libpq_support.h" 33 | 34 | /* htonl(), ntohl() */ 35 | #ifdef _WIN32 36 | #include 37 | /* gettimeofday() */ 38 | #include "psycopg/win32_support.h" 39 | #else 40 | #include 41 | #include 42 | #endif 43 | 44 | /* support routines taken from pg_basebackup/streamutil.c */ 45 | 46 | /* 47 | * Frontend version of GetCurrentTimestamp(), since we are not linked with 48 | * backend code. The protocol always uses integer timestamps, regardless of 49 | * server setting. 50 | */ 51 | int64_t 52 | feGetCurrentTimestamp(void) 53 | { 54 | int64_t result; 55 | struct timeval tp; 56 | 57 | gettimeofday(&tp, NULL); 58 | 59 | result = (int64_t) tp.tv_sec - 60 | ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY); 61 | 62 | result = (result * USECS_PER_SEC) + tp.tv_usec; 63 | 64 | return result; 65 | } 66 | 67 | /* 68 | * Converts an int64 to network byte order. 69 | */ 70 | void 71 | fe_sendint64(int64_t i, char *buf) 72 | { 73 | uint32_t n32; 74 | 75 | /* High order half first, since we're doing MSB-first */ 76 | n32 = (uint32_t) (i >> 32); 77 | n32 = htonl(n32); 78 | memcpy(&buf[0], &n32, 4); 79 | 80 | /* Now the low order half */ 81 | n32 = (uint32_t) i; 82 | n32 = htonl(n32); 83 | memcpy(&buf[4], &n32, 4); 84 | } 85 | 86 | /* 87 | * Converts an int64 from network byte order to native format. 88 | */ 89 | int64_t 90 | fe_recvint64(char *buf) 91 | { 92 | int64_t result; 93 | uint32_t h32; 94 | uint32_t l32; 95 | 96 | memcpy(&h32, buf, 4); 97 | memcpy(&l32, buf + 4, 4); 98 | h32 = ntohl(h32); 99 | l32 = ntohl(l32); 100 | 101 | result = h32; 102 | result <<= 32; 103 | result |= l32; 104 | 105 | return result; 106 | } 107 | -------------------------------------------------------------------------------- /psycopg/libpq_support.h: -------------------------------------------------------------------------------- 1 | /* libpq_support.h - definitions for libpq_support.c 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | #ifndef PSYCOPG_LIBPQ_SUPPORT_H 27 | #define PSYCOPG_LIBPQ_SUPPORT_H 1 28 | 29 | #include "psycopg/config.h" 30 | 31 | /* type and constant definitions from internal postgres include */ 32 | typedef uint64_t XLogRecPtr; 33 | 34 | /* have to use lowercase %x, as PyString_FromFormat can't do %X */ 35 | #define XLOGFMTSTR "%x/%x" 36 | #define XLOGFMTARGS(x) ((uint32_t)((x) >> 32)), ((uint32_t)((x) & 0xFFFFFFFF)) 37 | 38 | /* Julian-date equivalents of Day 0 in Unix and Postgres reckoning */ 39 | #define UNIX_EPOCH_JDATE 2440588 /* == date2j(1970, 1, 1) */ 40 | #define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */ 41 | 42 | #define SECS_PER_DAY 86400 43 | #define USECS_PER_SEC 1000000LL 44 | 45 | HIDDEN int64_t feGetCurrentTimestamp(void); 46 | HIDDEN void fe_sendint64(int64_t i, char *buf); 47 | HIDDEN int64_t fe_recvint64(char *buf); 48 | 49 | #endif /* !defined(PSYCOPG_LIBPQ_SUPPORT_H) */ 50 | -------------------------------------------------------------------------------- /psycopg/lobject.h: -------------------------------------------------------------------------------- 1 | /* lobject.h - definition for the psycopg lobject type 2 | * 3 | * Copyright (C) 2006-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_LOBJECT_H 28 | #define PSYCOPG_LOBJECT_H 1 29 | 30 | #include 31 | 32 | #include "psycopg/connection.h" 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | extern HIDDEN PyTypeObject lobjectType; 39 | 40 | typedef struct { 41 | PyObject HEAD; 42 | 43 | connectionObject *conn; /* connection owning the lobject */ 44 | long int mark; /* copied from conn->mark */ 45 | 46 | char *smode; /* string mode if lobject was opened */ 47 | int mode; /* numeric version of smode */ 48 | 49 | int fd; /* the file descriptor for file-like ops */ 50 | Oid oid; /* the oid for this lobject */ 51 | } lobjectObject; 52 | 53 | /* functions exported from lobject_int.c */ 54 | 55 | RAISES_NEG HIDDEN int lobject_open(lobjectObject *self, connectionObject *conn, 56 | Oid oid, const char *smode, Oid new_oid, 57 | const char *new_file); 58 | RAISES_NEG HIDDEN int lobject_unlink(lobjectObject *self); 59 | RAISES_NEG HIDDEN int lobject_export(lobjectObject *self, const char *filename); 60 | 61 | RAISES_NEG HIDDEN Py_ssize_t lobject_read(lobjectObject *self, char *buf, size_t len); 62 | RAISES_NEG HIDDEN Py_ssize_t lobject_write(lobjectObject *self, const char *buf, 63 | size_t len); 64 | RAISES_NEG HIDDEN Py_ssize_t lobject_seek(lobjectObject *self, Py_ssize_t pos, int whence); 65 | RAISES_NEG HIDDEN Py_ssize_t lobject_tell(lobjectObject *self); 66 | RAISES_NEG HIDDEN int lobject_truncate(lobjectObject *self, size_t len); 67 | RAISES_NEG HIDDEN int lobject_close(lobjectObject *self); 68 | 69 | #define lobject_is_closed(self) \ 70 | ((self)->fd < 0 || !(self)->conn || (self)->conn->closed) 71 | 72 | /* exception-raising macros */ 73 | 74 | #define EXC_IF_LOBJ_CLOSED(self) \ 75 | if (lobject_is_closed(self)) { \ 76 | PyErr_SetString(InterfaceError, "lobject already closed"); \ 77 | return NULL; } 78 | 79 | #define EXC_IF_LOBJ_LEVEL0(self) \ 80 | if (self->conn->autocommit) { \ 81 | psyco_set_error(ProgrammingError, NULL, \ 82 | "can't use a lobject outside of transactions"); \ 83 | return NULL; \ 84 | } 85 | #define EXC_IF_LOBJ_UNMARKED(self) \ 86 | if (self->conn->mark != self->mark) { \ 87 | psyco_set_error(ProgrammingError, NULL, \ 88 | "lobject isn't valid anymore"); \ 89 | return NULL; \ 90 | } 91 | 92 | /* Values for the lobject mode */ 93 | #define LOBJECT_READ 1 94 | #define LOBJECT_WRITE 2 95 | #define LOBJECT_BINARY 4 96 | #define LOBJECT_TEXT 8 97 | 98 | #ifdef __cplusplus 99 | } 100 | #endif 101 | 102 | #endif /* !defined(PSYCOPG_LOBJECT_H) */ 103 | -------------------------------------------------------------------------------- /psycopg/microprotocols.h: -------------------------------------------------------------------------------- 1 | /* microprotocols.c - definitions for minimalist and non-validating protocols 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_MICROPROTOCOLS_H 28 | #define PSYCOPG_MICROPROTOCOLS_H 1 29 | 30 | #include "psycopg/connection.h" 31 | #include "psycopg/cursor.h" 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | /** adapters registry **/ 38 | 39 | extern HIDDEN PyObject *psyco_adapters; 40 | 41 | /** the names of the three mandatory methods **/ 42 | 43 | #define MICROPROTOCOLS_GETQUOTED_NAME "getquoted" 44 | #define MICROPROTOCOLS_GETSTRING_NAME "getstring" 45 | #define MICROPROTOCOLS_GETBINARY_NAME "getbinary" 46 | 47 | /** exported functions **/ 48 | 49 | /* used by module.c to init the microprotocols system */ 50 | HIDDEN RAISES_NEG int microprotocols_init(PyObject *dict); 51 | HIDDEN RAISES_NEG int microprotocols_add( 52 | PyTypeObject *type, PyObject *proto, PyObject *cast); 53 | 54 | HIDDEN PyObject *microprotocols_adapt( 55 | PyObject *obj, PyObject *proto, PyObject *alt); 56 | HIDDEN PyObject *microprotocol_getquoted( 57 | PyObject *obj, connectionObject *conn); 58 | 59 | HIDDEN PyObject * 60 | psyco_microprotocols_adapt(cursorObject *self, PyObject *args); 61 | #define psyco_microprotocols_adapt_doc \ 62 | "adapt(obj, protocol, alternate) -> object -- adapt obj to given protocol" 63 | 64 | #endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */ 65 | -------------------------------------------------------------------------------- /psycopg/microprotocols_proto.h: -------------------------------------------------------------------------------- 1 | /* microporotocols_proto.h - definition for psycopg's protocols 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_ISQLQUOTE_H 28 | #define PSYCOPG_ISQLQUOTE_H 1 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | extern HIDDEN PyTypeObject isqlquoteType; 35 | 36 | typedef struct { 37 | PyObject_HEAD 38 | 39 | PyObject *wrapped; 40 | 41 | } isqlquoteObject; 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif /* !defined(PSYCOPG_ISQLQUOTE_H) */ 48 | -------------------------------------------------------------------------------- /psycopg/notify.h: -------------------------------------------------------------------------------- 1 | /* notify.h - definition for the psycopg Notify type 2 | * 3 | * Copyright (C) 2010-2019 Daniele Varrazzo 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_NOTIFY_H 28 | #define PSYCOPG_NOTIFY_H 1 29 | 30 | extern HIDDEN PyTypeObject notifyType; 31 | 32 | typedef struct { 33 | PyObject_HEAD 34 | 35 | PyObject *pid; 36 | PyObject *channel; 37 | PyObject *payload; 38 | 39 | } notifyObject; 40 | 41 | #endif /* PSYCOPG_NOTIFY_H */ 42 | -------------------------------------------------------------------------------- /psycopg/pgtypes.h: -------------------------------------------------------------------------------- 1 | #define BOOLOID 16 2 | #define BYTEAOID 17 3 | #define CHAROID 18 4 | #define NAMEOID 19 5 | #define INT8OID 20 6 | #define INT2OID 21 7 | #define INT2VECTOROID 22 8 | #define INT4OID 23 9 | #define REGPROCOID 24 10 | #define TEXTOID 25 11 | #define OIDOID 26 12 | #define TIDOID 27 13 | #define XIDOID 28 14 | #define CIDOID 29 15 | #define OIDVECTOROID 30 16 | #define PG_TYPE_RELTYPE_OID 71 17 | #define PG_ATTRIBUTE_RELTYPE_OID 75 18 | #define PG_PROC_RELTYPE_OID 81 19 | #define PG_CLASS_RELTYPE_OID 83 20 | #define POINTOID 600 21 | #define LSEGOID 601 22 | #define PATHOID 602 23 | #define BOXOID 603 24 | #define POLYGONOID 604 25 | #define LINEOID 628 26 | #define FLOAT4OID 700 27 | #define FLOAT8OID 701 28 | #define ABSTIMEOID 702 29 | #define RELTIMEOID 703 30 | #define TINTERVALOID 704 31 | #define UNKNOWNOID 705 32 | #define CIRCLEOID 718 33 | #define CASHOID 790 34 | #define MACADDROID 829 35 | #define INETOID 869 36 | #define CIDROID 650 37 | #define INT4ARRAYOID 1007 38 | #define ACLITEMOID 1033 39 | #define BPCHAROID 1042 40 | #define VARCHAROID 1043 41 | #define DATEOID 1082 42 | #define TIMEOID 1083 43 | #define TIMESTAMPOID 1114 44 | #define TIMESTAMPTZOID 1184 45 | #define INTERVALOID 1186 46 | #define TIMETZOID 1266 47 | #define BITOID 1560 48 | #define VARBITOID 1562 49 | #define NUMERICOID 1700 50 | #define REFCURSOROID 1790 51 | #define REGPROCEDUREOID 2202 52 | #define REGOPEROID 2203 53 | #define REGOPERATOROID 2204 54 | #define REGCLASSOID 2205 55 | #define REGTYPEOID 2206 56 | #define RECORDOID 2249 57 | #define CSTRINGOID 2275 58 | #define ANYOID 2276 59 | #define ANYARRAYOID 2277 60 | #define VOIDOID 2278 61 | #define TRIGGEROID 2279 62 | #define LANGUAGE_HANDLEROID 2280 63 | #define INTERNALOID 2281 64 | #define OPAQUEOID 2282 65 | #define ANYELEMENTOID 2283 66 | -------------------------------------------------------------------------------- /psycopg/pqpath.h: -------------------------------------------------------------------------------- 1 | /* pqpath.h - definitions for pqpath.c 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_PQPATH_H 28 | #define PSYCOPG_PQPATH_H 1 29 | 30 | #include "psycopg/cursor.h" 31 | #include "psycopg/connection.h" 32 | #include "psycopg/replication_cursor.h" 33 | #include "psycopg/replication_message.h" 34 | 35 | /* macro to clean the pg result */ 36 | #define CLEARPGRES(pgres) do { PQclear(pgres); pgres = NULL; } while (0) 37 | 38 | /* exported functions */ 39 | RAISES_NEG HIDDEN int pq_fetch(cursorObject *curs, int no_result); 40 | RAISES_NEG HIDDEN int pq_execute(cursorObject *curs, const char *query, 41 | int async, int no_result, int no_begin); 42 | HIDDEN int pq_send_query(connectionObject *conn, const char *query); 43 | HIDDEN int pq_begin_locked(connectionObject *conn, PyThreadState **tstate); 44 | HIDDEN int pq_commit(connectionObject *conn); 45 | RAISES_NEG HIDDEN int pq_abort_locked(connectionObject *conn, 46 | PyThreadState **tstate); 47 | RAISES_NEG HIDDEN int pq_abort(connectionObject *conn); 48 | HIDDEN int pq_reset_locked(connectionObject *conn, PyThreadState **tstate); 49 | RAISES_NEG HIDDEN int pq_reset(connectionObject *conn); 50 | HIDDEN char *pq_get_guc_locked(connectionObject *conn, const char *param, 51 | PyThreadState **tstate); 52 | HIDDEN int pq_set_guc_locked(connectionObject *conn, const char *param, 53 | const char *value, PyThreadState **tstate); 54 | HIDDEN int pq_tpc_command_locked(connectionObject *conn, 55 | const char *cmd, const char *tid, 56 | PyThreadState **tstate); 57 | RAISES_NEG HIDDEN int pq_get_result_async(connectionObject *conn); 58 | HIDDEN int pq_flush(connectionObject *conn); 59 | HIDDEN void pq_clear_async(connectionObject *conn); 60 | RAISES_NEG HIDDEN int pq_set_non_blocking(connectionObject *conn, int arg); 61 | 62 | HIDDEN void pq_set_critical(connectionObject *conn, const char *msg); 63 | 64 | HIDDEN int pq_execute_command_locked(connectionObject *conn, const char *query, 65 | PyThreadState **tstate); 66 | RAISES HIDDEN void pq_complete_error(connectionObject *conn); 67 | 68 | /* replication protocol support */ 69 | HIDDEN int pq_copy_both(replicationCursorObject *repl, PyObject *consumer); 70 | HIDDEN int pq_read_replication_message(replicationCursorObject *repl, 71 | replicationMessageObject **msg); 72 | HIDDEN int pq_send_replication_feedback(replicationCursorObject *repl, int reply_requested); 73 | 74 | #endif /* !defined(PSYCOPG_PQPATH_H) */ 75 | -------------------------------------------------------------------------------- /psycopg/psycopg.h: -------------------------------------------------------------------------------- 1 | /* psycopg.h - definitions for the psycopg python module 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_H 28 | #define PSYCOPG_H 1 29 | 30 | #include 31 | #if PG_VERSION_NUM < 90100 32 | #error "Psycopg requires PostgreSQL client library (libpq) >= 9.1" 33 | #endif 34 | 35 | #define PY_SSIZE_T_CLEAN 36 | #include 37 | #include 38 | 39 | #include "psycopg/config.h" 40 | #include "psycopg/python.h" 41 | #include "psycopg/utils.h" 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | 47 | /* DBAPI compliance parameters */ 48 | #define APILEVEL "2.0" 49 | #define THREADSAFETY 2 50 | #define PARAMSTYLE "pyformat" 51 | 52 | /* global exceptions */ 53 | extern HIDDEN PyObject *Error, *Warning, *InterfaceError, *DatabaseError, 54 | *InternalError, *OperationalError, *ProgrammingError, 55 | *IntegrityError, *DataError, *NotSupportedError; 56 | extern HIDDEN PyObject *QueryCanceledError, *TransactionRollbackError; 57 | 58 | /* sqlstate -> exception map */ 59 | extern HIDDEN PyObject *sqlstate_errors; 60 | 61 | /* postgresql<->python encoding map */ 62 | extern HIDDEN PyObject *psycoEncodings; 63 | 64 | /* SQL NULL */ 65 | extern HIDDEN PyObject *psyco_null; 66 | 67 | /* Exceptions docstrings */ 68 | #define Error_doc \ 69 | "Base class for error exceptions." 70 | 71 | #define Warning_doc \ 72 | "A database warning." 73 | 74 | #define InterfaceError_doc \ 75 | "Error related to the database interface." 76 | 77 | #define DatabaseError_doc \ 78 | "Error related to the database engine." 79 | 80 | #define InternalError_doc \ 81 | "The database encountered an internal error." 82 | 83 | #define OperationalError_doc \ 84 | "Error related to database operation (disconnect, memory allocation etc)." 85 | 86 | #define ProgrammingError_doc \ 87 | "Error related to database programming (SQL error, table not found etc)." 88 | 89 | #define IntegrityError_doc \ 90 | "Error related to database integrity." 91 | 92 | #define DataError_doc \ 93 | "Error related to problems with the processed data." 94 | 95 | #define NotSupportedError_doc \ 96 | "A method or database API was used which is not supported by the database." 97 | 98 | #define QueryCanceledError_doc \ 99 | "Error related to SQL query cancellation." 100 | 101 | #define TransactionRollbackError_doc \ 102 | "Error causing transaction rollback (deadlocks, serialization failures, etc)." 103 | 104 | #ifdef __cplusplus 105 | } 106 | #endif 107 | 108 | #endif /* !defined(PSYCOPG_H) */ 109 | -------------------------------------------------------------------------------- /psycopg/python.h: -------------------------------------------------------------------------------- 1 | /* python.h - python version compatibility stuff 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_PYTHON_H 28 | #define PSYCOPG_PYTHON_H 1 29 | 30 | #if PY_VERSION_HEX < 0x03080000 31 | #error "psycopg requires Python 3.8" 32 | #endif 33 | 34 | #include 35 | 36 | /* Since Py_TYPE() is changed to the inline static function, 37 | * Py_TYPE(obj) = new_type must be replaced with Py_SET_TYPE(obj, new_type) 38 | * https://docs.python.org/3.10/whatsnew/3.10.html#id2 39 | */ 40 | #if PY_VERSION_HEX < 0x030900A4 41 | #define Py_SET_TYPE(obj, type) ((Py_TYPE(obj) = (type)), (void)0) 42 | #endif 43 | 44 | /* FORMAT_CODE_PY_SSIZE_T is for Py_ssize_t: */ 45 | #define FORMAT_CODE_PY_SSIZE_T "%" PY_FORMAT_SIZE_T "d" 46 | 47 | /* FORMAT_CODE_SIZE_T is for plain size_t, not for Py_ssize_t: */ 48 | #ifdef _MSC_VER 49 | /* For MSVC: */ 50 | #define FORMAT_CODE_SIZE_T "%Iu" 51 | #else 52 | /* C99 standard format code: */ 53 | #define FORMAT_CODE_SIZE_T "%zu" 54 | #endif 55 | 56 | #define Text_Type PyUnicode_Type 57 | #define Text_Check(s) PyUnicode_Check(s) 58 | #define Text_Format(f,a) PyUnicode_Format(f,a) 59 | #define Text_FromUTF8(s) PyUnicode_FromString(s) 60 | #define Text_FromUTF8AndSize(s,n) PyUnicode_FromStringAndSize(s,n) 61 | 62 | #define PyInt_Type PyLong_Type 63 | #define PyInt_Check PyLong_Check 64 | #define PyInt_AsLong PyLong_AsLong 65 | #define PyInt_FromLong PyLong_FromLong 66 | #define PyInt_FromString PyLong_FromString 67 | #define PyInt_FromSsize_t PyLong_FromSsize_t 68 | #define PyExc_StandardError PyExc_Exception 69 | #define PyString_FromFormat PyUnicode_FromFormat 70 | #define Py_TPFLAGS_HAVE_ITER 0L 71 | #define Py_TPFLAGS_HAVE_RICHCOMPARE 0L 72 | #define Py_TPFLAGS_HAVE_WEAKREFS 0L 73 | 74 | #ifndef PyNumber_Int 75 | #define PyNumber_Int PyNumber_Long 76 | #endif 77 | 78 | #define Bytes_Type PyBytes_Type 79 | #define Bytes_Check PyBytes_Check 80 | #define Bytes_CheckExact PyBytes_CheckExact 81 | #define Bytes_AS_STRING PyBytes_AS_STRING 82 | #define Bytes_GET_SIZE PyBytes_GET_SIZE 83 | #define Bytes_Size PyBytes_Size 84 | #define Bytes_AsString PyBytes_AsString 85 | #define Bytes_AsStringAndSize PyBytes_AsStringAndSize 86 | #define Bytes_FromString PyBytes_FromString 87 | #define Bytes_FromStringAndSize PyBytes_FromStringAndSize 88 | #define Bytes_FromFormat PyBytes_FromFormat 89 | #define Bytes_ConcatAndDel PyBytes_ConcatAndDel 90 | #define _Bytes_Resize _PyBytes_Resize 91 | 92 | #define INIT_MODULE(m) PyInit_ ## m 93 | 94 | #define PyLong_FromOid(x) (PyLong_FromUnsignedLong((unsigned long)(x))) 95 | 96 | /* expose Oid attributes in Python C objects */ 97 | #define T_OID T_UINT 98 | 99 | #endif /* !defined(PSYCOPG_PYTHON_H) */ 100 | -------------------------------------------------------------------------------- /psycopg/replication_connection.h: -------------------------------------------------------------------------------- 1 | /* replication_connection.h - definition for the psycopg replication connection type 2 | * 3 | * Copyright (C) 2015-2019 Daniele Varrazzo 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_REPLICATION_CONNECTION_H 28 | #define PSYCOPG_REPLICATION_CONNECTION_H 1 29 | 30 | #include "psycopg/connection.h" 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | extern HIDDEN PyTypeObject replicationConnectionType; 37 | 38 | typedef struct replicationConnectionObject { 39 | connectionObject conn; 40 | 41 | long int type; 42 | } replicationConnectionObject; 43 | 44 | /* The funny constant values should help to avoid mixups with some 45 | commonly used numbers like 1 and 2. */ 46 | #define REPLICATION_PHYSICAL 12345678 47 | #define REPLICATION_LOGICAL 87654321 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif /* !defined(PSYCOPG_REPLICATION_CONNECTION_H) */ 54 | -------------------------------------------------------------------------------- /psycopg/replication_cursor.h: -------------------------------------------------------------------------------- 1 | /* replication_cursor.h - definition for the psycopg replication cursor type 2 | * 3 | * Copyright (C) 2015-2019 Daniele Varrazzo 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_REPLICATION_CURSOR_H 28 | #define PSYCOPG_REPLICATION_CURSOR_H 1 29 | 30 | #include "psycopg/cursor.h" 31 | #include "libpq_support.h" 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | extern HIDDEN PyTypeObject replicationCursorType; 38 | 39 | typedef struct replicationCursorObject { 40 | cursorObject cur; 41 | 42 | int consuming:1; /* if running the consume loop */ 43 | int decode:1; /* if we should use character decoding on the messages */ 44 | 45 | struct timeval last_io; /* timestamp of the last exchange with the server */ 46 | struct timeval status_interval; /* time between status packets sent to the server */ 47 | 48 | XLogRecPtr write_lsn; /* LSNs for replication feedback messages */ 49 | XLogRecPtr flush_lsn; 50 | XLogRecPtr apply_lsn; 51 | 52 | XLogRecPtr wal_end; /* WAL end pointer from the last exchange with the server */ 53 | 54 | XLogRecPtr last_msg_data_start; /* WAL pointer to the last non-keepalive message from the server */ 55 | struct timeval last_feedback; /* timestamp of the last feedback message to the server */ 56 | XLogRecPtr explicitly_flushed_lsn; /* the flush LSN explicitly set by the send_feedback call */ 57 | } replicationCursorObject; 58 | 59 | 60 | RAISES_NEG HIDDEN int repl_curs_datetime_init(void); 61 | 62 | #ifdef __cplusplus 63 | } 64 | #endif 65 | 66 | #endif /* !defined(PSYCOPG_REPLICATION_CURSOR_H) */ 67 | -------------------------------------------------------------------------------- /psycopg/replication_message.h: -------------------------------------------------------------------------------- 1 | /* replication_message.h - definition for the psycopg ReplicationMessage type 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_REPLICATION_MESSAGE_H 28 | #define PSYCOPG_REPLICATION_MESSAGE_H 1 29 | 30 | #include "cursor.h" 31 | #include "libpq_support.h" 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | extern HIDDEN PyTypeObject replicationMessageType; 38 | 39 | /* the typedef is forward-declared in psycopg.h */ 40 | struct replicationMessageObject { 41 | PyObject_HEAD 42 | 43 | cursorObject *cursor; 44 | PyObject *payload; 45 | 46 | int data_size; 47 | XLogRecPtr data_start; 48 | XLogRecPtr wal_end; 49 | int64_t send_time; 50 | }; 51 | 52 | RAISES_NEG HIDDEN int replmsg_datetime_init(void); 53 | 54 | #ifdef __cplusplus 55 | } 56 | #endif 57 | 58 | #endif /* !defined(PSYCOPG_REPLICATION_MESSAGE_H) */ 59 | -------------------------------------------------------------------------------- /psycopg/solaris_support.c: -------------------------------------------------------------------------------- 1 | /* solaris_support.c - emulate functions missing on Solaris 2 | * 3 | * Copyright (C) 2017 My Karlsson 4 | * Copyright (c) 2018, Joyent, Inc. 5 | * Copyright (C) 2020-2021 The Psycopg Team 6 | * 7 | * This file is part of psycopg. 8 | * 9 | * psycopg2 is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * In addition, as a special exception, the copyright holders give 15 | * permission to link this program with the OpenSSL library (or with 16 | * modified versions of OpenSSL that use the same license as OpenSSL), 17 | * and distribute linked combinations including the two. 18 | * 19 | * You must obey the GNU Lesser General Public License in all respects for 20 | * all of the code used other than OpenSSL. 21 | * 22 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 23 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 24 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 25 | * License for more details. 26 | */ 27 | 28 | #define PSYCOPG_MODULE 29 | #include "psycopg/psycopg.h" 30 | #include "psycopg/solaris_support.h" 31 | 32 | #if defined(__sun) && defined(__SVR4) 33 | /* timeradd is missing on Solaris 10 */ 34 | #ifndef timeradd 35 | void 36 | timeradd(struct timeval *a, struct timeval *b, struct timeval *c) 37 | { 38 | c->tv_sec = a->tv_sec + b->tv_sec; 39 | c->tv_usec = a->tv_usec + b->tv_usec; 40 | if (c->tv_usec >= 1000000) { 41 | c->tv_usec -= 1000000; 42 | c->tv_sec += 1; 43 | } 44 | } 45 | 46 | /* timersub is missing on Solaris */ 47 | void 48 | timersub(struct timeval *a, struct timeval *b, struct timeval *c) 49 | { 50 | c->tv_sec = a->tv_sec - b->tv_sec; 51 | c->tv_usec = a->tv_usec - b->tv_usec; 52 | if (c->tv_usec < 0) { 53 | c->tv_usec += 1000000; 54 | c->tv_sec -= 1; 55 | } 56 | } 57 | #endif /* timeradd */ 58 | #endif /* defined(__sun) && defined(__SVR4) */ 59 | -------------------------------------------------------------------------------- /psycopg/solaris_support.h: -------------------------------------------------------------------------------- 1 | /* solaris_support.h - definitions for solaris_support.c 2 | * 3 | * Copyright (C) 2017 My Karlsson 4 | * Copyright (c) 2018-2019, Joyent, Inc. 5 | * Copyright (C) 2020-2021 The Psycopg Team 6 | * 7 | * This file is part of psycopg. 8 | * 9 | * psycopg2 is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * In addition, as a special exception, the copyright holders give 15 | * permission to link this program with the OpenSSL library (or with 16 | * modified versions of OpenSSL that use the same license as OpenSSL), 17 | * and distribute linked combinations including the two. 18 | * 19 | * You must obey the GNU Lesser General Public License in all respects for 20 | * all of the code used other than OpenSSL. 21 | * 22 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 23 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 24 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 25 | * License for more details. 26 | */ 27 | #ifndef PSYCOPG_SOLARIS_SUPPORT_H 28 | #define PSYCOPG_SOLARIS_SUPPORT_H 29 | 30 | #include "psycopg/config.h" 31 | 32 | #if defined(__sun) && defined(__SVR4) 33 | #include 34 | 35 | #ifndef timeradd 36 | extern HIDDEN void timeradd(struct timeval *a, struct timeval *b, struct timeval *c); 37 | extern HIDDEN void timersub(struct timeval *a, struct timeval *b, struct timeval *c); 38 | #endif 39 | 40 | #ifndef timercmp 41 | #define timercmp(a, b, cmp) \ 42 | (((a)->tv_sec == (b)->tv_sec) ? \ 43 | ((a)->tv_usec cmp (b)->tv_usec) : \ 44 | ((a)->tv_sec cmp (b)->tv_sec)) 45 | #endif 46 | #endif 47 | 48 | #endif /* !defined(PSYCOPG_SOLARIS_SUPPORT_H) */ 49 | -------------------------------------------------------------------------------- /psycopg/typecast.h: -------------------------------------------------------------------------------- 1 | /* typecast.h - definitions for typecasters 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_TYPECAST_H 28 | #define PSYCOPG_TYPECAST_H 1 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | /* type of type-casting functions (both C and Python) */ 35 | typedef PyObject *(*typecast_function)(const char *str, Py_ssize_t len, 36 | PyObject *cursor); 37 | 38 | /** typecast type **/ 39 | 40 | extern HIDDEN PyTypeObject typecastType; 41 | 42 | typedef struct { 43 | PyObject_HEAD 44 | 45 | PyObject *name; /* the name of this type */ 46 | PyObject *values; /* the different types this instance can match */ 47 | 48 | typecast_function ccast; /* the C casting function */ 49 | PyObject *pcast; /* the python casting function */ 50 | PyObject *bcast; /* base cast, used by array typecasters */ 51 | } typecastObject; 52 | 53 | /* the initialization values are stored here */ 54 | 55 | typedef struct { 56 | char *name; 57 | long int *values; 58 | typecast_function cast; 59 | 60 | /* base is the base typecaster for arrays */ 61 | char *base; 62 | } typecastObject_initlist; 63 | 64 | /* the type dictionary, much faster to access it globally */ 65 | extern HIDDEN PyObject *psyco_types; 66 | extern HIDDEN PyObject *psyco_binary_types; 67 | 68 | /* the default casting objects, used when no other objects are available */ 69 | extern HIDDEN PyObject *psyco_default_cast; 70 | extern HIDDEN PyObject *psyco_default_binary_cast; 71 | 72 | /** exported functions **/ 73 | 74 | /* used by module.c to init the type system and register types */ 75 | RAISES_NEG HIDDEN int typecast_init(PyObject *dict); 76 | RAISES_NEG HIDDEN int typecast_add(PyObject *obj, PyObject *dict, int binary); 77 | 78 | /* the C callable typecastObject creator function */ 79 | HIDDEN PyObject *typecast_from_c(typecastObject_initlist *type, PyObject *d); 80 | 81 | /* the python callable typecast creator functions */ 82 | HIDDEN PyObject *typecast_from_python( 83 | PyObject *self, PyObject *args, PyObject *keywds); 84 | HIDDEN PyObject *typecast_array_from_python( 85 | PyObject *self, PyObject *args, PyObject *keywds); 86 | 87 | /* the function used to dispatch typecasting calls */ 88 | HIDDEN PyObject *typecast_cast( 89 | PyObject *self, const char *str, Py_ssize_t len, PyObject *curs); 90 | 91 | #endif /* !defined(PSYCOPG_TYPECAST_H) */ 92 | -------------------------------------------------------------------------------- /psycopg/typecast_basic.c: -------------------------------------------------------------------------------- 1 | /* pgcasts_basic.c - basic typecasting functions to python types 2 | * 3 | * Copyright (C) 2001-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | /** INTEGER - cast normal integers (4 bytes) to python int **/ 28 | 29 | #define typecast_INTEGER_cast typecast_LONGINTEGER_cast 30 | 31 | /** LONGINTEGER - cast long integers (8 bytes) to python long **/ 32 | 33 | static PyObject * 34 | typecast_LONGINTEGER_cast(const char *s, Py_ssize_t len, PyObject *curs) 35 | { 36 | char buffer[24]; 37 | 38 | if (s == NULL) { Py_RETURN_NONE; } 39 | if (s[len] != '\0') { 40 | strncpy(buffer, s, (size_t) len); buffer[len] = '\0'; 41 | s = buffer; 42 | } 43 | return PyLong_FromString((char *)s, NULL, 0); 44 | } 45 | 46 | /** FLOAT - cast floating point numbers to python float **/ 47 | 48 | static PyObject * 49 | typecast_FLOAT_cast(const char *s, Py_ssize_t len, PyObject *curs) 50 | { 51 | PyObject *str = NULL, *flo = NULL; 52 | 53 | if (s == NULL) { Py_RETURN_NONE; } 54 | if (!(str = Text_FromUTF8AndSize(s, len))) { return NULL; } 55 | flo = PyFloat_FromString(str); 56 | Py_DECREF(str); 57 | return flo; 58 | } 59 | 60 | 61 | /** BYTES - cast strings of any type to python bytes **/ 62 | 63 | static PyObject * 64 | typecast_BYTES_cast(const char *s, Py_ssize_t len, PyObject *curs) 65 | { 66 | if (s == NULL) { Py_RETURN_NONE; } 67 | return Bytes_FromStringAndSize(s, len); 68 | } 69 | 70 | 71 | /** UNICODE - cast strings of any type to a python unicode object **/ 72 | 73 | static PyObject * 74 | typecast_UNICODE_cast(const char *s, Py_ssize_t len, PyObject *curs) 75 | { 76 | connectionObject *conn; 77 | 78 | if (s == NULL) { Py_RETURN_NONE; } 79 | 80 | conn = ((cursorObject*)curs)->conn; 81 | return conn_decode(conn, s, len); 82 | } 83 | 84 | 85 | /** STRING - cast strings of any type to python string **/ 86 | 87 | #define typecast_STRING_cast typecast_UNICODE_cast 88 | 89 | 90 | /** BOOLEAN - cast boolean value into right python object **/ 91 | 92 | static PyObject * 93 | typecast_BOOLEAN_cast(const char *s, Py_ssize_t len, PyObject *curs) 94 | { 95 | PyObject *res = NULL; 96 | 97 | if (s == NULL) { Py_RETURN_NONE; } 98 | 99 | switch (s[0]) { 100 | case 't': 101 | case 'T': 102 | res = Py_True; 103 | break; 104 | 105 | case 'f': 106 | case 'F': 107 | res = Py_False; 108 | break; 109 | 110 | default: 111 | PyErr_Format(InterfaceError, "can't parse boolean: '%s'", s); 112 | break; 113 | } 114 | 115 | Py_XINCREF(res); 116 | return res; 117 | } 118 | 119 | /** DECIMAL - cast any kind of number into a Python Decimal object **/ 120 | 121 | static PyObject * 122 | typecast_DECIMAL_cast(const char *s, Py_ssize_t len, PyObject *curs) 123 | { 124 | PyObject *res = NULL; 125 | PyObject *decimalType; 126 | char *buffer; 127 | 128 | if (s == NULL) { Py_RETURN_NONE; } 129 | 130 | if ((buffer = PyMem_Malloc(len+1)) == NULL) 131 | return PyErr_NoMemory(); 132 | strncpy(buffer, s, (size_t) len); buffer[len] = '\0'; 133 | decimalType = psyco_get_decimal_type(); 134 | /* Fall back on float if decimal is not available */ 135 | if (decimalType != NULL) { 136 | res = PyObject_CallFunction(decimalType, "s", buffer); 137 | Py_DECREF(decimalType); 138 | } 139 | else { 140 | PyErr_Clear(); 141 | res = PyObject_CallFunction((PyObject*)&PyFloat_Type, "s", buffer); 142 | } 143 | PyMem_Free(buffer); 144 | 145 | return res; 146 | } 147 | 148 | /* some needed aliases */ 149 | #define typecast_NUMBER_cast typecast_FLOAT_cast 150 | #define typecast_ROWID_cast typecast_INTEGER_cast 151 | -------------------------------------------------------------------------------- /psycopg/typecast_binary.h: -------------------------------------------------------------------------------- 1 | /* typecast_binary.h - definitions for binary typecaster 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef PSYCOPG_TYPECAST_BINARY_H 28 | #define PSYCOPG_TYPECAST_BINARY_H 1 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | /** chunk type **/ 35 | 36 | extern HIDDEN PyTypeObject chunkType; 37 | 38 | typedef struct { 39 | PyObject_HEAD 40 | 41 | void *base; /* Pointer to the memory chunk. */ 42 | Py_ssize_t len; /* Size in bytes of the memory chunk. */ 43 | 44 | } chunkObject; 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | #endif /* !defined(PSYCOPG_TYPECAST_BINARY_H) */ 51 | -------------------------------------------------------------------------------- /psycopg/typecast_builtins.c: -------------------------------------------------------------------------------- 1 | static long int typecast_NUMBER_types[] = {20, 23, 21, 701, 700, 1700, 0}; 2 | static long int typecast_LONGINTEGER_types[] = {20, 0}; 3 | static long int typecast_INTEGER_types[] = {23, 21, 0}; 4 | static long int typecast_FLOAT_types[] = {701, 700, 0}; 5 | static long int typecast_DECIMAL_types[] = {1700, 0}; 6 | static long int typecast_STRING_types[] = {19, 18, 25, 1042, 1043, 0}; 7 | static long int typecast_BOOLEAN_types[] = {16, 0}; 8 | static long int typecast_DATETIME_types[] = {1114, 0}; 9 | static long int typecast_DATETIMETZ_types[] = {1184, 0}; 10 | static long int typecast_TIME_types[] = {1083, 1266, 0}; 11 | static long int typecast_DATE_types[] = {1082, 0}; 12 | static long int typecast_INTERVAL_types[] = {704, 1186, 0}; 13 | static long int typecast_BINARY_types[] = {17, 0}; 14 | static long int typecast_ROWID_types[] = {26, 0}; 15 | static long int typecast_LONGINTEGERARRAY_types[] = {1016, 0}; 16 | static long int typecast_INTEGERARRAY_types[] = {1005, 1006, 1007, 0}; 17 | static long int typecast_FLOATARRAY_types[] = {1021, 1022, 0}; 18 | static long int typecast_DECIMALARRAY_types[] = {1231, 0}; 19 | static long int typecast_STRINGARRAY_types[] = {1002, 1003, 1009, 1014, 1015, 0}; 20 | static long int typecast_BOOLEANARRAY_types[] = {1000, 0}; 21 | static long int typecast_DATETIMEARRAY_types[] = {1115, 0}; 22 | static long int typecast_DATETIMETZARRAY_types[] = {1185, 0}; 23 | static long int typecast_TIMEARRAY_types[] = {1183, 1270, 0}; 24 | static long int typecast_DATEARRAY_types[] = {1182, 0}; 25 | static long int typecast_INTERVALARRAY_types[] = {1187, 0}; 26 | static long int typecast_BINARYARRAY_types[] = {1001, 0}; 27 | static long int typecast_ROWIDARRAY_types[] = {1028, 1013, 0}; 28 | static long int typecast_INETARRAY_types[] = {1041, 0}; 29 | static long int typecast_CIDRARRAY_types[] = {651, 0}; 30 | static long int typecast_MACADDRARRAY_types[] = {1040, 0}; 31 | static long int typecast_UNKNOWN_types[] = {705, 0}; 32 | 33 | 34 | static typecastObject_initlist typecast_builtins[] = { 35 | {"NUMBER", typecast_NUMBER_types, typecast_NUMBER_cast, NULL}, 36 | {"LONGINTEGER", typecast_LONGINTEGER_types, typecast_LONGINTEGER_cast, NULL}, 37 | {"INTEGER", typecast_INTEGER_types, typecast_INTEGER_cast, NULL}, 38 | {"FLOAT", typecast_FLOAT_types, typecast_FLOAT_cast, NULL}, 39 | {"DECIMAL", typecast_DECIMAL_types, typecast_DECIMAL_cast, NULL}, 40 | {"UNICODE", typecast_STRING_types, typecast_UNICODE_cast, NULL}, 41 | {"BYTES", typecast_STRING_types, typecast_BYTES_cast, NULL}, 42 | {"STRING", typecast_STRING_types, typecast_STRING_cast, NULL}, 43 | {"BOOLEAN", typecast_BOOLEAN_types, typecast_BOOLEAN_cast, NULL}, 44 | {"DATETIME", typecast_DATETIME_types, typecast_DATETIME_cast, NULL}, 45 | {"DATETIMETZ", typecast_DATETIMETZ_types, typecast_DATETIMETZ_cast, NULL}, 46 | {"TIME", typecast_TIME_types, typecast_TIME_cast, NULL}, 47 | {"DATE", typecast_DATE_types, typecast_DATE_cast, NULL}, 48 | {"INTERVAL", typecast_INTERVAL_types, typecast_INTERVAL_cast, NULL}, 49 | {"BINARY", typecast_BINARY_types, typecast_BINARY_cast, NULL}, 50 | {"ROWID", typecast_ROWID_types, typecast_ROWID_cast, NULL}, 51 | {"LONGINTEGERARRAY", typecast_LONGINTEGERARRAY_types, typecast_LONGINTEGERARRAY_cast, "LONGINTEGER"}, 52 | {"INTEGERARRAY", typecast_INTEGERARRAY_types, typecast_INTEGERARRAY_cast, "INTEGER"}, 53 | {"FLOATARRAY", typecast_FLOATARRAY_types, typecast_FLOATARRAY_cast, "FLOAT"}, 54 | {"DECIMALARRAY", typecast_DECIMALARRAY_types, typecast_DECIMALARRAY_cast, "DECIMAL"}, 55 | {"UNICODEARRAY", typecast_STRINGARRAY_types, typecast_UNICODEARRAY_cast, "UNICODE"}, 56 | {"BYTESARRAY", typecast_STRINGARRAY_types, typecast_BYTESARRAY_cast, "BYTES"}, 57 | {"STRINGARRAY", typecast_STRINGARRAY_types, typecast_STRINGARRAY_cast, "STRING"}, 58 | {"BOOLEANARRAY", typecast_BOOLEANARRAY_types, typecast_BOOLEANARRAY_cast, "BOOLEAN"}, 59 | {"DATETIMEARRAY", typecast_DATETIMEARRAY_types, typecast_DATETIMEARRAY_cast, "DATETIME"}, 60 | {"DATETIMETZARRAY", typecast_DATETIMETZARRAY_types, typecast_DATETIMETZARRAY_cast, "DATETIMETZ"}, 61 | {"TIMEARRAY", typecast_TIMEARRAY_types, typecast_TIMEARRAY_cast, "TIME"}, 62 | {"DATEARRAY", typecast_DATEARRAY_types, typecast_DATEARRAY_cast, "DATE"}, 63 | {"INTERVALARRAY", typecast_INTERVALARRAY_types, typecast_INTERVALARRAY_cast, "INTERVAL"}, 64 | {"BINARYARRAY", typecast_BINARYARRAY_types, typecast_BINARYARRAY_cast, "BINARY"}, 65 | {"ROWIDARRAY", typecast_ROWIDARRAY_types, typecast_ROWIDARRAY_cast, "ROWID"}, 66 | {"UNKNOWN", typecast_UNKNOWN_types, typecast_UNKNOWN_cast, NULL}, 67 | {"INETARRAY", typecast_INETARRAY_types, typecast_STRINGARRAY_cast, "STRING"}, 68 | {"CIDRARRAY", typecast_CIDRARRAY_types, typecast_STRINGARRAY_cast, "STRING"}, 69 | {"MACADDRARRAY", typecast_MACADDRARRAY_types, typecast_STRINGARRAY_cast, "STRING"}, 70 | {NULL, NULL, NULL, NULL} 71 | }; 72 | -------------------------------------------------------------------------------- /psycopg/utils.h: -------------------------------------------------------------------------------- 1 | /* utils.h - function definitions for utility file 2 | * 3 | * Copyright (C) 2018-2019 Daniele Varrazzo 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #ifndef UTILS_H 28 | #define UTILS_H 1 29 | 30 | /* forward declarations */ 31 | typedef struct cursorObject cursorObject; 32 | typedef struct connectionObject connectionObject; 33 | typedef struct replicationMessageObject replicationMessageObject; 34 | 35 | HIDDEN char *psyco_escape_string( 36 | connectionObject *conn, 37 | const char *from, Py_ssize_t len, char *to, Py_ssize_t *tolen); 38 | 39 | HIDDEN char *psyco_escape_identifier( 40 | connectionObject *conn, const char *str, Py_ssize_t len); 41 | 42 | HIDDEN int psyco_strdup(char **to, const char *from, Py_ssize_t len); 43 | 44 | STEALS(1) HIDDEN PyObject * psyco_ensure_bytes(PyObject *obj); 45 | STEALS(1) HIDDEN PyObject * psyco_ensure_text(PyObject *obj); 46 | 47 | HIDDEN int psyco_is_text_file(PyObject *f); 48 | 49 | HIDDEN PyObject *psyco_dict_from_conninfo_options( 50 | PQconninfoOption *options, int include_password); 51 | 52 | HIDDEN PyObject *psyco_make_dsn(PyObject *dsn, PyObject *kwargs); 53 | 54 | HIDDEN PyObject *psyco_text_from_chars_safe( 55 | const char *str, Py_ssize_t len, PyObject *decoder); 56 | 57 | HIDDEN RAISES BORROWED PyObject *psyco_set_error( 58 | PyObject *exc, cursorObject *curs, const char *msg); 59 | 60 | HIDDEN PyObject *psyco_get_decimal_type(void); 61 | 62 | HIDDEN PyObject *Bytes_Format(PyObject *format, PyObject *args); 63 | 64 | 65 | #endif /* !defined(UTILS_H) */ 66 | -------------------------------------------------------------------------------- /psycopg/win32_support.c: -------------------------------------------------------------------------------- 1 | /* win32_support.c - emulate some functions missing on Win32 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | 27 | #define PSYCOPG_MODULE 28 | #include "psycopg/psycopg.h" 29 | 30 | #include "psycopg/win32_support.h" 31 | 32 | #ifdef _WIN32 33 | 34 | #ifndef __MINGW32__ 35 | /* millisecond-precision port of gettimeofday for Win32, taken from 36 | src/port/gettimeofday.c in PostgreSQL core */ 37 | 38 | /* FILETIME of Jan 1 1970 00:00:00. */ 39 | static const unsigned __int64 epoch = ((unsigned __int64) 116444736000000000ULL); 40 | 41 | /* 42 | * timezone information is stored outside the kernel so tzp isn't used anymore. 43 | * 44 | * Note: this function is not for Win32 high precision timing purpose. See 45 | * elapsed_time(). 46 | */ 47 | int 48 | gettimeofday(struct timeval * tp, void * tzp) 49 | { 50 | FILETIME file_time; 51 | SYSTEMTIME system_time; 52 | ULARGE_INTEGER ularge; 53 | 54 | GetSystemTime(&system_time); 55 | SystemTimeToFileTime(&system_time, &file_time); 56 | ularge.LowPart = file_time.dwLowDateTime; 57 | ularge.HighPart = file_time.dwHighDateTime; 58 | 59 | tp->tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L); 60 | tp->tv_usec = (long) (system_time.wMilliseconds * 1000); 61 | 62 | return 0; 63 | } 64 | 65 | /* timeradd missing on MS VC */ 66 | void 67 | timeradd(struct timeval *a, struct timeval *b, struct timeval *c) 68 | { 69 | c->tv_sec = a->tv_sec + b->tv_sec; 70 | c->tv_usec = a->tv_usec + b->tv_usec; 71 | if(c->tv_usec >= 1000000L) { 72 | c->tv_usec -= 1000000L; 73 | c->tv_sec += 1; 74 | } 75 | } 76 | #endif /* !defined(__MINGW32__) */ 77 | 78 | /* timersub is missing on mingw & MS VC */ 79 | void 80 | timersub(struct timeval *a, struct timeval *b, struct timeval *c) 81 | { 82 | c->tv_sec = a->tv_sec - b->tv_sec; 83 | c->tv_usec = a->tv_usec - b->tv_usec; 84 | if (c->tv_usec < 0) { 85 | c->tv_usec += 1000000; 86 | c->tv_sec -= 1; 87 | } 88 | } 89 | 90 | #endif /* defined(_WIN32) */ 91 | -------------------------------------------------------------------------------- /psycopg/win32_support.h: -------------------------------------------------------------------------------- 1 | /* win32_support.h - definitions for win32_support.c 2 | * 3 | * Copyright (C) 2003-2019 Federico Di Gregorio 4 | * Copyright (C) 2020-2021 The Psycopg Team 5 | * 6 | * This file is part of psycopg. 7 | * 8 | * psycopg2 is free software: you can redistribute it and/or modify it 9 | * under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * In addition, as a special exception, the copyright holders give 14 | * permission to link this program with the OpenSSL library (or with 15 | * modified versions of OpenSSL that use the same license as OpenSSL), 16 | * and distribute linked combinations including the two. 17 | * 18 | * You must obey the GNU Lesser General Public License in all respects for 19 | * all of the code used other than OpenSSL. 20 | * 21 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | * License for more details. 25 | */ 26 | #ifndef PSYCOPG_WIN32_SUPPORT_H 27 | #define PSYCOPG_WIN32_SUPPORT_H 28 | 29 | #include "psycopg/config.h" 30 | 31 | #ifdef _WIN32 32 | #include 33 | #endif 34 | #ifdef __MINGW32__ 35 | #include 36 | #endif 37 | 38 | 39 | #ifdef _WIN32 40 | #ifndef __MINGW32__ 41 | extern HIDDEN int gettimeofday(struct timeval * tp, void * tzp); 42 | extern HIDDEN void timeradd(struct timeval *a, struct timeval *b, struct timeval *c); 43 | #elif 44 | #endif 45 | 46 | extern HIDDEN void timersub(struct timeval *a, struct timeval *b, struct timeval *c); 47 | 48 | #ifndef timercmp 49 | #define timercmp(a, b, cmp) \ 50 | (((a)->tv_sec == (b)->tv_sec) ? \ 51 | ((a)->tv_usec cmp (b)->tv_usec) : \ 52 | ((a)->tv_sec cmp (b)->tv_sec)) 53 | #endif 54 | #endif 55 | 56 | #endif /* !defined(PSYCOPG_WIN32_SUPPORT_H) */ 57 | -------------------------------------------------------------------------------- /psycopg/xid.h: -------------------------------------------------------------------------------- 1 | /* xid.h - definition for the psycopg Xid type 2 | * 3 | * Copyright (C) 2008-2019 James Henstridge 4 | * Copyright (C) 2010-2019 Daniele Varrazzo 5 | * Copyright (C) 2020-2021 The Psycopg Team 6 | * 7 | * This file is part of psycopg. 8 | * 9 | * psycopg2 is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU Lesser General Public License as published 11 | * by the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * In addition, as a special exception, the copyright holders give 15 | * permission to link this program with the OpenSSL library (or with 16 | * modified versions of OpenSSL that use the same license as OpenSSL), 17 | * and distribute linked combinations including the two. 18 | * 19 | * You must obey the GNU Lesser General Public License in all respects for 20 | * all of the code used other than OpenSSL. 21 | * 22 | * psycopg2 is distributed in the hope that it will be useful, but WITHOUT 23 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 24 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 25 | * License for more details. 26 | */ 27 | 28 | #ifndef PSYCOPG_XID_H 29 | #define PSYCOPG_XID_H 1 30 | 31 | extern HIDDEN PyTypeObject xidType; 32 | 33 | typedef struct { 34 | PyObject_HEAD 35 | 36 | /* the Python-style three-part transaction ID */ 37 | PyObject *format_id; 38 | PyObject *gtrid; 39 | PyObject *bqual; 40 | 41 | /* Additional information PostgreSQL exposes about prepared transactions */ 42 | PyObject *prepared; 43 | PyObject *owner; 44 | PyObject *database; 45 | } xidObject; 46 | 47 | HIDDEN xidObject *xid_ensure(PyObject *oxid); 48 | HIDDEN xidObject *xid_from_string(PyObject *s); 49 | HIDDEN PyObject *xid_get_tid(xidObject *self); 50 | HIDDEN PyObject *xid_recover(PyObject *conn); 51 | 52 | #endif /* PSYCOPG_XID_H */ 53 | -------------------------------------------------------------------------------- /scripts/build/build_macos_arm64.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Build psycopg2-binary wheel packages for Apple M1 (cpNNN-macosx_arm64) 4 | # 5 | # This script is designed to run on Scaleway Apple Silicon machines. 6 | # 7 | # The script cannot be run as sudo (installing brew fails), but requires sudo, 8 | # so it can pretty much only be executed by a sudo user as it is. 9 | 10 | set -euo pipefail 11 | # set -x 12 | 13 | python_versions="3.8.18 3.9.18 3.10.13 3.11.6 3.12.0" 14 | pg_version=16 15 | 16 | function log { 17 | echo "$@" >&2 18 | } 19 | 20 | # Move to the root of the project 21 | dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 22 | cd "${dir}/../../" 23 | 24 | # Add /usr/local/bin to the path. It seems it's not, in non-interactive sessions 25 | if ! (echo $PATH | grep -q '/usr/local/bin'); then 26 | export PATH=/usr/local/bin:$PATH 27 | fi 28 | 29 | # Install brew, if necessary. Otherwise just make sure it's in the path 30 | if [[ -x /opt/homebrew/bin/brew ]]; then 31 | eval "$(/opt/homebrew/bin/brew shellenv)" 32 | else 33 | log "installing brew" 34 | command -v brew > /dev/null || ( 35 | # Not necessary: already installed 36 | # xcode-select --install 37 | NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL \ 38 | https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" 39 | ) 40 | eval "$(/opt/homebrew/bin/brew shellenv)" 41 | fi 42 | 43 | export PGDATA=/opt/homebrew/var/postgresql@${pg_version} 44 | 45 | # Install PostgreSQL, if necessary 46 | command -v pg_config > /dev/null || ( 47 | log "installing postgres" 48 | brew install postgresql@${pg_version} 49 | ) 50 | 51 | # Starting from PostgreSQL 15, the bin path is not in the path. 52 | export PATH="$(ls -d1 /opt/homebrew/Cellar/postgresql@${pg_version}/*/bin):$PATH" 53 | 54 | # Make sure the server is running 55 | 56 | # Currently not working 57 | # brew services start postgresql@${pg_version} 58 | 59 | if ! pg_ctl status; then 60 | log "starting the server" 61 | pg_ctl -l "/opt/homebrew/var/log/postgresql@${pg_version}.log" start 62 | fi 63 | 64 | 65 | # Install the Python versions we want to build 66 | for ver3 in $python_versions; do 67 | ver2=$(echo $ver3 | sed 's/\([^\.]*\)\(\.[^\.]*\)\(.*\)/\1\2/') 68 | command -v python${ver2} > /dev/null || ( 69 | log "installing Python $ver3" 70 | (cd /tmp && 71 | curl -fsSl -O \ 72 | https://www.python.org/ftp/python/${ver3}/python-${ver3}-macos11.pkg) 73 | sudo installer -pkg /tmp/python-${ver3}-macos11.pkg -target / 74 | ) 75 | done 76 | 77 | # Create a virtualenv where to work 78 | if [[ ! -x .venv/bin/python ]]; then 79 | log "creating a virtualenv" 80 | python3 -m venv .venv 81 | fi 82 | 83 | log "installing cibuildwheel" 84 | source .venv/bin/activate 85 | pip install cibuildwheel 86 | 87 | log "building wheels" 88 | 89 | # Build the binary packages 90 | export CIBW_PLATFORM=macos 91 | export CIBW_ARCHS=arm64 92 | export CIBW_BUILD='cp{38,39,310,311,312}-*' 93 | export CIBW_TEST_COMMAND='python -c "import tests; tests.unittest.main(defaultTest=\"tests.test_suite\")"' 94 | 95 | export PSYCOPG2_TESTDB=postgres 96 | export PYTHONPATH=$(pwd) 97 | 98 | # For some reason, cibuildwheel tests says that psycopg2 is already installed, 99 | # refuses to install, then promptly fails import. So, please, seriously, 100 | # install this thing. 101 | export PIP_FORCE_REINSTALL=1 102 | 103 | # Replace the package name 104 | sed -i .bak 's/^setup(name="psycopg2"/setup(name="psycopg2-binary"/' setup.py 105 | 106 | cibuildwheel 107 | -------------------------------------------------------------------------------- /scripts/build/build_sdist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | set -x 5 | 6 | dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | prjdir="$( cd "${dir}/../.." && pwd )" 8 | 9 | # Find psycopg version 10 | version=$(grep -e ^PSYCOPG_VERSION setup.py | sed "s/.*'\(.*\)'/\1/") 11 | # A gratuitous comment to fix broken vim syntax file: '") 12 | distdir="${prjdir}/dist" 13 | 14 | # Replace the package name 15 | if [[ "${PACKAGE_NAME:-}" ]]; then 16 | sed -i "s/^setup(name=\"psycopg2\"/setup(name=\"${PACKAGE_NAME}\"/" \ 17 | "${prjdir}/setup.py" 18 | fi 19 | 20 | # Build the source package 21 | python setup.py sdist -d "$distdir" 22 | 23 | # install and test 24 | pip install "${distdir}"/*.tar.gz 25 | 26 | python -c "import tests; tests.unittest.main(defaultTest='tests.test_suite')" 27 | -------------------------------------------------------------------------------- /scripts/build/pg_config_vcpkg_stub/pg_config_vcpkg_stub/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | We use vcpkg in github actions to build psycopg-binary. 4 | 5 | This is a stub to work as `pg_config --libdir` or `pg_config --includedir` to 6 | make it work with vcpkg. 7 | 8 | You will need install `vcpkg`, set `VCPKG_ROOT` env, and run `vcpkg install 9 | libpq:x64-windows-release` before using this script. 10 | """ 11 | 12 | import os 13 | import sys 14 | import platform 15 | from pathlib import Path 16 | from argparse import ArgumentParser, Namespace, RawDescriptionHelpFormatter 17 | 18 | 19 | class ScriptError(Exception): 20 | """Controlled exception raised by the script.""" 21 | 22 | 23 | def _main() -> None: 24 | # only x64-windows 25 | if not (sys.platform == "win32" and platform.machine() == "AMD64"): 26 | raise ScriptError("this script should only be used in x64-windows") 27 | 28 | vcpkg_root = os.environ.get( 29 | "VCPKG_ROOT", os.environ.get("VCPKG_INSTALLATION_ROOT", "") 30 | ) 31 | if not vcpkg_root: 32 | raise ScriptError("VCPKG_ROOT/VCPKG_INSTALLATION_ROOT env var not specified") 33 | vcpkg_platform_root = (Path(vcpkg_root) / "installed/x64-windows-release").resolve() 34 | 35 | args = parse_cmdline() 36 | 37 | if args.libdir: 38 | if not (f := vcpkg_platform_root / "lib/libpq.lib").exists(): 39 | raise ScriptError(f"libpq library not found: {f}") 40 | print(vcpkg_platform_root.joinpath("lib")) 41 | 42 | elif args.includedir or args.includedir_server: 43 | # NOTE: on linux, the includedir-server dir contains pg_config.h 44 | # which we need because it includes the PG_VERSION_NUM macro. 45 | # In the vcpkg directory this file is in the includedir directory, 46 | # therefore we return the same value. 47 | if not (d := vcpkg_platform_root / "include/libpq").is_dir(): 48 | raise ScriptError(f"libpq include directory not found: {d}") 49 | print(vcpkg_platform_root.joinpath("include")) 50 | 51 | elif args.cppflags or args.ldflags: 52 | print("") 53 | 54 | else: 55 | raise ScriptError("command not handled") 56 | 57 | 58 | def parse_cmdline() -> Namespace: 59 | parser = ArgumentParser( 60 | description=__doc__, formatter_class=RawDescriptionHelpFormatter 61 | ) 62 | g = parser.add_mutually_exclusive_group(required=True) 63 | g.add_argument( 64 | "--libdir", 65 | action="store_true", 66 | help="show location of object code libraries", 67 | ) 68 | g.add_argument( 69 | "--includedir", 70 | action="store_true", 71 | help="show location of C header files of the client interfaces", 72 | ) 73 | g.add_argument( 74 | "--includedir-server", 75 | action="store_true", 76 | help="show location of C header files for the server", 77 | ) 78 | g.add_argument( 79 | "--cppflags", 80 | action="store_true", 81 | help="(dummy) show CPPFLAGS value used when PostgreSQL was built", 82 | ) 83 | g.add_argument( 84 | "--ldflags", 85 | action="store_true", 86 | help="(dummy) show LDFLAGS value used when PostgreSQL was built", 87 | ) 88 | opt = parser.parse_args() 89 | return opt 90 | 91 | 92 | def main() -> None: 93 | try: 94 | _main() 95 | except ScriptError as e: 96 | print(f"ERROR: {e}.", file=sys.stderr) 97 | sys.exit(1) 98 | 99 | 100 | if __name__ == "__main__": 101 | main() 102 | -------------------------------------------------------------------------------- /scripts/build/pg_config_vcpkg_stub/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = 'pg_config_vcpkg_stub' 7 | version = "0" 8 | description = "see docs string in pg_config_vcpkg_stub for more details" 9 | 10 | [project.scripts] 11 | pg_config = 'pg_config_vcpkg_stub:main' 12 | -------------------------------------------------------------------------------- /scripts/build/print_so_versions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Take a .so file as input and print the Debian packages and versions of the 4 | # libraries it links. 5 | 6 | set -euo pipefail 7 | # set -x 8 | 9 | source /etc/os-release 10 | 11 | sofile="$1" 12 | 13 | case "$ID" in 14 | alpine) 15 | depfiles=$( (ldd "$sofile" 2>/dev/null || true) | grep '=>' | sed 's/.*=> \(.*\) (.*)/\1/') 16 | (for depfile in $depfiles; do 17 | echo "$(basename "$depfile") => $(apk info --who-owns "${depfile}" | awk '{print $(NF)}')" 18 | done) | sort | uniq 19 | ;; 20 | 21 | debian) 22 | depfiles=$(ldd "$sofile" | grep '=>' | sed 's/.*=> \(.*\) (.*)/\1/') 23 | (for depfile in $depfiles; do 24 | pkgname=$(dpkg -S "${depfile}" | sed 's/\(\): .*/\1/') 25 | dpkg -l "${pkgname}" | grep '^ii' | awk '{print $2 " => " $3}' 26 | done) | sort | uniq 27 | ;; 28 | 29 | centos) 30 | echo "TODO!" 31 | ;; 32 | 33 | *) 34 | echo "$0: unexpected Linux distribution: '$ID'" >&2 35 | exit 1 36 | ;; 37 | esac 38 | -------------------------------------------------------------------------------- /scripts/build/run_build_macos_arm64.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Build psycopg2-binary wheel packages for Apple M1 (cpNNN-macosx_arm64) 4 | # 5 | # This script is designed to run on a local machine: it will clone the repos 6 | # remotely and execute the `build_macos_arm64.sh` script remotely, then will 7 | # download the built packages. A tag to build must be specified. 8 | 9 | # The script requires a Scaleway secret key in the SCW_SECRET_KEY env var: 10 | # It will use scaleway_m1.sh to provision a server and use it. 11 | 12 | set -euo pipefail 13 | # set -x 14 | 15 | function log { 16 | echo "$@" >&2 17 | } 18 | function error { 19 | # Print an error message and exit. 20 | log "ERROR: $@" 21 | exit 1 22 | } 23 | 24 | tag=${1:-} 25 | 26 | if [[ ! "${tag}" ]]; then 27 | error "Usage: $0 REF" 28 | fi 29 | 30 | dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 31 | 32 | server=$("${dir}/scaleway_m1.sh" ensure) 33 | 34 | status=$(echo "$server" | jq -r .status) 35 | if [[ "$status" != "ready" ]]; then 36 | error "server status is $status" 37 | fi 38 | 39 | # Get user, password, ip from vnc url 40 | tmp=$(echo "$server" | jq -r .vnc_url) # vnc://m1:PASS@1.2.3.4:5900 41 | tmp=${tmp/vnc:\/\//} # m1:PASS@1.2.3.4:5900 42 | user=${tmp%%:*} # m1 43 | tmp=${tmp#*:} # PASS@1.2.3.4:5900 44 | password=${tmp%%@*} # PASS 45 | tmp=${tmp#*@} # 1.2.3.4:5900 46 | host=${tmp%%:*} # 1.2.3.4 47 | 48 | ssh="ssh ${user}@${host} -o StrictHostKeyChecking=no" 49 | 50 | # Allow the user to sudo without asking for password. 51 | echo "$password" | \ 52 | $ssh sh -c "test -f /etc/sudoers.d/${user} \ 53 | || sudo -S --prompt= sh -c \ 54 | 'echo \"${user} ALL=(ALL) NOPASSWD:ALL\" > /etc/sudoers.d/${user}'" 55 | 56 | # Clone the repos 57 | rdir=psycobuild 58 | $ssh rm -rf "${rdir}" 59 | $ssh git clone https://github.com/psycopg/psycopg2.git --branch ${tag} "${rdir}" 60 | 61 | # Build the wheel packages 62 | $ssh "${rdir}/scripts/build/build_macos_arm64.sh" 63 | 64 | # Transfer the packages locally 65 | scp -r "${user}@${host}:${rdir}/wheelhouse" . 66 | -------------------------------------------------------------------------------- /scripts/build/scaleway_m1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Implement the following commands: 4 | # 5 | # ensure: 6 | # 7 | # Get data about currently provisioned M1 server on Scaleway. If needed, 8 | # provision one. 9 | # 10 | # The script requires the SCW_SECRET_KEY env var set to a valid secret. 11 | # 12 | # If successful, return the response data on stdout. It may look like: 13 | # 14 | # { 15 | # "id": "8b196119-3cea-4a9d-b916-265037a85e60", 16 | # "type": "M1-M", 17 | # "name": "mac-m1-psycopg", 18 | # "project_id": "4cf7a85e-f21e-40d4-b758-21d1f4ad3dfb", 19 | # "organization_id": "4cf7a85e-f21e-40d4-b758-21d1f4ad3dfb", 20 | # "ip": "1.2.3.4", 21 | # "vnc_url": "vnc://m1:PASSWORD@1.2.3.4:5900", 22 | # "status": "starting", 23 | # "created_at": "2023-09-22T18:00:18.754646Z", 24 | # "updated_at": "2023-09-22T18:00:18.754646Z", 25 | # "deletable_at": "2023-09-23T18:00:18.754646Z", 26 | # "zone": "fr-par-3" 27 | # } 28 | # 29 | # delete: 30 | # 31 | # Delete one provisioned server, if available. 32 | # 33 | # See https://www.scaleway.com/en/developers/api/apple-silicon/ for api docs. 34 | 35 | set -euo pipefail 36 | # set -x 37 | 38 | project_id="4cf7a85e-f21e-40d4-b758-21d1f4ad3dfb" 39 | zone=fr-par-3 40 | servers_url="https://api.scaleway.com/apple-silicon/v1alpha1/zones/${zone}/servers" 41 | 42 | function log { 43 | echo "$@" >&2 44 | } 45 | function error { 46 | log "ERROR: $@" 47 | exit 1 48 | } 49 | 50 | function req { 51 | method=$1 52 | shift 53 | curl -sSL --fail-with-body -X $method \ 54 | -H "Content-Type: application/json" \ 55 | -H "X-Auth-Token: ${SCW_SECRET_KEY}" \ 56 | "$@" 57 | } 58 | function get { 59 | req GET "$@" 60 | } 61 | function post { 62 | req POST "$@" 63 | } 64 | function delete { 65 | req DELETE "$@" 66 | } 67 | 68 | function server_id { 69 | # Return the id of the first server available, else the empty string 70 | servers=$(get $servers_url || error "failed to request servers list") 71 | server_ids=$(echo "$servers" | jq -r ".servers[].id") 72 | for id in $server_ids; do 73 | echo $id 74 | break 75 | done 76 | } 77 | 78 | function maybe_jq { 79 | # Process the output via jq if displaying on console, otherwise leave 80 | # it unprocessed. 81 | if [ -t 1 ]; then 82 | jq . 83 | else 84 | cat 85 | fi 86 | } 87 | 88 | cmd=${1:-list} 89 | case $cmd in 90 | ensure) 91 | id=$(server_id) 92 | if [[ "$id" ]]; then 93 | log "You have servers." 94 | get "$servers_url/$id" | maybe_jq 95 | else 96 | log "Creating new server." 97 | post $servers_url -d " 98 | { 99 | \"name\": \"mac-m1-psycopg\", 100 | \"project_id\": \"$project_id\", 101 | \"type\": \"M1-M\" 102 | }" | maybe_jq 103 | fi 104 | ;; 105 | delete) 106 | id=$(server_id) 107 | if [[ "$id" ]]; then 108 | log "Deleting server $id." 109 | delete "$servers_url/$id" | maybe_jq 110 | else 111 | log "No server found." 112 | fi 113 | ;; 114 | list) 115 | get $servers_url | maybe_jq 116 | ;; 117 | *) 118 | error "Usage: $(basename $0) [list|ensure|delete]" 119 | esac 120 | -------------------------------------------------------------------------------- /scripts/build/strip_wheel.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Strip symbols inplace from the libraries in a zip archive. 4 | # 5 | # Stripping symbols is beneficial (reduction of 30% of the final package, > 6 | # %90% of the installed libraries. However just running `auditwheel repair 7 | # --strip` breaks some of the libraries included from the system, which fail at 8 | # import with errors such as "ELF load command address/offset not properly 9 | # aligned". 10 | # 11 | # System libraries are already pretty stripped. _psycopg2.so goes around 12 | # 1.6M -> 300K (python 3.8, x86_64) 13 | # 14 | # This script is designed to run on a wheel archive before auditwheel. 15 | 16 | set -euo pipefail 17 | # set -x 18 | 19 | source /etc/os-release 20 | dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 21 | 22 | wheel=$(realpath "$1") 23 | shift 24 | 25 | tmpdir=$(mktemp -d) 26 | trap "rm -r ${tmpdir}" EXIT 27 | 28 | cd "${tmpdir}" 29 | python -m zipfile -e "${wheel}" . 30 | 31 | echo " 32 | Libs before:" 33 | # Busybox doesn't have "find -ls" 34 | find . -name \*.so | xargs ls -l 35 | 36 | # On Debian, print the package versions libraries come from 37 | echo " 38 | Dependencies versions of '_psycopg.so' library:" 39 | "${dir}/print_so_versions.sh" "$(find . -name \*_psycopg\*.so)" 40 | 41 | find . -name \*.so -exec strip "$@" {} \; 42 | 43 | echo " 44 | Libs after:" 45 | find . -name \*.so | xargs ls -l 46 | 47 | python -m zipfile -c ${wheel} * 48 | 49 | cd - 50 | -------------------------------------------------------------------------------- /scripts/build/wheel_linux_before_all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Configure the libraries needed to build wheel packages on linux. 4 | # This script is designed to be used by cibuildwheel as CIBW_BEFORE_ALL_LINUX 5 | 6 | set -euo pipefail 7 | set -x 8 | 9 | dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 10 | prjdir="$( cd "${dir}/../.." && pwd )" 11 | 12 | source /etc/os-release 13 | 14 | # Install PostgreSQL development files. 15 | case "$ID" in 16 | alpine) 17 | "${dir}/build_libpq.sh" > /dev/null 18 | ;; 19 | 20 | debian) 21 | # Note that the pgdg doesn't have an aarch64 repository so wheels are 22 | # build with the libpq packaged with Debian 9, which is 9.6. 23 | if [ "$AUDITWHEEL_ARCH" != 'aarch64' ]; then 24 | echo "deb http://apt.postgresql.org/pub/repos/apt $VERSION_CODENAME-pgdg main" \ 25 | > /etc/apt/sources.list.d/pgdg.list 26 | # TODO: On 2021-11-09 curl fails on 'ppc64le' with: 27 | # curl: (60) SSL certificate problem: certificate has expired 28 | # Test again later if -k can be removed. 29 | curl -skf https://www.postgresql.org/media/keys/ACCC4CF8.asc \ 30 | > /etc/apt/trusted.gpg.d/postgresql.asc 31 | fi 32 | 33 | apt-get update 34 | apt-get -y upgrade 35 | apt-get -y install libpq-dev 36 | ;; 37 | 38 | centos) 39 | "${dir}/build_libpq.sh" > /dev/null 40 | ;; 41 | 42 | *) 43 | echo "$0: unexpected Linux distribution: '$ID'" >&2 44 | exit 1 45 | ;; 46 | esac 47 | 48 | # Replace the package name 49 | if [[ "${PACKAGE_NAME:-}" ]]; then 50 | sed -i "s/^setup(name=\"psycopg2\"/setup(name=\"${PACKAGE_NAME}\"/" \ 51 | "${prjdir}/setup.py" 52 | fi 53 | 54 | -------------------------------------------------------------------------------- /scripts/build/wheel_macos_before_all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Configure the environment needed to build wheel packages on Mac OS. 4 | # This script is designed to be used by cibuildwheel as CIBW_BEFORE_ALL_MACOS 5 | # 6 | # The PG_VERSION env var must be set to a Postgres major version (e.g. 16). 7 | 8 | set -euo pipefail 9 | set -x 10 | 11 | dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 12 | prjdir="$( cd "${dir}/../.." && pwd )" 13 | 14 | # Build dependency libraries 15 | "${prjdir}/scripts/build/build_libpq.sh" 16 | 17 | # Show dependency tree 18 | otool -L /tmp/libpq.build/lib/*.dylib 19 | 20 | brew install gnu-sed postgresql@${PG_VERSION} 21 | brew link --overwrite postgresql@${PG_VERSION} 22 | 23 | # Start the database for testing 24 | brew services start postgresql@${PG_VERSION} 25 | 26 | # Wait for postgres to come up 27 | for i in $(seq 10 -1 0); do 28 | eval pg_isready && break 29 | if [ $i == 0 ]; then 30 | echo "PostgreSQL service not ready, giving up" 31 | exit 1 32 | fi 33 | echo "PostgreSQL service not ready, waiting a bit, attempts left: $i" 34 | sleep 5 35 | done 36 | 37 | # Replace the package name 38 | if [[ "${PACKAGE_NAME:-}" ]]; then 39 | gsed -i "s/^setup(name=\"psycopg2\"/setup(name=\"${PACKAGE_NAME}\"/" \ 40 | "${prjdir}/setup.py" 41 | fi 42 | -------------------------------------------------------------------------------- /scripts/build/wheel_win32_before_build.bat: -------------------------------------------------------------------------------- 1 | @echo on 2 | 3 | pip install delvewheel wheel 4 | 5 | vcpkg install libpq:x64-windows-release 6 | 7 | pipx install .\scripts\build\pg_config_vcpkg_stub\ 8 | -------------------------------------------------------------------------------- /scripts/make_errorcodes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Generate the errorcodes module starting from PostgreSQL documentation. 3 | 4 | The script can be run at a new PostgreSQL release to refresh the module. 5 | """ 6 | 7 | # Copyright (C) 2010-2019 Daniele Varrazzo 8 | # Copyright (C) 2020-2021 The Psycopg Team 9 | # 10 | # psycopg2 is free software: you can redistribute it and/or modify it 11 | # under the terms of the GNU Lesser General Public License as published 12 | # by the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # psycopg2 is distributed in the hope that it will be useful, but WITHOUT 16 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 18 | # License for more details. 19 | 20 | import re 21 | import sys 22 | import time 23 | from urllib.request import urlopen 24 | from collections import defaultdict 25 | 26 | 27 | def main(): 28 | if len(sys.argv) != 2: 29 | print(f"usage: {sys.argv[0]} /path/to/errorcodes.py", file=sys.stderr) 30 | return 2 31 | 32 | filename = sys.argv[1] 33 | 34 | file_start = read_base_file(filename) 35 | # If you add a version to the list fix the docs (in errorcodes.rst) 36 | classes, errors = fetch_errors("11 12 13 14 15 16 17".split()) 37 | 38 | disambiguate(errors) 39 | 40 | f = open(filename, "w") 41 | for line in file_start: 42 | print(line, file=f) 43 | for line in generate_module_data(classes, errors): 44 | print(line, file=f) 45 | 46 | 47 | def read_base_file(filename): 48 | rv = [] 49 | for line in open(filename): 50 | rv.append(line.rstrip("\n")) 51 | if line.startswith("# autogenerated"): 52 | return rv 53 | 54 | raise ValueError("can't find the separator. Is this the right file?") 55 | 56 | 57 | def parse_errors_txt(url): 58 | classes = {} 59 | errors = defaultdict(dict) 60 | 61 | page = urlopen(url) 62 | for line in page: 63 | # Strip comments and skip blanks 64 | line = line.decode("ascii").split('#')[0].strip() 65 | if not line: 66 | continue 67 | 68 | # Parse a section 69 | m = re.match(r"Section: (Class (..) - .+)", line) 70 | if m: 71 | label, class_ = m.groups() 72 | classes[class_] = label 73 | continue 74 | 75 | # Parse an error 76 | m = re.match(r"(.....)\s+(?:E|W|S)\s+ERRCODE_(\S+)(?:\s+(\S+))?$", line) 77 | if m: 78 | errcode, macro, spec = m.groups() 79 | # skip errcodes without specs as they are not publicly visible 80 | if not spec: 81 | continue 82 | errlabel = spec.upper() 83 | errors[class_][errcode] = errlabel 84 | continue 85 | 86 | # We don't expect anything else 87 | raise ValueError(f"unexpected line:\n{line}") 88 | 89 | return classes, errors 90 | 91 | 92 | errors_txt_url = \ 93 | "https://raw.githubusercontent.com/postgres/postgres/refs/heads/%s" \ 94 | "/src/backend/utils/errcodes.txt" 95 | 96 | 97 | def fetch_errors(versions): 98 | classes = {} 99 | errors = defaultdict(dict) 100 | 101 | for version in versions: 102 | print(version, file=sys.stderr) 103 | tver = tuple(map(int, version.split()[0].split('.'))) 104 | tag = f"{tver[0] >= 10 and 'REL_' or 'REL'}{version.replace('.', '_')}_STABLE" 105 | c1, e1 = parse_errors_txt(errors_txt_url % tag) 106 | classes.update(c1) 107 | 108 | # This error was in old server versions but probably never used 109 | # https://github.com/postgres/postgres/commit/12f87b2c82 110 | errors['22']['22020'] = 'INVALID_LIMIT_VALUE' 111 | 112 | for c, cerrs in e1.items(): 113 | errors[c].update(cerrs) 114 | 115 | return classes, errors 116 | 117 | 118 | def disambiguate(errors): 119 | """ 120 | Change name for exception defined more than once. 121 | 122 | Change the first occurrence, because before introdcing the function 123 | they were pretty much lost (see ticket #1133) 124 | """ 125 | # Note: if some code is missing it will be caught downstream 126 | for code in "01004 22004 2F002 2F003 2F004".split(): 127 | errors[code[:2]][code] += "_" 128 | 129 | 130 | def generate_module_data(classes, errors): 131 | yield "" 132 | yield "# Error classes" 133 | for clscode, clslabel in sorted(classes.items()): 134 | err = clslabel.split(" - ")[1].split("(")[0] \ 135 | .strip().replace(" ", "_").replace('/', "_").upper() 136 | yield f"CLASS_{err} = {clscode!r}" 137 | 138 | seen = set() 139 | 140 | for clscode, clslabel in sorted(classes.items()): 141 | yield "" 142 | yield f"# {clslabel}" 143 | 144 | for errcode, errlabel in sorted(errors[clscode].items()): 145 | if errlabel in seen: 146 | raise Exception(f"error label already seen: {errlabel}") 147 | seen.add(errlabel) 148 | yield f"{errlabel} = {errcode!r}" 149 | 150 | 151 | if __name__ == '__main__': 152 | sys.exit(main()) 153 | -------------------------------------------------------------------------------- /scripts/make_errors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Generate the errors module from PostgreSQL source code. 3 | 4 | The script can be run at a new PostgreSQL release to refresh the module. 5 | """ 6 | 7 | # Copyright (C) 2018-2019 Daniele Varrazzo 8 | # Copyright (C) 2020-2021 The Psycopg Team 9 | # 10 | # psycopg2 is free software: you can redistribute it and/or modify it 11 | # under the terms of the GNU Lesser General Public License as published 12 | # by the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # psycopg2 is distributed in the hope that it will be useful, but WITHOUT 16 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 18 | # License for more details. 19 | 20 | import os 21 | import re 22 | import sys 23 | from urllib.request import urlopen 24 | from collections import defaultdict 25 | 26 | 27 | def main(): 28 | filename = os.path.join( 29 | os.path.dirname(__file__), "../psycopg/sqlstate_errors.h") 30 | 31 | # If you add a version to the list fix the docs (in errors.rst) 32 | classes, errors = fetch_errors("11 12 13 14 15 16 17".split()) 33 | 34 | f = open(filename, "w") 35 | print("/*\n * Autogenerated by 'scripts/make_errors.py'.\n */\n", file=f) 36 | for line in generate_module_data(classes, errors): 37 | print(line, file=f) 38 | 39 | 40 | def parse_errors_txt(url): 41 | classes = {} 42 | errors = defaultdict(dict) 43 | 44 | page = urlopen(url) 45 | for line in page: 46 | # Strip comments and skip blanks 47 | line = line.decode('ascii').split('#')[0].strip() 48 | if not line: 49 | continue 50 | 51 | # Parse a section 52 | m = re.match(r"Section: (Class (..) - .+)", line) 53 | if m: 54 | label, class_ = m.groups() 55 | classes[class_] = label 56 | continue 57 | 58 | # Parse an error 59 | m = re.match(r"(.....)\s+(?:E|W|S)\s+ERRCODE_(\S+)(?:\s+(\S+))?$", line) 60 | if m: 61 | errcode, macro, spec = m.groups() 62 | # skip errcodes without specs as they are not publicly visible 63 | if not spec: 64 | continue 65 | errlabel = spec.upper() 66 | errors[class_][errcode] = errlabel 67 | continue 68 | 69 | # We don't expect anything else 70 | raise ValueError(f"unexpected line:\n{line}") 71 | 72 | return classes, errors 73 | 74 | 75 | errors_txt_url = \ 76 | "https://raw.githubusercontent.com/postgres/postgres/refs/heads/%s" \ 77 | "/src/backend/utils/errcodes.txt" 78 | 79 | 80 | def fetch_errors(versions): 81 | classes = {} 82 | errors = defaultdict(dict) 83 | 84 | for version in versions: 85 | print(version, file=sys.stderr) 86 | tver = tuple(map(int, version.split()[0].split('.'))) 87 | tag = f"{tver[0] >= 10 and 'REL_' or 'REL'}{version.replace('.', '_')}_STABLE" 88 | c1, e1 = parse_errors_txt(errors_txt_url % tag) 89 | classes.update(c1) 90 | 91 | for c, cerrs in e1.items(): 92 | errors[c].update(cerrs) 93 | 94 | return classes, errors 95 | 96 | 97 | def generate_module_data(classes, errors): 98 | tmpl = '{"%(errcode)s", "%(cls)s"},' 99 | specific = { 100 | '38002': 'ModifyingSqlDataNotPermittedExt', 101 | '38003': 'ProhibitedSqlStatementAttemptedExt', 102 | '38004': 'ReadingSqlDataNotPermittedExt', 103 | '39004': 'NullValueNotAllowedExt', 104 | 'XX000': 'InternalError_', 105 | } 106 | 107 | seen = set(""" 108 | Error Warning InterfaceError DataError DatabaseError ProgrammingError 109 | IntegrityError InternalError NotSupportedError OperationalError 110 | QueryCanceledError TransactionRollbackError 111 | """.split()) 112 | 113 | for clscode, clslabel in sorted(classes.items()): 114 | if clscode in ('00', '01'): 115 | # success and warning - never raised 116 | continue 117 | 118 | yield f"\n/* {clslabel} */" 119 | 120 | for errcode, errlabel in sorted(errors[clscode].items()): 121 | if errcode in specific: 122 | clsname = specific[errcode] 123 | else: 124 | clsname = errlabel.title().replace('_', '') 125 | if clsname in seen: 126 | raise Exception(f"class already existing: {clsname}") 127 | seen.add(clsname) 128 | 129 | yield tmpl % { 130 | 'cls': clsname, 131 | 'errcode': errcode 132 | } 133 | 134 | 135 | if __name__ == '__main__': 136 | sys.exit(main()) 137 | -------------------------------------------------------------------------------- /scripts/refcounter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Detect reference leaks after several unit test runs. 3 | 4 | The script runs the unit test and counts the objects alive after the run. If 5 | the object count differs between the last two runs, a report is printed and the 6 | script exits with error 1. 7 | """ 8 | 9 | # Copyright (C) 2011-2019 Daniele Varrazzo 10 | # Copyright (C) 2020-2021 The Psycopg Team 11 | # 12 | # psycopg2 is free software: you can redistribute it and/or modify it 13 | # under the terms of the GNU Lesser General Public License as published 14 | # by the Free Software Foundation, either version 3 of the License, or 15 | # (at your option) any later version. 16 | # 17 | # psycopg2 is distributed in the hope that it will be useful, but WITHOUT 18 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 20 | # License for more details. 21 | 22 | import argparse 23 | import gc 24 | import sys 25 | import difflib 26 | import unittest 27 | from pprint import pprint 28 | from collections import defaultdict 29 | 30 | 31 | def main(): 32 | opt = parse_args() 33 | 34 | import tests 35 | test = tests 36 | if opt.suite: 37 | test = getattr(test, opt.suite) 38 | 39 | sys.stdout.write(f"test suite {test.__name__}\n") 40 | 41 | for i in range(1, opt.nruns + 1): 42 | sys.stdout.write(f"test suite run {i} of {opt.nruns}\n") 43 | runner = unittest.TextTestRunner() 44 | runner.run(test.test_suite()) 45 | dump(i, opt) 46 | 47 | f1 = open(f'debug-{(opt.nruns - 1):02}.txt').readlines() 48 | f2 = open(f'debug-{opt.nruns:02}.txt').readlines() 49 | for line in difflib.unified_diff(f1, f2, 50 | f"run {opt.nruns - 1}", f"run {opt.nruns}"): 51 | sys.stdout.write(line) 52 | 53 | rv = f1 != f2 and 1 or 0 54 | 55 | if opt.objs: 56 | f1 = open(f'objs-{(opt.nruns - 1):02}.txt').readlines() 57 | f2 = open(f'objs-{opt.nruns:02}.txt').readlines() 58 | for line in difflib.unified_diff(f1, f2, 59 | f"run {opt.nruns - 1}", f"run {opt.nruns}"): 60 | sys.stdout.write(line) 61 | 62 | return rv 63 | 64 | 65 | def parse_args(): 66 | parser = argparse.ArgumentParser(description=__doc__) 67 | parser.add_argument('--nruns', type=int, metavar="N", default=3, 68 | help="number of test suite runs [default: %(default)d]") 69 | parser.add_argument('--suite', metavar="NAME", 70 | help="the test suite to run (e.g. 'test_cursor'). [default: all]") 71 | parser.add_argument('--objs', metavar="TYPE", 72 | help="in case of leaks, print a report of object TYPE " 73 | "(support still incomplete)") 74 | 75 | return parser.parse_args() 76 | 77 | 78 | def dump(i, opt): 79 | gc.collect() 80 | objs = gc.get_objects() 81 | 82 | c = defaultdict(int) 83 | for o in objs: 84 | c[type(o)] += 1 85 | 86 | pprint( 87 | sorted(((v, str(k)) for k, v in c.items()), reverse=True), 88 | stream=open(f"debug-{i:02}.txt", "w")) 89 | 90 | if opt.objs: 91 | co = [] 92 | t = getattr(__builtins__, opt.objs) 93 | for o in objs: 94 | if type(o) is t: 95 | co.append(o) 96 | 97 | # TODO: very incomplete 98 | if t is dict: 99 | co.sort(key=lambda d: d.items()) 100 | else: 101 | co.sort() 102 | 103 | pprint(co, stream=open(f"objs-{i:02}.txt", "w")) 104 | 105 | 106 | if __name__ == '__main__': 107 | sys.exit(main()) 108 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [build_ext] 2 | # PSYCOPG_DEBUG can be added to enable verbose debug information 3 | define=PSYCOPG_DEBUG 4 | 5 | # "pg_config" is required to locate PostgreSQL headers and libraries needed to 6 | # build psycopg2. If pg_config is not in the path or is installed under a 7 | # different name set the following option to the pg_config full path. 8 | pg_config= 9 | 10 | # For Windows only: 11 | # Set to 1 if the PostgreSQL library was built with OpenSSL. 12 | # Required to link in OpenSSL libraries and dependencies. 13 | have_ssl=0 14 | 15 | # Set to 1 to statically link against the postgresql client library. 16 | static_libpq=0 17 | 18 | # Add here eventual extra libraries required to link the module. 19 | libraries= 20 | 21 | [metadata] 22 | license_files = LICENSE 23 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # psycopg2 test suite 4 | # 5 | # Copyright (C) 2007-2019 Federico Di Gregorio 6 | # Copyright (C) 2020-2021 The Psycopg Team 7 | # 8 | # psycopg2 is free software: you can redistribute it and/or modify it 9 | # under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # In addition, as a special exception, the copyright holders give 14 | # permission to link this program with the OpenSSL library (or with 15 | # modified versions of OpenSSL that use the same license as OpenSSL), 16 | # and distribute linked combinations including the two. 17 | # 18 | # You must obey the GNU Lesser General Public License in all respects for 19 | # all of the code used other than OpenSSL. 20 | # 21 | # psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | # License for more details. 25 | 26 | # Convert warnings into errors here. We can't do it with -W because on 27 | # Travis importing site raises a warning. 28 | import warnings 29 | warnings.simplefilter('error') # noqa 30 | 31 | import sys 32 | from .testconfig import dsn 33 | import unittest 34 | 35 | from . import test_async 36 | from . import test_bugX000 37 | from . import test_bug_gc 38 | from . import test_cancel 39 | from . import test_connection 40 | from . import test_copy 41 | from . import test_cursor 42 | from . import test_dates 43 | from . import test_errcodes 44 | from . import test_errors 45 | from . import test_extras_dictcursor 46 | from . import test_fast_executemany 47 | from . import test_green 48 | from . import test_ipaddress 49 | from . import test_lobject 50 | from . import test_module 51 | from . import test_notify 52 | from . import test_psycopg2_dbapi20 53 | from . import test_quote 54 | from . import test_replication 55 | from . import test_sql 56 | from . import test_transaction 57 | from . import test_types_basic 58 | from . import test_types_extras 59 | from . import test_with 60 | 61 | 62 | def test_suite(): 63 | # If connection to test db fails, bail out early. 64 | import psycopg2 65 | try: 66 | cnn = psycopg2.connect(dsn) 67 | except Exception as e: 68 | print("Failed connection to test db:", e.__class__.__name__, e) 69 | print("Please set env vars 'PSYCOPG2_TESTDB*' to valid values.") 70 | sys.exit(1) 71 | else: 72 | cnn.close() 73 | 74 | suite = unittest.TestSuite() 75 | suite.addTest(test_async.test_suite()) 76 | suite.addTest(test_bugX000.test_suite()) 77 | suite.addTest(test_bug_gc.test_suite()) 78 | suite.addTest(test_cancel.test_suite()) 79 | suite.addTest(test_connection.test_suite()) 80 | suite.addTest(test_copy.test_suite()) 81 | suite.addTest(test_cursor.test_suite()) 82 | suite.addTest(test_dates.test_suite()) 83 | suite.addTest(test_errcodes.test_suite()) 84 | suite.addTest(test_errors.test_suite()) 85 | suite.addTest(test_extras_dictcursor.test_suite()) 86 | suite.addTest(test_fast_executemany.test_suite()) 87 | suite.addTest(test_green.test_suite()) 88 | suite.addTest(test_ipaddress.test_suite()) 89 | suite.addTest(test_lobject.test_suite()) 90 | suite.addTest(test_module.test_suite()) 91 | suite.addTest(test_notify.test_suite()) 92 | suite.addTest(test_psycopg2_dbapi20.test_suite()) 93 | suite.addTest(test_quote.test_suite()) 94 | suite.addTest(test_replication.test_suite()) 95 | suite.addTest(test_sql.test_suite()) 96 | suite.addTest(test_transaction.test_suite()) 97 | suite.addTest(test_types_basic.test_suite()) 98 | suite.addTest(test_types_extras.test_suite()) 99 | suite.addTest(test_with.test_suite()) 100 | return suite 101 | 102 | 103 | if __name__ == '__main__': 104 | unittest.main(defaultTest='test_suite') 105 | -------------------------------------------------------------------------------- /tests/dbapi20_tpc.py: -------------------------------------------------------------------------------- 1 | """ Python DB API 2.0 driver Two Phase Commit compliance test suite. 2 | 3 | """ 4 | 5 | import unittest 6 | 7 | 8 | class TwoPhaseCommitTests(unittest.TestCase): 9 | 10 | driver = None 11 | 12 | def connect(self): 13 | """Make a database connection.""" 14 | raise NotImplementedError 15 | 16 | _last_id = 0 17 | _global_id_prefix = "dbapi20_tpc:" 18 | 19 | def make_xid(self, con): 20 | id = TwoPhaseCommitTests._last_id 21 | TwoPhaseCommitTests._last_id += 1 22 | return con.xid(42, f"{self._global_id_prefix}{id}", "qualifier") 23 | 24 | def test_xid(self): 25 | con = self.connect() 26 | try: 27 | xid = con.xid(42, "global", "bqual") 28 | except self.driver.NotSupportedError: 29 | self.fail("Driver does not support transaction IDs.") 30 | 31 | self.assertEquals(xid[0], 42) 32 | self.assertEquals(xid[1], "global") 33 | self.assertEquals(xid[2], "bqual") 34 | 35 | # Try some extremes for the transaction ID: 36 | xid = con.xid(0, "", "") 37 | self.assertEquals(tuple(xid), (0, "", "")) 38 | xid = con.xid(0x7fffffff, "a" * 64, "b" * 64) 39 | self.assertEquals(tuple(xid), (0x7fffffff, "a" * 64, "b" * 64)) 40 | 41 | def test_tpc_begin(self): 42 | con = self.connect() 43 | try: 44 | xid = self.make_xid(con) 45 | try: 46 | con.tpc_begin(xid) 47 | except self.driver.NotSupportedError: 48 | self.fail("Driver does not support tpc_begin()") 49 | finally: 50 | con.close() 51 | 52 | def test_tpc_commit_without_prepare(self): 53 | con = self.connect() 54 | try: 55 | xid = self.make_xid(con) 56 | con.tpc_begin(xid) 57 | cursor = con.cursor() 58 | cursor.execute("SELECT 1") 59 | con.tpc_commit() 60 | finally: 61 | con.close() 62 | 63 | def test_tpc_rollback_without_prepare(self): 64 | con = self.connect() 65 | try: 66 | xid = self.make_xid(con) 67 | con.tpc_begin(xid) 68 | cursor = con.cursor() 69 | cursor.execute("SELECT 1") 70 | con.tpc_rollback() 71 | finally: 72 | con.close() 73 | 74 | def test_tpc_commit_with_prepare(self): 75 | con = self.connect() 76 | try: 77 | xid = self.make_xid(con) 78 | con.tpc_begin(xid) 79 | cursor = con.cursor() 80 | cursor.execute("SELECT 1") 81 | con.tpc_prepare() 82 | con.tpc_commit() 83 | finally: 84 | con.close() 85 | 86 | def test_tpc_rollback_with_prepare(self): 87 | con = self.connect() 88 | try: 89 | xid = self.make_xid(con) 90 | con.tpc_begin(xid) 91 | cursor = con.cursor() 92 | cursor.execute("SELECT 1") 93 | con.tpc_prepare() 94 | con.tpc_rollback() 95 | finally: 96 | con.close() 97 | 98 | def test_tpc_begin_in_transaction_fails(self): 99 | con = self.connect() 100 | try: 101 | xid = self.make_xid(con) 102 | 103 | cursor = con.cursor() 104 | cursor.execute("SELECT 1") 105 | self.assertRaises(self.driver.ProgrammingError, 106 | con.tpc_begin, xid) 107 | finally: 108 | con.close() 109 | 110 | def test_tpc_begin_in_tpc_transaction_fails(self): 111 | con = self.connect() 112 | try: 113 | xid = self.make_xid(con) 114 | 115 | cursor = con.cursor() 116 | cursor.execute("SELECT 1") 117 | self.assertRaises(self.driver.ProgrammingError, 118 | con.tpc_begin, xid) 119 | finally: 120 | con.close() 121 | 122 | def test_commit_in_tpc_fails(self): 123 | # calling commit() within a TPC transaction fails with 124 | # ProgrammingError. 125 | con = self.connect() 126 | try: 127 | xid = self.make_xid(con) 128 | con.tpc_begin(xid) 129 | 130 | self.assertRaises(self.driver.ProgrammingError, con.commit) 131 | finally: 132 | con.close() 133 | 134 | def test_rollback_in_tpc_fails(self): 135 | # calling rollback() within a TPC transaction fails with 136 | # ProgrammingError. 137 | con = self.connect() 138 | try: 139 | xid = self.make_xid(con) 140 | con.tpc_begin(xid) 141 | 142 | self.assertRaises(self.driver.ProgrammingError, con.rollback) 143 | finally: 144 | con.close() 145 | -------------------------------------------------------------------------------- /tests/test_bugX000.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # bugX000.py - test for DateTime object allocation bug 4 | # 5 | # Copyright (C) 2007-2019 Federico Di Gregorio 6 | # Copyright (C) 2020-2021 The Psycopg Team 7 | # 8 | # psycopg2 is free software: you can redistribute it and/or modify it 9 | # under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # In addition, as a special exception, the copyright holders give 14 | # permission to link this program with the OpenSSL library (or with 15 | # modified versions of OpenSSL that use the same license as OpenSSL), 16 | # and distribute linked combinations including the two. 17 | # 18 | # You must obey the GNU Lesser General Public License in all respects for 19 | # all of the code used other than OpenSSL. 20 | # 21 | # psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | # License for more details. 25 | 26 | import psycopg2 27 | import time 28 | import unittest 29 | 30 | 31 | class DateTimeAllocationBugTestCase(unittest.TestCase): 32 | def test_date_time_allocation_bug(self): 33 | d1 = psycopg2.Date(2002, 12, 25) 34 | d2 = psycopg2.DateFromTicks(time.mktime((2002, 12, 25, 0, 0, 0, 0, 0, 0))) 35 | t1 = psycopg2.Time(13, 45, 30) 36 | t2 = psycopg2.TimeFromTicks(time.mktime((2001, 1, 1, 13, 45, 30, 0, 0, 0))) 37 | t1 = psycopg2.Timestamp(2002, 12, 25, 13, 45, 30) 38 | t2 = psycopg2.TimestampFromTicks( 39 | time.mktime((2002, 12, 25, 13, 45, 30, 0, 0, 0))) 40 | del d1, d2, t1, t2 41 | 42 | 43 | def test_suite(): 44 | return unittest.TestLoader().loadTestsFromName(__name__) 45 | 46 | 47 | if __name__ == "__main__": 48 | unittest.main() 49 | -------------------------------------------------------------------------------- /tests/test_bug_gc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # bug_gc.py - test for refcounting/GC bug 4 | # 5 | # Copyright (C) 2010-2019 Federico Di Gregorio 6 | # Copyright (C) 2020-2021 The Psycopg Team 7 | # 8 | # psycopg2 is free software: you can redistribute it and/or modify it 9 | # under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # In addition, as a special exception, the copyright holders give 14 | # permission to link this program with the OpenSSL library (or with 15 | # modified versions of OpenSSL that use the same license as OpenSSL), 16 | # and distribute linked combinations including the two. 17 | # 18 | # You must obey the GNU Lesser General Public License in all respects for 19 | # all of the code used other than OpenSSL. 20 | # 21 | # psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | # License for more details. 25 | 26 | import psycopg2 27 | import psycopg2.extensions 28 | import unittest 29 | import gc 30 | 31 | from .testutils import ConnectingTestCase, skip_if_no_uuid 32 | 33 | 34 | class StolenReferenceTestCase(ConnectingTestCase): 35 | @skip_if_no_uuid 36 | def test_stolen_reference_bug(self): 37 | def fish(val, cur): 38 | gc.collect() 39 | return 42 40 | UUID = psycopg2.extensions.new_type((2950,), "UUID", fish) 41 | psycopg2.extensions.register_type(UUID, self.conn) 42 | curs = self.conn.cursor() 43 | curs.execute("select 'b5219e01-19ab-4994-b71e-149225dc51e4'::uuid") 44 | curs.fetchone() 45 | 46 | 47 | def test_suite(): 48 | return unittest.TestLoader().loadTestsFromName(__name__) 49 | 50 | 51 | if __name__ == "__main__": 52 | unittest.main() 53 | -------------------------------------------------------------------------------- /tests/test_cancel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # test_cancel.py - unit test for query cancellation 4 | # 5 | # Copyright (C) 2010-2019 Jan Urbański 6 | # Copyright (C) 2020-2021 The Psycopg Team 7 | # 8 | # psycopg2 is free software: you can redistribute it and/or modify it 9 | # under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # In addition, as a special exception, the copyright holders give 14 | # permission to link this program with the OpenSSL library (or with 15 | # modified versions of OpenSSL that use the same license as OpenSSL), 16 | # and distribute linked combinations including the two. 17 | # 18 | # You must obey the GNU Lesser General Public License in all respects for 19 | # all of the code used other than OpenSSL. 20 | # 21 | # psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | # License for more details. 25 | 26 | import time 27 | import threading 28 | 29 | import psycopg2 30 | import psycopg2.extensions 31 | from psycopg2 import extras 32 | 33 | from .testconfig import dsn 34 | import unittest 35 | from .testutils import ConnectingTestCase, skip_before_postgres, slow 36 | from .testutils import skip_if_crdb 37 | 38 | 39 | class CancelTests(ConnectingTestCase): 40 | 41 | def setUp(self): 42 | ConnectingTestCase.setUp(self) 43 | 44 | skip_if_crdb("cancel", self.conn) 45 | 46 | cur = self.conn.cursor() 47 | cur.execute(''' 48 | CREATE TEMPORARY TABLE table1 ( 49 | id int PRIMARY KEY 50 | )''') 51 | self.conn.commit() 52 | 53 | def test_empty_cancel(self): 54 | self.conn.cancel() 55 | 56 | @slow 57 | @skip_before_postgres(8, 2) 58 | def test_cancel(self): 59 | errors = [] 60 | 61 | def neverending(conn): 62 | cur = conn.cursor() 63 | try: 64 | self.assertRaises(psycopg2.extensions.QueryCanceledError, 65 | cur.execute, "select pg_sleep(60)") 66 | # make sure the connection still works 67 | conn.rollback() 68 | cur.execute("select 1") 69 | self.assertEqual(cur.fetchall(), [(1, )]) 70 | except Exception as e: 71 | errors.append(e) 72 | raise 73 | 74 | def canceller(conn): 75 | cur = conn.cursor() 76 | try: 77 | conn.cancel() 78 | except Exception as e: 79 | errors.append(e) 80 | raise 81 | del cur 82 | 83 | thread1 = threading.Thread(target=neverending, args=(self.conn, )) 84 | # wait a bit to make sure that the other thread is already in 85 | # pg_sleep -- ugly and racy, but the chances are ridiculously low 86 | thread2 = threading.Timer(0.3, canceller, args=(self.conn, )) 87 | thread1.start() 88 | thread2.start() 89 | thread1.join() 90 | thread2.join() 91 | 92 | self.assertEqual(errors, []) 93 | 94 | @slow 95 | @skip_before_postgres(8, 2) 96 | def test_async_cancel(self): 97 | async_conn = psycopg2.connect(dsn, async_=True) 98 | self.assertRaises(psycopg2.OperationalError, async_conn.cancel) 99 | extras.wait_select(async_conn) 100 | cur = async_conn.cursor() 101 | cur.execute("select pg_sleep(10)") 102 | time.sleep(1) 103 | self.assertTrue(async_conn.isexecuting()) 104 | async_conn.cancel() 105 | self.assertRaises(psycopg2.extensions.QueryCanceledError, 106 | extras.wait_select, async_conn) 107 | cur.execute("select 1") 108 | extras.wait_select(async_conn) 109 | self.assertEqual(cur.fetchall(), [(1, )]) 110 | 111 | 112 | def test_suite(): 113 | return unittest.TestLoader().loadTestsFromName(__name__) 114 | 115 | 116 | if __name__ == "__main__": 117 | unittest.main() 118 | -------------------------------------------------------------------------------- /tests/test_errcodes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # test_errcodes.py - unit test for psycopg2.errcodes module 4 | # 5 | # Copyright (C) 2015-2019 Daniele Varrazzo 6 | # Copyright (C) 2020-2021 The Psycopg Team 7 | # 8 | # psycopg2 is free software: you can redistribute it and/or modify it 9 | # under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # In addition, as a special exception, the copyright holders give 14 | # permission to link this program with the OpenSSL library (or with 15 | # modified versions of OpenSSL that use the same license as OpenSSL), 16 | # and distribute linked combinations including the two. 17 | # 18 | # You must obey the GNU Lesser General Public License in all respects for 19 | # all of the code used other than OpenSSL. 20 | # 21 | # psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | # License for more details. 25 | 26 | import unittest 27 | from .testutils import ConnectingTestCase, slow, reload 28 | 29 | from threading import Thread 30 | from psycopg2 import errorcodes 31 | 32 | 33 | class ErrocodeTests(ConnectingTestCase): 34 | @slow 35 | def test_lookup_threadsafe(self): 36 | 37 | # Increase if it does not fail with KeyError 38 | MAX_CYCLES = 2000 39 | 40 | errs = [] 41 | 42 | def f(pg_code='40001'): 43 | try: 44 | errorcodes.lookup(pg_code) 45 | except Exception as e: 46 | errs.append(e) 47 | 48 | for __ in range(MAX_CYCLES): 49 | reload(errorcodes) 50 | (t1, t2) = (Thread(target=f), Thread(target=f)) 51 | (t1.start(), t2.start()) 52 | (t1.join(), t2.join()) 53 | 54 | if errs: 55 | self.fail( 56 | "raised {} errors in {} cycles (first is {} {})".format( 57 | len(errs), MAX_CYCLES, 58 | errs[0].__class__.__name__, errs[0])) 59 | 60 | def test_ambiguous_names(self): 61 | self.assertEqual( 62 | errorcodes.lookup('2F004'), "READING_SQL_DATA_NOT_PERMITTED") 63 | self.assertEqual( 64 | errorcodes.lookup('38004'), "READING_SQL_DATA_NOT_PERMITTED") 65 | self.assertEqual(errorcodes.READING_SQL_DATA_NOT_PERMITTED, '38004') 66 | self.assertEqual(errorcodes.READING_SQL_DATA_NOT_PERMITTED_, '2F004') 67 | 68 | 69 | def test_suite(): 70 | return unittest.TestLoader().loadTestsFromName(__name__) 71 | 72 | 73 | if __name__ == "__main__": 74 | unittest.main() 75 | -------------------------------------------------------------------------------- /tests/test_errors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # test_errors.py - unit test for psycopg2.errors module 4 | # 5 | # Copyright (C) 2018-2019 Daniele Varrazzo 6 | # Copyright (C) 2020-2021 The Psycopg Team 7 | # 8 | # psycopg2 is free software: you can redistribute it and/or modify it 9 | # under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # In addition, as a special exception, the copyright holders give 14 | # permission to link this program with the OpenSSL library (or with 15 | # modified versions of OpenSSL that use the same license as OpenSSL), 16 | # and distribute linked combinations including the two. 17 | # 18 | # You must obey the GNU Lesser General Public License in all respects for 19 | # all of the code used other than OpenSSL. 20 | # 21 | # psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | # License for more details. 25 | 26 | import unittest 27 | from .testutils import ConnectingTestCase 28 | 29 | import psycopg2 30 | from psycopg2 import errors 31 | from psycopg2._psycopg import sqlstate_errors 32 | from psycopg2.errors import UndefinedTable 33 | 34 | 35 | class ErrorsTests(ConnectingTestCase): 36 | def test_exception_class(self): 37 | cur = self.conn.cursor() 38 | try: 39 | cur.execute("select * from nonexist") 40 | except psycopg2.Error as exc: 41 | e = exc 42 | 43 | self.assert_(isinstance(e, UndefinedTable), type(e)) 44 | self.assert_(isinstance(e, self.conn.ProgrammingError)) 45 | 46 | def test_exception_class_fallback(self): 47 | cur = self.conn.cursor() 48 | 49 | x = sqlstate_errors.pop('42P01') 50 | try: 51 | cur.execute("select * from nonexist") 52 | except psycopg2.Error as exc: 53 | e = exc 54 | finally: 55 | sqlstate_errors['42P01'] = x 56 | 57 | self.assertEqual(type(e), self.conn.ProgrammingError) 58 | 59 | def test_lookup(self): 60 | self.assertIs(errors.lookup('42P01'), errors.UndefinedTable) 61 | 62 | with self.assertRaises(KeyError): 63 | errors.lookup('XXXXX') 64 | 65 | def test_connection_exceptions_backwards_compatibility(self): 66 | err = errors.lookup('08000') 67 | # connection exceptions are classified as operational errors 68 | self.assert_(issubclass(err, errors.OperationalError)) 69 | # previously these errors were classified only as DatabaseError 70 | self.assert_(issubclass(err, errors.DatabaseError)) 71 | 72 | def test_has_base_exceptions(self): 73 | excs = [] 74 | for n in dir(psycopg2): 75 | obj = getattr(psycopg2, n) 76 | if isinstance(obj, type) and issubclass(obj, Exception): 77 | excs.append(obj) 78 | 79 | self.assert_(len(excs) > 8, str(excs)) 80 | 81 | excs.append(psycopg2.extensions.QueryCanceledError) 82 | excs.append(psycopg2.extensions.TransactionRollbackError) 83 | 84 | for exc in excs: 85 | self.assert_(hasattr(errors, exc.__name__)) 86 | self.assert_(getattr(errors, exc.__name__) is exc) 87 | 88 | 89 | def test_suite(): 90 | return unittest.TestLoader().loadTestsFromName(__name__) 91 | 92 | 93 | if __name__ == "__main__": 94 | unittest.main() 95 | -------------------------------------------------------------------------------- /tests/test_psycopg2_dbapi20.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # test_psycopg2_dbapi20.py - DB API conformance test for psycopg2 4 | # 5 | # Copyright (C) 2006-2019 Federico Di Gregorio 6 | # Copyright (C) 2020-2021 The Psycopg Team 7 | # 8 | # psycopg2 is free software: you can redistribute it and/or modify it 9 | # under the terms of the GNU Lesser General Public License as published 10 | # by the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # In addition, as a special exception, the copyright holders give 14 | # permission to link this program with the OpenSSL library (or with 15 | # modified versions of OpenSSL that use the same license as OpenSSL), 16 | # and distribute linked combinations including the two. 17 | # 18 | # You must obey the GNU Lesser General Public License in all respects for 19 | # all of the code used other than OpenSSL. 20 | # 21 | # psycopg2 is distributed in the hope that it will be useful, but WITHOUT 22 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | # License for more details. 25 | 26 | from . import dbapi20 27 | from . import dbapi20_tpc 28 | from .testutils import skip_if_tpc_disabled 29 | import unittest 30 | import psycopg2 31 | 32 | from .testconfig import dsn 33 | 34 | 35 | class Psycopg2Tests(dbapi20.DatabaseAPI20Test): 36 | driver = psycopg2 37 | connect_args = () 38 | connect_kw_args = {'dsn': dsn} 39 | 40 | lower_func = 'lower' # For stored procedure test 41 | 42 | def test_callproc(self): 43 | # Until DBAPI 2.0 compliance, callproc should return None or it's just 44 | # misleading. Therefore, we will skip the return value test for 45 | # callproc and only perform the fetch test. 46 | # 47 | # For what it's worth, the DBAPI2.0 test_callproc doesn't actually 48 | # test for DBAPI2.0 compliance! It doesn't check for modified OUT and 49 | # IN/OUT parameters in the return values! 50 | con = self._connect() 51 | try: 52 | cur = con.cursor() 53 | if self.lower_func and hasattr(cur, 'callproc'): 54 | cur.callproc(self.lower_func, ('FOO',)) 55 | r = cur.fetchall() 56 | self.assertEqual(len(r), 1, 'callproc produced no result set') 57 | self.assertEqual(len(r[0]), 1, 58 | 'callproc produced invalid result set') 59 | self.assertEqual(r[0][0], 'foo', 60 | 'callproc produced invalid results') 61 | finally: 62 | con.close() 63 | 64 | def test_setoutputsize(self): 65 | # psycopg2's setoutputsize() is a no-op 66 | pass 67 | 68 | def test_nextset(self): 69 | # psycopg2 does not implement nextset() 70 | pass 71 | 72 | 73 | @skip_if_tpc_disabled 74 | class Psycopg2TPCTests(dbapi20_tpc.TwoPhaseCommitTests, unittest.TestCase): 75 | driver = psycopg2 76 | 77 | def connect(self): 78 | return psycopg2.connect(dsn=dsn) 79 | 80 | 81 | def test_suite(): 82 | return unittest.TestLoader().loadTestsFromName(__name__) 83 | 84 | 85 | if __name__ == '__main__': 86 | unittest.main() 87 | -------------------------------------------------------------------------------- /tests/testconfig.py: -------------------------------------------------------------------------------- 1 | # Configure the test suite from the env variables. 2 | 3 | import os 4 | 5 | dbname = os.environ.get('PSYCOPG2_TESTDB', 'psycopg2_test') 6 | dbhost = os.environ.get('PSYCOPG2_TESTDB_HOST', os.environ.get('PGHOST')) 7 | dbport = os.environ.get('PSYCOPG2_TESTDB_PORT', os.environ.get('PGPORT')) 8 | dbuser = os.environ.get('PSYCOPG2_TESTDB_USER', os.environ.get('PGUSER')) 9 | dbpass = os.environ.get('PSYCOPG2_TESTDB_PASSWORD', os.environ.get('PGPASSWORD')) 10 | 11 | # Check if we want to test psycopg's green path. 12 | green = os.environ.get('PSYCOPG2_TEST_GREEN', None) 13 | if green: 14 | if green == '1': 15 | from psycopg2.extras import wait_select as wait_callback 16 | elif green == 'eventlet': 17 | from eventlet.support.psycopg2_patcher import eventlet_wait_callback \ 18 | as wait_callback 19 | else: 20 | raise ValueError("please set 'PSYCOPG2_TEST_GREEN' to a valid value") 21 | 22 | import psycopg2.extensions 23 | psycopg2.extensions.set_wait_callback(wait_callback) 24 | 25 | # Construct a DSN to connect to the test database: 26 | dsn = f'dbname={dbname}' 27 | if dbhost is not None: 28 | dsn += f' host={dbhost}' 29 | if dbport is not None: 30 | dsn += f' port={dbport}' 31 | if dbuser is not None: 32 | dsn += f' user={dbuser}' 33 | if dbpass is not None: 34 | dsn += f' password={dbpass}' 35 | 36 | # Don't run replication tests if REPL_DSN is not set, default to normal DSN if 37 | # set to empty string. 38 | repl_dsn = os.environ.get('PSYCOPG2_TEST_REPL_DSN', None) 39 | if repl_dsn == '': 40 | repl_dsn = dsn 41 | 42 | repl_slot = os.environ.get('PSYCOPG2_TEST_REPL_SLOT', 'psycopg2_test_slot') 43 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = {3.8,3.9,3.10,3.11,3.12,3.13} 3 | 4 | [testenv] 5 | commands = make check 6 | whitelist_externals = make 7 | passenv = PG* PSYCOPG2_TEST* 8 | basepython = python{envname} 9 | 10 | [flake8] 11 | max-line-length = 85 12 | ignore = E128, W503, E741 13 | exclude = build, doc, tests/dbapi20.py 14 | --------------------------------------------------------------------------------