docker setup

This commit is contained in:
AdrienLSH
2023-11-23 16:43:30 +01:00
parent fd19180e1d
commit f29003c66a
5410 changed files with 869440 additions and 0 deletions

View File

@ -0,0 +1,19 @@
"""
CockroachDB support package.
"""
# Copyright (C) 2022 The Psycopg Team
from . import _types
from .connection import CrdbConnection, AsyncCrdbConnection, CrdbConnectionInfo
adapters = _types.adapters # exposed by the package
connect = CrdbConnection.connect
_types.register_crdb_adapters(adapters)
__all__ = [
"AsyncCrdbConnection",
"CrdbConnection",
"CrdbConnectionInfo",
]

View File

@ -0,0 +1,163 @@
"""
Types configuration specific for CockroachDB.
"""
# Copyright (C) 2022 The Psycopg Team
from enum import Enum
from .._typeinfo import TypeInfo, TypesRegistry
from ..abc import AdaptContext, NoneType
from ..postgres import TEXT_OID
from .._adapters_map import AdaptersMap
from ..types.enum import EnumDumper, EnumBinaryDumper
from ..types.none import NoneDumper
types = TypesRegistry()
# Global adapter maps with PostgreSQL types configuration
adapters = AdaptersMap(types=types)
class CrdbEnumDumper(EnumDumper):
oid = TEXT_OID
class CrdbEnumBinaryDumper(EnumBinaryDumper):
oid = TEXT_OID
class CrdbNoneDumper(NoneDumper):
oid = TEXT_OID
def register_postgres_adapters(context: AdaptContext) -> None:
# Same adapters used by PostgreSQL, or a good starting point for customization
from ..types import array, bool, composite, datetime
from ..types import numeric, string, uuid
array.register_default_adapters(context)
bool.register_default_adapters(context)
composite.register_default_adapters(context)
datetime.register_default_adapters(context)
numeric.register_default_adapters(context)
string.register_default_adapters(context)
uuid.register_default_adapters(context)
def register_crdb_adapters(context: AdaptContext) -> None:
from .. import dbapi20
from ..types import array
register_postgres_adapters(context)
# String must come after enum to map text oid -> string dumper
register_crdb_enum_adapters(context)
register_crdb_string_adapters(context)
register_crdb_json_adapters(context)
register_crdb_net_adapters(context)
register_crdb_none_adapters(context)
dbapi20.register_dbapi20_adapters(adapters)
array.register_all_arrays(adapters)
def register_crdb_string_adapters(context: AdaptContext) -> None:
from ..types import string
# Dump strings with text oid instead of unknown.
# Unlike PostgreSQL, CRDB seems able to cast text to most types.
context.adapters.register_dumper(str, string.StrDumper)
context.adapters.register_dumper(str, string.StrBinaryDumper)
def register_crdb_enum_adapters(context: AdaptContext) -> None:
context.adapters.register_dumper(Enum, CrdbEnumBinaryDumper)
context.adapters.register_dumper(Enum, CrdbEnumDumper)
def register_crdb_json_adapters(context: AdaptContext) -> None:
from ..types import json
adapters = context.adapters
# CRDB doesn't have json/jsonb: both names map to the jsonb oid
adapters.register_dumper(json.Json, json.JsonbBinaryDumper)
adapters.register_dumper(json.Json, json.JsonbDumper)
adapters.register_dumper(json.Jsonb, json.JsonbBinaryDumper)
adapters.register_dumper(json.Jsonb, json.JsonbDumper)
adapters.register_loader("json", json.JsonLoader)
adapters.register_loader("jsonb", json.JsonbLoader)
adapters.register_loader("json", json.JsonBinaryLoader)
adapters.register_loader("jsonb", json.JsonbBinaryLoader)
def register_crdb_net_adapters(context: AdaptContext) -> None:
from ..types import net
adapters = context.adapters
adapters.register_dumper("ipaddress.IPv4Address", net.InterfaceDumper)
adapters.register_dumper("ipaddress.IPv6Address", net.InterfaceDumper)
adapters.register_dumper("ipaddress.IPv4Interface", net.InterfaceDumper)
adapters.register_dumper("ipaddress.IPv6Interface", net.InterfaceDumper)
adapters.register_dumper("ipaddress.IPv4Address", net.AddressBinaryDumper)
adapters.register_dumper("ipaddress.IPv6Address", net.AddressBinaryDumper)
adapters.register_dumper("ipaddress.IPv4Interface", net.InterfaceBinaryDumper)
adapters.register_dumper("ipaddress.IPv6Interface", net.InterfaceBinaryDumper)
adapters.register_dumper(None, net.InetBinaryDumper)
adapters.register_loader("inet", net.InetLoader)
adapters.register_loader("inet", net.InetBinaryLoader)
def register_crdb_none_adapters(context: AdaptContext) -> None:
context.adapters.register_dumper(NoneType, CrdbNoneDumper)
for t in [
TypeInfo("json", 3802, 3807, regtype="jsonb"), # Alias json -> jsonb.
TypeInfo("int8", 20, 1016, regtype="integer"), # Alias integer -> int8
TypeInfo('"char"', 18, 1002), # special case, not generated
# autogenerated: start
# Generated from CockroachDB 22.1.0
TypeInfo("bit", 1560, 1561),
TypeInfo("bool", 16, 1000, regtype="boolean"),
TypeInfo("bpchar", 1042, 1014, regtype="character"),
TypeInfo("bytea", 17, 1001),
TypeInfo("date", 1082, 1182),
TypeInfo("float4", 700, 1021, regtype="real"),
TypeInfo("float8", 701, 1022, regtype="double precision"),
TypeInfo("inet", 869, 1041),
TypeInfo("int2", 21, 1005, regtype="smallint"),
TypeInfo("int2vector", 22, 1006),
TypeInfo("int4", 23, 1007),
TypeInfo("int8", 20, 1016, regtype="bigint"),
TypeInfo("interval", 1186, 1187),
TypeInfo("jsonb", 3802, 3807),
TypeInfo("name", 19, 1003),
TypeInfo("numeric", 1700, 1231),
TypeInfo("oid", 26, 1028),
TypeInfo("oidvector", 30, 1013),
TypeInfo("record", 2249, 2287),
TypeInfo("regclass", 2205, 2210),
TypeInfo("regnamespace", 4089, 4090),
TypeInfo("regproc", 24, 1008),
TypeInfo("regprocedure", 2202, 2207),
TypeInfo("regrole", 4096, 4097),
TypeInfo("regtype", 2206, 2211),
TypeInfo("text", 25, 1009),
TypeInfo("time", 1083, 1183, regtype="time without time zone"),
TypeInfo("timestamp", 1114, 1115, regtype="timestamp without time zone"),
TypeInfo("timestamptz", 1184, 1185, regtype="timestamp with time zone"),
TypeInfo("timetz", 1266, 1270, regtype="time with time zone"),
TypeInfo("unknown", 705, 0),
TypeInfo("uuid", 2950, 2951),
TypeInfo("varbit", 1562, 1563, regtype="bit varying"),
TypeInfo("varchar", 1043, 1015, regtype="character varying"),
# autogenerated: end
]:
types.add(t)

View File

@ -0,0 +1,185 @@
"""
CockroachDB-specific connections.
"""
# Copyright (C) 2022 The Psycopg Team
import re
from typing import Any, Optional, Type, Union, overload, TYPE_CHECKING
from .. import errors as e
from ..abc import AdaptContext
from ..rows import Row, RowFactory, AsyncRowFactory, TupleRow
from ..conninfo import ConnectionInfo
from ..connection import Connection
from .._adapters_map import AdaptersMap
from ..connection_async import AsyncConnection
from ._types import adapters
if TYPE_CHECKING:
from ..pq.abc import PGconn
from ..cursor import Cursor
from ..cursor_async import AsyncCursor
class _CrdbConnectionMixin:
_adapters: Optional[AdaptersMap]
pgconn: "PGconn"
@classmethod
def is_crdb(
cls, conn: Union[Connection[Any], AsyncConnection[Any], "PGconn"]
) -> bool:
"""
Return `!True` if the server connected to `!conn` is CockroachDB.
"""
if isinstance(conn, (Connection, AsyncConnection)):
conn = conn.pgconn
return bool(conn.parameter_status(b"crdb_version"))
@property
def adapters(self) -> AdaptersMap:
if not self._adapters:
# By default, use CockroachDB adapters map
self._adapters = AdaptersMap(adapters)
return self._adapters
@property
def info(self) -> "CrdbConnectionInfo":
return CrdbConnectionInfo(self.pgconn)
def _check_tpc(self) -> None:
if self.is_crdb(self.pgconn):
raise e.NotSupportedError("CockroachDB doesn't support prepared statements")
class CrdbConnection(_CrdbConnectionMixin, Connection[Row]):
"""
Wrapper for a connection to a CockroachDB database.
"""
__module__ = "psycopg.crdb"
# TODO: this method shouldn't require re-definition if the base class
# implements a generic self.
# https://github.com/psycopg/psycopg/issues/308
@overload
@classmethod
def connect(
cls,
conninfo: str = "",
*,
autocommit: bool = False,
row_factory: RowFactory[Row],
prepare_threshold: Optional[int] = 5,
cursor_factory: "Optional[Type[Cursor[Row]]]" = None,
context: Optional[AdaptContext] = None,
**kwargs: Union[None, int, str],
) -> "CrdbConnection[Row]":
...
@overload
@classmethod
def connect(
cls,
conninfo: str = "",
*,
autocommit: bool = False,
prepare_threshold: Optional[int] = 5,
cursor_factory: "Optional[Type[Cursor[Any]]]" = None,
context: Optional[AdaptContext] = None,
**kwargs: Union[None, int, str],
) -> "CrdbConnection[TupleRow]":
...
@classmethod
def connect(cls, conninfo: str = "", **kwargs: Any) -> "CrdbConnection[Any]":
"""
Connect to a database server and return a new `CrdbConnection` instance.
"""
return super().connect(conninfo, **kwargs) # type: ignore[return-value]
class AsyncCrdbConnection(_CrdbConnectionMixin, AsyncConnection[Row]):
"""
Wrapper for an async connection to a CockroachDB database.
"""
__module__ = "psycopg.crdb"
# TODO: this method shouldn't require re-definition if the base class
# implements a generic self.
# https://github.com/psycopg/psycopg/issues/308
@overload
@classmethod
async def connect(
cls,
conninfo: str = "",
*,
autocommit: bool = False,
prepare_threshold: Optional[int] = 5,
row_factory: AsyncRowFactory[Row],
cursor_factory: "Optional[Type[AsyncCursor[Row]]]" = None,
context: Optional[AdaptContext] = None,
**kwargs: Union[None, int, str],
) -> "AsyncCrdbConnection[Row]":
...
@overload
@classmethod
async def connect(
cls,
conninfo: str = "",
*,
autocommit: bool = False,
prepare_threshold: Optional[int] = 5,
cursor_factory: "Optional[Type[AsyncCursor[Any]]]" = None,
context: Optional[AdaptContext] = None,
**kwargs: Union[None, int, str],
) -> "AsyncCrdbConnection[TupleRow]":
...
@classmethod
async def connect(
cls, conninfo: str = "", **kwargs: Any
) -> "AsyncCrdbConnection[Any]":
return await super().connect(conninfo, **kwargs) # type: ignore [no-any-return]
class CrdbConnectionInfo(ConnectionInfo):
"""
`~psycopg.ConnectionInfo` subclass to get info about a CockroachDB database.
"""
__module__ = "psycopg.crdb"
@property
def vendor(self) -> str:
return "CockroachDB"
@property
def server_version(self) -> int:
"""
Return the CockroachDB server version connected.
Return a number in the PostgreSQL format (e.g. 21.2.10 -> 210210).
"""
sver = self.parameter_status("crdb_version")
if not sver:
raise e.InternalError("'crdb_version' parameter status not set")
ver = self.parse_crdb_version(sver)
if ver is None:
raise e.InterfaceError(f"couldn't parse CockroachDB version from: {sver!r}")
return ver
@classmethod
def parse_crdb_version(self, sver: str) -> Optional[int]:
m = re.search(r"\bv(\d+)\.(\d+)\.(\d+)", sver)
if not m:
return None
return int(m.group(1)) * 10000 + int(m.group(2)) * 100 + int(m.group(3))