pypostgresql.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. # postgresql/pypostgresql.py
  2. # Copyright (C) 2005-2022 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: https://www.opensource.org/licenses/mit-license.php
  7. """
  8. .. dialect:: postgresql+pypostgresql
  9. :name: py-postgresql
  10. :dbapi: pypostgresql
  11. :connectstring: postgresql+pypostgresql://user:password@host:port/dbname[?key=value&key=value...]
  12. :url: https://python.projects.pgfoundry.org/
  13. .. note::
  14. The pypostgresql dialect is **not tested as part of SQLAlchemy's continuous
  15. integration** and may have unresolved issues. The recommended PostgreSQL
  16. driver is psycopg2.
  17. .. deprecated:: 1.4 The py-postgresql DBAPI is deprecated and will be removed
  18. in a future version. This DBAPI is superseded by the external
  19. version available at external-dialect_. Please use the external version or
  20. one of the supported DBAPIs to connect to PostgreSQL.
  21. .. TODO update link
  22. .. _external-dialect: https://github.com/PyGreSQL
  23. """ # noqa
  24. from .base import PGDialect
  25. from .base import PGExecutionContext
  26. from ... import processors
  27. from ... import types as sqltypes
  28. from ... import util
  29. class PGNumeric(sqltypes.Numeric):
  30. def bind_processor(self, dialect):
  31. return processors.to_str
  32. def result_processor(self, dialect, coltype):
  33. if self.asdecimal:
  34. return None
  35. else:
  36. return processors.to_float
  37. class PGExecutionContext_pypostgresql(PGExecutionContext):
  38. pass
  39. class PGDialect_pypostgresql(PGDialect):
  40. driver = "pypostgresql"
  41. supports_statement_cache = True
  42. supports_unicode_statements = True
  43. supports_unicode_binds = True
  44. description_encoding = None
  45. default_paramstyle = "pyformat"
  46. # requires trunk version to support sane rowcounts
  47. # TODO: use dbapi version information to set this flag appropriately
  48. supports_sane_rowcount = True
  49. supports_sane_multi_rowcount = False
  50. execution_ctx_cls = PGExecutionContext_pypostgresql
  51. colspecs = util.update_copy(
  52. PGDialect.colspecs,
  53. {
  54. sqltypes.Numeric: PGNumeric,
  55. # prevents PGNumeric from being used
  56. sqltypes.Float: sqltypes.Float,
  57. },
  58. )
  59. @classmethod
  60. def dbapi(cls):
  61. from postgresql.driver import dbapi20
  62. # TODO update link
  63. util.warn_deprecated(
  64. "The py-postgresql DBAPI is deprecated and will be removed "
  65. "in a future version. This DBAPI is superseded by the external"
  66. "version available at https://github.com/PyGreSQL. Please "
  67. "use one of the supported DBAPIs to connect to PostgreSQL.",
  68. version="1.4",
  69. )
  70. return dbapi20
  71. _DBAPI_ERROR_NAMES = [
  72. "Error",
  73. "InterfaceError",
  74. "DatabaseError",
  75. "DataError",
  76. "OperationalError",
  77. "IntegrityError",
  78. "InternalError",
  79. "ProgrammingError",
  80. "NotSupportedError",
  81. ]
  82. @util.memoized_property
  83. def dbapi_exception_translation_map(self):
  84. if self.dbapi is None:
  85. return {}
  86. return dict(
  87. (getattr(self.dbapi, name).__name__, name)
  88. for name in self._DBAPI_ERROR_NAMES
  89. )
  90. def create_connect_args(self, url):
  91. opts = url.translate_connect_args(username="user")
  92. if "port" in opts:
  93. opts["port"] = int(opts["port"])
  94. else:
  95. opts["port"] = 5432
  96. opts.update(url.query)
  97. return ([], opts)
  98. def is_disconnect(self, e, connection, cursor):
  99. return "connection is closed" in str(e)
  100. dialect = PGDialect_pypostgresql