【问题标题】:Alternative to using dryRun to differentiate a Standard and Legacy SQL query in BigQuery?在 BigQuery 中使用 dryRun 区分标准和旧版 SQL 查询的替代方法?
【发布时间】: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 时存在诸多限制,我想检测哪些查询和视图是使用它编写的,从而允许我相应地调整处理方法。

【问题讨论】:

    标签: google-api google-bigquery bigquery-standard-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 谢谢,我添加了缺少的功能,如果代码中还有其他需要改进的地方,请告诉我
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 2017-10-24
    • 1970-01-01
    相关资源
    最近更新 更多