diff --git a/connectorx-python/connectorx/tests/test_arrow.py b/connectorx-python/connectorx/tests/test_arrow.py index 9a09743617..398a37c0ee 100644 --- a/connectorx-python/connectorx/tests/test_arrow.py +++ b/connectorx-python/connectorx/tests/test_arrow.py @@ -75,7 +75,7 @@ def test_arrow2(postgres_url: str) -> None: def test_arrow2_type(postgres_url: str) -> None: - query = "SELECT test_date, test_timestamp, test_timestamptz, test_int16, test_int64, test_float32, test_numeric, test_bpchar, test_char, test_varchar, test_uuid, test_time, test_bytea, test_json, test_jsonb, test_f4array, test_f8array, test_narray, test_i2array, test_i4array, test_i8array FROM test_types" + query = "SELECT test_date, test_timestamp, test_timestamptz, test_int16, test_int64, test_float32, test_numeric, test_bpchar, test_char, test_varchar, test_uuid, test_time, test_bytea, test_json, test_jsonb, test_f4array, test_f8array, test_narray, test_i2array, test_i4array, test_i8array, test_enum, test_ltree FROM test_types" df = read_sql(postgres_url, query, return_type="arrow2") df = df.to_pandas(date_as_object=False) df.sort_values(by="test_int16", inplace=True, ignore_index=True) @@ -178,6 +178,10 @@ def test_arrow2_type(postgres_url: str) -> None: [[-9223372036854775808, 9223372036854775807], [], [0], None], dtype="object", ), + "test_enum": pd.Series( + ["happy", "very happy", "ecstatic", None], dtype="object" + ), + "test_ltree": pd.Series(["A.B.C.D", "A.B.E", "A", None], dtype="object"), }, ) assert_frame_equal(df, expected, check_names=True) diff --git a/connectorx-python/connectorx/tests/test_postgres.py b/connectorx-python/connectorx/tests/test_postgres.py index eb424a91ce..db5d476883 100644 --- a/connectorx-python/connectorx/tests/test_postgres.py +++ b/connectorx-python/connectorx/tests/test_postgres.py @@ -450,7 +450,7 @@ def test_postgres_with_index_col(postgres_url: str) -> None: def test_postgres_types_binary(postgres_url: str) -> None: - query = "SELECT test_date, test_timestamp, test_timestamptz, test_int16, test_int64, test_float32, test_numeric, test_bpchar, test_char, test_varchar, test_uuid, test_time, test_json, test_jsonb, test_bytea, test_enum, test_f4array, test_f8array, test_narray, test_i2array, test_i4array, test_i8array, test_citext, test_ltree FROM test_types" + query = "SELECT test_date, test_timestamp, test_timestamptz, test_int16, test_int64, test_float32, test_numeric, test_bpchar, test_char, test_varchar, test_uuid, test_time, test_json, test_jsonb, test_bytea, test_enum, test_f4array, test_f8array, test_narray, test_i2array, test_i4array, test_i8array, test_citext, test_ltree, test_lquery, test_ltxtquery FROM test_types" df = read_sql(postgres_url, query) expected = pd.DataFrame( index=range(4), @@ -550,6 +550,8 @@ def test_postgres_types_binary(postgres_url: str) -> None: ), "test_citext": pd.Series(["str_citext", "", "s", None], dtype="object"), "test_ltree": pd.Series(["A.B.C.D", "A.B.E", "A", None], dtype="object"), + "test_lquery": pd.Series(["*.B.*", "A.*", "*", None], dtype="object"), + "test_ltxtquery": pd.Series(["A & B*", "A | B", "A@", None], dtype="object"), }, ) assert_frame_equal(df, expected, check_names=True) diff --git a/connectorx/src/sources/postgres/typesystem.rs b/connectorx/src/sources/postgres/typesystem.rs index e2e27acec0..ac9cc9a383 100644 --- a/connectorx/src/sources/postgres/typesystem.rs +++ b/connectorx/src/sources/postgres/typesystem.rs @@ -83,7 +83,7 @@ impl<'a> From<&'a Type> for PostgresTypeSystem { "_numeric" => NumericArray(true), "bool" => Bool(true), "char" => Char(true), - "text" | "citext" | "ltree" => Text(true), + "text" | "citext" | "ltree" | "lquery" | "ltxtquery" => Text(true), "bpchar" => BpChar(true), "varchar" => VarChar(true), "bytea" => ByteA(true), diff --git a/connectorx/src/transports/postgres_arrow2.rs b/connectorx/src/transports/postgres_arrow2.rs index d27a633403..ee1ce9ed1d 100644 --- a/connectorx/src/transports/postgres_arrow2.rs +++ b/connectorx/src/transports/postgres_arrow2.rs @@ -51,6 +51,7 @@ macro_rules! impl_postgres_transport { { Text[&'r str] => LargeUtf8[String] | conversion owned } { BpChar[&'r str] => LargeUtf8[String] | conversion none } { VarChar[&'r str] => LargeUtf8[String] | conversion none } + { Enum[&'r str] => LargeUtf8[String] | conversion none } { Timestamp[NaiveDateTime] => Date64[NaiveDateTime] | conversion auto } { Date[NaiveDate] => Date32[NaiveDate] | conversion auto } { Time[NaiveTime] => Time64[NaiveTime] | conversion auto } diff --git a/docs/databases/postgres.md b/docs/databases/postgres.md index bed2962f67..a40b07de32 100644 --- a/docs/databases/postgres.md +++ b/docs/databases/postgres.md @@ -41,7 +41,9 @@ cx.read_sql(conn, query) # read data from | JSON | object | | | JSONB | object | | | ENUM | object | need to convert enum column to text manually (`::text`) when using `csv` and `cursor` protocol | -| ltree | object | | +| ltree | object | binary protocol supported only after Postgres version 13 | +| lquery | object | binary protocol supported only after Postgres version 13 | +| ltxtquery | object | binary protocol supported only after Postgres version 13 | | INT2[] | object | list of i64 | | INT4[] | object | list of i64 | | INT8[] | object | list of i64 | diff --git a/scripts/postgres.sql b/scripts/postgres.sql index 0a93386678..7c9698859f 100644 --- a/scripts/postgres.sql +++ b/scripts/postgres.sql @@ -64,13 +64,16 @@ CREATE TABLE IF NOT EXISTS test_types( test_i4array Integer[], test_i8array BIGINT[], test_citext CITEXT, - test_ltree ltree + test_ltree ltree, + test_lquery lquery, + test_ltxtquery ltxtquery ); -INSERT INTO test_types VALUES ('1970-01-01', '1970-01-01 00:00:01', '1970-01-01 00:00:01-00', 0, -9223372036854775808, NULL, NULL, 'a', 'a', NULL, '86b494cc-96b2-11eb-9298-3e22fbb9fe9d', '08:12:40', '1 year 2 months 3 days', '{"customer": "John Doe", "items": {"product": "Beer","qty": 6}}', '{"product": "Beer","qty": 6}', NULL, 'happy','{}', '{}', '{}', '{-1, 0, 1}', '{-1, 0, 1123}', '{-9223372036854775808, 9223372036854775807}', 'str_citext', 'A.B.C.D'); -INSERT INTO test_types VALUES ('2000-02-28', '2000-02-28 12:00:10', '2000-02-28 12:00:10-04', 1, 0, 3.1415926535, 521.34, 'bb', 'b', 'bb', '86b49b84-96b2-11eb-9298-3e22fbb9fe9d', NULL, '2 weeks ago', '{"customer": "Lily Bush", "items": {"product": "Diaper","qty": 24}}', '{"product": "Diaper","qty": 24}', 'Здра́вствуйте', 'very happy', NULL, NULL, NULL, '{}', '{}', '{}', '', 'A.B.E'); -INSERT INTO test_types VALUES ('2038-01-18', '2038-01-18 23:59:59', '2038-01-18 23:59:59+08', 2, 9223372036854775807, 2.71, 999.99, 'ccc', NULL, 'c', '86b49c42-96b2-11eb-9298-3e22fbb9fe9d', '23:00:10', '3 months 2 days ago', '{"customer": "Josh William", "items": {"product": "Toy Car","qty": 1}}', '{"product": "Toy Car","qty": 1}', '', 'ecstatic', '{123.123}', '{-1e-307, 1e308}', '{521.34}', '{-32768, 32767}', '{-2147483648, 2147483647}', '{0}', 's', 'A'); -INSERT INTO test_types VALUES (NULL, NULL, NULL, 3, NULL, 0.00, -1e-37, NULL, 'd', 'defghijklm', NULL, '18:30:00', '3 year', NULL, NULL, '😜', NULL, '{-1e-37, 1e37}', '{0.000234, -12.987654321}', '{0.12, 333.33, 22.22}', NULL, NULL, NULL, NULL, NULL); +INSERT INTO test_types VALUES ('1970-01-01', '1970-01-01 00:00:01', '1970-01-01 00:00:01-00', 0, -9223372036854775808, NULL, NULL, 'a', 'a', NULL, '86b494cc-96b2-11eb-9298-3e22fbb9fe9d', '08:12:40', '1 year 2 months 3 days', '{"customer": "John Doe", "items": {"product": "Beer","qty": 6}}', '{"product": "Beer","qty": 6}', NULL, 'happy','{}', '{}', '{}', '{-1, 0, 1}', '{-1, 0, 1123}', '{-9223372036854775808, 9223372036854775807}', 'str_citext', 'A.B.C.D', '*.B.*', 'A & B*'); +INSERT INTO test_types VALUES ('2000-02-28', '2000-02-28 12:00:10', '2000-02-28 12:00:10-04', 1, 0, 3.1415926535, 521.34, 'bb', 'b', 'bb', '86b49b84-96b2-11eb-9298-3e22fbb9fe9d', NULL, '2 weeks ago', '{"customer": "Lily Bush", "items": {"product": "Diaper","qty": 24}}', '{"product": "Diaper","qty": 24}', 'Здра́вствуйте', 'very happy', NULL, NULL, NULL, '{}', '{}', '{}', '', 'A.B.E', 'A.*', 'A | B'); +INSERT INTO test_types VALUES ('2038-01-18', '2038-01-18 23:59:59', '2038-01-18 23:59:59+08', 2, 9223372036854775807, 2.71, 999.99, 'ccc', NULL, 'c', '86b49c42-96b2-11eb-9298-3e22fbb9fe9d', '23:00:10', '3 months 2 days ago', '{"customer": "Josh William", "items": {"product": "Toy Car","qty": 1}}', '{"product": "Toy Car","qty": 1}', '', 'ecstatic', '{123.123}', '{-1e-307, 1e308}', '{521.34}', '{-32768, 32767}', '{-2147483648, 2147483647}', '{0}', 's', 'A', '*', 'A@'); + +INSERT INTO test_types VALUES (NULL, NULL, NULL, 3, NULL, 0.00, -1e-37, NULL, 'd', 'defghijklm', NULL, '18:30:00', '3 year', NULL, NULL, '😜', NULL, '{-1e-37, 1e37}', '{0.000234, -12.987654321}', '{0.12, 333.33, 22.22}', NULL, NULL, NULL, NULL, NULL, NULL, NULL); CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$ BEGIN