MicroAd Developers Blog

マイクロアドのエンジニアブログです。インフラ、開発、分析について発信していきます。

Hiveでarray、struct型などをNULLにする方法

f:id:microad-developers:20181018170746p:plain:w200

こんにちは。マイクロアドでサーバーサイドエンジニアをしている大澤です。
今回はApache HiveでComplex型(ARRAY, STRUCT, MAP, UNION)を使用している際に発生した問題と解決方法について紹介します。

問題の内容

Hive上に下記の様なテーブルが存在する場合を想定します。

CREATE TABLE example_table (
    column1 INT,
    column2 STRUCT<field:INT>,
    column3 ARRAY<INT>
);

Primitive型は暗黙にNULLが変換されるので下記の様なクエリでは特に問題は起きません。

INSERT INTO example_table SELECT NULL, NAMED_STRUCT("field", 1), ARRAY(1);

ただ、Complex型は各カラムの定義がテーブル定義と完全に一致する必要があるので下記の様なINSERTは行うことが出来ません。*1

INSERT INTO example_table SELECT 1, NULL, NULL;
Error: Error while compiling statement: FAILED: SemanticException Line 0:-1 Cannot insert into target table because column number/types are different 'example_table': Cannot convert column 1 from void to struct<field:int>. (state=42000,code=40000)

型の一致が求められる場合にはCAST構文を使用すると思いますが、HiveのCASTはPrimitive型にしか対応していないので実行することが出来ません。*2

INSERT INTO example_table SELECT 1, CAST(NULL AS STRUCT<field:INT>), CAST(NULL AS ARRAY<INT>);
Error: Error while compiling statement: FAILED: ParseException line 1:42 cannot recognize input near 'struct' '<' 'field' in primitive type specification (state=42000,code=40000)

問題の解決方法

IF関数を使用するとNULLを該当のComplex型として認識させることができるのでComplex型をNULLにすることができます。*3

INSERT INTO example_table SELECT 1, IF(FALSE, NAMED_STRUCT('field', 1), NULL), IF(FALSE, ARRAY(2), NULL);

参考資料

https://issues.apache.org/jira/browse/HIVE-4022