Repository: aws/aws-sdk-pandas

Issue:
Copying to Redshift fails if one of the primary key columns includes a hyphen
### Describe the bug

Copying to Redshift (`awswrangler.redshift.copy`) fails if one of the primary key columns (`primary_keys`) in the table has a hyphen in its name. The `CREATE TABLE` statement will then fail with the following error message:

> ProgrammingError: {'S': 'ERROR', 'C': '42601', 'M': 'syntax error at or near "-"', 'P': '1026', 'F': '/home/ec2-user/padb/src/pg/src/backend/parser/parser_scan.l', 'L': '732', 'R': 'yyerror'}

This is because when creating the SQL Query for this, the column names are not escaped in the `PRIMARY KEY ()` part.

Since this is an easy fix, I'll also open a PR for this myself today.

### How to Reproduce

Create a pandas data frame where one of the columns is e.g. `my-column-name` and then use this column in the `primary_keys` parameter of the `awswrangler.redshift.copy` method.

### Expected behavior

No error and table is written.

### Your project

_No response_

### Screenshots

_No response_

### OS

Linux

### Python version

3.9

### AWS SDK for pandas version

2.17.0

### Additional context

_No response_


Discussion:

Resolving patch:
diff --git a/awswrangler/redshift/_utils.py b/awswrangler/redshift/_utils.py
--- a/awswrangler/redshift/_utils.py
+++ b/awswrangler/redshift/_utils.py
@@ -349,7 +349,9 @@ def _create_table(  # pylint: disable=too-many-locals,too-many-arguments,too-man
         primary_keys=primary_keys,
     )
     cols_str: str = "".join([f'"{k}" {v},\n' for k, v in redshift_types.items()])[:-2]
-    primary_keys_str: str = f",\nPRIMARY KEY ({', '.join(primary_keys)})" if primary_keys else ""
+    primary_keys_str: str = (
+        ",\nPRIMARY KEY ({})".format(", ".join('"' + pk + '"' for pk in primary_keys)) if primary_keys else ""
+    )
     distkey_str: str = f"\nDISTKEY({distkey})" if distkey and diststyle == "KEY" else ""
     sortkey_str: str = f"\n{sortstyle} SORTKEY({','.join(sortkey)})" if sortkey else ""
     sql = (


Test patch:
diff --git a/tests/unit/test_redshift.py b/tests/unit/test_redshift.py
--- a/tests/unit/test_redshift.py
+++ b/tests/unit/test_redshift.py
@@ -17,6 +17,7 @@
 from awswrangler import _utils
 
 from .._utils import (
+    assert_pandas_equals,
     dt,
     ensure_data_types,
     ensure_data_types_category,
@@ -63,6 +64,21 @@ def test_to_sql_simple(redshift_table: str, redshift_con: redshift_connector.Con
     wr.redshift.to_sql(df, redshift_con, redshift_table, "public", "overwrite", overwrite_method, True)
 
 
+def test_to_sql_with_hyphenated_primary_key(
+    redshift_table: str,
+    redshift_con: redshift_connector.Connection,
+) -> None:
+    schema = "public"
+    df = pd.DataFrame({"id-col": [1, 2, 3], "other-col": ["foo", "boo", "bar"]})
+    df["id-col"] = df["id-col"].astype("Int64")
+    df["other-col"] = df["other-col"].astype("string")
+    wr.redshift.to_sql(
+        df=df, con=redshift_con, table=redshift_table, schema=schema, mode="overwrite", primary_keys=["id-col"]
+    )
+    df_out = wr.redshift.read_sql_table(table=redshift_table, con=redshift_con, schema=schema)
+    assert_pandas_equals(df, df_out)
+
+
 def test_empty_table(redshift_table: str, redshift_con: redshift_connector.Connection) -> None:
     with redshift_con.cursor() as cursor:
         cursor.execute(f"CREATE TABLE public.{redshift_table}(c0 integer not null, c1 integer, primary key(c0));")