Избегайте обработки неверной кодовой точки в Bigquery - PullRequest
0 голосов
/ 13 сентября 2018

Я использую следующий код SQL для декодирования символов UTF-8 в запросе Big:

#standardSQL
CREATE TEMP FUNCTION DecodeUnicode(s STRING) AS (
  (SELECT CODE_POINTS_TO_STRING(ARRAY_AGG(CAST(CONCAT('0x', x) AS INT64)))
   FROM UNNEST(SPLIT(s, '\\u')) AS x
   WHERE x != '' 
  )
);
WITH normal AS (
select '\\u05DE\\u05EA\\u05DE\\u05D8\\u05D9\\u05E7\\u05D4123' as edited
), uchars AS (
SELECT DISTINCT
c,
DecodeUnicode(c) uchar
FROM normal,
UNNEST(REGEXP_EXTRACT_ALL(edited, r'(\\u[ABCDEF0-9]{4,8})')) c
)
SELECT
 edited,
 STRING_AGG(IFNULL(uchar, x), '' ORDER BY pos) decoded
 FROM(
   SELECT 
   edited, 
   pos,
   SUBSTR(edited, 
   SUM(CASE char WHEN '' THEN 1 ELSE 6 END) 
     OVER(PARTITION BY edited ORDER BY pos) - CASE char WHEN '' THEN 0 ELSE 5 END, 
  CASE char WHEN '' THEN 1 ELSE 6 END) x,
  uchar
  FROM normal ,
  UNNEST(REGEXP_EXTRACT_ALL(edited, r'(\\u[ABCDEF0-9]{4,8})|.')) char WITH 
  OFFSET AS pos  LEFT JOIN uchars u ON u.c = char
 )
GROUP BY edited

Проблема в том, что некоторые значения, которые я обрабатываю, недопустимы при использованиивышеуказанная функция ('DecodeUnicode') - например, эта часть 'u05D4123' недопустима для charbase.Что я могу изменить в своем коде, чтобы при наличии таких значений функция не обрабатывала его, и поэтому я не получу ошибку «Неверный код», которую я получаю сейчас?

1 Ответ

0 голосов
/ 13 сентября 2018

Один из вариантов - использовать SAFE.CODE_POINTS_TO_STRING вместо CODE_POINTS_TO_STRING, но тогда вам все равно придется исключить необработанный код из результата - например, с помощью regexp, как в примере ниже

#standardSQL
CREATE TEMP FUNCTION DecodeUnicode(s STRING) AS (
  (SELECT SAFE.CODE_POINTS_TO_STRING(ARRAY_AGG(CAST(CONCAT('0x', x) AS INT64)))
   FROM UNNEST(SPLIT(s, '\\u')) AS x
   WHERE x != '' 
  )
);
WITH normal AS (
SELECT '\\u05DE\\u05EA\\u05DE\\u05D8\\u05D9\\u05E7\\u05D4123' AS edited
), uchars AS (
SELECT DISTINCT
c,
DecodeUnicode(c) uchar
FROM normal,
UNNEST(REGEXP_EXTRACT_ALL(edited, r'(\\u[ABCDEF0-9]{4,8})')) c
)
SELECT
 edited,
 STRING_AGG(IFNULL(uchar, x), '' ORDER BY pos) decoded, 
 REGEXP_REPLACE(STRING_AGG(IFNULL(uchar, x), '' ORDER BY pos) ,r'\\u[ABCDEF0-9]{4,8}', '') decoded_and_fixed
 FROM(
   SELECT 
   edited, 
   pos,
   SUBSTR(edited, 
   SUM(CASE char WHEN '' THEN 1 ELSE 6 END) 
     OVER(PARTITION BY edited ORDER BY pos) - CASE char WHEN '' THEN 0 ELSE 5 END, 
  CASE char WHEN '' THEN 1 ELSE 6 END) x,
  uchar
  FROM normal ,
  UNNEST(REGEXP_EXTRACT_ALL(edited, r'(\\u[ABCDEF0-9]{4,8})|.')) char WITH 
  OFFSET AS pos  LEFT JOIN uchars u ON u.c = char
 )
GROUP BY edited   

с результатом

Row edited                                          decoded        decoded_and_fixed     
1   \u05DE\u05EA\u05DE\u05D8\u05D9\u05E7\u05D4123   מתמטיק\u05D4    מתמטיק  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...