【问题标题】:Parameterized Redshift COPY from S3 via redshift-data API通过 redshift-data API 从 S3 参数化 Redshift COPY
【发布时间】:2021-12-21 17:04:54
【问题描述】:

我正在发出COPY 命令以连接到 S3 并将数据加载到 Redshift。我正在尝试使用 Redshift-Data API 来执行此操作,该 API 声明它支持参数化查询。这就是我需要的。然而,即使尝试了最简单的示例,Redshift-Data API 实际上能够发出带有参数的COPY 命令,但它很高兴通过 API 运行其他查询。您可以在您使用的任何客户端中重现以下内容,我通过 cli 在本地进行了测试,但在 Python boto3 客户端(最终我想使用)中得到了相同的结果。

最小的可重现示例

在 S3 中有一个文件:

echo 'id,foo,is_test
1,foo,true
2,bar,true
3,baz,false' > testfile.csv
aws s3 cp ./testfile.csv s3://mybucket/testfile.csv

尝试通过 CLI(或 Python,随便你)运行复制命令

###
# DOES NOT WORK
export MYFILE='s3://mybucket/testfile.csv'
aws redshift-data execute-statement \
    --database dev \
    --cluster-id redshift-clister-id \
    --secret-arn 'arn:aws:secret....' \
    --region us-east-1 \
    --sql "COPY public.table FROM :s3_uri IAM_ROLE 'my-iam-role' REGION 'us-east-1' IGNOREHEADER 1 CSV;" \
    --parameters "[{\"name\": \"s3_uri\", \"value\": \"${MYFILE}\"}]"

###
# ALSO DOES NOT WORK
export MYFILE="'s3://mybucket/testfile.csv'"
aws redshift-data execute-statement \
    --database dev \
    --cluster-id redshift-clister-id \
    --secret-arn 'arn:aws:secret....' \
    --region us-east-1 \
    --sql "COPY public.table FROM :s3_uri IAM_ROLE 'my-iam-role' REGION 'us-east-1' IGNOREHEADER 1 CSV;" \
    --parameters "[{\"name\": \"s3_uri\", \"value\": \"${MYFILE}\"}]"

###
# WORKS
export MYFILE="'s3://mybucket/testfile.csv'"
aws redshift-data execute-statement \
    --database dev \
    --cluster-id redshift-clister-id \
    --secret-arn 'arn:aws:secret....' \
    --region us-east-1 \
    --sql "SELECT COUNT(*) FROM schema.table WHERE column = :s3_uri;" \
    --parameters "[{\"name\": \"s3_uri\", \"value\": \"${MYFILE}\"}]"

###
# ALSO "WORKS" but not for my use case
aws redshift-data execute-statement \
    --database dev \
    --cluster-id redshift-clister-id \
    --secret-arn 'arn:aws:secret....' \
    --region us-east-1 \
    --sql "COPY public.table FROM 's3://mybucket/testfile.csv' IAM_ROLE 'my-iam-role' REGION 'us-east-1' IGNOREHEADER 1 CSV;" \

结果总是给我一些大意:

"Error": "ERROR: syntax error at or near \"$1\"\n  Position: ##",

它始终指向 S3 URI 变量的开始位置。当我完全删除参数并对值进行硬编码时,COPY 操作成功了。我尝试将参数用单引号括起来,并且还在针对 API 的 SELECT 查询中尝试了完全相同的参数。 SELECT 查询很容易工作,没有麻烦,只是不是 COPY

所以最终我想使用参数来更安全地运行查询,因为我不会提前知道s3_uri。我当然可以将字符串插入到查询中,但那时我有一个我无法控制的 SQL 注入向量(s3 对象名称)。我验证了您可以使用给定的对象名称来利用它,因为 s3 对象名称允许空格和创建注入场景所需的任何字符。

我发现redshift_connector 中存在相同的奇怪行为,其中参数适用于SELECT,但不适用于COPY。任何说明不支持或说明如何执行此操作的文档或示例的链接都很好,我只是找不到它。

【问题讨论】:

    标签: amazon-web-services amazon-s3 amazon-redshift


    【解决方案1】:

    我怀疑您只是缺少传递值中的单引号。试试

    export MYFILE="'s3://mybucket/testfile.csv'"
    

    您的 shell 正在删除示例中的单引号

    【讨论】:

    • 不,先生,正如我在问题中所说,我尝试在 s3 uri 中使用和不使用单引号来执行此操作,但无论哪种方式都没有成功。您是否尝试使用 CLI 完成此操作并取得了成功?
    • 您是否尝试过在您的 shell 中使用“set -x”运行 cli 命令?这有助于理解实际解析的内容。
    • 我有。它是用引号“做正确的事”,正如我也说过,如果你用 SELECT FROM 类型的查询替换 COPY FROM 它可以工作,所以 bash 脚本不是问题。您是否真的尝试过运行它来复制问题?
    • 您是否将带引号的字符串参数传递给您的 SELECT 类型查询?您是否尝试过将 s3 对象硬编码到 --sql 选项(无参数)中的 COPY?我认为您正在使用基于语句类型的 Redshift 的选择性行为是关键的错误树。我可能是错的,但是到目前为止您所展示的内容在不同案例之间发生了太多变化,无法得出结论。
    • 我将发布所有尝试过的事物的排列。我不清楚您是否真的阅读了这篇文章,因为您的所有 cmets 都已在问题本身中得到解决,而您的“解决方案”既不工作也不解决问题。
    猜你喜欢
    • 2021-07-07
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-10
    • 1970-01-01
    相关资源
    最近更新 更多