在 BigQuery 中使用 dryRun 区分标准和旧版 SQL 查询的替代方法?
Posted
技术标签:
【中文标题】在 BigQuery 中使用 dryRun 区分标准和旧版 SQL 查询的替代方法?【英文标题】:Alternative to using dryRun to differentiate a Standard and Legacy SQL query in BigQuery? 【发布时间】:2019-03-05 12:04:20 【问题描述】:什么
有谁知道使用 BigQuery API 识别/区分以旧版或标准 SQL 编写的视图或查询的更好方法?
想到的唯一方法是运行 SQL 并将 dryRun
属性设置为 true
(这将产生最小的处理开销)并且如果它失败并显示包含短语“尝试使用标准SQL”我可以假设它是旧版 SQL,否则它可以工作并且是标准的。例如
...
"code": 400,
"message":
"Invalid table name: `my-project.my_dataset.hello_world`
[Try using standard SQL (https://cloud.google.com/bigquery/docs/reference/standard-sql/enabling-standard-sql)]."
原因
我正在维护一个使用 BigQuery API 迁移数据的集成层(用 Cloud Functions - Node.js 8 编写)。
不幸的是,用户社区已被允许在标准或旧版 SQL 中编写视图和查询。由于在处理 Legacy SQL 时存在诸多限制,我想检测哪些查询和视图是使用它编写的,从而允许我相应地调整处理方法。
【问题讨论】:
【参考方案1】:有谁知道使用 BigQuery API 识别/区分以旧版或标准 SQL 编写的视图或查询的更好方法?
您可以尝试使用 javascript 正则表达式来识别 SQL 的类型。
您可以使用以下代码 sn-p 作为基线
isStandardSql(idString)
let isStandard, fullId, partialId, projectId = '';
// This 'if' checks if the provided idString is of type standard and makes sure there is only one ':' in the expression (as in legacy syntax)
const splitted = idString.split(/[:.]/g);
if (splitted.length > 3)
const __ret = this.try2findProjectId(idString, projectId);
idString = __ret.idString;
projectId = __ret.projectId;
if ((idString.match(/:/g)))
// Regex that checks if the format of the id match legacy
let matched = idString.match(/([\[]([^[]|[\[][\]])*[\]])/g);
if (matched && matched[0])
fullId = projectId + matched[0].substring(1, idString.length - 1);
isStandard = false;
else
this.errorMessage("First Regex", idString);
// Same as the first only that here instead of ':' we are looking for '.' and we want to make sure there is more than 1 (as in standard syntax)
else if ((idString.match(/\./g) && idString.match(/\./g).length === 2))
// Regex that checks if the format of the id match standard
let matched = idString.match(/(`([^`]|``)*`)/g);// ? idString.match(/(`([^`]|``)*`)/g) : [idString];
if (matched && matched[0])
fullId = projectId + matched[0].substring(1, idString.length - 1);
isStandard = true
else if(!matched && idString)
fullId = projectId + idString;
isStandard = true;
else
this.errorMessage("Second Regex", idString);
else //projectID.dataset
// In case of id without projectId of proxy "use" project.dataset
if(splitted.length === 2)
fullId = '';
if (idString[0] === '[' && idString[idString.length - 1] === ']')
isStandard = false;
else if (idString[0] === '`' && idString[idString.length - 1] === '`')
isStandard = true;
partialId = idString.replace(/`|\[|\]/g, '')
else
this.errorMessage("Third Regex", idString);
// Return values is flag the determine the type (standard or legacy) and id without staring/ ending chars (``, [])
return
isStandard,
fullId: fullId,
partialId: partialId
;
try2findProjectId(idString, projectId)
let numOfInstances = 0
for (let i = idString.length; i > 0; i--)
const char = idString[i - 1]
if (char === ':' || char === '.')
numOfInstances++
if (numOfInstances === 2)
projectId = idString.substring(1, i - 1)
idString = idString.substring(i - 1, idString.length)
idString = idString[idString.length - 1] === '`' ? '`' + idString : idString
idString = idString[idString.length - 1] === ']' ? '[' + idString : idString
return idString, projectId
【讨论】:
不错!您知道正则表达式的任何警告吗? IE。可能不适合的偷偷摸摸或奇怪的 SQL 示例?只是为了获得风险的大致百分比?或者你会考虑这个完整的覆盖范围吗? 到目前为止对我来说非常好用了几个月,没有任何问题。如果此答案有帮助,请将其标记为其他人关注的解决方案 我已将其标记为答案,但我不得不重新配置一些东西,并且第一个 if 语句“if (splitted.length > 3)”也遇到了问题,因为 if 引用缺少函数“try2findProjectId”。 @FreeZey 谢谢,我添加了缺少的功能,如果代码中还有其他需要改进的地方,请告诉我以上是关于在 BigQuery 中使用 dryRun 区分标准和旧版 SQL 查询的替代方法?的主要内容,如果未能解决你的问题,请参考以下文章
我可以以编程方式检查 google bigquery 查询成本吗?