Repository: aws/aws-sdk-pandas

Issue:
awswrangler.s3.read_parquet_metadata does not support large_string datatype
### Describe the bug

Storing parquet data in S3 which contains the `large_string` datatype, running `awswrangler.s3.read_parquet_metadata(..)` on that file results in error `Unsupported Pyarrow type: large_string`. Haven't tested, but hen also assume in general that reading parquet with the aws-sdk-pandas does not support large_string since it's not a mapped data type.

We did use a quite old version of AWS Wrangler and PyArrow and then this worked. Could it be that PyArrow under the hood has hardened the data types handling and that long_string previously was reported as string type and hence it worked? Not sure. 

Suggested fix is that https://github.com/aws/aws-sdk-pandas/blob/6c0f65b6b63b223bec1059ecd037697b068f7e63/awswrangler/_data_types.py#L41C8-L41C8 supports mapping of large_string to string, pseudo

```python
    if pa.types.is_large_string(dtype):
        return "string"
```
as per https://arrow.apache.org/docs/python/generated/pyarrow.types.is_large_string.html#pyarrow.types.is_large_string

Data type as mentioned by the pyarrow spec: https://arrow.apache.org/docs/python/generated/pyarrow.large_string.html

### How to Reproduce

```python
import awswrangler

# Simple parquet file on S3 with large_string datatype
awswrangler.s3.read_parquet_metadata('s3://<bucket>/path/to/file.parquet')
```


### Expected behavior

Expected behaviour would be that `large_string` is mapped to `string`.

However, this can possibly be questioned since Athena and Glue, due to Hive under the hood, does not support strings of size > 2GB. Still it seems like having support for `large_string` would be good as it can be strings of size < 2GB only.

### Your project

_No response_

### Screenshots

_No response_

### OS

AWS Lambda

### Python version

3.11

### AWS SDK for pandas version

3.5.2 (Lambda Layer arn:aws:lambda:eu-west-1:336392948345:layer:AWSSDKPandas-Python311:7)

### Additional context

_No response_

### Discussed in https://github.com/aws/aws-sdk-pandas/discussions/2392

<div type='discussions-op-text'>

<sup>Originally posted by **rkissell** July 12, 2023</sup>
I am trying to create an Athena table on top of existing parquet files on S3. These files have the pyarrow large_string type for some columns, so when doing a `wr.s3.read_parquet_metadata` I get `awswrangler.exceptions.UnsupportedType: Unsupported Pyarrow type: large_string`.

The pyarrow2athena function only checks for string and not large_string:
https://github.com/aws/aws-sdk-pandas/blob/6c0f65b6b63b223bec1059ecd037697b068f7e63/awswrangler/_data_types.py#L41C8-L41C8

Curious if the pyarrow large_string type could be supported here?

When I create a glue table with `string` as the type for these existing parquet files, Athena queries seem to function normally. I believe the string limit is 2gb in Athena, so not sure it that's motivation for not supporting the type.</div>


Discussion:

Resolving patch:
diff --git a/awswrangler/_data_types.py b/awswrangler/_data_types.py
--- a/awswrangler/_data_types.py
+++ b/awswrangler/_data_types.py
@@ -40,7 +40,7 @@ def pyarrow2athena(  # noqa: PLR0911,PLR0912
         return "double"
     if pa.types.is_boolean(dtype):
         return "boolean"
-    if pa.types.is_string(dtype):
+    if pa.types.is_string(dtype) or pa.types.is_large_string(dtype):
         return "string"
     if pa.types.is_timestamp(dtype):
         return "timestamp"
@@ -87,7 +87,7 @@ def pyarrow2redshift(  # noqa: PLR0911,PLR0912
         return "FLOAT8"
     if pa.types.is_boolean(dtype):
         return "BOOL"
-    if pa.types.is_string(dtype):
+    if pa.types.is_string(dtype) or pa.types.is_large_string(dtype):
         return string_type
     if pa.types.is_timestamp(dtype):
         return "TIMESTAMP"
@@ -132,7 +132,7 @@ def pyarrow2mysql(  # noqa: PLR0911,PLR0912
         return "DOUBLE PRECISION"
     if pa.types.is_boolean(dtype):
         return "BOOLEAN"
-    if pa.types.is_string(dtype):
+    if pa.types.is_string(dtype) or pa.types.is_large_string(dtype):
         return string_type
     if pa.types.is_timestamp(dtype):
         return "TIMESTAMP"
@@ -167,7 +167,7 @@ def pyarrow2oracle(  # noqa: PLR0911
         return "BINARY_DOUBLE"
     if pa.types.is_boolean(dtype):
         return "NUMBER(3)"
-    if pa.types.is_string(dtype):
+    if pa.types.is_string(dtype) or pa.types.is_large_string(dtype):
         return string_type
     if pa.types.is_timestamp(dtype):
         return "TIMESTAMP"
@@ -202,7 +202,7 @@ def pyarrow2postgresql(  # noqa: PLR0911
         return "FLOAT8"
     if pa.types.is_boolean(dtype):
         return "BOOL"
-    if pa.types.is_string(dtype):
+    if pa.types.is_string(dtype) or pa.types.is_large_string(dtype):
         return string_type
     if pa.types.is_timestamp(dtype):
         return "TIMESTAMP"
@@ -237,7 +237,7 @@ def pyarrow2sqlserver(  # noqa: PLR0911
         return "FLOAT"
     if pa.types.is_boolean(dtype):
         return "BIT"
-    if pa.types.is_string(dtype):
+    if pa.types.is_string(dtype) or pa.types.is_large_string(dtype):
         return string_type
     if pa.types.is_timestamp(dtype):
         return "DATETIME2"
@@ -270,7 +270,7 @@ def pyarrow2timestream(dtype: pa.DataType) -> str:  # noqa: PLR0911
         return "DOUBLE"
     if pa.types.is_boolean(dtype):
         return "BOOLEAN"
-    if pa.types.is_string(dtype):
+    if pa.types.is_string(dtype) or pa.types.is_large_string(dtype):
         return "VARCHAR"
     if pa.types.is_date(dtype):
         return "DATE"
@@ -470,7 +470,7 @@ def pyarrow2pandas_extension(  # noqa: PLR0911
         return pd.UInt64Dtype()
     if pa.types.is_boolean(dtype):
         return pd.BooleanDtype()
-    if pa.types.is_string(dtype):
+    if pa.types.is_string(dtype) or pa.types.is_large_string(dtype):
         return pd.StringDtype()
     return None
 


Test patch: