diff --git a/README-zh.md b/README-zh.md index 23d13b4..7b2f48b 100644 --- a/README-zh.md +++ b/README-zh.md @@ -33,7 +33,7 @@ mvn clean package 如果你想跳过单元测试,可以这样运行: ``` cd ${project_home} -mvn clean package -DskipTests +mvn clean package -DskipTests -Dmaven.javadoc.skip=true ``` 命令执行完成后, 将会在target目录下生成hive-third-functions-${version}-shaded.jar文件. @@ -63,6 +63,7 @@ mvn clean package -DskipTests |pinyin(string) -> string | 将汉字转换为拼音| |md5(string) -> string | md5 哈希| |sha256(string) -> string |sha256 哈希| +|full2half(string) -> string |将全角转换成半角| ### 2. 数组函数 @@ -159,7 +160,8 @@ mvn clean package -DskipTests | 函数| 描述 | |:--|:--| |url_encode(value) -> string | escapes value by encoding it so that it can be safely included in URL query parameter names and values| -|url_decode(value) -> string | unescape the URL encoded value. This function is the inverse of `url_encode`. | +|url_decode(value) -> string | unescape the URL encoded value. This function is the inverse of `url_encode`. | +|standard_url_format(string,string) -> array(varchar) | The normalized url returns the standard url and the 3-level category name| ### 10. 数学函数 @@ -181,85 +183,86 @@ mvn clean package -DskipTests ``` add jar ${jar_location_dir}/hive-third-functions-${version}-shaded.jar -create temporary function array_contains as 'com.github.aaronshan.functions.array.UDFArrayContains'; -create temporary function array_equals as 'com.github.aaronshan.functions.array.UDFArrayEquals'; -create temporary function array_intersect as 'com.github.aaronshan.functions.array.UDFArrayIntersect'; -create temporary function array_max as 'com.github.aaronshan.functions.array.UDFArrayMax'; -create temporary function array_min as 'com.github.aaronshan.functions.array.UDFArrayMin'; -create temporary function array_join as 'com.github.aaronshan.functions.array.UDFArrayJoin'; -create temporary function array_distinct as 'com.github.aaronshan.functions.array.UDFArrayDistinct'; -create temporary function array_position as 'com.github.aaronshan.functions.array.UDFArrayPosition'; -create temporary function array_remove as 'com.github.aaronshan.functions.array.UDFArrayRemove'; -create temporary function array_reverse as 'com.github.aaronshan.functions.array.UDFArrayReverse'; -create temporary function array_sort as 'com.github.aaronshan.functions.array.UDFArraySort'; -create temporary function array_concat as 'com.github.aaronshan.functions.array.UDFArrayConcat'; -create temporary function array_value_count as 'com.github.aaronshan.functions.array.UDFArrayValueCount'; -create temporary function array_slice as 'com.github.aaronshan.functions.array.UDFArraySlice'; -create temporary function array_element_at as 'com.github.aaronshan.functions.array.UDFArrayElementAt'; -create temporary function array_shuffle as 'com.github.aaronshan.functions.array.UDFArrayShuffle'; -create temporary function sequence as 'com.github.aaronshan.functions.array.UDFSequence'; -create temporary function array_value_count as 'com.github.aaronshan.functions.array.UDFArrayValueCount'; -create temporary function bit_count as 'com.github.aaronshan.functions.bitwise.UDFBitCount'; -create temporary function bitwise_and as 'com.github.aaronshan.functions.bitwise.UDFBitwiseAnd'; -create temporary function bitwise_not as 'com.github.aaronshan.functions.bitwise.UDFBitwiseNot'; -create temporary function bitwise_or as 'com.github.aaronshan.functions.bitwise.UDFBitwiseOr'; -create temporary function bitwise_xor as 'com.github.aaronshan.functions.bitwise.UDFBitwiseXor'; -create temporary function map_build as 'com.github.aaronshan.functions.map.UDFMapBuild'; -create temporary function map_concat as 'com.github.aaronshan.functions.map.UDFMapConcat'; -create temporary function map_element_at as 'com.github.aaronshan.functions.map.UDFMapElementAt'; -create temporary function map_equals as 'com.github.aaronshan.functions.map.UDFMapEquals'; -create temporary function day_of_week as 'com.github.aaronshan.functions.date.UDFDayOfWeek'; -create temporary function day_of_year as 'com.github.aaronshan.functions.date.UDFDayOfYear'; -create temporary function type_of_day as 'com.github.aaronshan.functions.date.UDFTypeOfDay'; -create temporary function zodiac_cn as 'com.github.aaronshan.functions.date.UDFZodiacSignCn'; -create temporary function zodiac_en as 'com.github.aaronshan.functions.date.UDFZodiacSignEn'; -create temporary function pinyin as 'com.github.aaronshan.functions.string.UDFChineseToPinYin'; -create temporary function md5 as 'com.github.aaronshan.functions.string.UDFMd5'; -create temporary function sha256 as 'com.github.aaronshan.functions.string.UDFSha256'; -create temporary function codepoint as 'com.github.aaronshan.functions.string.UDFCodePoint'; -create temporary function hamming_distance as 'com.github.aaronshan.functions.string.UDFStringHammingDistance'; -create temporary function levenshtein_distance as 'com.github.aaronshan.functions.string.UDFStringLevenshteinDistance'; -create temporary function normalize as 'com.github.aaronshan.functions.string.UDFStringNormalize'; -create temporary function strpos as 'com.github.aaronshan.functions.string.UDFStringPosition'; -create temporary function split_to_map as 'com.github.aaronshan.functions.string.UDFStringSplitToMap'; -create temporary function split_to_multimap as 'com.github.aaronshan.functions.string.UDFStringSplitToMultimap'; -create temporary function json_array_get as 'com.github.aaronshan.functions.json.UDFJsonArrayGet'; -create temporary function json_array_length as 'com.github.aaronshan.functions.json.UDFJsonArrayLength'; -create temporary function json_array_extract as 'com.github.aaronshan.functions.json.UDFJsonArrayExtract'; -create temporary function json_array_extract_scalar as 'com.github.aaronshan.functions.json.UDFJsonArrayExtractScalar'; -create temporary function json_extract as 'com.github.aaronshan.functions.json.UDFJsonExtract'; -create temporary function json_extract_scalar as 'com.github.aaronshan.functions.json.UDFJsonExtractScalar'; -create temporary function json_size as 'com.github.aaronshan.functions.json.UDFJsonSize'; -create temporary function id_card_province as 'com.github.aaronshan.functions.card.UDFChinaIdCardProvince'; -create temporary function id_card_city as 'com.github.aaronshan.functions.card.UDFChinaIdCardCity'; -create temporary function id_card_area as 'com.github.aaronshan.functions.card.UDFChinaIdCardArea'; -create temporary function id_card_birthday as 'com.github.aaronshan.functions.card.UDFChinaIdCardBirthday'; -create temporary function id_card_gender as 'com.github.aaronshan.functions.card.UDFChinaIdCardGender'; -create temporary function is_valid_id_card as 'com.github.aaronshan.functions.card.UDFChinaIdCardValid'; -create temporary function id_card_info as 'com.github.aaronshan.functions.card.UDFChinaIdCardInfo'; -create temporary function wgs_distance as 'com.github.aaronshan.functions.geo.UDFGeoWgsDistance'; -create temporary function gcj_to_bd as 'com.github.aaronshan.functions.geo.UDFGeoGcjToBd'; -create temporary function bd_to_gcj as 'com.github.aaronshan.functions.geo.UDFGeoBdToGcj'; -create temporary function wgs_to_gcj as 'com.github.aaronshan.functions.geo.UDFGeoWgsToGcj'; -create temporary function gcj_to_wgs as 'com.github.aaronshan.functions.geo.UDFGeoGcjToWgs'; -create temporary function gcj_extract_wgs as 'com.github.aaronshan.functions.geo.UDFGeoGcjExtractWgs'; -create temporary function url_encode as 'com.github.aaronshan.functions.url.UDFUrlEncode'; -create temporary function url_decode as 'com.github.aaronshan.functions.url.UDFUrlDecode'; -create temporary function infinity as 'com.github.aaronshan.functions.math.UDFMathInfinity'; -create temporary function is_finite as 'com.github.aaronshan.functions.math.UDFMathIsFinite'; -create temporary function is_infinite as 'com.github.aaronshan.functions.math.UDFMathIsInfinite'; -create temporary function nan as 'com.github.aaronshan.functions.math.UDFMathNaN'; -create temporary function is_nan as 'com.github.aaronshan.functions.math.UDFMathIsNaN'; -create temporary function from_base as 'com.github.aaronshan.functions.math.UDFMathFromBase'; -create temporary function to_base as 'com.github.aaronshan.functions.math.UDFMathToBase'; -create temporary function cosine_similarity as 'com.github.aaronshan.functions.math.UDFMathCosineSimilarity'; -create temporary function normal_cdf as 'com.github.aaronshan.functions.math.UDFMathNormalCdf'; -create temporary function inverse_normal_cdf as 'com.github.aaronshan.functions.math.UDFMathInverseNormalCdf'; -create temporary function regexp_extract as 'com.github.aaronshan.functions.regexp.UDFRe2JRegexpExtract'; -create temporary function regexp_extract_all as 'com.github.aaronshan.functions.regexp.UDFRe2JRegexpExtractAll'; -create temporary function regexp_like as 'com.github.aaronshan.functions.regexp.UDFRe2JRegexpLike'; -create temporary function regexp_replace as 'com.github.aaronshan.functions.regexp.UDFRe2JRegexpReplace'; -create temporary function regexp_split as 'com.github.aaronshan.functions.regexp.UDFRe2JRegexpSplit'; +create temporary function array_contains as 'UDFArrayContains'; +create temporary function array_equals as 'UDFArrayEquals'; +create temporary function array_intersect as 'UDFArrayIntersect'; +create temporary function array_max as 'UDFArrayMax'; +create temporary function array_min as 'UDFArrayMin'; +create temporary function array_join as 'UDFArrayJoin'; +create temporary function array_distinct as 'UDFArrayDistinct'; +create temporary function array_position as 'UDFArrayPosition'; +create temporary function array_remove as 'UDFArrayRemove'; +create temporary function array_reverse as 'UDFArrayReverse'; +create temporary function array_sort as 'UDFArraySort'; +create temporary function array_concat as 'UDFArrayConcat'; +create temporary function array_value_count as 'UDFArrayValueCount'; +create temporary function array_slice as 'UDFArraySlice'; +create temporary function array_element_at as 'UDFArrayElementAt'; +create temporary function array_shuffle as 'UDFArrayShuffle'; +create temporary function sequence as 'UDFSequence'; +create temporary function array_value_count as 'UDFArrayValueCount'; +create temporary function bit_count as 'UDFBitCount'; +create temporary function bitwise_and as 'UDFBitwiseAnd'; +create temporary function bitwise_not as 'UDFBitwiseNot'; +create temporary function bitwise_or as 'UDFBitwiseOr'; +create temporary function bitwise_xor as 'UDFBitwiseXor'; +create temporary function map_build as 'UDFMapBuild'; +create temporary function map_concat as 'UDFMapConcat'; +create temporary function map_element_at as 'UDFMapElementAt'; +create temporary function map_equals as 'UDFMapEquals'; +create temporary function day_of_week as 'UDFDayOfWeek'; +create temporary function day_of_year as 'UDFDayOfYear'; +create temporary function type_of_day as 'UDFTypeOfDay'; +create temporary function zodiac_cn as 'UDFZodiacSignCn'; +create temporary function zodiac_en as 'UDFZodiacSignEn'; +create temporary function pinyin as 'UDFChineseToPinYin'; +create temporary function md5 as 'UDFMd5'; +create temporary function sha256 as 'UDFSha256'; +create temporary function codepoint as 'UDFCodePoint'; +create temporary function hamming_distance as 'UDFStringHammingDistance'; +create temporary function levenshtein_distance as 'UDFStringLevenshteinDistance'; +create temporary function normalize as 'UDFStringNormalize'; +create temporary function strpos as 'UDFStringPosition'; +create temporary function split_to_map as 'UDFStringSplitToMap'; +create temporary function split_to_multimap as 'UDFStringSplitToMultimap'; +create temporary function json_array_get as 'UDFJsonArrayGet'; +create temporary function json_array_length as 'UDFJsonArrayLength'; +create temporary function json_array_extract as 'UDFJsonArrayExtract'; +create temporary function json_array_extract_scalar as 'UDFJsonArrayExtractScalar'; +create temporary function json_extract as 'UDFJsonExtract'; +create temporary function json_extract_scalar as 'UDFJsonExtractScalar'; +create temporary function json_size as 'UDFJsonSize'; +create temporary function id_card_province as 'UDFChinaIdCardProvince'; +create temporary function id_card_city as 'UDFChinaIdCardCity'; +create temporary function id_card_area as 'UDFChinaIdCardArea'; +create temporary function id_card_birthday as 'UDFChinaIdCardBirthday'; +create temporary function id_card_gender as 'UDFChinaIdCardGender'; +create temporary function is_valid_id_card as 'UDFChinaIdCardValid'; +create temporary function id_card_info as 'UDFChinaIdCardInfo'; +create temporary function wgs_distance as 'UDFGeoWgsDistance'; +create temporary function gcj_to_bd as 'UDFGeoGcjToBd'; +create temporary function bd_to_gcj as 'UDFGeoBdToGcj'; +create temporary function wgs_to_gcj as 'UDFGeoWgsToGcj'; +create temporary function gcj_to_wgs as 'UDFGeoGcjToWgs'; +create temporary function gcj_extract_wgs as 'UDFGeoGcjExtractWgs'; +create temporary function url_encode as 'UDFUrlEncode'; +create temporary function url_decode as 'UDFUrlDecode'; +create temporary function infinity as 'UDFMathInfinity'; +create temporary function is_finite as 'UDFMathIsFinite'; +create temporary function is_infinite as 'UDFMathIsInfinite'; +create temporary function nan as 'UDFMathNaN'; +create temporary function is_nan as 'UDFMathIsNaN'; +create temporary function from_base as 'UDFMathFromBase'; +create temporary function to_base as 'UDFMathToBase'; +create temporary function cosine_similarity as 'UDFMathCosineSimilarity'; +create temporary function normal_cdf as 'UDFMathNormalCdf'; +create temporary function inverse_normal_cdf as 'UDFMathInverseNormalCdf'; +create temporary function regexp_extract as 'UDFRe2JRegexpExtract'; +create temporary function regexp_extract_all as 'UDFRe2JRegexpExtractAll'; +create temporary function regexp_like as 'UDFRe2JRegexpLike'; +create temporary function regexp_replace as 'UDFRe2JRegexpReplace'; +create temporary function regexp_split as 'UDFRe2JRegexpSplit'; +create temporary function standard_url_format as 'UDFStandardUrlFormat'; ``` 你可以在hive的命令杭中使用下面的语句来查看函数的细节. @@ -361,6 +364,7 @@ select gcj_extract_wgs(39.915, 116.404) => {"lng":116.39775549316407,"lat":39.91 ``` select url_encode('http://shanruifeng.cc/') => http%3A%2F%2Fshanruifeng.cc%2F +select standard_url_format('wap','https://m.chinagoods.com/en/venue?id=14&dsds=d') => ["https://m.chinagoods.com/en/venue/?id=14","营销会场","营销会场","测试-领券中心"] ``` ``` diff --git a/README.md b/README.md index 44f959e..1c9e0b2 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Some useful custom hive udf functions, especial array and json functions. Now, jdo2-api-2.3-ec.jar not available in the maven central repository, so we have to manually install it into our local maven repository. ``` -wget http://www.datanucleus.org/downloads/maven2/javax/jdo/jdo2-api/2.3-ec/jdo2-api-2.3-ec.jar -O ~/jdo2-api-2.3-ec.jar +wget https://repository.mapr.com/nexus/content/groups/mapr-public/releases/javax/jdo/jdo2-api/2.3-ec/jdo2-api-2.3-ec.jar -O ~/jdo2-api-2.3-ec.jar mvn install:install-file -DgroupId=javax.jdo -DartifactId=jdo2-api -Dversion=2.3-ec -Dpackaging=jar -Dfile=~/jdo2-api-2.3-ec.jar ``` @@ -29,13 +29,13 @@ mvn install:install-file -DgroupId=javax.jdo -DartifactId=jdo2-api -Dversion=2.3 ``` cd ${project_home} -mvn clean package +mvn clean package -Ppro ``` If you want to skip unit tests, please run: ``` cd ${project_home} -mvn clean package -DskipTests +mvn clean package -DskipTests -Ppro ``` It will generate hive-third-functions-${version}-shaded.jar in target directory. @@ -179,6 +179,7 @@ Now, I had already release `hive-third-functions` to maven repositories. To add |:--|:--| |url_encode(value) -> string | escapes value by encoding it so that it can be safely included in URL query parameter names and values| |url_decode(value) -> string | unescape the URL encoded value. This function is the inverse of `url_encode`. | +|standard_url_format(string,string) -> array(varchar) | The normalized url returns the standard url and the 3-level category name| ### 10. math functions @@ -204,91 +205,98 @@ Now, I had already release `hive-third-functions` to maven repositories. To add |regexp_replace(string, pattern) -> varchar | Removes every instance of the substring matched by the regular expression pattern from string.| |regexp_replace(string, pattern, replacement) -> varchar | Replaces every instance of the substring matched by the regular expression pattern in string with replacement. | +### 12. parse functions +|parse_user_agent(string) -> array(varchar) | Parses the user agent and returns an ArrayList containing device_family, os_family, os_minor, os_major, user_agent_minor, and user_agent_major.| + ## Use Put these statements into `${HOME}/.hiverc` or exec its on hive cli env. ``` add jar ${jar_location_dir}/hive-third-functions-${version}-shaded.jar -create temporary function array_contains as 'com.github.aaronshan.functions.array.UDFArrayContains'; -create temporary function array_equals as 'com.github.aaronshan.functions.array.UDFArrayEquals'; -create temporary function array_intersect as 'com.github.aaronshan.functions.array.UDFArrayIntersect'; -create temporary function array_max as 'com.github.aaronshan.functions.array.UDFArrayMax'; -create temporary function array_min as 'com.github.aaronshan.functions.array.UDFArrayMin'; -create temporary function array_join as 'com.github.aaronshan.functions.array.UDFArrayJoin'; -create temporary function array_distinct as 'com.github.aaronshan.functions.array.UDFArrayDistinct'; -create temporary function array_position as 'com.github.aaronshan.functions.array.UDFArrayPosition'; -create temporary function array_remove as 'com.github.aaronshan.functions.array.UDFArrayRemove'; -create temporary function array_reverse as 'com.github.aaronshan.functions.array.UDFArrayReverse'; -create temporary function array_sort as 'com.github.aaronshan.functions.array.UDFArraySort'; -create temporary function array_concat as 'com.github.aaronshan.functions.array.UDFArrayConcat'; -create temporary function array_value_count as 'com.github.aaronshan.functions.array.UDFArrayValueCount'; -create temporary function array_slice as 'com.github.aaronshan.functions.array.UDFArraySlice'; -create temporary function array_element_at as 'com.github.aaronshan.functions.array.UDFArrayElementAt'; -create temporary function array_shuffle as 'com.github.aaronshan.functions.array.UDFArrayShuffle'; -create temporary function sequence as 'com.github.aaronshan.functions.array.UDFSequence'; -create temporary function array_value_count as 'com.github.aaronshan.functions.array.UDFArrayValueCount'; -create temporary function bit_count as 'com.github.aaronshan.functions.bitwise.UDFBitCount'; -create temporary function bitwise_and as 'com.github.aaronshan.functions.bitwise.UDFBitwiseAnd'; -create temporary function bitwise_not as 'com.github.aaronshan.functions.bitwise.UDFBitwiseNot'; -create temporary function bitwise_or as 'com.github.aaronshan.functions.bitwise.UDFBitwiseOr'; -create temporary function bitwise_xor as 'com.github.aaronshan.functions.bitwise.UDFBitwiseXor'; -create temporary function map_build as 'com.github.aaronshan.functions.map.UDFMapBuild'; -create temporary function map_concat as 'com.github.aaronshan.functions.map.UDFMapConcat'; -create temporary function map_element_at as 'com.github.aaronshan.functions.map.UDFMapElementAt'; -create temporary function map_equals as 'com.github.aaronshan.functions.map.UDFMapEquals'; -create temporary function day_of_week as 'com.github.aaronshan.functions.date.UDFDayOfWeek'; -create temporary function day_of_year as 'com.github.aaronshan.functions.date.UDFDayOfYear'; -create temporary function type_of_day as 'com.github.aaronshan.functions.date.UDFTypeOfDay'; -create temporary function zodiac_cn as 'com.github.aaronshan.functions.date.UDFZodiacSignCn'; -create temporary function zodiac_en as 'com.github.aaronshan.functions.date.UDFZodiacSignEn'; -create temporary function pinyin as 'com.github.aaronshan.functions.string.UDFChineseToPinYin'; -create temporary function md5 as 'com.github.aaronshan.functions.string.UDFMd5'; -create temporary function sha256 as 'com.github.aaronshan.functions.string.UDFSha256'; -create temporary function codepoint as 'com.github.aaronshan.functions.string.UDFCodePoint'; -create temporary function hamming_distance as 'com.github.aaronshan.functions.string.UDFStringHammingDistance'; -create temporary function levenshtein_distance as 'com.github.aaronshan.functions.string.UDFStringLevenshteinDistance'; -create temporary function normalize as 'com.github.aaronshan.functions.string.UDFStringNormalize'; -create temporary function strpos as 'com.github.aaronshan.functions.string.UDFStringPosition'; -create temporary function split_to_map as 'com.github.aaronshan.functions.string.UDFStringSplitToMap'; -create temporary function split_to_multimap as 'com.github.aaronshan.functions.string.UDFStringSplitToMultimap'; -create temporary function json_array_get as 'com.github.aaronshan.functions.json.UDFJsonArrayGet'; -create temporary function json_array_length as 'com.github.aaronshan.functions.json.UDFJsonArrayLength'; -create temporary function json_array_extract as 'com.github.aaronshan.functions.json.UDFJsonArrayExtract'; -create temporary function json_array_extract_scalar as 'com.github.aaronshan.functions.json.UDFJsonArrayExtractScalar'; -create temporary function json_extract as 'com.github.aaronshan.functions.json.UDFJsonExtract'; -create temporary function json_extract_scalar as 'com.github.aaronshan.functions.json.UDFJsonExtractScalar'; -create temporary function json_size as 'com.github.aaronshan.functions.json.UDFJsonSize'; -create temporary function id_card_province as 'com.github.aaronshan.functions.card.UDFChinaIdCardProvince'; -create temporary function id_card_city as 'com.github.aaronshan.functions.card.UDFChinaIdCardCity'; -create temporary function id_card_area as 'com.github.aaronshan.functions.card.UDFChinaIdCardArea'; -create temporary function id_card_birthday as 'com.github.aaronshan.functions.card.UDFChinaIdCardBirthday'; -create temporary function id_card_gender as 'com.github.aaronshan.functions.card.UDFChinaIdCardGender'; -create temporary function is_valid_id_card as 'com.github.aaronshan.functions.card.UDFChinaIdCardValid'; -create temporary function id_card_info as 'com.github.aaronshan.functions.card.UDFChinaIdCardInfo'; -create temporary function wgs_distance as 'com.github.aaronshan.functions.geo.UDFGeoWgsDistance'; -create temporary function gcj_to_bd as 'com.github.aaronshan.functions.geo.UDFGeoGcjToBd'; -create temporary function bd_to_gcj as 'com.github.aaronshan.functions.geo.UDFGeoBdToGcj'; -create temporary function wgs_to_gcj as 'com.github.aaronshan.functions.geo.UDFGeoWgsToGcj'; -create temporary function gcj_to_wgs as 'com.github.aaronshan.functions.geo.UDFGeoGcjToWgs'; -create temporary function gcj_extract_wgs as 'com.github.aaronshan.functions.geo.UDFGeoGcjExtractWgs'; -create temporary function url_encode as 'com.github.aaronshan.functions.url.UDFUrlEncode'; -create temporary function url_decode as 'com.github.aaronshan.functions.url.UDFUrlDecode'; -create temporary function infinity as 'com.github.aaronshan.functions.math.UDFMathInfinity'; -create temporary function is_finite as 'com.github.aaronshan.functions.math.UDFMathIsFinite'; -create temporary function is_infinite as 'com.github.aaronshan.functions.math.UDFMathIsInfinite'; -create temporary function nan as 'com.github.aaronshan.functions.math.UDFMathNaN'; -create temporary function is_nan as 'com.github.aaronshan.functions.math.UDFMathIsNaN'; -create temporary function from_base as 'com.github.aaronshan.functions.math.UDFMathFromBase'; -create temporary function to_base as 'com.github.aaronshan.functions.math.UDFMathToBase'; -create temporary function cosine_similarity as 'com.github.aaronshan.functions.math.UDFMathCosineSimilarity'; -create temporary function normal_cdf as 'com.github.aaronshan.functions.math.UDFMathNormalCdf'; -create temporary function inverse_normal_cdf as 'com.github.aaronshan.functions.math.UDFMathInverseNormalCdf'; -create temporary function regexp_extract as 'com.github.aaronshan.functions.regexp.UDFRe2JRegexpExtract'; -create temporary function regexp_extract_all as 'com.github.aaronshan.functions.regexp.UDFRe2JRegexpExtractAll'; -create temporary function regexp_like as 'com.github.aaronshan.functions.regexp.UDFRe2JRegexpLike'; -create temporary function regexp_replace as 'com.github.aaronshan.functions.regexp.UDFRe2JRegexpReplace'; -create temporary function regexp_split as 'com.github.aaronshan.functions.regexp.UDFRe2JRegexpSplit'; +create temporary function array_contains as 'UDFArrayContains'; +create temporary function array_equals as 'UDFArrayEquals'; +create temporary function array_intersect as 'UDFArrayIntersect'; +create temporary function array_max as 'UDFArrayMax'; +create temporary function array_min as 'UDFArrayMin'; +create temporary function array_join as 'UDFArrayJoin'; +create temporary function array_distinct as 'UDFArrayDistinct'; +create temporary function array_position as 'UDFArrayPosition'; +create temporary function array_remove as 'UDFArrayRemove'; +create temporary function array_reverse as 'UDFArrayReverse'; +create temporary function array_sort as 'UDFArraySort'; +create temporary function array_concat as 'UDFArrayConcat'; +create temporary function array_value_count as 'UDFArrayValueCount'; +create temporary function array_slice as 'UDFArraySlice'; +create temporary function array_element_at as 'UDFArrayElementAt'; +create temporary function array_shuffle as 'UDFArrayShuffle'; +create temporary function sequence as 'UDFSequence'; +create temporary function array_value_count as 'UDFArrayValueCount'; +create temporary function bit_count as 'UDFBitCount'; +create temporary function bitwise_and as 'UDFBitwiseAnd'; +create temporary function bitwise_not as 'UDFBitwiseNot'; +create temporary function bitwise_or as 'UDFBitwiseOr'; +create temporary function bitwise_xor as 'UDFBitwiseXor'; +create temporary function map_build as 'UDFMapBuild'; +create temporary function map_concat as 'UDFMapConcat'; +create temporary function map_element_at as 'UDFMapElementAt'; +create temporary function map_equals as 'UDFMapEquals'; +create temporary function day_of_week as 'UDFDayOfWeek'; +create temporary function day_of_year as 'UDFDayOfYear'; +create temporary function type_of_day as 'UDFTypeOfDay'; +create temporary function zodiac_cn as 'UDFZodiacSignCn'; +create temporary function zodiac_en as 'UDFZodiacSignEn'; +create temporary function pinyin as 'UDFChineseToPinYin'; +create temporary function md5 as 'UDFMd5'; +create temporary function sha256 as 'UDFSha256'; +create temporary function codepoint as 'UDFCodePoint'; +create temporary function hamming_distance as 'UDFStringHammingDistance'; +create temporary function levenshtein_distance as 'UDFStringLevenshteinDistance'; +create temporary function normalize as 'UDFStringNormalize'; +create temporary function strpos as 'UDFStringPosition'; +create temporary function split_to_map as 'UDFStringSplitToMap'; +create temporary function split_to_multimap as 'UDFStringSplitToMultimap'; +create temporary function json_array_get as 'UDFJsonArrayGet'; +create temporary function json_array_length as 'UDFJsonArrayLength'; +create temporary function json_array_extract as 'UDFJsonArrayExtract'; +create temporary function json_array_extract_scalar as 'UDFJsonArrayExtractScalar'; +create temporary function json_extract as 'UDFJsonExtract'; +create temporary function json_extract_scalar as 'UDFJsonExtractScalar'; +create temporary function json_size as 'UDFJsonSize'; +create temporary function id_card_province as 'UDFChinaIdCardProvince'; +create temporary function id_card_city as 'UDFChinaIdCardCity'; +create temporary function id_card_area as 'UDFChinaIdCardArea'; +create temporary function id_card_birthday as 'UDFChinaIdCardBirthday'; +create temporary function id_card_gender as 'UDFChinaIdCardGender'; +create temporary function is_valid_id_card as 'UDFChinaIdCardValid'; +create temporary function id_card_info as 'UDFChinaIdCardInfo'; +create temporary function wgs_distance as 'UDFGeoWgsDistance'; +create temporary function gcj_to_bd as 'UDFGeoGcjToBd'; +create temporary function bd_to_gcj as 'UDFGeoBdToGcj'; +create temporary function wgs_to_gcj as 'UDFGeoWgsToGcj'; +create temporary function gcj_to_wgs as 'UDFGeoGcjToWgs'; +create temporary function gcj_extract_wgs as 'UDFGeoGcjExtractWgs'; +create temporary function url_encode as 'UDFUrlEncode'; +create temporary function url_decode as 'UDFUrlDecode'; +create temporary function infinity as 'UDFMathInfinity'; +create temporary function is_finite as 'UDFMathIsFinite'; +create temporary function is_infinite as 'UDFMathIsInfinite'; +create temporary function nan as 'UDFMathNaN'; +create temporary function is_nan as 'UDFMathIsNaN'; +create temporary function from_base as 'UDFMathFromBase'; +create temporary function to_base as 'UDFMathToBase'; +create temporary function cosine_similarity as 'UDFMathCosineSimilarity'; +create temporary function normal_cdf as 'UDFMathNormalCdf'; +create temporary function inverse_normal_cdf as 'UDFMathInverseNormalCdf'; +create temporary function regexp_extract as 'UDFRe2JRegexpExtract'; +create temporary function regexp_extract_all as 'UDFRe2JRegexpExtractAll'; +create temporary function regexp_like as 'UDFRe2JRegexpLike'; +create temporary function regexp_replace as 'UDFRe2JRegexpReplace'; +create temporary function regexp_split as 'UDFRe2JRegexpSplit'; +create temporary function standard_url_format as 'UDFStandardUrlFormat'; +create temporary function parse_user_agent as 'UDFParseUserAgent'; + + ``` You can use these statements on hive cli env get detail of function. @@ -390,8 +398,13 @@ select gcj_extract_wgs(39.915, 116.404) => {"lng":116.39775549316407,"lat":39.91 ``` select url_encode('http://shanruifeng.cc/') => http%3A%2F%2Fshanruifeng.cc%2F +select standard_url_format('wap','https://m.chinagoods.com/en/venue?id=14&dsds=d') => ["https://m.chinagoods.com/en/venue/?id=14","营销会场","营销会场","测试-领券中心"] ``` ``` select cosine_similarity(map_build(array['a'], array[1.0]), map_build(array['a'], array[2.0])); => 1.0 ``` + +``` +select parse_user_agent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36') => [Mac, Mac OS X, 15, 10, 0, 69] +``` diff --git a/pom.xml b/pom.xml index b7bdf35..ad2a744 100644 --- a/pom.xml +++ b/pom.xml @@ -4,9 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.github.aaronshan + com.chinagoods.bigdata hive-third-functions - 2.2.1 + 2.2.7 hive-third-functions https://github.com/aaronshan/hive-third-functions @@ -27,7 +27,7 @@ UTF-8 - 1.6 + 1.8 UTF-8 UTF-8 @@ -42,6 +42,8 @@ 1.9.3 4.12 1.6 + 1.2.4 + compile @@ -50,12 +52,24 @@ org.apache.hive hive-jdbc ${hive.version} + + + org.slf4j + slf4j-log4j12 + + org.apache.hadoop hadoop-common ${hadoop.version} + + + org.slf4j + slf4j-log4j12 + + @@ -142,6 +156,28 @@ + + + org.lionsoul + ip2region + 1.7.2 + + + + + mysql + mysql-connector-java + 5.1.47 + + + + + + org.springframework.security + spring-security-jwt + 1.0.10.RELEASE + + @@ -149,13 +185,25 @@ org.apache.hive hive-jdbc - provided + ${jar-scope} + + + org.slf4j + slf4j-log4j12 + + org.apache.hadoop hadoop-common - provided + ${jar-scope} + + + org.slf4j + slf4j-log4j12 + + @@ -163,6 +211,13 @@ joda-time + + + javax.jdo + jdo2-api + 2.3-eb + + com.belerweb pinyin4j @@ -218,6 +273,74 @@ junit test + + + org.slf4j + slf4j-api + 1.7.25 + ${jar-scope} + + + org.slf4j + jcl-over-slf4j + 1.7.25 + ${jar-scope} + + + org.slf4j + slf4j-simple + 1.7.25 + ${jar-scope} + + + + + + + + + + + + + + + + org.slf4j + log4j-over-slf4j + 1.7.15 + ${jar-scope} + + + + + org.lionsoul + ip2region + + + + + mysql + mysql-connector-java + + + com.konghq + unirest-java + 3.11.11 + + + + com.github.ua-parser + uap-java + 1.5.0 + compile + + + + org.springframework.security + spring-security-jwt + @@ -226,7 +349,7 @@ org.apache.maven.plugins maven-shade-plugin - 2.4.3 + 3.2.0 package @@ -234,12 +357,42 @@ shade + false + - + org.apache.flink:force-shading + com.google.code.findbugs:jsr305 + org.slf4j:* + log4j:* + + + com.fasterxml.jackson + com.chinagoods.shaded.com.fasterxml.jackson + + true + + + + *:* + + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + @@ -284,7 +437,10 @@ - release + pro + + provided + diff --git a/src/main/java/com/chinagoods/bigdata/functions/array/UDAFSortKeyByValue.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDAFSortKeyByValue.java new file mode 100644 index 0000000..9c49f71 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDAFSortKeyByValue.java @@ -0,0 +1,225 @@ +package com.chinagoods.bigdata.functions.array; + +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.parse.SemanticException; +import org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator; +import org.apache.hadoop.hive.serde2.objectinspector.*; +import org.apache.hadoop.hive.serde2.objectinspector.StructField; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo; + +import java.util.*; + +/** + * @author assistant + * date: 2025-07-25 + * time: 12:00 + */ +@Description(name = "sort_key_by_value" + , value = "_FUNC_(key, value) - Returns an array of keys sorted by their corresponding values in descending order." + , extended = "Example:\n > select _FUNC_(key, value) from table group by group_col;") +public class UDAFSortKeyByValue extends AbstractGenericUDAFResolver { + + @Override + public GenericUDAFEvaluator getEvaluator(TypeInfo[] parameters) throws SemanticException { + if (parameters.length != 2) { + throw new UDFArgumentTypeException(parameters.length - 1, + "Exactly two arguments are expected for sort_key_by_value function."); + } + return new SortKeyByValueEvaluator(); + } + + public static class SortKeyByValueEvaluator extends GenericUDAFEvaluator { + + // Input object inspectors + private PrimitiveObjectInspector keyOI; + private ObjectInspector valueOI; + + // Output object inspector + private ListObjectInspector listOI; + private StandardListObjectInspector internalMergeOI; + + @Override + public ObjectInspector init(Mode m, ObjectInspector[] parameters) throws HiveException { + super.init(m, parameters); + + if (m == Mode.PARTIAL1 || m == Mode.COMPLETE) { + // Original data + keyOI = (PrimitiveObjectInspector) parameters[0]; + valueOI = parameters[1]; + } else { + // Partial aggregation results + internalMergeOI = (StandardListObjectInspector) parameters[0]; + } + + if (m == Mode.PARTIAL1 || m == Mode.PARTIAL2) { + // Partial results: return list of key-value pairs + return ObjectInspectorFactory.getStandardListObjectInspector( + ObjectInspectorFactory.getStandardStructObjectInspector( + Arrays.asList("key", "value"), + Arrays.asList( + PrimitiveObjectInspectorFactory.javaStringObjectInspector, + PrimitiveObjectInspectorFactory.javaStringObjectInspector + ) + ) + ); + } else { + // Final result: return list of keys + return ObjectInspectorFactory.getStandardListObjectInspector( + PrimitiveObjectInspectorFactory.javaStringObjectInspector + ); + } + } + + static class KeyValuePair { + String key; + String value; + + KeyValuePair(String key, String value) { + this.key = key; + this.value = value; + } + } + + static class SortBuffer implements AggregationBuffer { + List keyValuePairs = new ArrayList<>(); + } + + @Override + public AggregationBuffer getNewAggregationBuffer() throws HiveException { + return new SortBuffer(); + } + + @Override + public void reset(AggregationBuffer agg) throws HiveException { + ((SortBuffer) agg).keyValuePairs.clear(); + } + + @Override + public void iterate(AggregationBuffer agg, Object[] parameters) throws HiveException { + if (parameters[0] != null && parameters[1] != null) { + SortBuffer sortBuffer = (SortBuffer) agg; + + String key = keyOI.getPrimitiveJavaObject(parameters[0]).toString(); + + // 获取value的字符串表示,保持原始类型信息 + String value; + if (valueOI instanceof PrimitiveObjectInspector) { + Object valueObj = ((PrimitiveObjectInspector) valueOI).getPrimitiveJavaObject(parameters[1]); + value = valueObj != null ? valueObj.toString() : ""; + } else { + // 处理复杂类型,转换为字符串 + value = parameters[1] != null ? parameters[1].toString() : ""; + } + + sortBuffer.keyValuePairs.add(new KeyValuePair(key, value)); + } + } + + @Override + public Object terminatePartial(AggregationBuffer agg) throws HiveException { + SortBuffer sortBuffer = (SortBuffer) agg; + List result = new ArrayList<>(); + + for (KeyValuePair pair : sortBuffer.keyValuePairs) { + List keyValueList = Arrays.asList(pair.key, pair.value); + result.add(keyValueList); + } + + return result; + } + + @Override + public void merge(AggregationBuffer agg, Object partial) throws HiveException { + if (partial != null) { + SortBuffer sortBuffer = (SortBuffer) agg; + + // 使用ObjectInspector来正确处理partial结果 + if (internalMergeOI != null) { + int listSize = internalMergeOI.getListLength(partial); + ObjectInspector structOI = internalMergeOI.getListElementObjectInspector(); + + if (structOI instanceof StructObjectInspector) { + StructObjectInspector structInspector = (StructObjectInspector) structOI; + List fields = structInspector.getAllStructFieldRefs(); + + if (fields.size() >= 2) { + StructField keyField = fields.get(0); + StructField valueField = fields.get(1); + ObjectInspector keyFieldOI = keyField.getFieldObjectInspector(); + ObjectInspector valueFieldOI = valueField.getFieldObjectInspector(); + + for (int i = 0; i < listSize; i++) { + Object listElement = internalMergeOI.getListElement(partial, i); + if (listElement != null) { + Object keyObj = structInspector.getStructFieldData(listElement, keyField); + Object valueObj = structInspector.getStructFieldData(listElement, valueField); + + if (keyObj != null && valueObj != null) { + String key = ((PrimitiveObjectInspector) keyFieldOI).getPrimitiveJavaObject(keyObj).toString(); + String value = ((PrimitiveObjectInspector) valueFieldOI).getPrimitiveJavaObject(valueObj).toString(); + sortBuffer.keyValuePairs.add(new KeyValuePair(key, value)); + } + } + } + } + } + } + } + } + + + + @Override + public Object terminate(AggregationBuffer agg) throws HiveException { + SortBuffer sortBuffer = (SortBuffer) agg; + + // Check if all values can be parsed as numbers + boolean allNumeric = true; + for (KeyValuePair pair : sortBuffer.keyValuePairs) { + try { + Double.parseDouble(pair.value); + } catch (NumberFormatException e) { + allNumeric = false; + break; + } + } + + // Sort by value using appropriate comparison (降序) + if (allNumeric) { + // All values are numeric, use numeric comparison + sortBuffer.keyValuePairs.sort((a, b) -> { + Double num1 = Double.parseDouble(a.value); + Double num2 = Double.parseDouble(b.value); + int cmp = Double.compare(num2, num1); // 降序:大值在前 + if (cmp == 0) { + // If values are equal, sort by key for consistent results (升序) + return a.key.compareTo(b.key); + } + return cmp; + }); + } else { + // Mixed types, use string comparison + sortBuffer.keyValuePairs.sort((a, b) -> { + int cmp = b.value.compareTo(a.value); // 降序:字符串比较 + if (cmp == 0) { + // If values are equal, sort by key for consistent results (升序) + return a.key.compareTo(b.key); + } + return cmp; + }); + } + + // Extract sorted keys + List sortedKeys = new ArrayList<>(); + for (KeyValuePair pair : sortBuffer.keyValuePairs) { + sortedKeys.add(pair.key); + } + + return sortedKeys; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/chinagoods/bigdata/functions/array/UDFArray2String.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArray2String.java new file mode 100644 index 0000000..9d1a567 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArray2String.java @@ -0,0 +1,114 @@ +package com.chinagoods.bigdata.functions.array; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; +import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ListObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.MapObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector; +import org.apache.hadoop.io.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author xiaowei.song + * date: 2021-10-27 + * time: 15:10 + */ +@Description(name = "array2string", value = "_FUNC_(json) - array数组转换成string. " + , extended = "Example:\n" + + " > SELECT _FUNC_(array) FROM src LIMIT 1;") +public class UDFArray2String extends GenericUDF { + public static final Logger logger = LoggerFactory.getLogger(UDFArray2String.class); + private Text result; + + private static final int ARRAY_IDX = 0; + private static final int ARG_COUNT = 1; // Number of arguments to this UDF + private transient ListObjectInspector arrayOI; + private transient ObjectInspector arrayElementOI; + private transient MapObjectInspector mapObjectInspector; + + public UDFArray2String() { + } + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + // Check if two arguments were passed + if (arguments.length != ARG_COUNT) { + throw new UDFArgumentLengthException( + "The function array_remove(array, value) takes exactly " + ARG_COUNT + " arguments."); + } + + // Check if ARRAY_IDX argument is of category LIST + if (!(arguments[ARRAY_IDX].getCategory().equals(ObjectInspector.Category.LIST))) { + throw new UDFArgumentTypeException(ARRAY_IDX, + "\"" + org.apache.hadoop.hive.serde.serdeConstants.LIST_TYPE_NAME + "\" " + + "expected at function array2string, but " + + "\"" + arguments[ARRAY_IDX].getTypeName() + "\" " + + "is found"); + } + + arrayOI = (ListObjectInspector) arguments[ARRAY_IDX]; + arrayElementOI = arrayOI.getListElementObjectInspector(); + result = new Text(); + return PrimitiveObjectInspectorFactory.writableStringObjectInspector; + } + + @Override + public Object evaluate(DeferredObject[] arguments) throws HiveException { + result.clear(); + Object array = arguments[ARRAY_IDX].get(); + + int arrayLength = arrayOI.getListLength(array); + + // Check if array is null or empty + if (arrayLength <= 0) { + result.set("[]"); + return result; + } + ArrayList resultList = new ArrayList<>(); + StringObjectInspector stringObjectInspector = (StringObjectInspector) arrayOI.getListElementObjectInspector(); + for (int i = 0; i < arrayLength; i++) { + Object arrayElement = arrayOI.getListElement(array, i); + String elementValue = stringObjectInspector.getPrimitiveJavaObject(arrayElement); + logger.info("map对象元素为: {}", elementValue); + resultList.add(elementValue); + } + + // Creating Object of ObjectMapper define in Jakson Api + ObjectMapper ObjMapper = new ObjectMapper(); + try { + String resultStr = ObjMapper.writeValueAsString(resultList); + result.set(resultStr); + } catch (JsonProcessingException e) { + logger.error("解析对象失败,错误为: ", e); + } + return result; + } + + @Override + public String getDisplayString(String[] strings) { + assert (strings.length == ARG_COUNT); + return "array2string(" + strings[ARRAY_IDX] + ")"; + } + + public static void main(String[] args) throws JsonProcessingException { + List ls = new ArrayList<>(); + ls.add("1"); + ObjectMapper ObjMapper = new ObjectMapper(); + String resultStr = ObjMapper.writeValueAsString(ls); + System.out.println(resultStr); + } + +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayCast.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayCast.java new file mode 100644 index 0000000..3b3e85a --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayCast.java @@ -0,0 +1,177 @@ +package com.chinagoods.bigdata.functions.array; + +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ConstantObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ListObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; +import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector; +import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo; +import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author ruifeng.shan + * 2016-07-26 + * 18:03 + * Cast an Array of objects to an Array of a different type + * to avoid Hive UDF casting problems + */ +@Description(name = "array_cast" + , value = "_FUNC_(array, string) - Convert each element in the array to the target type." + , extended = "Example:\n > select _FUNC_(array, string) from src;") +public class UDFArrayCast extends GenericUDF { + private static final Logger LOG = LoggerFactory.getLogger(UDFArrayCast.class); + private ListObjectInspector listInspector; + private PrimitiveObjectInspector fromInspector; + private PrimitiveObjectInspector toInspector; + private String returnElemType; + + + public List evaluate(List uninspArray) { + List newList = new ArrayList(); + for (Object uninsp : uninspArray) { + LOG.info("Uninspected = " + uninsp); + Object stdObject = ObjectInspectorUtils.copyToStandardJavaObject(uninsp, fromInspector); + Object castedObject = coerceObject(stdObject); + newList.add(castedObject); + } + return newList; + } + + private Object coerceObject(Object stdObj) { + LOG.info("Casting " + stdObj + " from " + fromInspector.getPrimitiveCategory() + " to " + toInspector.getPrimitiveCategory() + " of type " + toInspector.getTypeName()); + if (stdObj == null) { + return null; + } + switch (fromInspector.getPrimitiveCategory()) { + case STRING: + String fromStr = (String) stdObj; + switch (toInspector.getPrimitiveCategory()) { + case STRING: + return fromStr; + case BOOLEAN: + if (fromStr.equals("true")) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + case BYTE: + /// XXX TODO + case SHORT: + return Short.parseShort(fromStr); + case INT: + return Integer.parseInt(fromStr); + case LONG: + return Long.parseLong(fromStr); + case FLOAT: + return Float.parseFloat(fromStr); + case DOUBLE: + return Double.parseDouble(fromStr); + case TIMESTAMP: + //// XXX TODO + case VOID: + return null; + + } + return null; + case SHORT: + case INT: + case FLOAT: + case LONG: + case DOUBLE: + Number fromNum = (Number) stdObj; + switch (toInspector.getPrimitiveCategory()) { + case SHORT: + return fromNum.shortValue(); + case INT: + return fromNum.intValue(); + case LONG: + return fromNum.longValue(); + case FLOAT: + return fromNum.floatValue(); + case DOUBLE: + return fromNum.doubleValue(); + case STRING: + return fromNum.toString(); + case TIMESTAMP: + //// XXX TODO + case VOID: + return null; + } + return null; + } + return null; + } + + @Override + public Object evaluate(DeferredObject[] arg0) throws HiveException { + List argList = listInspector.getList(arg0[0].get()); + if (argList == null) { + return null; + } + + return evaluate(argList); + } + + @Override + public String getDisplayString(String[] arg0) { + StringBuilder sb = new StringBuilder("cast_array("); + sb.append(arg0[0]); + if (arg0.length > 1) { + sb.append(" , "); + sb.append(arg0[1]); + } + return sb.toString(); + } + + private static PrimitiveObjectInspector GetObjectInspectorForTypeName(String typeString) { + TypeInfo typeInfo = TypeInfoUtils.getTypeInfoFromTypeString(typeString); + LOG.info("Type for " + typeString + " is " + typeInfo); + + return (PrimitiveObjectInspector) TypeInfoUtils.getStandardJavaObjectInspectorFromTypeInfo(typeInfo); + } + + @Override + public ObjectInspector initialize(ObjectInspector[] arg0) + throws UDFArgumentException { + if (arg0[0].getCategory() != Category.LIST) { + throw new UDFArgumentException("cast_array() takes a list, and an optional type to cast to."); + } + this.listInspector = (ListObjectInspector) arg0[0]; + if (listInspector.getListElementObjectInspector().getCategory() != Category.PRIMITIVE) { + throw new UDFArgumentException("cast_array() only handles arrays of primitives."); + } + this.fromInspector = (PrimitiveObjectInspector) listInspector.getListElementObjectInspector(); + + LOG.info(" Cast Array input type is " + listInspector + " element = " + listInspector.getListElementObjectInspector()); + if (arg0.length > 1) { + if (!(arg0[1] instanceof ConstantObjectInspector) + || !(arg0[1] instanceof StringObjectInspector)) { + throw new UDFArgumentException("cast_array() takes a list, and an optional type to cast to."); + } + ConstantObjectInspector constInsp = (ConstantObjectInspector) arg0[1]; + this.returnElemType = constInsp.getWritableConstantValue().toString(); + this.toInspector = GetObjectInspectorForTypeName(returnElemType); + ObjectInspector returnType = ObjectInspectorFactory.getStandardListObjectInspector(toInspector); + return returnType; + } + + /// Otherwise, assume we're casting to strings ... + this.returnElemType = "string"; + this.toInspector = GetObjectInspectorForTypeName(returnElemType); + ObjectInspector returnType = ObjectInspectorFactory.getStandardListObjectInspector(PrimitiveObjectInspectorFactory.javaStringObjectInspector); + return returnType; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayConcat.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayConcat.java similarity index 99% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayConcat.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayConcat.java index 880f7eb..60cc56c 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayConcat.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayConcat.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; import java.util.ArrayList; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayContains.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayContains.java old mode 100755 new mode 100644 similarity index 98% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayContains.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayContains.java index dd123ea..de7de46 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayContains.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayContains.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayDistinct.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayDistinct.java similarity index 95% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayDistinct.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayDistinct.java index 93c5143..5240762 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayDistinct.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayDistinct.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; -import com.github.aaronshan.functions.fastuitl.ints.IntArrays; +import com.chinagoods.bigdata.functions.fastuitl.ints.IntArrays; import java.util.ArrayList; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; @@ -10,7 +10,7 @@ import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; import org.apache.hadoop.hive.serde2.objectinspector.*; -import static com.github.aaronshan.functions.utils.ArrayUtils.IntArrayCompare; +import static com.chinagoods.bigdata.functions.utils.ArrayUtils.IntArrayCompare; /** * @author ruifeng.shan diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayElementAt.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayElementAt.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayElementAt.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayElementAt.java index ca93b02..a8e95d8 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayElementAt.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayElementAt.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayEquals.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayEquals.java similarity index 97% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayEquals.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayEquals.java index 7a6e5e0..56fc3c0 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayEquals.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayEquals.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; -import com.github.aaronshan.functions.utils.ArrayUtils; +import com.chinagoods.bigdata.functions.utils.ArrayUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayIntersect.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayIntersect.java similarity index 71% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayIntersect.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayIntersect.java index bf269da..eaa9fce 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayIntersect.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayIntersect.java @@ -1,8 +1,7 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; -import com.github.aaronshan.functions.fastuitl.ints.IntArrays; +import com.chinagoods.bigdata.functions.fastuitl.ints.IntArrays; import java.util.ArrayList; -import java.util.Arrays; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; @@ -13,7 +12,7 @@ import org.apache.hadoop.hive.serde2.objectinspector.*; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters.Converter; -import static com.github.aaronshan.functions.utils.ArrayUtils.IntArrayCompare; +import static com.chinagoods.bigdata.functions.utils.ArrayUtils.IntArrayCompare; /** * @author ruifeng.shan @@ -28,10 +27,10 @@ public class UDFArrayIntersect extends GenericUDF { private static final int ARG_COUNT = 2; // Number of arguments to this UDF private int[] leftPositions = new int[INITIAL_SIZE]; private int[] rightPositions = new int[INITIAL_SIZE]; - private transient ListObjectInspector leftArrayOI; - private transient ListObjectInspector rightArrayOI; - private transient ObjectInspector leftArrayElementOI; - private transient ObjectInspector rightArrayElementOI; + private transient ListObjectInspector leftArrayOi; + private transient ListObjectInspector rightArrayOi; + private transient ObjectInspector leftArrayElementOi; + private transient ObjectInspector rightArrayElementOi; private transient ArrayList result = new ArrayList(); private transient Converter converter; @@ -58,32 +57,32 @@ public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumen } } - leftArrayOI = (ListObjectInspector) arguments[0]; - rightArrayOI = (ListObjectInspector) arguments[1]; + leftArrayOi = (ListObjectInspector) arguments[0]; + rightArrayOi = (ListObjectInspector) arguments[1]; - leftArrayElementOI = leftArrayOI.getListElementObjectInspector(); - rightArrayElementOI = rightArrayOI.getListElementObjectInspector(); + leftArrayElementOi = leftArrayOi.getListElementObjectInspector(); + rightArrayElementOi = rightArrayOi.getListElementObjectInspector(); // Check if two array are of same type - if (!ObjectInspectorUtils.compareTypes(leftArrayElementOI, rightArrayElementOI)) { + if (!ObjectInspectorUtils.compareTypes(leftArrayElementOi, rightArrayElementOi)) { throw new UDFArgumentTypeException(1, - "\"" + leftArrayElementOI.getTypeName() + "\"" + "\"" + leftArrayElementOi.getTypeName() + "\"" + " expected at function array_intersect, but " - + "\"" + rightArrayElementOI.getTypeName() + "\"" + + "\"" + rightArrayElementOi.getTypeName() + "\"" + " is found"); } // Check if the comparison is supported for this type - if (!ObjectInspectorUtils.compareSupported(leftArrayElementOI)) { + if (!ObjectInspectorUtils.compareSupported(leftArrayElementOi)) { throw new UDFArgumentException("The function array_intersect" + " does not support comparison for " - + "\"" + leftArrayElementOI.getTypeName() + "\"" + + "\"" + leftArrayElementOi.getTypeName() + "\"" + " types"); } - converter = ObjectInspectorConverters.getConverter(leftArrayElementOI, leftArrayElementOI); + converter = ObjectInspectorConverters.getConverter(leftArrayElementOi, leftArrayElementOi); - return ObjectInspectorFactory.getStandardListObjectInspector(leftArrayElementOI); + return ObjectInspectorFactory.getStandardListObjectInspector(leftArrayElementOi); } @Override @@ -91,8 +90,8 @@ public Object evaluate(DeferredObject[] arguments) throws HiveException { Object leftArray = arguments[0].get(); Object rightArray = arguments[1].get(); - int leftArrayLength = leftArrayOI.getListLength(leftArray); - int rightArrayLength = rightArrayOI.getListLength(rightArray); + int leftArrayLength = leftArrayOi.getListLength(leftArray); + int rightArrayLength = rightArrayOi.getListLength(rightArray); // Check if array is null or empty if (leftArray == null || rightArray == null || leftArrayLength < 0 || rightArrayLength < 0) { @@ -121,34 +120,32 @@ public Object evaluate(DeferredObject[] arguments) throws HiveException { rightPositions[i] = i; } - IntArrays.quickSort(leftPositions, 0, leftArrayLength, IntArrayCompare(leftArray, leftArrayOI)); - IntArrays.quickSort(rightPositions, 0, rightArrayLength, IntArrayCompare(rightArray, rightArrayOI)); + IntArrays.quickSort(leftPositions, 0, leftArrayLength, IntArrayCompare(leftArray, leftArrayOi)); + IntArrays.quickSort(rightPositions, 0, rightArrayLength, IntArrayCompare(rightArray, rightArrayOi)); result.clear(); - int leftCurrentPosition = 0; - int rightCurrentPosition = 0; - int leftBasePosition; - int rightBasePosition; + int leftCurrentPosition = 0, rightCurrentPosition = 0; + int leftBasePosition = 0, rightBasePosition = 0; while (leftCurrentPosition < leftArrayLength && rightCurrentPosition < rightArrayLength) { leftBasePosition = leftCurrentPosition; rightBasePosition = rightCurrentPosition; - Object leftArrayElement = leftArrayOI.getListElement(leftArray, leftPositions[leftCurrentPosition]); - Object rightArrayElement = rightArrayOI.getListElement(rightArray, rightPositions[rightCurrentPosition]); - int compareValue = ObjectInspectorUtils.compare(leftArrayElement, leftArrayElementOI, rightArrayElement, rightArrayElementOI); + Object leftArrayElement = leftArrayOi.getListElement(leftArray, leftPositions[leftCurrentPosition]); + Object rightArrayElement = rightArrayOi.getListElement(rightArray, rightPositions[rightCurrentPosition]); + int compareValue = ObjectInspectorUtils.compare(leftArrayElement, leftArrayElementOi, rightArrayElement, rightArrayElementOi); if (compareValue > 0) { rightCurrentPosition++; } else if (compareValue < 0) { leftCurrentPosition++; } else { - result.add(converter.convert(leftArrayOI.getListElement(leftArray, leftPositions[leftCurrentPosition]))); + result.add(converter.convert(leftArrayOi.getListElement(leftArray, leftPositions[leftCurrentPosition]))); leftCurrentPosition++; rightCurrentPosition++; - while (leftCurrentPosition < leftArrayLength && compare(leftArrayOI, leftArray, leftBasePosition, leftCurrentPosition) == 0) { + while (leftCurrentPosition < leftArrayLength && compare(leftArrayOi, leftArray, leftPositions[leftBasePosition], leftPositions[leftCurrentPosition]) == 0) { leftCurrentPosition++; } - while (rightCurrentPosition < rightArrayLength && compare(rightArrayOI, rightArray, rightBasePosition, rightCurrentPosition) == 0) { + while (rightCurrentPosition < rightArrayLength && compare(rightArrayOi, rightArray, rightPositions[rightBasePosition], rightPositions[rightCurrentPosition]) == 0) { rightCurrentPosition++; } } @@ -157,11 +154,11 @@ public Object evaluate(DeferredObject[] arguments) throws HiveException { return result; } - private int compare(ListObjectInspector arrayOI, Object array, int position1, int position2) { - ObjectInspector arrayElementOI = arrayOI.getListElementObjectInspector(); - Object arrayElementTmp1 = arrayOI.getListElement(array, leftPositions[position1]); - Object arrayElementTmp2 = arrayOI.getListElement(array, leftPositions[position2]); - return ObjectInspectorUtils.compare(arrayElementTmp1, arrayElementOI, arrayElementTmp2, arrayElementOI); + private int compare(ListObjectInspector arrayOi, Object array, int position1, int position2) { + ObjectInspector arrayElementOi = arrayOi.getListElementObjectInspector(); + Object arrayElementTmp1 = arrayOi.getListElement(array, position1); + Object arrayElementTmp2 = arrayOi.getListElement(array, position2); + return ObjectInspectorUtils.compare(arrayElementTmp1, arrayElementOi, arrayElementTmp2, arrayElementOi); } @Override diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayJoin.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayJoin.java similarity index 99% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayJoin.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayJoin.java index b62c93d..ba9e9b3 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayJoin.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayJoin.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayMax.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayMax.java similarity index 94% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayMax.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayMax.java index 2c2ef37..228571d 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayMax.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayMax.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; -import com.github.aaronshan.functions.fastuitl.ints.IntArrays; +import com.chinagoods.bigdata.functions.fastuitl.ints.IntArrays; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; @@ -11,7 +11,7 @@ import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; -import static com.github.aaronshan.functions.utils.ArrayUtils.IntArrayCompare; +import static com.chinagoods.bigdata.functions.utils.ArrayUtils.IntArrayCompare; /** * @author ruifeng.shan diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayMin.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayMin.java similarity index 94% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayMin.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayMin.java index 9775e3d..5461cde 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayMin.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayMin.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; -import com.github.aaronshan.functions.fastuitl.ints.IntArrays; +import com.chinagoods.bigdata.functions.fastuitl.ints.IntArrays; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; @@ -11,7 +11,7 @@ import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; -import static com.github.aaronshan.functions.utils.ArrayUtils.IntArrayCompare; +import static com.chinagoods.bigdata.functions.utils.ArrayUtils.IntArrayCompare; /** * @author ruifeng.shan diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayPosition.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayPosition.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayPosition.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayPosition.java index 39c0f64..6f20119 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayPosition.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayPosition.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayRemove.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayRemove.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayRemove.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayRemove.java index 601e1ad..c0f1913 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayRemove.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayRemove.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; import java.util.ArrayList; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayReverse.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayReverse.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayReverse.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayReverse.java index 843cecf..3c8a76c 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayReverse.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayReverse.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; import java.util.ArrayList; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayShuffle.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayShuffle.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayShuffle.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayShuffle.java index e7a60a8..fb4fd83 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayShuffle.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayShuffle.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArraySlice.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArraySlice.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/array/UDFArraySlice.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArraySlice.java index 82fddbb..6724b54 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArraySlice.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArraySlice.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; import java.util.ArrayList; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArraySort.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArraySort.java similarity index 93% rename from src/main/java/com/github/aaronshan/functions/array/UDFArraySort.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArraySort.java index d835361..7ee5ef5 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArraySort.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArraySort.java @@ -1,9 +1,9 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; -import com.github.aaronshan.functions.fastuitl.ints.IntArrays; +import com.chinagoods.bigdata.functions.fastuitl.ints.IntArrays; import java.util.ArrayList; -import com.github.aaronshan.functions.utils.ArrayUtils; +import com.chinagoods.bigdata.functions.utils.ArrayUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; @@ -12,8 +12,6 @@ import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; import org.apache.hadoop.hive.serde2.objectinspector.*; -import static com.github.aaronshan.functions.utils.ArrayUtils.IntArrayCompare; - /** * @author ruifeng.shan * date: 2016-07-26 diff --git a/src/main/java/com/chinagoods/bigdata/functions/array/UDFArraySum.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArraySum.java new file mode 100644 index 0000000..8614117 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArraySum.java @@ -0,0 +1,77 @@ +package com.chinagoods.bigdata.functions.array; + +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ListObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * @author ruifeng.shan + * date: 2016-07-26 + * time: 17:32 + */ +/** + * Hive UDF to sum the elements of an array + */ +@Description( + name = "array_sum", + value = " sum an array of doubles" +) +public class UDFArraySum extends GenericUDF { + private static final Logger LOG = LoggerFactory.getLogger(UDFArraySum.class); + private ListObjectInspector listInspector; + + + public Double evaluate(List strArray) { + double total = 0.0; + for (Object obj : strArray) { + Object dblObj = ((PrimitiveObjectInspector) (listInspector.getListElementObjectInspector())).getPrimitiveJavaObject(obj); + if (dblObj instanceof Number) { + Number dblNum = (Number) dblObj; + total += dblNum.doubleValue(); + } else { + //// Try to coerce it otherwise + String dblStr = (dblObj.toString()); + try { + Double dblCoerce = Double.parseDouble(dblStr); + total += dblCoerce; + } catch (NumberFormatException formatExc) { + LOG.info(" Unable to interpret " + dblStr + " as a number"); + } + } + } + return total; + } + + @Override + public Object evaluate(DeferredObject[] arg0) throws HiveException { + List argList = listInspector.getList(arg0[0].get()); + if (argList != null) + return evaluate(argList); + else + return null; + } + + @Override + public String getDisplayString(String[] arg0) { + return "array_sum()"; + } + + @Override + public ObjectInspector initialize(ObjectInspector[] arg0) + throws UDFArgumentException { + this.listInspector = (ListObjectInspector) arg0[0]; + LOG.info(" Sum Array input type is " + listInspector + " element = " + listInspector.getListElementObjectInspector()); + + ObjectInspector returnType = PrimitiveObjectInspectorFactory.javaDoubleObjectInspector; + return returnType; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFArrayValueCount.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayValueCount.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/array/UDFArrayValueCount.java rename to src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayValueCount.java index c095d3c..4b85b82 100644 --- a/src/main/java/com/github/aaronshan/functions/array/UDFArrayValueCount.java +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFArrayValueCount.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; diff --git a/src/main/java/com/chinagoods/bigdata/functions/array/UDFSequence.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFSequence.java new file mode 100644 index 0000000..bb94ed5 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFSequence.java @@ -0,0 +1,68 @@ +package com.chinagoods.bigdata.functions.array; + +import com.chinagoods.bigdata.functions.utils.Failures; +import com.google.common.collect.Lists; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.io.LongWritable; + +import java.util.ArrayList; + +/** + * @author aaron02 + * date: 2018-08-18 上午9:23 + */ +@Description(name = "sequence" + , value = "_FUNC_(start, stop) - Generate a sequence of integers from start to stop.\n" + + "_FUNC_(start, stop, step) - Generate a sequence of integers from start to stop, incrementing by step." + , extended = "Example:\n > select _FUNC_(1, 5) from src;\n > select _FUNC_(1, 9, 4) from src;\n") +public class UDFSequence extends UDF { + private static final long MAX_RESULT_ENTRIES = 10000; + + public UDFSequence() { + + } + + public ArrayList evaluate(LongWritable start, LongWritable stop) throws HiveException { + return fixedWidthSequence(start.get(), stop.get(), stop.get() >= start.get() ? 1 : -1); + } + + public ArrayList evaluate(LongWritable start, LongWritable stop, LongWritable step) throws HiveException { + return fixedWidthSequence(start.get(), stop.get(), step.get()); + } + + public static int toIntExact(long value) { + if ((int)value != value) { + throw new ArithmeticException("integer overflow"); + } + return (int)value; + } + + private static ArrayList fixedWidthSequence(long start, long stop, long step) throws HiveException { + checkValidStep(start, stop, step); + + int length = toIntExact((stop - start) / step + 1L); + checkMaxEntry(length); + ArrayList result = Lists.newArrayList(); + for (long i = 0, value = start; i < length; ++i, value += step) { + result.add(value); + } + return result; + } + + private static void checkValidStep(long start, long stop, long step) throws HiveException { + Failures.checkCondition( + step != 0, + "step must not be zero"); + Failures.checkCondition( + step > 0 ? stop >= start : stop <= start, + "sequence stop value should be greater than or equal to start value if step is greater than zero otherwise stop should be less than or equal to start"); + } + + private static void checkMaxEntry(int length) throws HiveException { + Failures.checkCondition( + length <= MAX_RESULT_ENTRIES, + "result of sequence function must not have more than 10000 entries"); + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/array/UDFSequenceDate.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDFSequenceDate.java new file mode 100644 index 0000000..44d01fc --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDFSequenceDate.java @@ -0,0 +1,106 @@ +package com.chinagoods.bigdata.functions.array; + +import com.chinagoods.bigdata.functions.utils.Failures; +import com.google.common.collect.Lists; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.io.Text; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; + +/** + * @author xiaowei.song + * date: 2021-09-04 上午9:23 + */ +@Description(name = "sequence_date" + , value = "_FUNC_(start, stop, step) - Generate a sequence of integers from start to stop, incrementing by step." + , extended = "Example:\n > select _FUNC_('2016-04-12', '2016-04-14') from src; \n" + + " > select _FUNC_('2016-04-12 00:00:00', '2016-04-14 00:00:00', 86400000) from src;") +public class UDFSequenceDate extends UDF { + + private static final Logger logger = LoggerFactory.getLogger(UDFSequenceDate.class); + + public final static DateTimeFormatter DEFAULT_DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"); + public final static DateTimeFormatter DEFAULT_DATE_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd"); + private static final long MAX_RESULT_ENTRIES = 10000; + private static final long MAX_1_DAY_MS = 24 * 3600 * 1000; + + public UDFSequenceDate() { + + } + + public ArrayList evaluate(Text start, Text stop) throws HiveException { + DateTimeFormatter format = exactFormat(start, stop); + long startMillis = DateTime.parse(start.toString(), format).getMillis(); + long stopMillis = DateTime.parse(stop.toString(), format).getMillis(); + return fixedWidthSequence(startMillis, stopMillis, MAX_1_DAY_MS, format); + } + + public ArrayList evaluate(Text start, Text stop, long step) throws HiveException { + DateTimeFormatter format = exactFormat(start, stop); + long startMillis = DateTime.parse(start.toString(), format).getMillis(); + long stopMillis = DateTime.parse(stop.toString(), format).getMillis(); + return fixedWidthSequence(startMillis, stopMillis, step, format); + } + + public static DateTimeFormatter exactFormat(Text start, Text stop) throws HiveException { + Failures.checkCondition( + start.toString().length() == stop.toString().length(), + "The two input formats are inconsistent, please check whether the two inputs are consistent."); + DateTimeFormatter format = UDFSequenceDate.DEFAULT_DATE_TIME_FORMATTER; + if (start.toString().length() == 10) { + format = UDFSequenceDate.DEFAULT_DATE_FORMATTER; + } + return format; + } + + public static int toIntExact(long value) { + if ((int)value != value) { + throw new ArithmeticException("integer overflow"); + } + return (int)value; + } + + private static ArrayList fixedWidthSequence(long start, long stop, long step, DateTimeFormatter format) throws HiveException { + checkValidStep(start, stop, step); + + + int length = toIntExact((stop - start) / step + 1L); + logger.info("stop: {}, start: {}, step: {}", stop, start, step); + checkMaxEntry(length); + + ArrayList result = Lists.newArrayList(); + for (long i = 0, value = start; i < length; ++i, value += step) { + DateTime dateTime = new DateTime(value); + result.add(new Text(dateTime.toString(format))); + } + return result; + } + + private static void checkValidStep(long start, long stop, long step) throws HiveException { + Failures.checkCondition( + step != 0, + "step must not be zero"); + Failures.checkCondition( + step > 0 ? stop >= start : stop <= start, + "sequence stop value should be greater than or equal to start value if step is greater than zero otherwise stop should be less than or equal to start"); + } + + private static void checkMaxEntry(int length) throws HiveException { + Failures.checkCondition( + length <= MAX_RESULT_ENTRIES, + "result of sequence function must not have more than 10000 entries"); + } + + public static void main(String[] args) throws HiveException { + UDFSequenceDate sequence = new UDFSequenceDate(); +// System.out.println(sequence.evaluate(new Text("2016-04-12 00:00:00"), new Text("2016-04-14 00:00:00"), 86400000)); + System.out.println(sequence.evaluate(new Text("2019-04-20"), new Text("2021-04-19"))); + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/array/UDTFArrayAroundCross.java b/src/main/java/com/chinagoods/bigdata/functions/array/UDTFArrayAroundCross.java new file mode 100644 index 0000000..50aa67d --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/array/UDTFArrayAroundCross.java @@ -0,0 +1,123 @@ +package com.chinagoods.bigdata.functions.array; + +import com.chinagoods.bigdata.functions.fastuitl.ints.IntArrays; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; +import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF; +import org.apache.hadoop.hive.serde2.objectinspector.*; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters.Converter; + +import java.util.ArrayList; +import java.util.Arrays; + +import static com.chinagoods.bigdata.functions.utils.ArrayUtils.IntArrayCompare; + +/** + * @author xiaowei.song + * date: 2022-10-26 + * time: 09:39 + */ +@Description(name = "array_around_cross" + , value = "_FUNC_(array) - Returns the cartesian product function in a collection." + , extended = "Example:\n > select _FUNC_(array) from src;") +public class UDTFArrayAroundCross extends GenericUDTF { + private static final int INITIAL_SIZE = 128; + /** + * Number of arguments to this UDF + **/ + private static final int ARG_COUNT = 1; + private int[] leftPositions = new int[INITIAL_SIZE]; + private transient ListObjectInspector arrayOi; + private transient ObjectInspector arrayElementOi; + + private transient Converter converter; + + public UDTFArrayAroundCross() { + } + + @Override + public StructObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + // Check if two arguments were passed + if (arguments.length != ARG_COUNT) { + throw new UDFArgumentLengthException( + "The function array_around_cross(array) takes exactly " + ARG_COUNT + "arguments."); + } + + // Check if two argument is of category LIST + for (int i = 0; i < ARG_COUNT; i++) { + if (!arguments[i].getCategory().equals(ObjectInspector.Category.LIST)) { + throw new UDFArgumentTypeException(i, + "\"" + org.apache.hadoop.hive.serde.serdeConstants.LIST_TYPE_NAME + "\" " + + "expected at function array_around_cross, but " + + "\"" + arguments[i].getTypeName() + "\" " + + "is found"); + } + } + arrayOi = (ListObjectInspector) arguments[0]; + arrayElementOi = arrayOi.getListElementObjectInspector(); + converter = ObjectInspectorConverters.getConverter(arrayElementOi, arrayElementOi); + + // 有2列,col1、col2 + return ObjectInspectorFactory.getStandardStructObjectInspector( + Arrays.asList("col1", "col2"), + Arrays.asList(arrayElementOi + ,arrayElementOi + ) + ); + } + + @Override + public void process(Object[] arguments) throws HiveException { + Object srcArray = arguments[0]; + int srcArrayLength = arrayOi.getListLength(srcArray); + + // Check if array is null or empty + if (srcArray == null || srcArrayLength < 0) { + return; + } + + // 若原始内容小于等于1,则返回null + if (srcArrayLength <= 1) { + return; + } + + if (leftPositions.length < srcArrayLength) { + leftPositions = new int[srcArrayLength]; + } + + for (int i = 0; i < srcArrayLength; i++) { + leftPositions[i] = i; + } + + IntArrays.quickSort(leftPositions, 0, srcArrayLength, IntArrayCompare(srcArray, arrayOi)); + + Object leftArrayElement; + Object rightArrayElement; + + + ArrayList tuple2Arr; + for (int i = 0; i < srcArrayLength; i++) { + leftArrayElement = arrayOi.getListElement(srcArray, leftPositions[i]); + for (int j = i + 1; j < srcArrayLength; j++) { + tuple2Arr = new ArrayList<>(2); + rightArrayElement = arrayOi.getListElement(srcArray, leftPositions[j]); + tuple2Arr.add(leftArrayElement); + tuple2Arr.add(rightArrayElement); + forward(tuple2Arr); + } + } + } + + @Override + public void close() throws HiveException { + + } + + public String getDisplayString(String[] strings) { + assert (strings.length == ARG_COUNT); + return "array_around_cross(" + strings[0] + ")"; + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/audio/UDFWhisper.java b/src/main/java/com/chinagoods/bigdata/functions/audio/UDFWhisper.java new file mode 100644 index 0000000..758591f --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/audio/UDFWhisper.java @@ -0,0 +1,152 @@ +package com.chinagoods.bigdata.functions.audio; + +import com.chinagoods.bigdata.functions.utils.JacksonBuilder; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import kong.unirest.HttpStatus; +import kong.unirest.Unirest; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.RandomStringUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.io.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Created by xiaowei.song on 20/4/23. + */ +@Description(name = "whisper" + , value = "_FUNC_(string) - get audio content by given input img url." + , extended = "Example:\n > select _FUNC_(string) from src;") +public class UDFWhisper extends UDF { + + public static final Logger logger = LoggerFactory.getLogger(UDFWhisper.class); + + private Text result = new Text(); +// public static final String DOWNLOAD_IMG_DIR = "e:\\phash"; + public static final String DOWNLOAD_IMG_DIR = "/tmp/audio"; + + public static final String DEFAULT_FEATURE_CODE = "0000"; + + public UDFWhisper() throws IOException { + // 若目录不存在,则重新创建目录 + FileUtils.forceMkdir(new File(DOWNLOAD_IMG_DIR)); + } + + public static final String IMG_OCR_URL = "http://172.18.5.14:25000/whisper"; + + static { + Unirest.config() + .socketTimeout(600000) + .connectTimeout(600000) + .concurrency(10, 5) + .setDefaultHeader("Accept", "application/json") + .followRedirects(false) + .enableCookieManagement(false) + ; + } + + /** + * md5 hash. + * + * @param text 字符串 + * @return md5 hash. + */ + public Text evaluate(Text text) throws IOException { + if (text == null) { + return null; + } + String urlStr = text.toString(); + URL url = new URL(urlStr); + Path filePath = Paths.get(DOWNLOAD_IMG_DIR, RandomStringUtils.randomAlphanumeric(10) + ".jpg"); + File file = filePath.toFile(); + // 下载文件到本地 + FileUtils.copyURLToFile(url, file); + logger.debug("本地图片路径为: {}", file.toString()); + String phashFeature; + File imgFile = file; + Map rspM = null; + try { + rspM = postAction(imgFile); + } finally { + // 计算完成,清理文件 + FileUtils.forceDelete(file); + } + // 解析内容 + String content = parseContent(rspM); + if (StringUtils.isNotBlank(content)) { + result.set(content); + } else { + result.set(DEFAULT_FEATURE_CODE); + } + return result; + } + + public static Map postAction(File f) { + Map resultMap=new HashMap<>(2); + + kong.unirest.HttpResponse response = Unirest.post(IMG_OCR_URL) + .header("accept", "*/*") + .field("file", f, "file") + .asString(); + + String statusText= response.getStatusText(); + int status = response.getStatus(); + + resultMap.put("statusText", statusText); + resultMap.put("status", status); + String content = "{}"; + boolean isSucc = true; + try { + content = response.getBody(); + if(status != HttpStatus.OK) { + isSucc = false; + } + } catch (Exception e) { + isSucc = false; + logger.error("请求错误,whisper解析音频内容失败,错误为: ", e); + } + resultMap.put("isSuc", isSucc); + JsonNode rspJn = null; + try { + rspJn = JacksonBuilder.mapper.readTree(content); + } catch (JsonProcessingException e) { + logger.error("请求错误,whisper解析音频内容返回内容反序列化错误,错误为: ", e); + } + + resultMap.put("responseJson", rspJn); + return resultMap; + } + + public String parseContent(Map rspM){ + StringBuffer sb = new StringBuffer(""); + JsonNode rspJn = (JsonNode) rspM.get("responseJson"); + Iterator resultsJnArr = rspJn.path("results").iterator(); + JsonNode textJn = null; + String text; + while (resultsJnArr.hasNext()) { + textJn = resultsJnArr.next(); + text = textJn.path("transcript").asText(""); + if (StringUtils.isNotBlank(text)) { + sb.append(text).append("\n"); + } + } + return sb.toString(); + } + + public static void main(String[] args) throws IOException { + UDFWhisper imgPHash = new UDFWhisper(); + System.out.println(imgPHash.evaluate(new Text("https://pics0.baidu.com/feed/adaf2edda3cc7cd97b91527811cf2933b90e9129.jpeg?token=0a3291326ec23fc3e009814b41da9bb1"))); + } +} diff --git a/src/main/java/com/github/aaronshan/functions/bitwise/UDFBitCount.java b/src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitCount.java similarity index 96% rename from src/main/java/com/github/aaronshan/functions/bitwise/UDFBitCount.java rename to src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitCount.java index 1df57e7..3e010eb 100644 --- a/src/main/java/com/github/aaronshan/functions/bitwise/UDFBitCount.java +++ b/src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitCount.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.bitwise; +package com.chinagoods.bigdata.functions.bitwise; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/github/aaronshan/functions/bitwise/UDFBitwiseAnd.java b/src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitwiseAnd.java similarity index 92% rename from src/main/java/com/github/aaronshan/functions/bitwise/UDFBitwiseAnd.java rename to src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitwiseAnd.java index 4a3e098..bdb91de 100644 --- a/src/main/java/com/github/aaronshan/functions/bitwise/UDFBitwiseAnd.java +++ b/src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitwiseAnd.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.bitwise; +package com.chinagoods.bigdata.functions.bitwise; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/github/aaronshan/functions/bitwise/UDFBitwiseNot.java b/src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitwiseNot.java similarity index 92% rename from src/main/java/com/github/aaronshan/functions/bitwise/UDFBitwiseNot.java rename to src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitwiseNot.java index fb7bc41..8e89a87 100644 --- a/src/main/java/com/github/aaronshan/functions/bitwise/UDFBitwiseNot.java +++ b/src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitwiseNot.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.bitwise; +package com.chinagoods.bigdata.functions.bitwise; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/github/aaronshan/functions/bitwise/UDFBitwiseOr.java b/src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitwiseOr.java similarity index 92% rename from src/main/java/com/github/aaronshan/functions/bitwise/UDFBitwiseOr.java rename to src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitwiseOr.java index 1573ff9..fc19e12 100644 --- a/src/main/java/com/github/aaronshan/functions/bitwise/UDFBitwiseOr.java +++ b/src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitwiseOr.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.bitwise; +package com.chinagoods.bigdata.functions.bitwise; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/github/aaronshan/functions/bitwise/UDFBitwiseXor.java b/src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitwiseXor.java similarity index 92% rename from src/main/java/com/github/aaronshan/functions/bitwise/UDFBitwiseXor.java rename to src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitwiseXor.java index 172cff0..744937d 100644 --- a/src/main/java/com/github/aaronshan/functions/bitwise/UDFBitwiseXor.java +++ b/src/main/java/com/chinagoods/bigdata/functions/bitwise/UDFBitwiseXor.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.bitwise; +package com.chinagoods.bigdata.functions.bitwise; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCard15to18.java b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCard15to18.java new file mode 100644 index 0000000..eaeae61 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCard15to18.java @@ -0,0 +1,202 @@ +package com.chinagoods.bigdata.functions.card; + +import com.chinagoods.bigdata.functions.utils.CardUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.io.BooleanWritable; +import org.apache.hadoop.io.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +/** + * @author ruifeng.shan + * date: 2016-07-25 + * time: 20:15 + */ +@Description(name = "id_card_15to18" + , value = "_FUNC_(string) - Convert 15-digit ID card number into 18-digit" + , extended = "Example:\n > select _FUNC_(string) from src;") +public class UDFChinaIdCard15to18 extends UDF { + private static final Logger log = LoggerFactory.getLogger(UDFChinaIdCard15to18.class); + + private Text result = new Text(); + + // 每位加权因子 + private static final int[] power = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 }; + + public UDFChinaIdCard15to18() { + } + + public Text evaluate(Text idCard) { + if (idCard == null) { + return null; + } + result.set(convertIdCardBy15bit(idCard.toString())); + return result; + } + + /** + * 将15位的身份证转成18位身份证 + * + * @param idCard 身份证号码 + * @return idCard 转换完成的身份证号码 + */ + public static String convertIdCardBy15bit(String idCard) { + String idCard17 = null; + // 非15位身份证 + if (idCard.length() != 15) { + return idCard; + } + + if (isDigital(idCard)) { + // 获取出生年月日 + String birthday = idCard.substring(6, 12); + Date birthDate = null; + try { + birthDate = new SimpleDateFormat("yyMMdd").parse(birthday); + } catch (ParseException e) { + log.error("解析身份证位数失败,身份证号码错误, {}", idCard, e); + return ""; + } + Calendar cDay = Calendar.getInstance(); + cDay.setTime(birthDate); + String year = String.valueOf(cDay.get(Calendar.YEAR)); + + idCard17 = idCard.substring(0, 6) + year + idCard.substring(8); + + char[] c = idCard17.toCharArray(); + String checkCode = ""; + + int[] bit; + + // 将字符数组转为整型数组 + bit = convertCharToInt(c); + int sum17 = 0; + + sum17 = getPowerSum(bit); + + // 获取和值与11取模得到余数进行校验码 + checkCode = getCheckCodeBySum(sum17); + // 获取不到校验位 + if (null == checkCode) { + return ""; + } + + // 将前17位与第18位校验码拼接 + idCard17 += checkCode; + } else { + // 身份证包含数字 + log.warn("身份证号码非法! 号码: {}", idCard); + return ""; + } + return idCard17; + } + + /** + * 数字验证 + * + * @param str + * @return + */ + public static boolean isDigital(String str) { + return str != null && !"".equals(str) && str.matches("^[0-9]*$"); + } + + /** + * 将字符数组转为整型数组 + * + * @param c + * @return + * @throws NumberFormatException + */ + public static int[] convertCharToInt(char[] c) throws NumberFormatException { + int[] a = new int[c.length]; + int k = 0; + for (char temp : c) { + a[k++] = Integer.parseInt(String.valueOf(temp)); + } + return a; + } + + + /** + * 将身份证的每位和对应位的加权因子相乘之后,再得到和值 + * + * @param bit + * @return + */ + public static int getPowerSum(int[] bit) { + + int sum = 0; + + if (power.length != bit.length) { + return sum; + } + + for (int i = 0; i < bit.length; i++) { + for (int j = 0; j < power.length; j++) { + if (i == j) { + sum = sum + bit[i] * power[j]; + } + } + } + return sum; + } + + /** + * 将和值与11取模得到余数进行校验码判断 + * + * @param sum17 + * @return 校验位 + */ + public static String getCheckCodeBySum(int sum17) { + String checkCode = null; + switch (sum17 % 11) { + case 10: + checkCode = "2"; + break; + case 9: + checkCode = "3"; + break; + case 8: + checkCode = "4"; + break; + case 7: + checkCode = "5"; + break; + case 6: + checkCode = "6"; + break; + case 5: + checkCode = "7"; + break; + case 4: + checkCode = "8"; + break; + case 3: + checkCode = "9"; + break; + case 2: + checkCode = "X"; + break; + case 1: + checkCode = "0"; + break; + case 0: + checkCode = "1"; + break; + } + return checkCode; + } + + public static void main(String[] args) { + UDFChinaIdCard15to18 udf = new UDFChinaIdCard15to18(); + System.out.println(udf.evaluate(new Text("330621690111306"))); + } + +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardAge.java b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardAge.java new file mode 100644 index 0000000..a9798b4 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardAge.java @@ -0,0 +1,59 @@ +package com.chinagoods.bigdata.functions.card; + +import com.chinagoods.bigdata.functions.utils.CardUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.io.Text; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * @author ruifeng.shan + * date: 2016-07-25 + * time: 20:14 + */ +@Description(name = "id_card_age" + , value = "_FUNC_(string, string) - get age by given china id card and ds." + , extended = "Example:\n > select _FUNC_(string, string) from src;") +public class UDFChinaIdCardAge extends UDF{ + private Text result = new Text(); + + public UDFChinaIdCardAge() { + } + + public Text evaluate(Text idCard, Text ds) throws ParseException { + if (idCard == null || ds == null) { + return null; + } + int birthday = CardUtils.getIdCardAge(idCard.toString(), ds.toString()); + if (birthday == -2) { + return null; + } + result.set(String.valueOf(birthday)); + return result; + } + + public Text evaluate(Text idCard) throws ParseException { + if (idCard == null) { + return null; + } + // 若未传日期,则自动使用当前时间作为日期 + SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd"); + String ds = df.format(new Date()); + int birthday = CardUtils.getIdCardAge(idCard.toString(), ds.toString()); + System.out.println(birthday); + if (birthday == -2) { + return null; + } + result.set(String.valueOf(birthday)); + return result; + } + + public static void main(String[] args) throws ParseException { + String idCard = "372927197901133326"; + UDFChinaIdCardAge udfChinaIdCardAge = new UDFChinaIdCardAge(); + System.out.println(udfChinaIdCardAge.evaluate(new Text(idCard))); + } +} diff --git a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardArea.java b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardArea.java similarity index 70% rename from src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardArea.java rename to src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardArea.java index 9a1d154..42e1ca6 100644 --- a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardArea.java +++ b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardArea.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.card; +package com.chinagoods.bigdata.functions.card; -import com.github.aaronshan.functions.utils.CardUtils; +import com.chinagoods.bigdata.functions.utils.CardUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; @@ -23,7 +23,11 @@ public Text evaluate(Text idCard) { if (idCard == null) { return null; } - result.set(CardUtils.getIdCardArea(idCard.toString())); + String area = CardUtils.getIdCardArea(idCard.toString()); + if (area == null) { + return null; + } + result.set(area); return result; } } diff --git a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardBirthday.java b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardBirthday.java similarity index 70% rename from src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardBirthday.java rename to src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardBirthday.java index f727937..e54723d 100644 --- a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardBirthday.java +++ b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardBirthday.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.card; +package com.chinagoods.bigdata.functions.card; -import com.github.aaronshan.functions.utils.CardUtils; +import com.chinagoods.bigdata.functions.utils.CardUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; @@ -23,7 +23,11 @@ public Text evaluate(Text idCard) { if (idCard == null) { return null; } - result.set(CardUtils.getIdCardBirthday(idCard.toString())); + String birthday = CardUtils.getIdCardBirthday(idCard.toString()); + if (birthday == null) { + return null; + } + result.set(birthday); return result; } } diff --git a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardCity.java b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardCity.java similarity index 70% rename from src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardCity.java rename to src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardCity.java index 9cdf185..07a3dd5 100644 --- a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardCity.java +++ b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardCity.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.card; +package com.chinagoods.bigdata.functions.card; -import com.github.aaronshan.functions.utils.CardUtils; +import com.chinagoods.bigdata.functions.utils.CardUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; @@ -23,7 +23,12 @@ public Text evaluate(Text idCard) { if (idCard == null) { return null; } - result.set(CardUtils.getIdCardCity(idCard.toString())); + String city = CardUtils.getIdCardCity(idCard.toString()); + if (city == null) { + return null; + } + result.set(city); + return result; } } diff --git a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardGender.java b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardGender.java similarity index 70% rename from src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardGender.java rename to src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardGender.java index 4ef5cfe..c370ef0 100644 --- a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardGender.java +++ b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardGender.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.card; +package com.chinagoods.bigdata.functions.card; -import com.github.aaronshan.functions.utils.CardUtils; +import com.chinagoods.bigdata.functions.utils.CardUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; @@ -23,7 +23,12 @@ public Text evaluate(Text idCard) { if (idCard == null) { return null; } - result.set(CardUtils.getIdCardGender(idCard.toString())); + String gender = CardUtils.getIdCardGender(idCard.toString()); + if (gender == null) { + return null; + } + result.set(gender); + return result; } } diff --git a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardInfo.java b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardInfo.java similarity index 70% rename from src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardInfo.java rename to src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardInfo.java index 5a79b4a..bdf5318 100644 --- a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardInfo.java +++ b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardInfo.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.card; +package com.chinagoods.bigdata.functions.card; -import com.github.aaronshan.functions.utils.CardUtils; +import com.chinagoods.bigdata.functions.utils.CardUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; @@ -23,7 +23,11 @@ public Text evaluate(Text idCard) { if (idCard == null) { return null; } - result.set(CardUtils.getJsonOfChinaIdCard(idCard.toString())); + String cardInfo = CardUtils.getJsonOfChinaIdCard(idCard.toString()); + if (cardInfo == null) { + return null; + } + result.set(cardInfo); return result; } } diff --git a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardProvince.java b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardProvince.java similarity index 70% rename from src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardProvince.java rename to src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardProvince.java index 274d201..2423540 100644 --- a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardProvince.java +++ b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardProvince.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.card; +package com.chinagoods.bigdata.functions.card; -import com.github.aaronshan.functions.utils.CardUtils; +import com.chinagoods.bigdata.functions.utils.CardUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; @@ -23,7 +23,11 @@ public Text evaluate(Text idCard) { if (idCard == null) { return null; } - result.set(CardUtils.getIdCardProvince(idCard.toString())); + String province = CardUtils.getIdCardProvince(idCard.toString()); + if (province == null) { + return null; + } + result.set(province); return result; } } diff --git a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardValid.java b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardValid.java similarity index 88% rename from src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardValid.java rename to src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardValid.java index 3abbd49..41957d6 100644 --- a/src/main/java/com/github/aaronshan/functions/card/UDFChinaIdCardValid.java +++ b/src/main/java/com/chinagoods/bigdata/functions/card/UDFChinaIdCardValid.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.card; +package com.chinagoods.bigdata.functions.card; -import com.github.aaronshan.functions.utils.CardUtils; +import com.chinagoods.bigdata.functions.utils.CardUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.BooleanWritable; diff --git a/src/main/java/com/chinagoods/bigdata/functions/date/UDFDateFormat.java b/src/main/java/com/chinagoods/bigdata/functions/date/UDFDateFormat.java new file mode 100644 index 0000000..02834ef --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/date/UDFDateFormat.java @@ -0,0 +1,64 @@ +package com.chinagoods.bigdata.functions.date; + +import com.chinagoods.bigdata.functions.utils.DateUtil; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.io.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.LocalDateTime; + +/** + * @author songxiaowei + * date: 2023-08-13 + */ +@Description(name = "date_format" + , value = "_FUNC_(date, format, target_format) - Take an original date string and its corresponding string date format as input, and output a date string in standard format or a customized target format." + , extended = "Example:\n > select _FUNC_(date_string, format, target_format) from src;\n > select _FUNC_(date, 'dd/MMM/yyyy:HH:mm:ss Z') from src;") +public class UDFDateFormat extends UDF { + public static final Logger logger = LoggerFactory.getLogger(UDFDateFormat.class); + + private Text result = new Text(); + + public UDFDateFormat() { + + } + + /** + * 将各种日期显示格式统一成标准UTC显示格式 + * + * @param dateString the dateString in the format of "yyyyMMdd". + * @param format eg "yyyyMMdd". + * @return 标准化YYYY-MM-dd HH:mm:ss UTC格式 + */ + public Text evaluate(Text dateString, Text format) { + if (dateString == null || format == null) { + logger.error("输入的内容不正确: date_string={}, format={}", dateString, format); + return null; + } + result.clear(); + LocalDateTime dateTime = DateUtil.parse(dateString.toString(), format.toString()); + result.set(DateUtil.format(dateTime)); + return result; + } + + /** + * 将各种日期显示成各种日期格式 + * + * @param dateString the dateString in the format of "yyyyMMdd". + * @param format eg "yyyyMMdd". + * @param targetFormat eg "yyyyMMdd". + * @return 自定义日期格式 + */ + public Text evaluate(Text dateString, Text format, Text targetFormat) { + if (dateString == null || format == null || targetFormat == null) { + logger.error("输入的内容不正确: date_string={}, format={}, target_format={}", dateString, format, targetFormat); + return null; + } + result.clear(); + LocalDateTime dateTime = DateUtil.parse(dateString.toString(), format.toString()); + result.set(DateUtil.format(dateTime)); + return result; + } +} diff --git a/src/main/java/com/github/aaronshan/functions/date/UDFDayOfWeek.java b/src/main/java/com/chinagoods/bigdata/functions/date/UDFDayOfWeek.java old mode 100755 new mode 100644 similarity index 97% rename from src/main/java/com/github/aaronshan/functions/date/UDFDayOfWeek.java rename to src/main/java/com/chinagoods/bigdata/functions/date/UDFDayOfWeek.java index 343f6af..46a396b --- a/src/main/java/com/github/aaronshan/functions/date/UDFDayOfWeek.java +++ b/src/main/java/com/chinagoods/bigdata/functions/date/UDFDayOfWeek.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.date; +package com.chinagoods.bigdata.functions.date; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/github/aaronshan/functions/date/UDFDayOfYear.java b/src/main/java/com/chinagoods/bigdata/functions/date/UDFDayOfYear.java similarity index 97% rename from src/main/java/com/github/aaronshan/functions/date/UDFDayOfYear.java rename to src/main/java/com/chinagoods/bigdata/functions/date/UDFDayOfYear.java index 8ee544d..65004de 100644 --- a/src/main/java/com/github/aaronshan/functions/date/UDFDayOfYear.java +++ b/src/main/java/com/chinagoods/bigdata/functions/date/UDFDayOfYear.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.date; +package com.chinagoods.bigdata.functions.date; import java.util.Calendar; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/github/aaronshan/functions/date/UDFTypeOfDay.java b/src/main/java/com/chinagoods/bigdata/functions/date/UDFTypeOfDay.java old mode 100755 new mode 100644 similarity index 96% rename from src/main/java/com/github/aaronshan/functions/date/UDFTypeOfDay.java rename to src/main/java/com/chinagoods/bigdata/functions/date/UDFTypeOfDay.java index c780301..d31b8e5 --- a/src/main/java/com/github/aaronshan/functions/date/UDFTypeOfDay.java +++ b/src/main/java/com/chinagoods/bigdata/functions/date/UDFTypeOfDay.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.date; +package com.chinagoods.bigdata.functions.date; -import com.github.aaronshan.functions.utils.ConfigUtils; +import com.chinagoods.bigdata.functions.utils.ConfigUtils; import java.util.Calendar; import java.util.Map; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/github/aaronshan/functions/date/UDFZodiacSignCn.java b/src/main/java/com/chinagoods/bigdata/functions/date/UDFZodiacSignCn.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/date/UDFZodiacSignCn.java rename to src/main/java/com/chinagoods/bigdata/functions/date/UDFZodiacSignCn.java index fecee21..c47f015 100644 --- a/src/main/java/com/github/aaronshan/functions/date/UDFZodiacSignCn.java +++ b/src/main/java/com/chinagoods/bigdata/functions/date/UDFZodiacSignCn.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.date; +package com.chinagoods.bigdata.functions.date; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/github/aaronshan/functions/date/UDFZodiacSignEn.java b/src/main/java/com/chinagoods/bigdata/functions/date/UDFZodiacSignEn.java similarity index 97% rename from src/main/java/com/github/aaronshan/functions/date/UDFZodiacSignEn.java rename to src/main/java/com/chinagoods/bigdata/functions/date/UDFZodiacSignEn.java index db2a0c2..0224ea7 100644 --- a/src/main/java/com/github/aaronshan/functions/date/UDFZodiacSignEn.java +++ b/src/main/java/com/chinagoods/bigdata/functions/date/UDFZodiacSignEn.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.date; +package com.chinagoods.bigdata.functions.date; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/github/aaronshan/functions/fastuitl/ints/AbstractIntComparator.java b/src/main/java/com/chinagoods/bigdata/functions/fastuitl/ints/AbstractIntComparator.java similarity index 88% rename from src/main/java/com/github/aaronshan/functions/fastuitl/ints/AbstractIntComparator.java rename to src/main/java/com/chinagoods/bigdata/functions/fastuitl/ints/AbstractIntComparator.java index 972ae97..09c2103 100644 --- a/src/main/java/com/github/aaronshan/functions/fastuitl/ints/AbstractIntComparator.java +++ b/src/main/java/com/chinagoods/bigdata/functions/fastuitl/ints/AbstractIntComparator.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.fastuitl.ints; +package com.chinagoods.bigdata.functions.fastuitl.ints; // Note: this code was forked from fastutil (http://fastutil.di.unimi.it/) // Copyright (C) 2010-2013 Sebastiano Vigna diff --git a/src/main/java/com/github/aaronshan/functions/fastuitl/ints/IntArrays.java b/src/main/java/com/chinagoods/bigdata/functions/fastuitl/ints/IntArrays.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/fastuitl/ints/IntArrays.java rename to src/main/java/com/chinagoods/bigdata/functions/fastuitl/ints/IntArrays.java index 9341566..d17998d 100644 --- a/src/main/java/com/github/aaronshan/functions/fastuitl/ints/IntArrays.java +++ b/src/main/java/com/chinagoods/bigdata/functions/fastuitl/ints/IntArrays.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.fastuitl.ints; +package com.chinagoods.bigdata.functions.fastuitl.ints; // Note: this code was forked from fastutil (http://fastutil.di.unimi.it/) // Copyright (C) 2010-2013 Sebastiano Vigna diff --git a/src/main/java/com/github/aaronshan/functions/fastuitl/ints/IntComparator.java b/src/main/java/com/chinagoods/bigdata/functions/fastuitl/ints/IntComparator.java similarity index 81% rename from src/main/java/com/github/aaronshan/functions/fastuitl/ints/IntComparator.java rename to src/main/java/com/chinagoods/bigdata/functions/fastuitl/ints/IntComparator.java index 67f9d03..f977f8e 100644 --- a/src/main/java/com/github/aaronshan/functions/fastuitl/ints/IntComparator.java +++ b/src/main/java/com/chinagoods/bigdata/functions/fastuitl/ints/IntComparator.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.fastuitl.ints; +package com.chinagoods.bigdata.functions.fastuitl.ints; import java.util.Comparator; diff --git a/src/main/java/com/github/aaronshan/functions/geo/UDFGeoBdToGcj.java b/src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoBdToGcj.java similarity index 85% rename from src/main/java/com/github/aaronshan/functions/geo/UDFGeoBdToGcj.java rename to src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoBdToGcj.java index 2dfa4e6..d06c03b 100644 --- a/src/main/java/com/github/aaronshan/functions/geo/UDFGeoBdToGcj.java +++ b/src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoBdToGcj.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.geo; +package com.chinagoods.bigdata.functions.geo; -import com.github.aaronshan.functions.utils.GeoUtils; +import com.chinagoods.bigdata.functions.utils.GeoUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; diff --git a/src/main/java/com/github/aaronshan/functions/geo/UDFGeoGcjExtractWgs.java b/src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoGcjExtractWgs.java similarity index 84% rename from src/main/java/com/github/aaronshan/functions/geo/UDFGeoGcjExtractWgs.java rename to src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoGcjExtractWgs.java index 85087cb..7e152cd 100644 --- a/src/main/java/com/github/aaronshan/functions/geo/UDFGeoGcjExtractWgs.java +++ b/src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoGcjExtractWgs.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.geo; +package com.chinagoods.bigdata.functions.geo; -import com.github.aaronshan.functions.utils.GeoUtils; +import com.chinagoods.bigdata.functions.utils.GeoUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.io.Text; diff --git a/src/main/java/com/github/aaronshan/functions/geo/UDFGeoGcjToBd.java b/src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoGcjToBd.java similarity index 84% rename from src/main/java/com/github/aaronshan/functions/geo/UDFGeoGcjToBd.java rename to src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoGcjToBd.java index 3b4796c..7f47921 100644 --- a/src/main/java/com/github/aaronshan/functions/geo/UDFGeoGcjToBd.java +++ b/src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoGcjToBd.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.geo; +package com.chinagoods.bigdata.functions.geo; -import com.github.aaronshan.functions.utils.GeoUtils; +import com.chinagoods.bigdata.functions.utils.GeoUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.io.Text; diff --git a/src/main/java/com/github/aaronshan/functions/geo/UDFGeoGcjToWgs.java b/src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoGcjToWgs.java similarity index 84% rename from src/main/java/com/github/aaronshan/functions/geo/UDFGeoGcjToWgs.java rename to src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoGcjToWgs.java index b49aba9..e5c2d6b 100644 --- a/src/main/java/com/github/aaronshan/functions/geo/UDFGeoGcjToWgs.java +++ b/src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoGcjToWgs.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.geo; +package com.chinagoods.bigdata.functions.geo; -import com.github.aaronshan.functions.utils.GeoUtils; +import com.chinagoods.bigdata.functions.utils.GeoUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.io.Text; diff --git a/src/main/java/com/github/aaronshan/functions/geo/UDFGeoWgsDistance.java b/src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoWgsDistance.java similarity index 86% rename from src/main/java/com/github/aaronshan/functions/geo/UDFGeoWgsDistance.java rename to src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoWgsDistance.java index ba6ed2b..f71d568 100644 --- a/src/main/java/com/github/aaronshan/functions/geo/UDFGeoWgsDistance.java +++ b/src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoWgsDistance.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.geo; +package com.chinagoods.bigdata.functions.geo; -import com.github.aaronshan.functions.utils.GeoUtils; +import com.chinagoods.bigdata.functions.utils.GeoUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.serde2.io.DoubleWritable; diff --git a/src/main/java/com/github/aaronshan/functions/geo/UDFGeoWgsToGcj.java b/src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoWgsToGcj.java similarity index 83% rename from src/main/java/com/github/aaronshan/functions/geo/UDFGeoWgsToGcj.java rename to src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoWgsToGcj.java index 7748c0a..f418c63 100644 --- a/src/main/java/com/github/aaronshan/functions/geo/UDFGeoWgsToGcj.java +++ b/src/main/java/com/chinagoods/bigdata/functions/geo/UDFGeoWgsToGcj.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.geo; +package com.chinagoods.bigdata.functions.geo; -import com.github.aaronshan.functions.utils.GeoUtils; +import com.chinagoods.bigdata.functions.utils.GeoUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.io.Text; diff --git a/src/main/java/com/chinagoods/bigdata/functions/img/UDFImgOcr.java b/src/main/java/com/chinagoods/bigdata/functions/img/UDFImgOcr.java new file mode 100644 index 0000000..c64c6f3 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/img/UDFImgOcr.java @@ -0,0 +1,148 @@ +package com.chinagoods.bigdata.functions.img; + +import com.chinagoods.bigdata.functions.utils.JacksonBuilder; +import com.chinagoods.bigdata.functions.utils.img.PHash; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import kong.unirest.HttpStatus; +import kong.unirest.Unirest; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.RandomStringUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.io.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Created by xiaowei.song on 17/3/23. + */ +@Description(name = "ocr" + , value = "_FUNC_(string) - get ocr content by given input img url." + , extended = "Example:\n > select _FUNC_(string) from src;") +public class UDFImgOcr extends UDF { + + public static final Logger logger = LoggerFactory.getLogger(UDFImgOcr.class); + + private Text result = new Text(); +// public static final String DOWNLOAD_IMG_DIR = "e:\\phash"; + public static final String DOWNLOAD_IMG_DIR = "/tmp/ocr"; + + public static final String DEFAULT_FEATURE_CODE = "0000"; + + public UDFImgOcr() throws IOException { + // 若目录不存在,则重新创建目录 + FileUtils.forceMkdir(new File(DOWNLOAD_IMG_DIR)); + } + + public static final String IMG_OCR_URL = "http://172.18.5.14:18501/ocr"; + + /** + * md5 hash. + * + * @param text 字符串 + * @return md5 hash. + */ + public Text evaluate(Text text) throws IOException { + if (text == null) { + return null; + } + String imageUrlStr = text.toString(); + URL imageUrl = new URL(imageUrlStr); + Path imageFilePath = Paths.get(DOWNLOAD_IMG_DIR, RandomStringUtils.randomAlphanumeric(10) + ".jpg"); + File imageFile = imageFilePath.toFile(); + // 下载文件到本地 + FileUtils.copyURLToFile(imageUrl, imageFile); + logger.debug("本地图片路径为: {}", imageFile.toString()); + String phashFeature; + File imgFile = imageFile; + Map rspM = null; + try { + rspM = postAction(imgFile); + } finally { + // 计算完成,清理文件 + FileUtils.forceDelete(imageFile); + } + // 解析内容 + String content = parseContent(rspM); + if (StringUtils.isNotBlank(content)) { + result.set(content); + } else { + result.set(DEFAULT_FEATURE_CODE); + } + return result; + } + + public static Map postAction(File f) throws JsonProcessingException { + Map resultMap=new HashMap<>(2); + kong.unirest.HttpResponse response = Unirest + .post(IMG_OCR_URL) + .header("accept", "*/*") + .field("image", f, "image") + .asString(); + + String statusText= response.getStatusText(); + int status = response.getStatus(); + + resultMap.put("statusText", statusText); + resultMap.put("status", status); + String content = "{}"; + boolean isSucc = true; + try { + content = response.getBody(); + if(status != HttpStatus.OK) { + isSucc = false; + } + } catch (Exception e) { + isSucc = false; + logger.error("请求错误,ocr解析图片内容失败,错误为: ", e); + } + resultMap.put("isSuc", isSucc); + JsonNode rspJn = JacksonBuilder.mapper.readTree("{}"); + try { + rspJn = JacksonBuilder.mapper.readTree(content); + } catch (JsonProcessingException e) { + logger.error("请求错误,ocr解析图片内容返回内容反序列化错误,错误为: ", e); + } + + resultMap.put("responseJson", rspJn); + return resultMap; + } + + public String parseContent(Map rspM){ + StringBuffer sb = new StringBuffer(""); + JsonNode rspJn = (JsonNode) rspM.get("responseJson"); + int statusCode = rspJn.path("status_code").asInt(); + if (statusCode != HttpStatus.OK) { + logger.error("解析返回内容失败,返回内容为: {}", rspJn); + return sb.toString(); + } + Iterator resultsJnArr = rspJn.path("results").iterator(); + JsonNode textJn = null; + String text; + while (resultsJnArr.hasNext()) { + textJn = resultsJnArr.next(); + text = textJn.path("text").asText(""); + if (StringUtils.isNotBlank(text)) { + sb.append(text).append("\n"); + } + } + return sb.toString(); + } + + public static void main(String[] args) throws IOException { + UDFImgOcr imgPHash = new UDFImgOcr(); + System.out.println(imgPHash.evaluate(new Text("https://pics0.baidu.com/feed/adaf2edda3cc7cd97b91527811cf2933b90e9129.jpeg?token=0a3291326ec23fc3e009814b41da9bb1"))); + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/img/UDFImgPHash.java b/src/main/java/com/chinagoods/bigdata/functions/img/UDFImgPHash.java new file mode 100644 index 0000000..561991f --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/img/UDFImgPHash.java @@ -0,0 +1,77 @@ +package com.chinagoods.bigdata.functions.img; + +import com.chinagoods.bigdata.functions.utils.img.PHash; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.RandomStringUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.io.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * Created by xiaowei.song on 17/3/23. + */ +@Description(name = "phash" + , value = "_FUNC_(string) - get phash code by given input img url." + , extended = "Example:\n > select _FUNC_(string) from src;") +public class UDFImgPHash extends UDF { + + public static final Logger logger = LoggerFactory.getLogger(UDFImgPHash.class); + + private Text result = new Text(); +// public static final String DOWNLOAD_IMG_DIR = "e:\\phash"; + public static final String DOWNLOAD_IMG_DIR = "/tmp/phash"; + + public static final String DEFAULT_FEATURE_CODE = "0000"; + + + public UDFImgPHash() throws IOException { + // 若目录不存在,则重新创建目录 + FileUtils.forceMkdir(new File(DOWNLOAD_IMG_DIR)); + } + + /** + * md5 hash. + * + * @param text 字符串 + * @return md5 hash. + */ + public Text evaluate(Text text) throws IOException { + if (text == null) { + return null; + } + String imageUrlStr = text.toString(); + URL imageUrl = new URL(imageUrlStr); + Path imageFilePath = Paths.get(DOWNLOAD_IMG_DIR, RandomStringUtils.randomAlphanumeric(10) + ".jpg"); + File imageFile = imageFilePath.toFile(); + // 下载文件到本地 + FileUtils.copyURLToFile(imageUrl, imageFile); + logger.debug("本地图片路径为: {}", imageFile.toString()); + String phashFeature; + try { + phashFeature = PHash.getFeatureValue(imageFile.toString()); + } finally { + // 计算完成,清理文件 + FileUtils.forceDelete(imageFile); + } + if (StringUtils.isNotBlank(phashFeature)) { + result.set(phashFeature); + } else { + result.set(DEFAULT_FEATURE_CODE); + } + return result; + } + + public static void main(String[] args) throws IOException { + UDFImgPHash imgPHash = new UDFImgPHash(); + System.out.println(imgPHash.evaluate(new Text("https://cdnimg.chinagoods.com/jpg/2020/05/14/e8a0c54311b5c8b967e7bbac0ef3c3ca.jpg"))); + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/ip/UDFIP2Region.java b/src/main/java/com/chinagoods/bigdata/functions/ip/UDFIP2Region.java new file mode 100644 index 0000000..fd9c04b --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/ip/UDFIP2Region.java @@ -0,0 +1,154 @@ +package com.chinagoods.bigdata.functions.ip; + +import com.chinagoods.bigdata.functions.utils.ConfigUtils; +import com.google.common.collect.ImmutableMap; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.io.IntWritable; +import org.apache.hadoop.io.LongWritable; +import org.apache.hadoop.io.Text; +import org.lionsoul.ip2region.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.time.format.DateTimeFormatter; +import java.util.Collections; +import java.util.Map; + +/** + * @author xiaowei.song + * date: 2020-12-7 + * time: 17:02 + */ +@Description(name = "ip2region" + , value = "_FUNC_(ip, pos) - Convert ip to region. returns a map created using the country|area|province|city|isp|city_id|region_content|data_ptr." + , extended = "Example:\n > select _FUNC_(ip, pos) from src;") +public class UDFIP2Region extends UDF { + public static final Logger logger = LoggerFactory.getLogger(UDFIP2Region.class); + // 初始化结果值 + private Text result = new Text(); + + public static DbConfig config; + public static final String IP2REGION_DB_PATH = "/ip2region.db"; +// public static final String IP2REGION_DB_PATH = "/user/hive/warehouse/resource/ip2region.db"; + public volatile byte[] IP2REGION_DB_BYTES; + static { + try { + config = new DbConfig(); + } catch (DbMakerConfigException e) { + logger.error("ip2region maker config error", e); + System.exit(-1); + } + } + + public static final Map DEFAULT_IP_REGION_FILED_MAP = ImmutableMap.builder() + .put(0, "0") + .put(1, "0") + .put(2, "0") + .put(3, "0") + .put(4, "0") + .put(5, "0") + .put(6, "0|0|0|0|0") + .put(7, "0") + .build(); + + public DbSearcher dbSearcher = null; + + public UDFIP2Region() { + } + + public Text evaluate(String ip, int pos) throws HiveException { + // 清理原始数据 + result.clear(); + + ip = StringUtils.trim(ip); + if(pos < 0 || pos > 7) { + logger.error("pos value range 0-7"); + throw new HiveException("pos value range 0-7"); + } + + if (IP2REGION_DB_BYTES == null) { + // 避免load就占用内存,使用才加载,否则不加载 + try { + IP2REGION_DB_BYTES = ConfigUtils.loadBinFile(IP2REGION_DB_PATH); + } catch (IOException e) { + logger.error("loading ip2region.db error", e); + throw new HiveException("loading ip2region.db error", e); + } + dbSearcher = new DbSearcher(config, IP2REGION_DB_BYTES); + logger.info("load ip2region.db success, path={}, bytes length={}!!!", IP2REGION_DB_PATH, IP2REGION_DB_BYTES.length); + } + if (StringUtils.isBlank(ip) || StringUtils.equals("0000", ip) || + StringUtils.equals("-", ip)) { + result.set(DEFAULT_IP_REGION_FILED_MAP.get(pos)); + return result; + } + logger.debug("ip is not empty: {}", ip); + // 若是非合法ip地址,返回null + if (!Util.isIpAddress(ip)) { + result.set(DEFAULT_IP_REGION_FILED_MAP.get(pos)); + return result; + } + + logger.debug("ip passed legality check, ip: {}", ip); + DataBlock db = null; + try { + db = dbSearcher.memorySearch(ip); + } catch (IOException e) { + logger.error("IO exception,details error:", e); + throw new HiveException("IO exception,details error:", e); + } + if (db == null) { + logger.error("Not exists ip: {}", ip); + result.set(DEFAULT_IP_REGION_FILED_MAP.get(pos)); + return result; + } + logger.debug("search ip:{} return DataBlock: {}.", ip, db); + String region = db.getRegion(); + String[] arr = StringUtils.split(region, '|'); + if (pos < 5) { + result.set(arr[pos]); + } else { + if (pos == 5) { + result.set(String.valueOf(db.getCityId())); + } else if (pos == 6) { + result.set(db.getRegion()); + } else { + result.set(String.valueOf(db.getDataPtr())); + } + } + return result; + } + + public Text evaluate(Text ipT, IntWritable posI) throws HiveException { + String ip = ipT.toString(); + int pos = posI.get(); + return new Text(evaluate(ip, pos)); + } + + public Text evaluate(Text ipT, Text posT) throws HiveException { + String ip = ipT.toString(); + int pos = Integer.parseInt(posT.toString()); + return new Text(evaluate(ip, pos)); + } + + public Text evaluate(Text ipT, LongWritable posI) throws HiveException { + String ip = ipT.toString(); + int pos = (int) posI.get(); + return new Text(evaluate(ip, pos)); + } + + public Text evaluate(Text ipT) throws HiveException { + String ip = ipT.toString(); + return new Text(evaluate(ip, 6)); + } + + public static void main(String[] args) throws HiveException { + UDFIP2Region udfip2Region = new UDFIP2Region(); + System.out.println(udfip2Region.evaluate("39.183.144.171", 0)); + + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArray.java b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArray.java new file mode 100644 index 0000000..a354091 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArray.java @@ -0,0 +1,39 @@ +package com.chinagoods.bigdata.functions.json; + +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.json.JSONArray; +import org.json.JSONException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; + +/** + * @author ruifeng.shan + * date: 2016-07-25 + * time: 16:26 + */ +@Description(name = "json_array", value = "_FUNC_(json) - Convert a string of JSON-encoded array to a Hive array of strings." + , extended = "Example:\n" + + " > SELECT _FUNC_(json_array) FROM src LIMIT 1;") +public class UDFJsonArray extends UDF { + public static final Logger logger = LoggerFactory.getLogger(UDFJsonArray.class); + public ArrayList evaluate(String jsonString) { + if (jsonString == null) { + logger.error("传入json字符串为空"); + return null; + } + try { + JSONArray extractObject = new JSONArray(jsonString); + ArrayList result = new ArrayList<>(); + for (int ii = 0; ii < extractObject.length(); ++ii) { + result.add(extractObject.get(ii).toString()); + } + return result; + } catch (JSONException | NumberFormatException e) { + logger.error("传入json字符串解析异常,\njsonString: {}", jsonString, e); + return null; + } + } +} diff --git a/src/main/java/com/github/aaronshan/functions/json/UDFJsonArrayExtract.java b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayExtract.java similarity index 93% rename from src/main/java/com/github/aaronshan/functions/json/UDFJsonArrayExtract.java rename to src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayExtract.java index 13af7b9..04fbee2 100644 --- a/src/main/java/com/github/aaronshan/functions/json/UDFJsonArrayExtract.java +++ b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayExtract.java @@ -1,8 +1,8 @@ -package com.github.aaronshan.functions.json; +package com.chinagoods.bigdata.functions.json; -import com.github.aaronshan.functions.utils.json.JsonExtract; -import com.github.aaronshan.functions.utils.json.JsonPath; -import com.github.aaronshan.functions.utils.json.JsonUtils; +import com.chinagoods.bigdata.functions.utils.json.JsonExtract; +import com.chinagoods.bigdata.functions.utils.json.JsonPath; +import com.chinagoods.bigdata.functions.utils.json.JsonUtils; import java.util.ArrayList; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; diff --git a/src/main/java/com/github/aaronshan/functions/json/UDFJsonArrayExtractScalar.java b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayExtractScalar.java similarity index 93% rename from src/main/java/com/github/aaronshan/functions/json/UDFJsonArrayExtractScalar.java rename to src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayExtractScalar.java index 97f00e9..767d944 100644 --- a/src/main/java/com/github/aaronshan/functions/json/UDFJsonArrayExtractScalar.java +++ b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayExtractScalar.java @@ -1,8 +1,8 @@ -package com.github.aaronshan.functions.json; +package com.chinagoods.bigdata.functions.json; -import com.github.aaronshan.functions.utils.json.JsonExtract; -import com.github.aaronshan.functions.utils.json.JsonPath; -import com.github.aaronshan.functions.utils.json.JsonUtils; +import com.chinagoods.bigdata.functions.utils.json.JsonExtract; +import com.chinagoods.bigdata.functions.utils.json.JsonPath; +import com.chinagoods.bigdata.functions.utils.json.JsonUtils; import java.util.ArrayList; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; diff --git a/src/main/java/com/github/aaronshan/functions/json/UDFJsonArrayGet.java b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayGet.java similarity index 88% rename from src/main/java/com/github/aaronshan/functions/json/UDFJsonArrayGet.java rename to src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayGet.java index 52c67ea..df0087a 100644 --- a/src/main/java/com/github/aaronshan/functions/json/UDFJsonArrayGet.java +++ b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayGet.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.json; +package com.chinagoods.bigdata.functions.json; -import com.github.aaronshan.functions.utils.json.JsonUtils; +import com.chinagoods.bigdata.functions.utils.json.JsonUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; diff --git a/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayGroup.java b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayGroup.java new file mode 100644 index 0000000..692fb04 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayGroup.java @@ -0,0 +1,102 @@ +package com.chinagoods.bigdata.functions.json; + +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.json.JSONArray; +import org.json.JSONException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; + +/** + * @author ruifeng.shan + * date: 2016-07-25 + * time: 16:26 + */ +@Description(name = "json_array_group", value = "_FUNC_(json_string, group_size, separator) - Convert a JSON array string to grouped arrays with specified group size and separator." + , extended = "Example:\n" + + " > SELECT _FUNC_('[\"a\",\"b\",\"c\",\"d\"]', 2, '#') FROM src LIMIT 1;\n" + + " > SELECT _FUNC_('[\"a\",\"b\",\"c\",\"d\"]', 2) FROM src LIMIT 1;\n" + + " > SELECT _FUNC_('[\"a\",\"b\",\"c\",\"d\"]') FROM src LIMIT 1;") +public class UDFJsonArrayGroup extends UDF { + public static final Logger logger = LoggerFactory.getLogger(UDFJsonArrayGroup.class); + + /** + * 默认分组元素个数 + */ + private static final int DEFAULT_GROUP_SIZE = 2; + + /** + * 默认元素拼接符号 + */ + private static final String DEFAULT_SEPARATOR = "#"; + + /** + * 使用默认参数进行分组 + * @param jsonString JSON数组字符串 + * @return 分组后的数组 + */ + public ArrayList evaluate(String jsonString) { + return evaluate(jsonString, DEFAULT_GROUP_SIZE, DEFAULT_SEPARATOR); + } + + /** + * 使用指定的分组大小和默认分隔符进行分组 + * @param jsonString JSON数组字符串 + * @param groupSize 分组元素个数 + * @return 分组后的数组 + */ + public ArrayList evaluate(String jsonString, Integer groupSize) { + return evaluate(jsonString, groupSize, DEFAULT_SEPARATOR); + } + + /** + * 使用指定的分组大小和分隔符进行分组 + * @param jsonString JSON数组字符串 + * @param groupSize 分组元素个数 + * @param separator 元素拼接符号 + * @return 分组后的数组 + */ + public ArrayList evaluate(String jsonString, Integer groupSize, String separator) { + if (jsonString == null) { + logger.error("传入json字符串为空"); + return null; + } + + if (groupSize == null || groupSize <= 0) { + logger.error("分组元素个数必须大于0,当前值: {}", groupSize); + return null; + } + + if (separator == null) { + separator = DEFAULT_SEPARATOR; + } + + try { + JSONArray jsonArray = new JSONArray(jsonString); + ArrayList result = new ArrayList<>(); + + // 按指定元素个数进行分组 + for (int i = 0; i < jsonArray.length(); i += groupSize) { + StringBuilder groupBuilder = new StringBuilder(); + + // 构建当前组 + for (int j = 0; j < groupSize && (i + j) < jsonArray.length(); j++) { + if (j > 0) { + groupBuilder.append(separator); + } + groupBuilder.append(jsonArray.get(i + j).toString()); + } + + result.add(groupBuilder.toString()); + } + + return result; + } catch (JSONException | NumberFormatException e) { + logger.error("传入json字符串解析异常,\njsonString: {}, groupSize: {}, separator: {}", + jsonString, groupSize, separator, e); + return null; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/github/aaronshan/functions/json/UDFJsonArrayLength.java b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayLength.java similarity index 88% rename from src/main/java/com/github/aaronshan/functions/json/UDFJsonArrayLength.java rename to src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayLength.java index 9f4d00f..117d120 100644 --- a/src/main/java/com/github/aaronshan/functions/json/UDFJsonArrayLength.java +++ b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayLength.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.json; +package com.chinagoods.bigdata.functions.json; -import com.github.aaronshan.functions.utils.json.JsonUtils; +import com.chinagoods.bigdata.functions.utils.json.JsonUtils; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.LongWritable; diff --git a/src/main/java/com/github/aaronshan/functions/json/UDFJsonExtract.java b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonExtract.java similarity index 83% rename from src/main/java/com/github/aaronshan/functions/json/UDFJsonExtract.java rename to src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonExtract.java index e594b40..1b56cbf 100644 --- a/src/main/java/com/github/aaronshan/functions/json/UDFJsonExtract.java +++ b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonExtract.java @@ -1,7 +1,7 @@ -package com.github.aaronshan.functions.json; +package com.chinagoods.bigdata.functions.json; -import com.github.aaronshan.functions.utils.json.JsonExtract; -import com.github.aaronshan.functions.utils.json.JsonPath; +import com.chinagoods.bigdata.functions.utils.json.JsonExtract; +import com.chinagoods.bigdata.functions.utils.json.JsonPath; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; diff --git a/src/main/java/com/github/aaronshan/functions/json/UDFJsonExtractScalar.java b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonExtractScalar.java similarity index 84% rename from src/main/java/com/github/aaronshan/functions/json/UDFJsonExtractScalar.java rename to src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonExtractScalar.java index 96157c4..77081fb 100644 --- a/src/main/java/com/github/aaronshan/functions/json/UDFJsonExtractScalar.java +++ b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonExtractScalar.java @@ -1,7 +1,7 @@ -package com.github.aaronshan.functions.json; +package com.chinagoods.bigdata.functions.json; -import com.github.aaronshan.functions.utils.json.JsonExtract; -import com.github.aaronshan.functions.utils.json.JsonPath; +import com.chinagoods.bigdata.functions.utils.json.JsonExtract; +import com.chinagoods.bigdata.functions.utils.json.JsonPath; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; diff --git a/src/main/java/com/github/aaronshan/functions/json/UDFJsonSize.java b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonSize.java similarity index 80% rename from src/main/java/com/github/aaronshan/functions/json/UDFJsonSize.java rename to src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonSize.java index e934ebe..c7f8d06 100644 --- a/src/main/java/com/github/aaronshan/functions/json/UDFJsonSize.java +++ b/src/main/java/com/chinagoods/bigdata/functions/json/UDFJsonSize.java @@ -1,9 +1,7 @@ -package com.github.aaronshan.functions.json; +package com.chinagoods.bigdata.functions.json; -import com.github.aaronshan.functions.utils.json.JsonExtract; -import com.github.aaronshan.functions.utils.json.JsonPath; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import com.chinagoods.bigdata.functions.utils.json.JsonExtract; +import com.chinagoods.bigdata.functions.utils.json.JsonPath; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.LongWritable; diff --git a/src/main/java/com/chinagoods/bigdata/functions/json/UDFToJson.java b/src/main/java/com/chinagoods/bigdata/functions/json/UDFToJson.java new file mode 100644 index 0000000..41c6f07 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/json/UDFToJson.java @@ -0,0 +1,463 @@ +package com.chinagoods.bigdata.functions.json; + +import org.apache.hadoop.hive.common.type.HiveDecimal; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ConstantObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ListObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.MapObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category; +import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory; +import org.apache.hadoop.hive.serde2.objectinspector.StructField; +import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.*; +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; + +import java.io.IOException; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +@Description(name = "to_json", + value = "_FUNC_(struct, convert_to_camel_case) - Returns a JSON string from an arbitrary Hive structure." +) +public class UDFToJson extends GenericUDF { + private InspectorHandle inspHandle; + private Boolean convertFlag = Boolean.FALSE; + private JsonFactory jsonFactory; + + static public String toCamelCase(String underscore) { + StringBuilder sb = new StringBuilder(); + String[] splArr = underscore.toLowerCase().split("_"); + + sb.append(splArr[0]); + for (int i = 1; i < splArr.length; ++i) { + String word = splArr[i]; + char firstChar = word.charAt(0); + if (firstChar >= 'a' && firstChar <= 'z') { + sb.append((char) (word.charAt(0) + 'A' - 'a')); + sb.append(word.substring(1)); + } else { + sb.append(word); + } + + } + return sb.toString(); + } + + private interface InspectorHandle { + abstract public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException; + } + + + private class MapInspectorHandle implements InspectorHandle { + private MapObjectInspector mapInspector; + private StringObjectInspector keyObjectInspector; + private InspectorHandle valueInspector; + + + public MapInspectorHandle(MapObjectInspector mInsp) throws UDFArgumentException { + mapInspector = mInsp; + try { + keyObjectInspector = (StringObjectInspector) mInsp.getMapKeyObjectInspector(); + } catch (ClassCastException castExc) { + throw new UDFArgumentException("Only Maps with strings as keys can be converted to valid JSON"); + } + valueInspector = GenerateInspectorHandle(mInsp.getMapValueObjectInspector()); + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + if (obj == null) { + gen.writeNull(); + } else { + gen.writeStartObject(); + Map map = mapInspector.getMap(obj); + Iterator iter = map.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = iter.next(); + String keyJson = keyObjectInspector.getPrimitiveJavaObject(entry.getKey()); + if (convertFlag) { + gen.writeFieldName(toCamelCase(keyJson)); + } else { + gen.writeFieldName(keyJson); + } + valueInspector.generateJson(gen, entry.getValue()); + } + gen.writeEndObject(); + } + } + + } + + private class StructInspectorHandle implements InspectorHandle { + private StructObjectInspector structInspector; + private List fieldNames; + private List fieldInspectorHandles; + + public StructInspectorHandle(StructObjectInspector insp) throws UDFArgumentException { + structInspector = insp; + List fieldList = insp.getAllStructFieldRefs(); + this.fieldNames = new ArrayList<>(); + this.fieldInspectorHandles = new ArrayList<>(); + for (StructField sf : fieldList) { + fieldNames.add(sf.getFieldName()); + fieldInspectorHandles.add(GenerateInspectorHandle(sf.getFieldObjectInspector())); + } + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + //// Interpret a struct as a map ... + if (obj == null) { + gen.writeNull(); + } else { + gen.writeStartObject(); + List structObjs = structInspector.getStructFieldsDataAsList(obj); + + for (int i = 0; i < fieldNames.size(); ++i) { + String fieldName = fieldNames.get(i); + if (convertFlag) { + gen.writeFieldName(toCamelCase(fieldName)); + } else { + gen.writeFieldName(fieldName); + } + fieldInspectorHandles.get(i).generateJson(gen, structObjs.get(i)); + } + gen.writeEndObject(); + } + } + + } + + + private class ArrayInspectorHandle implements InspectorHandle { + private ListObjectInspector arrayInspector; + private InspectorHandle valueInspector; + + + public ArrayInspectorHandle(ListObjectInspector lInsp) throws UDFArgumentException { + arrayInspector = lInsp; + valueInspector = GenerateInspectorHandle(arrayInspector.getListElementObjectInspector()); + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + if (obj == null) { + gen.writeNull(); + } else { + gen.writeStartArray(); + List list = arrayInspector.getList(obj); + for (Object listObj : list) { + valueInspector.generateJson(gen, listObj); + } + gen.writeEndArray(); + } + } + + } + + private static class StringInspectorHandle implements InspectorHandle { + private StringObjectInspector strInspector; + + + public StringInspectorHandle(StringObjectInspector insp) { + strInspector = insp; + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + if (obj == null) { + gen.writeNull(); + } else { + String str = strInspector.getPrimitiveJavaObject(obj); + gen.writeString(str); + } + } + + } + + private class IntInspectorHandle implements InspectorHandle { + private IntObjectInspector intInspector; + + public IntInspectorHandle(IntObjectInspector insp) { + intInspector = insp; + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + if (obj == null) { + gen.writeNull(); + } else { + int num = intInspector.get(obj); + gen.writeNumber(num); + } + } + } + + private static class DecimalInspectorHandle implements InspectorHandle { + + private HiveDecimalObjectInspector decimalInspector; + + public DecimalInspectorHandle(HiveDecimalObjectInspector insp) { + decimalInspector = insp; + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + if (obj == null) { + gen.writeNull(); + } else { + HiveDecimal num = decimalInspector.getPrimitiveJavaObject(obj); + gen.writeNumber(num.bigDecimalValue()); + } + } + } + + private static class DoubleInspectorHandle implements InspectorHandle { + private DoubleObjectInspector dblInspector; + + public DoubleInspectorHandle(DoubleObjectInspector insp) { + dblInspector = insp; + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + if (obj == null) { + gen.writeNull(); + } else { + double num = dblInspector.get(obj); + gen.writeNumber(num); + } + } + } + + private static class LongInspectorHandle implements InspectorHandle { + private LongObjectInspector longInspector; + + public LongInspectorHandle(LongObjectInspector insp) { + longInspector = insp; + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + if (obj == null) { + gen.writeNull(); + } else { + long num = longInspector.get(obj); + gen.writeNumber(num); + } + } + } + + private static class ShortInspectorHandle implements InspectorHandle { + private ShortObjectInspector shortInspector; + + public ShortInspectorHandle(ShortObjectInspector insp) { + shortInspector = insp; + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + if (obj == null) { + gen.writeNull(); + } else { + short num = shortInspector.get(obj); + gen.writeNumber(num); + } + } + } + + + private static class ByteInspectorHandle implements InspectorHandle { + private ByteObjectInspector byteInspector; + + public ByteInspectorHandle(ByteObjectInspector insp) { + byteInspector = insp; + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + if (obj == null) { + gen.writeNull(); + } else { + byte num = byteInspector.get(obj); + gen.writeNumber(num); + } + } + } + + + private static class FloatInspectorHandle implements InspectorHandle { + private FloatObjectInspector floatInspector; + + public FloatInspectorHandle(FloatObjectInspector insp) { + floatInspector = insp; + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + if (obj == null) { + gen.writeNull(); + } else { + float num = floatInspector.get(obj); + gen.writeNumber(num); + } + } + } + + private static class BooleanInspectorHandle implements InspectorHandle { + private BooleanObjectInspector boolInspector; + + public BooleanInspectorHandle(BooleanObjectInspector insp) { + boolInspector = insp; + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + if (obj == null) { + gen.writeNull(); + } else { + boolean tf = boolInspector.get(obj); + gen.writeBoolean(tf); + } + } + } + + private static class BinaryInspectorHandle implements InspectorHandle { + private BinaryObjectInspector binaryInspector; + + public BinaryInspectorHandle(BinaryObjectInspector insp) { + binaryInspector = insp; + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + if (obj == null) { + gen.writeNull(); + } else { + byte[] bytes = binaryInspector.getPrimitiveJavaObject(obj); + gen.writeBinary(bytes); + } + } + } + + private static class TimestampInspectorHandle implements InspectorHandle { + private TimestampObjectInspector timestampInspector; + private DateTimeFormatter isoFormatter = ISODateTimeFormat.dateTimeNoMillis(); + + public TimestampInspectorHandle(TimestampObjectInspector insp) { + timestampInspector = insp; + } + + @Override + public void generateJson(JsonGenerator gen, Object obj) throws JsonGenerationException, IOException { + if (obj == null) { + gen.writeNull(); + } else { + Timestamp timestamp = timestampInspector.getPrimitiveJavaObject(obj); + String timeStr = isoFormatter.print(timestamp.getTime()); + gen.writeString(timeStr); + } + } + } + + + private InspectorHandle GenerateInspectorHandle(ObjectInspector insp) throws UDFArgumentException { + Category cat = insp.getCategory(); + if (cat == Category.MAP) { + return new MapInspectorHandle((MapObjectInspector) insp); + } else if (cat == Category.LIST) { + return new ArrayInspectorHandle((ListObjectInspector) insp); + } else if (cat == Category.STRUCT) { + return new StructInspectorHandle((StructObjectInspector) insp); + } else if (cat == Category.PRIMITIVE) { + PrimitiveObjectInspector primInsp = (PrimitiveObjectInspector) insp; + PrimitiveCategory primCat = primInsp.getPrimitiveCategory(); + if (primCat == PrimitiveCategory.STRING) { + return new StringInspectorHandle((StringObjectInspector) primInsp); + } else if (primCat == PrimitiveCategory.INT) { + return new IntInspectorHandle((IntObjectInspector) primInsp); + } else if (primCat == PrimitiveCategory.LONG) { + return new LongInspectorHandle((LongObjectInspector) primInsp); + } else if (primCat == PrimitiveCategory.SHORT) { + return new ShortInspectorHandle((ShortObjectInspector) primInsp); + } else if (primCat == PrimitiveCategory.BOOLEAN) { + return new BooleanInspectorHandle((BooleanObjectInspector) primInsp); + } else if (primCat == PrimitiveCategory.FLOAT) { + return new FloatInspectorHandle((FloatObjectInspector) primInsp); + } else if (primCat == PrimitiveCategory.DOUBLE) { + return new DoubleInspectorHandle((DoubleObjectInspector) primInsp); + } else if (primCat == PrimitiveCategory.BYTE) { + return new ByteInspectorHandle((ByteObjectInspector) primInsp); + } else if (primCat == PrimitiveCategory.BINARY) { + return new BinaryInspectorHandle((BinaryObjectInspector) primInsp); + } else if (primCat == PrimitiveCategory.TIMESTAMP) { + return new TimestampInspectorHandle((TimestampObjectInspector) primInsp); + } else if (primCat == PrimitiveCategory.DECIMAL) { + return new DecimalInspectorHandle((HiveDecimalObjectInspector) primInsp); + } + } + /// Dunno ... + throw new UDFArgumentException("Don't know how to handle object inspector " + insp); + } + + + @Override + public Object evaluate(DeferredObject[] args) throws HiveException { + try { + StringWriter writer = new StringWriter(); + JsonGenerator gen = jsonFactory.createJsonGenerator(writer); + inspHandle.generateJson(gen, args[0].get()); + gen.close(); + writer.close(); + return writer.toString(); + } catch (IOException io) { + throw new HiveException(io); + } + + } + + @Override + public String getDisplayString(String[] args) { + return "to_json(" + args[0] + ")"; + } + + @Override + public ObjectInspector initialize(ObjectInspector[] args) + throws UDFArgumentException { + if (args.length != 1 && args.length != 2) { + throw new UDFArgumentException(" ToJson takes an object as an argument, and an optional to_camel_case flag"); + } + ObjectInspector oi = args[0]; + inspHandle = GenerateInspectorHandle(oi); + + if (args.length == 2) { + ObjectInspector flagInsp = args[1]; + if (flagInsp.getCategory() != Category.PRIMITIVE + || ((PrimitiveObjectInspector) flagInsp).getPrimitiveCategory() + != PrimitiveCategory.BOOLEAN + || !(flagInsp instanceof ConstantObjectInspector)) { + throw new UDFArgumentException(" ToJson takes an object as an argument, and an optional to_camel_case flag"); + } + WritableConstantBooleanObjectInspector constInsp = (WritableConstantBooleanObjectInspector) flagInsp; + convertFlag = constInsp.getWritableConstantValue().get(); + } + + jsonFactory = new JsonFactory(); + + return PrimitiveObjectInspectorFactory.javaStringObjectInspector; + } +} \ No newline at end of file diff --git a/src/main/java/com/chinagoods/bigdata/functions/logistic/UDFLogisticNoValid.java b/src/main/java/com/chinagoods/bigdata/functions/logistic/UDFLogisticNoValid.java new file mode 100644 index 0000000..56ca86e --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/logistic/UDFLogisticNoValid.java @@ -0,0 +1,139 @@ +package com.chinagoods.bigdata.functions.logistic; + +import com.google.common.collect.ImmutableMap; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.io.BooleanWritable; +import org.apache.hadoop.io.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author xiaowei.song + * date: 2022-11-24 + * time: 14:56 + */ +@Description(name = "is_valid_logistic_no" + , value = "_FUNC_(string, string) - Determine whether the logistics order number corresponding to the entered logistics company is correct." + , extended = "Example:\n > select _FUNC_(string, string) from src;") +public class UDFLogisticNoValid extends UDF { + private static final Logger logger = LoggerFactory.getLogger(UDFLogisticNoValid.class); + + + private BooleanWritable result = new BooleanWritable(false); + + public static final Map LOGISTIC_NO_PATTERN_MAP = ImmutableMap.builder() + .put("宅急送", Pattern.compile("^[a-zA-Z0-9]{10}$|^(42|16)[0-9]{8}$|^A[0-9]{12}$|^ZJS[0-9]{12}$")) + // 12位 + .put("顺丰速运", Pattern.compile("^[A-Za-z0-9-]{4,35}$")) + // 12位 + .put("申通快递", Pattern.compile("^(268|888|588|688|368|468|568|668|773|768|868|968)[0-9]{9,13}$|^(11|22|40|268|888|588|688|368|468|568|668|768|868|968)[0-9]{10}$|^(STO)[0-9]{10}$|^(33)[0-9]{11}$|^(4)[0-9]{12}$|^(55)[0-9]{11}$|^(66)[0-9]{11}$|^(77)[0-9]{13}$|^(88)[0-9]{13}$|^(99)[0-9]{13}$")) + // 13位 + .put("EMS", Pattern.compile("^[A-Z]{2}[0-9]{9}[A-Z]{2}$|^(10|11|12)[0-9]{11}$|^(50|51|52)[0-9]{11}$|^(95|97|98|99)[0-9]{11}$")) + // 13位 + .put("韵达快递", Pattern.compile("^[0-9]{15}$|^[0-9]{13}$")) + // JT3002232682242 + .put("百世快递", Pattern.compile("^^JT[0-9]{12,13}$|(([ABDE])[0-9]{12})$|^(BXA[0-9]{10})$|^(K8[0-9]{11})$|^(02[0-9]{11})$|^(000[0-9]{10})$|^(C0000[0-9]{8})$|^((21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|61|63)[0-9]{10})$|^((5)[0-9]{13,14})$|^7[0-9]{13}$|^6[0-9]{13}$|^58[0-9]{14}$")) + // 12位 + .put("圆通速递", Pattern.compile("^[A-Za-z0-9]{2}[0-9]{10,13}$|^[A-Za-z0-9]{2}[0-9]{8}$|^[6-9][0-9]{17}$|^[DD]{2}[8-9][0-9]{15}$|^[Y][0-9]{12}$")) + .put("天天快递", Pattern.compile("(66|77|88|(5(5|6|8)))\\d{10}|(99(5|8))\\d{9}|TT(66|88|99|(5(6|7)))\\d{11}")) + .put("全峰快递", Pattern.compile("^[0-6|9][0-9]{11}$|^[7][0-8][0-9]{10}$|^[0-9]{15}$|^[S][0-9]{9,11}(-|)P[0-9]{1,2}$|^[0-9]{13}$|^[8][0,2-9][0,2-9][0-9]{9}$|^[8][1][0,2-9][0-9]{9}$|^[8][0,2-9][0-9]{10}$|^[8][1][1][0][8][9][0-9]{6}$")) + .put("EMS经济快递", Pattern.compile("^[A-Z]{2}[0-9]{9}[A-Z]{2}$|^(10|11)[0-9]{11}$|^(50|51)[0-9]{11}$|^(95|97)[0-9]{11}$")) + .put("优速快递", Pattern.compile("^VIP[0-9]{9}|V[0-9]{11}|[0-9]{12}$|^LBX[0-9]{15}-[2-9AZ]{1}-[1-9A-Z]{1}$|^(9001)[0-9]{8}$")) + // 8-9位 + .put("德邦快递", Pattern.compile("^[0-9]{8,10}$|^\\d{15,}[-\\d]+$|^DPK\\d{11,}[-\\d]+$")) + // DPK300585915441 + .put("德邦", Pattern.compile("^[0-9]{8,10}$|^\\d{15,}[-\\d]+$|^DPK\\d{11,}[-\\d]+$")) + .put("速尔快运", Pattern.compile("^(SUR)[0-9]{12}$|^[0-9]{12}$")) + .put("联邦快递", Pattern.compile("^[0-9]{12}$")) + .put("华强物流", Pattern.compile("^[A-Za-z0-9]*[0|2|4|6|8]$")) + .put("全一快递", Pattern.compile("^\\d{12}|\\d{11}$")) + .put("天地华宇", Pattern.compile("^[A-Za-z0-9]{8,9}$")) + .put("百世物流", Pattern.compile("^[0-9]{11,12}$")) + .put("龙邦速递", Pattern.compile("^[0-9]{12}$|^LBX[0-9]{15}-[2-9AZ]{1}-[1-9A-Z]{1}$|^[0-9]{15}$|^[0-9]{15}-[1-9A-Z]{1}-[1-9A-Z]{1}$")) + .put("新邦物流", Pattern.compile("^[0-9]{8}$|^[0-9]{10}$")) + // 432542035598773 + .put("中通快递", Pattern.compile("^([0-9]{14})$|^((5711|2008|2009|2010|2013)[0-9]{8})$|^((91|92|93|94|95|98|36|68|39|50|53|37)[0-9]{10})$|^(4)[0-9]{11}$|^(90)[0-9]{10}$|^(120)[0-9]{9}$|^(780)[0-9]{9}$|^(881)[0-9]{9}$|^(882|885)[0-9]{9}$|^(54|55|56)[0-9]{10}$|^(960)[0-9]{9}$|^(665|666)[0-9]{9}$|^(63)[0-9]{10}$|^(64)[0-9]{10}$|^(72)[0-9]{10}$|^2[1-9][0-9]{10}$")) + // 12位 + .put("中通快运", Pattern.compile("^([0-9]{12})$")) + .put("国通快递", Pattern.compile("^(3(([0-6]|[8-9])\\d{8})|((2|4|5|6)\\d{9})|(7(?![0|1|2|3|4|5|7|8|9])\\d{9})|(8(?![2-9])\\d{9})|(2|4)\\d{11})$")) + .put("快捷快递", Pattern.compile("^(?!440)(?!510)(?!520)(?!5231)([0-9]{9,13})$|^(P330[0-9]{8})$|^(D[0-9]{11})$|^(319)[0-9]{11}$|^(56)[0-9]{10}$|^(536)[0-9]{9}$")) + .put("能达速递", Pattern.compile("^((88|)[0-9]{10})$|^((1|2|3|5|)[0-9]{9})$|^(90000[0-9]{7})$")) + .put("如风达配送", Pattern.compile("^[\\x21-\\x7e]{1,100}$")) + .put("信丰物流", Pattern.compile("^130[0-9]{9}|13[7-9]{1}[0-9]{9}|18[8-9]{1}[0-9]{9}$")) + .put("广东EMS", Pattern.compile("^[a-zA-Z]{2}[0-9]{9}[a-zA-Z]{2}$")) + // 1240921381750 + .put("邮政快递包裹", Pattern.compile("^([GA]|[KQ]|[PH]){2}[0-9]{9}([2-5][0-9]|[1][1-9]|[6][0-5])$|^[0-9]{13}$|^[99]{2}[0-9]{11}$|^[96]{2}[0-9]{11}$|^[98]{2}[0-9]{11}$")) + .put("德邦物流", Pattern.compile("^[0-9]{8,10}$|^\\d{15,}[-\\d]+$")) + .put("黑猫宅急便", Pattern.compile("^[0-9]{12}$")) + .put("联昊通", Pattern.compile("^[0-9]{9,12}$")) + .put("E速宝", Pattern.compile("[0-9a-zA-Z-]{5,20}")) + .put("增益速递", Pattern.compile("^[0-9]{12,13}$")) + .put("极兔速递", Pattern.compile("^JT[0-9]{12,13}$")) + // JDVA11408814483 + .put("京东物流", Pattern.compile("^JD[XK][0-9]{12}$|^JDV[A-Z][0-9]{11}$")) + //300527476792 + .put("安能快运", Pattern.compile("^[0-9]{12}$")) + // 300527476792 + .put("安能快递", Pattern.compile("^[0-9]{12}$")) + // 106027097895 + .put("壹米滴答", Pattern.compile("^[0-9]{12}$")) + .build(); + + public UDFLogisticNoValid() { + } + + /** + * 判断物流单号是否合规 + * @param companyNameT 物流公司名称 + * @param noT 物流单号 + * @return 是否合规 + **/ + public BooleanWritable evaluate(Text companyNameT, Text noT) { + result.set(false); + if (companyNameT == null || noT == null) { + return result; + } + + String companyName = companyNameT.toString(); + String no = noT.toString(); + + Pattern pattern = LOGISTIC_NO_PATTERN_MAP.get(companyName); + logger.debug("匹配模式为: {}", pattern); + if (pattern == null) { + logger.error("对应快递公司模式为空,快递公司: {}", companyName); + return result; + } + Matcher m = pattern.matcher(no); + result.set(false); + if(m.find()) { + result.set(true); + } else { + result.set(false); + logger.warn("匹配失败,快递公司为:[{}], 单号为: [{}]", companyName, no); + } + return result; + } + + public static void main(String[] args) { + UDFLogisticNoValid udfLogisticNoValid = new UDFLogisticNoValid(); +// System.out.println(udfLogisticNoValid.evaluate(new Text("圆通速递"), new Text("855658868"))); +// System.out.println(udfLogisticNoValid.evaluate(new Text("中通快递"), new Text("432542035598773"))); +// System.out.println(udfLogisticNoValid.evaluate(new Text("中通快运"), new Text("202197601431"))); +// System.out.println(udfLogisticNoValid.evaluate(new Text("申通快递"), new Text("77316523125896"))); +// System.out.println(udfLogisticNoValid.evaluate(new Text("韵达快递"), new Text("462598779470531"))); + System.out.println(udfLogisticNoValid.evaluate(new Text("邮政快递包裹"), new Text("1240921381750"))); +// System.out.println(udfLogisticNoValid.evaluate(new Text("极兔速递"), new Text("JT0006968326954"))); +// System.out.println(udfLogisticNoValid.evaluate(new Text("德邦快递"), new Text("DPK364112047425"))); +// System.out.println(udfLogisticNoValid.evaluate(new Text("德邦"), new Text("DPK300585915441"))); +// System.out.println(udfLogisticNoValid.evaluate(new Text("百世快递"), new Text("JT3002232682242"))); +// System.out.println(udfLogisticNoValid.evaluate(new Text("京东物流"), new Text("JDVA11408814483"))); +// System.out.println(udfLogisticNoValid.evaluate(new Text("邮政快递包裹"), new Text("4309597495550"))); +// System.out.println(udfLogisticNoValid.evaluate(new Text("壹米滴答"), new Text("106027097895"))); +// System.out.println(udfLogisticNoValid.evaluate(new Text("安能快递"), new Text("300527476792"))); + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/map/UDFMap2SortKeyArray.java b/src/main/java/com/chinagoods/bigdata/functions/map/UDFMap2SortKeyArray.java new file mode 100644 index 0000000..0d4a3d8 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/map/UDFMap2SortKeyArray.java @@ -0,0 +1,106 @@ +package com.chinagoods.bigdata.functions.map; + +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; +import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF.DeferredJavaObject; +import org.apache.hadoop.hive.serde.serdeConstants; +import org.apache.hadoop.hive.serde2.objectinspector.MapObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory; +import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author xiaowei.song + * date: 2016-07-27 + * time: 15:39 + */ +@Description(name = "map2sort_key_array" + , value = "_FUNC_(map) - Returns the value array of map keys in positive order." + , extended = "Example:\n > select _FUNC_(map) from src;") +public class UDFMap2SortKeyArray extends GenericUDF { + /** + * Number of arguments to this UDF + **/ + private static final int ARG_COUNT = 1; + private transient MapObjectInspector mapOi; + List result = new ArrayList<>(); + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + // Check if two arguments were passed + if (arguments.length != ARG_COUNT) { + throw new UDFArgumentLengthException( + "The function map2sort_key_array(map) takes exactly " + ARG_COUNT + " arguments."); + } + + // Check if one argument is of category Map + for (int i = 0; i < 1; i++) { + if (!arguments[i].getCategory().equals(ObjectInspector.Category.MAP)) { + throw new UDFArgumentTypeException(i, + "\"" + serdeConstants.MAP_TYPE_NAME + "\" " + + "expected at function map2sort_key_array, but " + + "\"" + arguments[i].getTypeName() + "\" " + + "is found"); + } + } + + mapOi = (MapObjectInspector) arguments[0]; + + ObjectInspector mapValueOI = mapOi.getMapValueObjectInspector(); + + return ObjectInspectorFactory.getStandardListObjectInspector(mapValueOI); + } + + @Override + public Object evaluate(DeferredObject[] arguments) throws HiveException { + Map mObj = mapOi.getMap(arguments[0].get()); + + if (mObj == null || mObj.size() <= 0) { + return null; + } + result.clear(); + Map mTrans = new HashMap<>(mObj.size()); + mObj.forEach((k, v) -> { + mTrans.put(k.toString(), v); + }); + Set mKeySet = mObj.keySet(); + List mKeyList = mKeySet.stream().map(Object::toString).sorted(Comparator.naturalOrder()).collect(Collectors.toList()); + for (String k : mKeyList) { + result.add(mTrans.get(k)); + } + return result; + } + + @Override + public String getDisplayString(String[] strings) { + assert (strings.length == ARG_COUNT); + return "map2sort_key_array(" + strings[0] + ")"; + } + + public static void main(String[] args) throws HiveException { + UDFMap2SortKeyArray map2SortKeyArray = new UDFMap2SortKeyArray(); + Map sourceMap = new HashMap(){ + { + put("2021-04-05", "2"); + put("2021-05-04", "1"); + put("2021-06-03", "8"); + put("2021-01-01", "100"); + } + }; + DeferredObject[] arr = new DeferredObject[1]; + arr[0] = new GenericUDF.DeferredJavaObject(sourceMap); + ObjectInspector[] objArr = new ObjectInspector[1]; + objArr[0] = ObjectInspectorFactory.getStandardMapObjectInspector(PrimitiveObjectInspectorFactory.javaStringObjectInspector, PrimitiveObjectInspectorFactory.javaStringObjectInspector); + map2SortKeyArray.initialize(objArr); + System.out.println(map2SortKeyArray.evaluate(arr)); + } +} diff --git a/src/main/java/com/github/aaronshan/functions/map/UDFMapBuild.java b/src/main/java/com/chinagoods/bigdata/functions/map/UDFMapBuild.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/map/UDFMapBuild.java rename to src/main/java/com/chinagoods/bigdata/functions/map/UDFMapBuild.java index 12d628e..9bc912f 100644 --- a/src/main/java/com/github/aaronshan/functions/map/UDFMapBuild.java +++ b/src/main/java/com/chinagoods/bigdata/functions/map/UDFMapBuild.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.map; +package com.chinagoods.bigdata.functions.map; import java.util.LinkedHashMap; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/github/aaronshan/functions/map/UDFMapConcat.java b/src/main/java/com/chinagoods/bigdata/functions/map/UDFMapConcat.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/map/UDFMapConcat.java rename to src/main/java/com/chinagoods/bigdata/functions/map/UDFMapConcat.java index 6558cbf..355a938 100644 --- a/src/main/java/com/github/aaronshan/functions/map/UDFMapConcat.java +++ b/src/main/java/com/chinagoods/bigdata/functions/map/UDFMapConcat.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.map; +package com.chinagoods.bigdata.functions.map; import java.util.LinkedHashMap; import java.util.Map; diff --git a/src/main/java/com/github/aaronshan/functions/map/UDFMapElementAt.java b/src/main/java/com/chinagoods/bigdata/functions/map/UDFMapElementAt.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/map/UDFMapElementAt.java rename to src/main/java/com/chinagoods/bigdata/functions/map/UDFMapElementAt.java index e3024ab..b67698c 100644 --- a/src/main/java/com/github/aaronshan/functions/map/UDFMapElementAt.java +++ b/src/main/java/com/chinagoods/bigdata/functions/map/UDFMapElementAt.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.map; +package com.chinagoods.bigdata.functions.map; import java.util.Map; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/github/aaronshan/functions/map/UDFMapEquals.java b/src/main/java/com/chinagoods/bigdata/functions/map/UDFMapEquals.java similarity index 96% rename from src/main/java/com/github/aaronshan/functions/map/UDFMapEquals.java rename to src/main/java/com/chinagoods/bigdata/functions/map/UDFMapEquals.java index e46c75c..d4b78a7 100644 --- a/src/main/java/com/github/aaronshan/functions/map/UDFMapEquals.java +++ b/src/main/java/com/chinagoods/bigdata/functions/map/UDFMapEquals.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.map; +package com.chinagoods.bigdata.functions.map; -import com.github.aaronshan.functions.utils.MapUtils; +import com.chinagoods.bigdata.functions.utils.MapUtils; import java.util.Map; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; @@ -11,7 +11,6 @@ import org.apache.hadoop.hive.serde.serdeConstants; import org.apache.hadoop.hive.serde2.objectinspector.MapObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; -import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; import org.apache.hadoop.io.BooleanWritable; diff --git a/src/main/java/com/github/aaronshan/functions/math/UDFMathCosineSimilarity.java b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathCosineSimilarity.java similarity index 99% rename from src/main/java/com/github/aaronshan/functions/math/UDFMathCosineSimilarity.java rename to src/main/java/com/chinagoods/bigdata/functions/math/UDFMathCosineSimilarity.java index 000ac43..eefc624 100644 --- a/src/main/java/com/github/aaronshan/functions/math/UDFMathCosineSimilarity.java +++ b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathCosineSimilarity.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.math; +package com.chinagoods.bigdata.functions.math; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; diff --git a/src/main/java/com/github/aaronshan/functions/math/UDFMathFromBase.java b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathFromBase.java similarity index 90% rename from src/main/java/com/github/aaronshan/functions/math/UDFMathFromBase.java rename to src/main/java/com/chinagoods/bigdata/functions/math/UDFMathFromBase.java index a8770c3..3c39dd7 100644 --- a/src/main/java/com/github/aaronshan/functions/math/UDFMathFromBase.java +++ b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathFromBase.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.math; +package com.chinagoods.bigdata.functions.math; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; @@ -6,7 +6,7 @@ import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; -import static com.github.aaronshan.functions.utils.MathUtils.checkRadix; +import static com.chinagoods.bigdata.functions.utils.MathUtils.checkRadix; import static java.lang.String.format; /** diff --git a/src/main/java/com/github/aaronshan/functions/math/UDFMathInfinity.java b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathInfinity.java similarity index 92% rename from src/main/java/com/github/aaronshan/functions/math/UDFMathInfinity.java rename to src/main/java/com/chinagoods/bigdata/functions/math/UDFMathInfinity.java index 1c66a2a..f47d70d 100644 --- a/src/main/java/com/github/aaronshan/functions/math/UDFMathInfinity.java +++ b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathInfinity.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.math; +package com.chinagoods.bigdata.functions.math; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/github/aaronshan/functions/math/UDFMathInverseNormalCdf.java b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathInverseNormalCdf.java similarity index 88% rename from src/main/java/com/github/aaronshan/functions/math/UDFMathInverseNormalCdf.java rename to src/main/java/com/chinagoods/bigdata/functions/math/UDFMathInverseNormalCdf.java index 05b36f3..6e60a51 100644 --- a/src/main/java/com/github/aaronshan/functions/math/UDFMathInverseNormalCdf.java +++ b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathInverseNormalCdf.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.math; +package com.chinagoods.bigdata.functions.math; import org.apache.commons.math3.special.Erf; import org.apache.hadoop.hive.ql.exec.Description; @@ -6,7 +6,7 @@ import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.io.DoubleWritable; -import static com.github.aaronshan.functions.utils.Failures.checkCondition; +import static com.chinagoods.bigdata.functions.utils.Failures.checkCondition; /** * @author ruifeng.shan diff --git a/src/main/java/com/github/aaronshan/functions/math/UDFMathIsFinite.java b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathIsFinite.java similarity index 95% rename from src/main/java/com/github/aaronshan/functions/math/UDFMathIsFinite.java rename to src/main/java/com/chinagoods/bigdata/functions/math/UDFMathIsFinite.java index 02c8ce1..b5850ec 100644 --- a/src/main/java/com/github/aaronshan/functions/math/UDFMathIsFinite.java +++ b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathIsFinite.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.math; +package com.chinagoods.bigdata.functions.math; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/github/aaronshan/functions/math/UDFMathIsInfinite.java b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathIsInfinite.java similarity index 96% rename from src/main/java/com/github/aaronshan/functions/math/UDFMathIsInfinite.java rename to src/main/java/com/chinagoods/bigdata/functions/math/UDFMathIsInfinite.java index ab448b5..97d6f62 100644 --- a/src/main/java/com/github/aaronshan/functions/math/UDFMathIsInfinite.java +++ b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathIsInfinite.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.math; +package com.chinagoods.bigdata.functions.math; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/github/aaronshan/functions/math/UDFMathIsNaN.java b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathIsNaN.java similarity index 94% rename from src/main/java/com/github/aaronshan/functions/math/UDFMathIsNaN.java rename to src/main/java/com/chinagoods/bigdata/functions/math/UDFMathIsNaN.java index ca590ba..444ad52 100644 --- a/src/main/java/com/github/aaronshan/functions/math/UDFMathIsNaN.java +++ b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathIsNaN.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.math; +package com.chinagoods.bigdata.functions.math; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/github/aaronshan/functions/math/UDFMathNaN.java b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathNaN.java similarity index 94% rename from src/main/java/com/github/aaronshan/functions/math/UDFMathNaN.java rename to src/main/java/com/chinagoods/bigdata/functions/math/UDFMathNaN.java index 640c651..7ce819c 100644 --- a/src/main/java/com/github/aaronshan/functions/math/UDFMathNaN.java +++ b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathNaN.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.math; +package com.chinagoods.bigdata.functions.math; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/github/aaronshan/functions/math/UDFMathNormalCdf.java b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathNormalCdf.java similarity index 88% rename from src/main/java/com/github/aaronshan/functions/math/UDFMathNormalCdf.java rename to src/main/java/com/chinagoods/bigdata/functions/math/UDFMathNormalCdf.java index 98058bc..06169a1 100644 --- a/src/main/java/com/github/aaronshan/functions/math/UDFMathNormalCdf.java +++ b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathNormalCdf.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.math; +package com.chinagoods.bigdata.functions.math; import org.apache.commons.math3.special.Erf; import org.apache.hadoop.hive.ql.exec.Description; @@ -6,7 +6,7 @@ import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.io.DoubleWritable; -import static com.github.aaronshan.functions.utils.Failures.checkCondition; +import static com.chinagoods.bigdata.functions.utils.Failures.checkCondition; /** * @author ruifeng.shan diff --git a/src/main/java/com/github/aaronshan/functions/math/UDFMathToBase.java b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathToBase.java similarity index 87% rename from src/main/java/com/github/aaronshan/functions/math/UDFMathToBase.java rename to src/main/java/com/chinagoods/bigdata/functions/math/UDFMathToBase.java index 5a97b60..ba22f68 100644 --- a/src/main/java/com/github/aaronshan/functions/math/UDFMathToBase.java +++ b/src/main/java/com/chinagoods/bigdata/functions/math/UDFMathToBase.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.math; +package com.chinagoods.bigdata.functions.math; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; @@ -6,7 +6,7 @@ import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; -import static com.github.aaronshan.functions.utils.MathUtils.checkRadix; +import static com.chinagoods.bigdata.functions.utils.MathUtils.checkRadix; /** * @author ruifeng.shan diff --git a/src/main/java/com/github/aaronshan/functions/model/ChinaIdArea.java b/src/main/java/com/chinagoods/bigdata/functions/model/ChinaIdArea.java similarity index 56% rename from src/main/java/com/github/aaronshan/functions/model/ChinaIdArea.java rename to src/main/java/com/chinagoods/bigdata/functions/model/ChinaIdArea.java index 3257826..46fe6ee 100644 --- a/src/main/java/com/github/aaronshan/functions/model/ChinaIdArea.java +++ b/src/main/java/com/chinagoods/bigdata/functions/model/ChinaIdArea.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.model; +package com.chinagoods.bigdata.functions.model; /** * @author ruifeng.shan @@ -27,4 +27,14 @@ public String getCity() { public String getArea() { return area; } + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("ChinaIdArea{"); + sb.append("province='").append(province).append('\''); + sb.append(", city='").append(city).append('\''); + sb.append(", area='").append(area).append('\''); + sb.append('}'); + return sb.toString(); + } } diff --git a/src/main/java/com/chinagoods/bigdata/functions/parse/UDFParseAuthorization.java b/src/main/java/com/chinagoods/bigdata/functions/parse/UDFParseAuthorization.java new file mode 100644 index 0000000..4e49c63 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/parse/UDFParseAuthorization.java @@ -0,0 +1,251 @@ +package com.chinagoods.bigdata.functions.parse; + +import com.chinagoods.bigdata.functions.utils.DateUtil; +import com.chinagoods.bigdata.functions.utils.JacksonBuilder; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.jwt.Jwt; +import org.springframework.security.jwt.JwtHelper; + +import javax.servlet.http.Cookie; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +/** + * @author xiaowei.song + * date: 2023-09-04 + * time: 17:53 + * describe: 解析headers中的authorization,获取user_id, login_name, phone, email, nick_name, client_id, register_time + */ +@Description(name = "parse_token" + , value = "_FUNC_(string, string) - Parses the token and returns an ArrayList containing 0: user_id 1: login_name 2: phone 3: email 4: nick_name 5: client_id 6: register_time." + , extended = "Example:\n> SELECT _FUNC_(headers, cookies) FROM src;") +public class UDFParseAuthorization extends GenericUDF { + public static final Logger logger = LoggerFactory.getLogger(UDFParseAuthorization.class); + + private static final int ARG_COUNT = 2; + public static final Integer RET_ARRAY_SIZE = 7; + public static final String SEMICOLON_SEP = ";"; + public static final String COMMA_SEP = ","; + public static final String UNKNOWN_STR = "unknown"; + public static final String RST_UNKNOWN_STR = initRst(); + + private CacheLoader tokenLoader = null; + + public LoadingCache tokenCache = null; + + private ObjectInspectorConverters.Converter[] converters; + + public UDFParseAuthorization() {} + + + public static String getAccessTokenFromCookieString(String cookieString) { + String[] cookiePairs = cookieString.split("; "); + for (String pair : cookiePairs) { + String[] keyValue = pair.split("="); + if (keyValue.length == 2) { + String key = keyValue[0]; + String value = keyValue[1]; + if ("access_token".equals(key)) { + return value; + } + } + } + return null; // 返回null表示未找到access_token + } + + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + if (arguments.length != ARG_COUNT) { + throw new UDFArgumentException ( + "The function parse_ua takes exactly " + ARG_COUNT + " arguments."); + } + + converters = new ObjectInspectorConverters.Converter[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + converters[i] = ObjectInspectorConverters.getConverter(arguments[i], + PrimitiveObjectInspectorFactory.javaStringObjectInspector); + } + tokenLoader = new CacheLoader() { + @Override + public String load(String key) { + // 缓存miss时,加载数据的方法 + logger.debug("进入加载数据, key: {}", key); + return tokenParse(key); + } + }; + tokenCache = CacheBuilder.newBuilder() + .maximumSize(10000) + //缓存项在给定时间内没有被写访问(创建或覆盖),则回收。如果认为缓存数据总是在固定时候后变得陈旧不可用,这种回收方式是可取的。 + .expireAfterAccess(5, TimeUnit.MINUTES) + .build(tokenLoader); +// return ObjectInspectorFactory.getStandardListObjectInspector(PrimitiveObjectInspectorFactory.javaStringObjectInspector); + return PrimitiveObjectInspectorFactory.javaStringObjectInspector; + } + + @Override + public Object evaluate(DeferredObject[] arguments) throws HiveException { + assert (arguments.length == ARG_COUNT); + String headers = converters[0].convert(arguments[0].get()).toString(); + String cookies = converters[1].convert(arguments[1].get()).toString(); + String token = ""; + // 解析headers中的参数,获取authorization + for (String header : headers.split("\n")) { + if (StringUtils.startsWith(header, "authorization: Bearer ")) { + token = StringUtils.replace(header, "authorization: ", ""); + break; + } + } + + // 解析cookies中的参数,获取access_token + if (StringUtils.isBlank(token)) { + String accessToken = getAccessTokenFromCookieString(cookies); + if (StringUtils.isNotBlank(accessToken)) { + try { + accessToken = URLDecoder.decode(accessToken, "UTF-8"); + } catch (Exception e) { + logger.error("解析access_token失败, access_token={}", accessToken, e); + } + } + logger.debug("access_token: {}", accessToken); + if (StringUtils.isNotBlank(accessToken)) { + token = accessToken; + } + } + + String rstUaStr = RST_UNKNOWN_STR; + try { + rstUaStr = tokenCache.get(token); + } catch (ExecutionException e) { + logger.error("缓存获取失败,原始token为: {}", token, e); + } + return rstUaStr; + } + + private String tokenParse(String token) { + ArrayList rstList = new ArrayList<>(RET_ARRAY_SIZE); + // 默认值设置为null + if (StringUtils.isBlank(token) || !(StringUtils.startsWith(token, "bearer ") || StringUtils.startsWith(token, "Bearer "))) { + return RST_UNKNOWN_STR; + } + + // 其它异常情况 + if (token.contains("undefined") || token.contains("Bearer null")) { + return RST_UNKNOWN_STR; + } + token = token.replaceFirst("bearer ", "").replaceFirst("Bearer ", ""); + JsonNode content = null; + try { + Jwt jwt = JwtHelper.decode(token); + String claims = jwt.getClaims(); + content = JacksonBuilder.mapper.readTree(claims); + } catch (Exception e) { + logger.error("解析json字符串异常,请检查原始输入数据: {}", token, e); + return RST_UNKNOWN_STR; + } + Map result = new HashMap<>(0); + try { + result = JacksonBuilder.mapper.convertValue(content, new TypeReference>(){}); + } catch (Exception e) { + logger.error("解析json字符串异常检查原始输入数据: {}", token, e); + } + logger.debug("Result: {}", result); + JsonNode userNameJsonNode = result.get("user_name"); + if (userNameJsonNode == null) { + return RST_UNKNOWN_STR; + } + // 清除默认值 + // 0: user_id 1: login_name 2: phone 3: email 4: nick_name 5: client_id 6: register_time + rstList.add(formatValue(userNameJsonNode, "userId", UNKNOWN_STR)); + rstList.add(formatValue(userNameJsonNode, "loginName", UNKNOWN_STR)); + rstList.add(formatValue(userNameJsonNode, "phone", UNKNOWN_STR)); + rstList.add(formatValue(userNameJsonNode, "email", UNKNOWN_STR)); + rstList.add(formatValue(userNameJsonNode, "nickName", UNKNOWN_STR)); + if (Objects.nonNull(result.get("client_id"))) { + rstList.add(result.get("client_id").asText()); + } else { + rstList.add(UNKNOWN_STR); + } + String registerTimeStr = formatValue(userNameJsonNode, "registerTime", 63043200000L); + rstList.add(registerTimeStr); + return StringUtils.join(rstList, ","); + } + + private static String initRst() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < RET_ARRAY_SIZE; i++) { + sb.append(UNKNOWN_STR); + sb.append(COMMA_SEP); + } + return sb.substring(0, sb.length() - 1); + } + + private static String formatValue(JsonNode jn, String key, String defaultValue) { + JsonNode valJn = jn.get(key); + if (valJn == null) { + return UNKNOWN_STR; + } + String val = valJn.asText(defaultValue); + if (StringUtils.isBlank(val)) { + return UNKNOWN_STR; + } + return val; + } + + private static String formatValue(JsonNode jn, String key, long defaultValue) { + JsonNode valJn = jn.get(key); + if (valJn == null) { + return "0000-00-00 00:00:00"; + } + Long val = valJn.asLong(defaultValue); + + return DateUtil.parse(val, DateUtil.DEFAULT_DATE_TIME_FORMAT); + } + + @Override + public String getDisplayString(String[] children) { + return "parse_token(" + children[0] + ")"; + } + + public static void main(String[] args) throws HiveException { +// String tokenStr = "remote-port: 34021\n" + +// "authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzb3VyY2VPbmUiXSwidXNlcl9uYW1lIjp7ImxvZ2luVHlwZSI6ImFkbWluU21zIiwibG9naW5OYW1lIjoiMTg4Njc5NDkwNzMiLCJhcHBJZCI6IkNISU5BX0dPT0RTIiwidW5pb25JZCI6bnVsbCwiYWxpcGF5VXNlcklkIjpudWxsLCJpc0FkbWluIjp0cnVlLCJ3eFVzZXJJZCI6IiIsImdlbmRlciI6IkYiLCJkZWwiOiJOIiwicHJpdmlsZWdlIjoiWSIsInNob3J0UGhvbmUiOiIiLCJ1c2VyTmFtZSI6IueOi-iVviIsInJhbmtJZExpc3QiOlsiV0FOR0xFSSJdLCJsYXN0TG9naW5UaW1lIjoiMjAyMy0wOS0wMVQxNzoxMzo1NiIsInJlYWxOYW1lIjoi546L6JW-IiwibW9kaWZ5VGltZSI6IjIwMjMtMDktMDFUMTc6MTM6NTYiLCJwb3NpdGlvbklkIjo2MjEsImNyZWF0ZVRpbWUiOiIyMDIyLTA2LTE0VDE0OjQxOjE0IiwicGFzc3dkIjoiJDJhJDEwJGwxN0hPTHNDRHQ0RWVsampUTmI4Sk92RHZhUG1KQ0xReDUwUTQucmFqQTVoQWthN1JEb0d5IiwicGhvbmUiOiIxODg2Nzk0OTA3MyIsImxvZ28iOiIiLCJzZWxmIjoiTiIsImlkIjo1MzYxfSwic2NvcGUiOlsiQURNSU4iXSwiZXhwIjoxNjk0NDIzNjQ4LCJhdXRob3JpdGllcyI6WyJXQU5HTEVJIl0sImp0aSI6ImNkMDFhYTE4LTRiMGItNGUyNC1hOTRjLWQwYjUyMDU0OGNmZiIsImNsaWVudF9pZCI6ImFkbWluIn0.qUDPy9DA1qq_KG7FiALO28aLi6ICUqmHe4V003iYjnnpkFHxfDR-LG"; + String tokenStr = "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.MQ.gSssTBEVe6X9aFEd0H_tt8kk2u7df90W1eOzNRnrsQ4"; +// String cookies = "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.MQ.gSssTBEVe6X9aFEd0H_tt8kk2u7df90W1eOzNRnrsQ4"; + String cookies = ""; + + long begin = System.currentTimeMillis(); + UDFParseAuthorization parseAuth = new UDFParseAuthorization(); + DeferredObject[] deferredObjects = new DeferredObject[2]; + deferredObjects[0] = new DeferredJavaObject(tokenStr); + deferredObjects[1] = new DeferredJavaObject(cookies); + + ObjectInspector[] inspectorArr = new ObjectInspector[2]; + inspectorArr[0] = PrimitiveObjectInspectorFactory.javaStringObjectInspector; + inspectorArr[1] = PrimitiveObjectInspectorFactory.javaStringObjectInspector; + parseAuth.initialize(inspectorArr); + for (int i = 0; i < 1; i++) { + Object retArr = parseAuth.evaluate(deferredObjects); + System.out.println(retArr); + } + long end = System.currentTimeMillis(); + System.out.println("测试1耗时:"+ (end - begin) + "ms"); + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/parse/UDFParseUserAgent.java b/src/main/java/com/chinagoods/bigdata/functions/parse/UDFParseUserAgent.java new file mode 100644 index 0000000..80a7476 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/parse/UDFParseUserAgent.java @@ -0,0 +1,288 @@ +package com.chinagoods.bigdata.functions.parse; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.apache.hadoop.io.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ua_parser.Client; +import ua_parser.Device; +import ua_parser.Parser; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +/** + * @author zyl + * date: 2023-07-19 + * time: 17:53 + * describe: 解析ua获取device_family、os_family、os_minor、os_major、user_agent_family、user_agent_minor和user_agent_major + */ +@Description(name = "parse_user_agent" + , value = "_FUNC_(string) - Parses the user agent and returns an ArrayList containing device_family, os_family, os_minor, os_major, user_agent_family, user_agent_minor, and user_agent_major." + , extended = "Example:\n> SELECT _FUNC_(ua) FROM src;") +public class UDFParseUserAgent extends GenericUDF { + public static final Logger logger = LoggerFactory.getLogger(UDFParseUserAgent.class); + + private static final int ARG_COUNT = 1; + public static final Integer RET_ARRAY_SIZE = 7; + public static final String ANDROID_UA_PREFIX = "com.scgroup.shop"; + public static final String IOS_UA_PREFIX = "com.ccc.chinagoods"; + public static final String BLANK_UA_STR = "-"; + public static final String UNKNOWN_UA_STR = "AppName"; + public static final String SEMICOLON_SEP = ";"; + public static final String COMMA_SEP = ","; + public static final String UNKNOWN_STR = "unknown"; + public static final String RST_UNKNOWN_STR = initRst(); + private Parser uaParser = null; + + private CacheLoader uaLoader = null; + + public LoadingCache uaCache = null; + + + + private ObjectInspectorConverters.Converter[] converters; + + public UDFParseUserAgent() {} + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + if (arguments.length != ARG_COUNT) { + throw new UDFArgumentException ( + "The function parse_ua takes exactly " + ARG_COUNT + " arguments."); + } + + uaParser = new Parser(); + + converters = new ObjectInspectorConverters.Converter[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + converters[i] = ObjectInspectorConverters.getConverter(arguments[i], + PrimitiveObjectInspectorFactory.javaStringObjectInspector); + } + uaLoader = new CacheLoader() { + @Override + public String load(String key) { + // 缓存miss时,加载数据的方法 + logger.debug("进入加载数据, key: {}", key); + return uaParse(key); + } + }; + uaCache = CacheBuilder.newBuilder() + .maximumSize(10000) + //缓存项在给定时间内没有被写访问(创建或覆盖),则回收。如果认为缓存数据总是在固定时候后变得陈旧不可用,这种回收方式是可取的。 + .expireAfterAccess(5, TimeUnit.MINUTES) + .build(uaLoader); +// return ObjectInspectorFactory.getStandardListObjectInspector(PrimitiveObjectInspectorFactory.javaStringObjectInspector); + return PrimitiveObjectInspectorFactory.javaStringObjectInspector; + } + + @Override + public Object evaluate(DeferredObject[] arguments) throws HiveException { + ArrayList result = new ArrayList<>(RET_ARRAY_SIZE); + assert (arguments.length == ARG_COUNT); + String uaStr = converters[0].convert(arguments[0].get()).toString(); + String rstUaStr = RST_UNKNOWN_STR; + try { + rstUaStr = uaCache.get(uaStr); + } catch (ExecutionException e) { + logger.error("缓存获取失败,原始UA为: {}", uaStr, e); + } + return rstUaStr; + } + + private String uaParse(String uaStr) { + ArrayList rstList = new ArrayList<>(RET_ARRAY_SIZE); + // 默认值设置为null + if (StringUtils.isBlank(uaStr) || StringUtils.equals(BLANK_UA_STR, uaStr) || StringUtils.equals(UNKNOWN_UA_STR, uaStr)) { + return RST_UNKNOWN_STR; + } + // 0: 设备硬件型号 1: 操作系统型号 2: 操作系统小版本 3: 操作系统大版本 4: 浏览器小版本 5: 浏览器大版本 + String deviceModel = UNKNOWN_STR; + String osName = UNKNOWN_STR; + String osVersion = UNKNOWN_STR; + String osVersionName = UNKNOWN_STR; + String userAgentFamily = UNKNOWN_STR; + String packageVersion = UNKNOWN_STR; + String packageName = UNKNOWN_STR; + + // 添加默认值 + if (!StringUtils.startsWith(uaStr, ANDROID_UA_PREFIX) && !StringUtils.startsWith(uaStr, IOS_UA_PREFIX)) { + // 清除默认值 + // 解析UA + Client c = null; + try { + c = uaParser.parse(uaStr); + } catch (Exception e) { + logger.error("解析UA失败,原始UA内容为: {}", uaStr); + } + + if (Objects.isNull(c)) { + return RST_UNKNOWN_STR; + } + // 0: 设备硬件型号 1: 操作系统型号 2: 操作系统小版本 3: 操作系统大版本 4: 浏览器小版本 5: 浏览器大版本 + deviceModel = formatValue(Optional.of(c.device).orElse(null).family); + osName = formatValue(Optional.of(c.os).orElse(null).family); + osVersion = formatValue(Optional.of(c.os).orElse(null).minor); + osVersionName = formatValue(Optional.of(c.os).orElse(null).major); + userAgentFamily = formatValue(Optional.of(c.userAgent).orElse(null).family); + packageVersion = formatValue(Optional.of(c.userAgent).orElse(null).minor); + packageName = formatValue(Optional.of(c.userAgent).orElse(null).major); + } + + // com.scgroup.shopmall/1.2.3 (Android ELE-AL00; U; OS 10; zh) + // com.scgroup.shopbusiness/2.4.0 (Android STK-AL00; U; OS 10; zh) + // com.ccc.chinagoodsbuyer/2.0.1 (iOS unknown; 16.3.1; zh) + uaStr = uaStr.replace(")", "") + .replace(" (", SEMICOLON_SEP) + .replace("; ", SEMICOLON_SEP); + if (StringUtils.startsWith(uaStr, ANDROID_UA_PREFIX)) { + // 正则切分 + try { + // com.scgroup.shopmall/1.2.3;Android ELE-AL00;U;OS 10;zh + // com.scgroup.shopbusiness/2.4.0;Android STK-AL00;U;OS 10;zh +// com.scgroup.shopmall/2.2.7;iOS iPhone X + String[] uaArr = uaStr.split(SEMICOLON_SEP); + String uaPackageVersion = uaArr[0]; + String[] uaPvArr = uaPackageVersion.split("/"); + userAgentFamily = "Android"; + packageName = uaPvArr[0]; + packageVersion = UNKNOWN_STR; + if (uaPvArr.length > 1) { + packageVersion = uaPvArr[1]; + } + + String[] uaOsDeviceFmParams = uaArr[1].split(" ", 2); + osName = uaOsDeviceFmParams[0]; + deviceModel = UNKNOWN_STR; + if (uaOsDeviceFmParams.length > 1) { + deviceModel = uaOsDeviceFmParams[1]; + } + + if (uaArr.length > 2) { + osVersionName = uaArr[2]; + osVersion = uaArr[3]; + } + } catch (Exception e) { + // 异常处理 + logger.error("解析android UA错误, ua = {}", uaStr, e); + } + } else if (StringUtils.startsWith(uaStr, IOS_UA_PREFIX)) { + userAgentFamily = "ios"; + // 处理旧版本ua + // 特殊ua + // com.ccc.chinagoodsbuyer/1.3.0;iOS + if (StringUtils.equals(uaStr.trim(), "com.ccc.chinagoodsbuyer/1.3.0;iOS")) { + packageName = "com.ccc.chinagoodsbuyer"; + packageVersion = "1.3.0"; + osName = "iOS"; + } else if (StringUtils.equals(uaStr.trim(), "com.ccc.chinagoodsbuyer/1.3.1;iOS")) { + packageName = "com.ccc.chinagoodsbuyer"; + packageVersion = "1.3.1"; + osName = "iOS"; + } else { + // com.ccc.chinagoodsbuyer/2.0.1;iOS unknown;16.3.1;zh + logger.debug("uaStr: {}", uaStr); + // 正则切分 + String[] uaArr = uaStr.split(SEMICOLON_SEP); + String uaPackageVersion = uaArr[0]; + String[] uaPvArr = uaPackageVersion.split("/"); + packageName = uaPvArr[0]; + packageVersion = UNKNOWN_STR; + if (uaPvArr.length > 1) { + packageVersion = uaPvArr[1]; + } + + String[] uaOsDeviceFmParams = uaArr[1].split(" ", 2); + osName = uaOsDeviceFmParams[0]; + osVersion = uaArr[2]; + logger.debug("当前uaArr: {}", uaArr[2]); + osVersionName = uaArr[2].split("\\.", 2)[0]; + deviceModel = "iPhone"; + } + } + + // 清除默认值 + rstList.add(deviceModel); + rstList.add(osName); + rstList.add(osVersion); + rstList.add(osVersionName); + rstList.add(userAgentFamily); + rstList.add(packageVersion); + rstList.add(packageName); + return StringUtils.join(rstList, ","); + } + + private static String initRst() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < RET_ARRAY_SIZE; i++) { + sb.append(UNKNOWN_STR); + sb.append(COMMA_SEP); + } + return sb.substring(0, sb.length() - 1); + } + + private String formatValue(String value) { + return value != null ? value : ""; + } + + + @Override + public String getDisplayString(String[] children) { + return "parse_user_agent(" + children[0] + ")"; + } + + public static void main(String[] args) throws HiveException { +// String uaStr = "Mozilla/5.0 (Linux; Android 12; NOH-AN00 Build/HUAWEINOH-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/111.0.5563.116 Mobile Safari/537.36 XWEB/5131 MMWEBSDK/20230504 MMWEBID/9466 MicroMessenger/8.0.37.2380(0x2800255B) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64"; +// String uaStr = "com.scgroup.shopbusiness/2.4.0 (Android STK-AL00; U; OS 10; zh)"; + String uaStr = "com.ccc.chinagoodsbuyer/1.3.1 (iOS"; +// String uaStr = "com.scgroup.shopmall/1.2.3 (Android ELE-AL00; U; OS 10; zh)"; +// String uaStr = "com.ccc.chinagoodsbuyer/2.0.1 (iOS unknown; 16.3.1; zh)"; +// String uaStr = "com.scgroup.shopmall/2.2.7;iOS iPhone X"; +// String uaStr = "Opera/6.0 (Windows XP; U) [de]"; + long begin = System.currentTimeMillis(); +// UDFParseUserAgent urlFormat = new UDFParseUserAgent(); +// DeferredObject[] deferredObjects = new DeferredObject[2]; +// // 平台类型、sc_url +// deferredObjects[0] = new DeferredJavaObject(uaStr); +// +// ObjectInspector[] inspectorArr = new ObjectInspector[1]; +// inspectorArr[0] = PrimitiveObjectInspectorFactory.javaStringObjectInspector; +// urlFormat.initialize(inspectorArr); +// Object retArr = urlFormat.evaluate(deferredObjects); +// System.out.println(retArr); + + UDFParseUserAgent urlFormat = new UDFParseUserAgent(); + DeferredObject[] deferredObjects = new DeferredObject[2]; + // 平台类型、sc_url + deferredObjects[0] = new DeferredJavaObject(uaStr); + + ObjectInspector[] inspectorArr = new ObjectInspector[1]; + inspectorArr[0] = PrimitiveObjectInspectorFactory.javaStringObjectInspector; + urlFormat.initialize(inspectorArr); + for (int i = 0; i < 1; i++) { + Object retArr = urlFormat.evaluate(deferredObjects); + System.out.println(retArr); + } + long end = System.currentTimeMillis(); + System.out.println("测试1耗时:"+ (end - begin) + "ms"); + +// Parser uaParser = new Parser(); +// Client c = uaParser.parse(uaStr); +// logger.info(Optional.of(c.device).orElseGet(null).family); +} +} diff --git a/src/main/java/com/github/aaronshan/functions/regexp/Re2JRegexp.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/Re2JRegexp.java similarity index 93% rename from src/main/java/com/github/aaronshan/functions/regexp/Re2JRegexp.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/Re2JRegexp.java index 88883b3..d2b441a 100644 --- a/src/main/java/com/github/aaronshan/functions/regexp/Re2JRegexp.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/Re2JRegexp.java @@ -1,8 +1,8 @@ -package com.github.aaronshan.functions.regexp; +package com.chinagoods.bigdata.functions.regexp; -import com.github.aaronshan.functions.regexp.re2j.Matcher; -import com.github.aaronshan.functions.regexp.re2j.Options; -import com.github.aaronshan.functions.regexp.re2j.Pattern; +import com.chinagoods.bigdata.functions.regexp.re2j.Pattern; +import com.chinagoods.bigdata.functions.regexp.re2j.Matcher; +import com.chinagoods.bigdata.functions.regexp.re2j.Options; import com.google.common.collect.Lists; import io.airlift.slice.Slice; import org.apache.hadoop.hive.ql.metadata.HiveException; @@ -11,7 +11,7 @@ import java.util.List; -import static com.github.aaronshan.functions.regexp.re2j.Options.Algorithm.DFA_FALLBACK_TO_NFA; +import static com.chinagoods.bigdata.functions.regexp.re2j.Options.Algorithm.DFA_FALLBACK_TO_NFA; import static com.google.common.base.Preconditions.checkState; import static java.lang.String.format; diff --git a/src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpExtract.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpExtract.java similarity index 96% rename from src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpExtract.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpExtract.java index ded1ea5..7bc9f8f 100644 --- a/src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpExtract.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpExtract.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.regexp; +package com.chinagoods.bigdata.functions.regexp; import io.airlift.slice.Slices; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpExtractAll.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpExtractAll.java similarity index 83% rename from src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpExtractAll.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpExtractAll.java index 9258ae0..19817ec 100644 --- a/src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpExtractAll.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpExtractAll.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.regexp; +package com.chinagoods.bigdata.functions.regexp; import io.airlift.slice.Slices; import java.util.ArrayList; @@ -9,6 +9,7 @@ import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; @@ -25,6 +26,7 @@ public class UDFRe2JRegexpExtractAll extends GenericUDF { private transient ArrayList result = new ArrayList(); private transient Re2JRegexp re2JRegexp; + private ObjectInspectorConverters.Converter[] converters; public UDFRe2JRegexpExtractAll() { @@ -37,7 +39,11 @@ public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumen throw new UDFArgumentLengthException( "The function regexp_extract_all takes exactly 2 or 3 arguments."); } - + converters = new ObjectInspectorConverters.Converter[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + converters[i] = ObjectInspectorConverters.getConverter(arguments[i], + PrimitiveObjectInspectorFactory.javaStringObjectInspector); + } for (int i = 0; i < 2; i++) { if (!ObjectInspectorUtils.compareTypes(PrimitiveObjectInspectorFactory.javaStringObjectInspector, arguments[i])) { throw new UDFArgumentTypeException(i, @@ -65,11 +71,11 @@ public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumen @Override public Object evaluate(DeferredObject[] arguments) throws HiveException { - String source = (String) arguments[0].get(); - String pattern = (String) arguments[1].get(); + String source = converters[0].convert(arguments[0].get()).toString();; + String pattern = converters[1].convert(arguments[1].get()).toString(); Long groupIndex = 0L; if (arguments.length == 3) { - groupIndex = (Long) arguments[2].get(); + groupIndex = Long.parseLong(converters[2].convert(arguments[2].get()).toString()); } if (source == null) { diff --git a/src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpLike.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpLike.java similarity index 94% rename from src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpLike.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpLike.java index 49387ea..fad465a 100644 --- a/src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpLike.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpLike.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.regexp; +package com.chinagoods.bigdata.functions.regexp; import io.airlift.slice.Slices; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpReplace.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpReplace.java similarity index 96% rename from src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpReplace.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpReplace.java index 26b1002..32b73cb 100644 --- a/src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpReplace.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpReplace.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.regexp; +package com.chinagoods.bigdata.functions.regexp; import io.airlift.slice.Slices; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpSplit.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpSplit.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpSplit.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpSplit.java index ebdd081..12db421 100644 --- a/src/main/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpSplit.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpSplit.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.regexp; +package com.chinagoods.bigdata.functions.regexp; import io.airlift.slice.Slices; import java.util.ArrayList; diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/CharClass.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/CharClass.java old mode 100755 new mode 100644 similarity index 99% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/CharClass.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/CharClass.java index 57f95e4..a58a3c1 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/CharClass.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/CharClass.java @@ -5,7 +5,7 @@ // Original Go source here: // http://code.google.com/p/go/source/browse/src/pkg/regexp/syntax/parse.go -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; /** * A "builder"-style helper class for manipulating character classes diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/CharGroup.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/CharGroup.java old mode 100755 new mode 100644 similarity index 98% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/CharGroup.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/CharGroup.java index 6a0a601..6f398b0 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/CharGroup.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/CharGroup.java @@ -1,7 +1,7 @@ // GENERATED BY make_perl_groups.pl; DO NOT EDIT. // make_perl_groups.pl >perl_groups.go -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; import java.util.HashMap; diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Compiler.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Compiler.java old mode 100755 new mode 100644 similarity index 94% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/Compiler.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Compiler.java index d6978ad..f1430ad --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Compiler.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Compiler.java @@ -5,16 +5,11 @@ // Original Go source here: // http://code.google.com/p/go/source/browse/src/pkg/regexp/syntax/compile.go -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; import java.util.LinkedList; import java.util.List; -import static com.github.aaronshan.functions.regexp.re2j.Inst.Op.BYTE; -import static com.github.aaronshan.functions.regexp.re2j.Inst.Op.BYTE1; -import static com.github.aaronshan.functions.regexp.re2j.RE2.FOLD_CASE; -import static com.github.aaronshan.functions.regexp.re2j.Unicode.*; - /** * Compiler from {@code Regexp} (RE2 abstract syntax) to {@code RE2} (compiled regular expression). *

@@ -149,10 +144,10 @@ private Frag empty(int op) { } private Frag rune(int rune, int flags) { - if ((flags & FOLD_CASE) == 0) { + if ((flags & RE2.FOLD_CASE) == 0) { return rune(new int[]{rune}, flags); } else { - return alt(rune(new int[]{rune}, flags), rune(new int[]{simpleFold(rune)}, flags)); + return alt(rune(new int[]{rune}, flags), rune(new int[]{Unicode.simpleFold(rune)}, flags)); } } @@ -177,8 +172,8 @@ private Frag rune(int[] runes, int flags) { private void expandRuneRange(int lo, int hi, List runes) { // Split range into same-length sized ranges. - for (int i = 1; i < UTF_MAX; i++) { - int max = maxRune(i); + for (int i = 1; i < Unicode.UTF_MAX; i++) { + int max = Unicode.maxRune(i); if (lo <= max && max < hi) { expandRuneRange(lo, max, runes); expandRuneRange(max + 1, hi, runes); @@ -187,14 +182,14 @@ private void expandRuneRange(int lo, int hi, List runes) { } // ASCII range is always a special case. - if (hi < RUNE_SELF) { + if (hi < Unicode.RUNE_SELF) { runes.add(lo); runes.add(hi); return; } // Split range into sections that agree on leading bytes. - for (int i = 1; i < UTF_MAX; i++) { + for (int i = 1; i < Unicode.UTF_MAX; i++) { int m = (1 << (6 * i)) - 1; // last i bytes of a UTF-8 sequence if ((lo & ~m) != (hi & ~m)) { if ((lo & m) != 0) { @@ -215,7 +210,7 @@ private void expandRuneRange(int lo, int hi, List runes) { } private Frag rune(int lo, int hi, int flags) { - return bytes(codePointToUtf8(lo), codePointToUtf8(hi), flags); + return bytes(Unicode.codePointToUtf8(lo), Unicode.codePointToUtf8(hi), flags); } private Frag bytes(byte[] lo, byte[] hi, int flags) { @@ -227,14 +222,14 @@ private Frag bytes(byte[] lo, byte[] hi, int flags) { } private Frag byteRange(byte[] byteRanges, int flags) { - Frag f = newInst(BYTE); + Frag f = newInst(Inst.Op.BYTE); Inst i = prog.getInst(f.i); i.byteRanges = byteRanges; i.arg = flags; f.out = f.i << 1; // Special cases for exec machine. if (byteRanges.length == 1 || (byteRanges.length == 2 && byteRanges[0] == byteRanges[1])) { - i.op = BYTE1; + i.op = Inst.Op.BYTE1; i.byteRanges = new byte[]{byteRanges[0]}; } return f; diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/DFA.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/DFA.java old mode 100755 new mode 100644 similarity index 97% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/DFA.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/DFA.java index c55d091..c2dd070 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/DFA.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/DFA.java @@ -5,19 +5,19 @@ // Original RE2 source here: // https://github.com/google/re2/blob/master/re2/dfa.cc -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; -import com.github.aaronshan.functions.regexp.re2j.RE2.MatchKind; +import com.chinagoods.bigdata.functions.regexp.re2j.RE2.MatchKind; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; -import static com.github.aaronshan.functions.regexp.re2j.DFAState.DEAD_STATE; -import static com.github.aaronshan.functions.regexp.re2j.Inst.Op.EMPTY_WIDTH; -import static com.github.aaronshan.functions.regexp.re2j.MachineInput.EOF; -import static com.github.aaronshan.functions.regexp.re2j.RE2.MatchKind.FIRST_MATCH; -import static com.github.aaronshan.functions.regexp.re2j.RE2.MatchKind.LONGEST_MATCH; -import static com.github.aaronshan.functions.regexp.re2j.Utils.*; +import static com.chinagoods.bigdata.functions.regexp.re2j.DFAState.DEAD_STATE; +import static com.chinagoods.bigdata.functions.regexp.re2j.Inst.Op.EMPTY_WIDTH; +import static com.chinagoods.bigdata.functions.regexp.re2j.MachineInput.EOF; +import static com.chinagoods.bigdata.functions.regexp.re2j.RE2.MatchKind.FIRST_MATCH; +import static com.chinagoods.bigdata.functions.regexp.re2j.RE2.MatchKind.LONGEST_MATCH; +import static com.chinagoods.bigdata.functions.regexp.re2j.Utils.*; import static java.util.Arrays.sort; class DFA { diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/DFAMachine.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/DFAMachine.java old mode 100755 new mode 100644 similarity index 87% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/DFAMachine.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/DFAMachine.java index 183eb44..cd6825a --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/DFAMachine.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/DFAMachine.java @@ -5,18 +5,17 @@ // Original RE2 source here: // https://github.com/google/re2/blob/master/re2/dfa.cc -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; -import com.github.aaronshan.functions.regexp.re2j.RE2.Anchor; -import com.github.aaronshan.functions.regexp.re2j.RE2.MatchKind; +import com.chinagoods.bigdata.functions.regexp.re2j.RE2.Anchor; +import com.chinagoods.bigdata.functions.regexp.re2j.RE2.MatchKind; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; -import static com.github.aaronshan.functions.regexp.re2j.DFA.NO_MATCH; -import static com.github.aaronshan.functions.regexp.re2j.RE2.Anchor.ANCHOR_START; -import static com.github.aaronshan.functions.regexp.re2j.RE2.MatchKind.FIRST_MATCH; -import static com.github.aaronshan.functions.regexp.re2j.RE2.MatchKind.LONGEST_MATCH; +import static com.chinagoods.bigdata.functions.regexp.re2j.RE2.Anchor.ANCHOR_START; +import static com.chinagoods.bigdata.functions.regexp.re2j.RE2.MatchKind.FIRST_MATCH; +import static com.chinagoods.bigdata.functions.regexp.re2j.RE2.MatchKind.LONGEST_MATCH; /** * A {@link Machine} implementation using a DFA. @@ -60,7 +59,7 @@ public boolean match(MachineInput in, int pos, Anchor anchor, int[] submatches) switch (anchor) { case UNANCHORED: matchEnd = searchDFA(in, pos, in.endPos(), anchor, wantMatchPosition, re2.matchKind, false); - if (matchEnd == NO_MATCH) { + if (matchEnd == DFA.NO_MATCH) { return false; } @@ -72,7 +71,7 @@ public boolean match(MachineInput in, int pos, Anchor anchor, int[] submatches) // SearchDFA gives match end position but we don't know where the match started. Run the // regexp backwards from end position to find the longest possible match -- that's where it started. matchStart = searchDFA(in, pos, matchEnd, ANCHOR_START, true, LONGEST_MATCH, true); - if (matchStart == NO_MATCH) { + if (matchStart == DFA.NO_MATCH) { throw new IllegalStateException("reverse DFA did not found a match"); } @@ -80,7 +79,7 @@ public boolean match(MachineInput in, int pos, Anchor anchor, int[] submatches) case ANCHOR_BOTH: case ANCHOR_START: matchEnd = searchDFA(in, pos, in.endPos(), anchor, wantMatchPosition, re2.matchKind, false); - if (matchEnd == NO_MATCH) { + if (matchEnd == DFA.NO_MATCH) { return false; } matchStart = 0; @@ -104,7 +103,7 @@ public boolean match(MachineInput in, int pos, Anchor anchor, int[] submatches) private int searchDFA(MachineInput in, int startPos, int endPos, Anchor anchor, boolean wantMatchPosition, MatchKind matchKind, boolean reversed) { boolean hasCarat = reversed ? anchor.isAnchorEnd() : anchor.isAnchorStart(); if (hasCarat && startPos != 0) { - return NO_MATCH; + return DFA.NO_MATCH; } // Handle end match by running an anchored longest match and then checking if it covers all of text. @@ -127,13 +126,13 @@ private int searchDFA(MachineInput in, int startPos, int endPos, Anchor anchor, DFA dfa = getDfa(matchKind, reversed); int match = dfa.search(in, startPos, endPos, anchored, wantEarliestMatch); - if (match == NO_MATCH) { - return NO_MATCH; + if (match == DFA.NO_MATCH) { + return DFA.NO_MATCH; } if (endMatch) { if ((reversed && match != startPos) || (!reversed && match != endPos)) { - return NO_MATCH; + return DFA.NO_MATCH; } } diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/DFAState.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/DFAState.java old mode 100755 new mode 100644 similarity index 91% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/DFAState.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/DFAState.java index f0efade..116cd58 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/DFAState.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/DFAState.java @@ -5,9 +5,8 @@ // Original RE2 source here: // https://github.com/google/re2/blob/master/re2/dfa.cc -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; -import static com.github.aaronshan.functions.regexp.re2j.DFA.FLAG_MATCH; import static java.lang.System.arraycopy; final class DFAState { @@ -42,7 +41,7 @@ public int[] getInstIndexes() { } public boolean isMatch() { - return (flag & FLAG_MATCH) != 0; + return (flag & DFA.FLAG_MATCH) != 0; } public boolean isDead() { diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/DFAStateKey.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/DFAStateKey.java old mode 100755 new mode 100644 similarity index 83% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/DFAStateKey.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/DFAStateKey.java index 859e4e2..17a47ce --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/DFAStateKey.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/DFAStateKey.java @@ -5,12 +5,10 @@ // Original RE2 source here: // https://github.com/google/re2/blob/master/re2/dfa.cc -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; import java.util.Arrays; -import static com.github.aaronshan.functions.regexp.re2j.Utils.arrayFirstElementsEqual; - final class DFAStateKey { private final int[] instIndexes; private final int nIndexes; @@ -29,7 +27,7 @@ public boolean equals(Object o) { DFAStateKey that = (DFAStateKey) o; - return nIndexes == that.nIndexes && flag == that.flag && arrayFirstElementsEqual(instIndexes, that.instIndexes, nIndexes); + return nIndexes == that.nIndexes && flag == that.flag && Utils.arrayFirstElementsEqual(instIndexes, that.instIndexes, nIndexes); } @Override diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Inst.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Inst.java old mode 100755 new mode 100644 similarity index 98% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/Inst.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Inst.java index 9e9af06..b0a5495 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Inst.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Inst.java @@ -5,7 +5,7 @@ // Original Go source here: // http://code.google.com/p/go/source/browse/src/pkg/regexp/syntax/prog.go -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; /** * A single instruction in the regular expression virtual machine. diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Machine.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Machine.java old mode 100755 new mode 100644 similarity index 85% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/Machine.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Machine.java index 99e44c1..bb955f1 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Machine.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Machine.java @@ -5,9 +5,9 @@ // Original Go source here: // http://code.google.com/p/go/source/browse/src/pkg/regexp/exec.go -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; -import com.github.aaronshan.functions.regexp.re2j.RE2.Anchor; +import com.chinagoods.bigdata.functions.regexp.re2j.RE2.Anchor; /** * A Machine matches an input string of Unicode characters against an RE2 instance. diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/MachineInput.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/MachineInput.java old mode 100755 new mode 100644 similarity index 97% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/MachineInput.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/MachineInput.java index 6ae8610..cd5fd0f --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/MachineInput.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/MachineInput.java @@ -5,7 +5,7 @@ // Original Go source here: // http://code.google.com/p/go/source/browse/src/pkg/regexp/regexp.go -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; import io.airlift.slice.Slice; import sun.misc.Unsafe; diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Matcher.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Matcher.java old mode 100755 new mode 100644 similarity index 95% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/Matcher.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Matcher.java index 0f2a6b2..890a48f --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Matcher.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Matcher.java @@ -1,14 +1,11 @@ // Copyright 2010 Google Inc. All Rights Reserved. -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; -import com.github.aaronshan.functions.regexp.re2j.RE2.Anchor; import io.airlift.slice.DynamicSliceOutput; import io.airlift.slice.Slice; import io.airlift.slice.SliceOutput; -import static com.github.aaronshan.functions.regexp.re2j.RE2.Anchor.*; - /** * A stateful iterator that interprets a regex {@code Pattern} on a * specific input. Its interface mimics the JDK 1.4.2 @@ -40,7 +37,7 @@ */ public final class Matcher { // The pattern being matched. - private final com.github.aaronshan.functions.regexp.re2j.Pattern pattern; + private final Pattern pattern; // The group indexes, in [start, end) pairs. Zeroth pair is overall match. private final int[] groups; @@ -61,9 +58,9 @@ public final class Matcher { private boolean hasGroups; // The anchor flag to use when repeating the match to find subgroups. - private Anchor anchorFlag; + private RE2.Anchor anchorFlag; - private Matcher(com.github.aaronshan.functions.regexp.re2j.Pattern pattern) { + private Matcher(Pattern pattern) { if (pattern == null) { throw new NullPointerException("pattern is null"); } @@ -76,7 +73,7 @@ private Matcher(com.github.aaronshan.functions.regexp.re2j.Pattern pattern) { /** * Creates a new {@code Matcher} with the given pattern and input. */ - Matcher(com.github.aaronshan.functions.regexp.re2j.Pattern pattern, Slice input) { + Matcher(Pattern pattern, Slice input) { this(pattern); reset(input); } @@ -244,7 +241,7 @@ private void loadGroup(int group) { * @return true if the entire input matches the pattern */ public boolean matches() { - return genMatch(0, ANCHOR_BOTH); + return genMatch(0, RE2.Anchor.ANCHOR_BOTH); } /** @@ -254,7 +251,7 @@ public boolean matches() { * @return true if the beginning of the input matches the pattern */ public boolean lookingAt() { - return genMatch(0, ANCHOR_START); + return genMatch(0, RE2.Anchor.ANCHOR_START); } /** @@ -273,7 +270,7 @@ public boolean find() { start++; } } - return genMatch(start, UNANCHORED); + return genMatch(start, RE2.Anchor.UNANCHORED); } /** @@ -291,13 +288,13 @@ public boolean find(int start) { "start index out of bounds: " + start); } reset(); - return genMatch(start, UNANCHORED); + return genMatch(start, RE2.Anchor.UNANCHORED); } /** * Helper: does match starting at start, with RE2 anchor flag. */ - private boolean genMatch(int startByte, Anchor anchor) { + private boolean genMatch(int startByte, RE2.Anchor anchor) { // TODO(rsc): Is matches/lookingAt supposed to reset the append or input positions? // From the JDK docs, looks like no. boolean ok = pattern.re2().match(input, startByte, diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/NFAMachine.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/NFAMachine.java old mode 100755 new mode 100644 similarity index 89% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/NFAMachine.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/NFAMachine.java index 7861bb4..4df958e --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/NFAMachine.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/NFAMachine.java @@ -5,28 +5,25 @@ // Original Go source here: // http://code.google.com/p/go/source/browse/src/pkg/regexp/exec.go -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; -import com.github.aaronshan.functions.regexp.re2j.RE2.Anchor; +import com.chinagoods.bigdata.functions.regexp.re2j.RE2.Anchor; import java.util.Arrays; -import static com.github.aaronshan.functions.regexp.re2j.MachineInput.EOF; -import static com.github.aaronshan.functions.regexp.re2j.RE2.MatchKind.LONGEST_MATCH; -import static com.github.aaronshan.functions.regexp.re2j.Utils.emptyOpContext; -import static com.github.aaronshan.functions.regexp.re2j.Utils.isRuneStart; +import static com.chinagoods.bigdata.functions.regexp.re2j.RE2.MatchKind.LONGEST_MATCH; import static java.lang.System.arraycopy; /** - * A {@link com.github.aaronshan.functions.regexp.re2j.Machine} implementation using a simple NFA. + * A {@link Machine} implementation using a simple NFA. */ -class NFAMachine implements com.github.aaronshan.functions.regexp.re2j.Machine { +class NFAMachine implements Machine { private static final int INITIAL_POOL_SIZE = 10; // Compiled program. private final Prog prog; // Program instructions. - private final com.github.aaronshan.functions.regexp.re2j.Inst[] instructions; + private final Inst[] instructions; // Two queues for runq, nextq. private final Queue q0, q1; // Corresponding compiled regexp. @@ -53,7 +50,7 @@ class NFAMachine implements com.github.aaronshan.functions.regexp.re2j.Machine { // alloc() allocates a new thread with the given instruction. // It uses the free pool if possible. - private Thread alloc(com.github.aaronshan.functions.regexp.re2j.Inst inst) { + private Thread alloc(Inst inst) { Thread t; if (poolSize > 0) { t = pool[--poolSize]; @@ -77,7 +74,7 @@ private void free(Thread t) { } @Override - public boolean match(com.github.aaronshan.functions.regexp.re2j.MachineInput in, int pos, Anchor anchor, int[] submatches) { + public boolean match(MachineInput in, int pos, Anchor anchor, int[] submatches) { init(submatches.length); int startCond = re2.cond; @@ -94,9 +91,9 @@ public boolean match(com.github.aaronshan.functions.regexp.re2j.MachineInput in, byte b1 = in.getByte(pos + 1); int flag; // bitmask of EMPTY_* flags if (pos == 0) { - flag = emptyOpContext(EOF, b); + flag = Utils.emptyOpContext(MachineInput.EOF, b); } else { - flag = emptyOpContext(in.getByte(pos - 1), b); + flag = Utils.emptyOpContext(in.getByte(pos - 1), b); } for (; ; ) { @@ -120,7 +117,7 @@ public boolean match(com.github.aaronshan.functions.regexp.re2j.MachineInput in, b1 = in.getByte(pos + 1); } } - if (!matched && (pos == 0 || anchor.isUnanchored()) && (b == EOF || isRuneStart(b))) { + if (!matched && (pos == 0 || anchor.isUnanchored()) && (b == MachineInput.EOF || Utils.isRuneStart(b))) { // If we are anchoring at begin then only add threads that begin // at |pos| = 0. if (matchcap.length > 0) { @@ -128,9 +125,9 @@ public boolean match(com.github.aaronshan.functions.regexp.re2j.MachineInput in, } add(runq, prog.start, pos, matchcap, flag, null); } - flag = emptyOpContext(b, b1); + flag = Utils.emptyOpContext(b, b1); step(runq, nextq, pos, pos + 1, b, flag, anchor, pos == in.endPos()); - if (b == EOF) { + if (b == MachineInput.EOF) { break; } if (matchcap.length == 0 && matched) { @@ -185,7 +182,7 @@ private void step(Queue runq, Queue nextq, int pos, int nextPos, byte b, free(t); continue; } - com.github.aaronshan.functions.regexp.re2j.Inst i = t.inst; + Inst i = t.inst; boolean add = false; switch (i.op) { case MATCH: @@ -245,7 +242,7 @@ private Thread add(Queue q, int pc, int pos, int[] cap, int cond, Thread t) { return t; } Queue.Entry d = q.add(pc); - com.github.aaronshan.functions.regexp.re2j.Inst inst = instructions[pc]; + Inst inst = instructions[pc]; switch (inst.op()) { default: throw new IllegalStateException("unhandled"); @@ -301,7 +298,7 @@ private Thread add(Queue q, int pc, int pos, int[] cap, int cond, Thread t) { // A logical thread in the NFA. private static class Thread { int[] cap; - com.github.aaronshan.functions.regexp.re2j.Inst inst; + Inst inst; Thread(int n) { this.cap = new int[n]; } diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Options.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Options.java similarity index 96% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/Options.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Options.java index fbbd8b3..dd8b06f 100644 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Options.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Options.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; /** * @author aaron02 @@ -9,7 +9,7 @@ import java.io.Serializable; -import static com.github.aaronshan.functions.regexp.re2j.Options.Algorithm.DFA; +import static com.chinagoods.bigdata.functions.regexp.re2j.Options.Algorithm.DFA; public final class Options implements Serializable { public static final Options DEFAULT_OPTIONS = builder().build(); diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Parser.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Parser.java old mode 100755 new mode 100644 similarity index 97% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/Parser.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Parser.java index 03b6332..5203d52 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Parser.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Parser.java @@ -9,7 +9,7 @@ // - Eliminate allocations (new int[], new Regexp[], new ArrayList) by // recycling old arrays on a freelist. -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; import java.util.ArrayList; @@ -248,11 +248,11 @@ private static void mergeCharClass(Regexp dst, Regexp src) { case CHAR_CLASS: // src is simpler, so either literal or char class if (src.op == Regexp.Op.LITERAL) { - dst.runes = new com.github.aaronshan.functions.regexp.re2j.CharClass(dst.runes). + dst.runes = new CharClass(dst.runes). appendLiteral(src.runes[0], src.flags). toArray(); } else { - dst.runes = new com.github.aaronshan.functions.regexp.re2j.CharClass(dst.runes).appendClass(src.runes).toArray(); + dst.runes = new CharClass(dst.runes).appendClass(src.runes).toArray(); } break; case LITERAL: @@ -261,7 +261,7 @@ private static void mergeCharClass(Regexp dst, Regexp src) { break; } dst.op = Regexp.Op.CHAR_CLASS; - dst.runes = new com.github.aaronshan.functions.regexp.re2j.CharClass(). + dst.runes = new CharClass(). appendLiteral(dst.runes[0], dst.flags). appendLiteral(src.runes[0], src.flags). toArray(); @@ -662,7 +662,7 @@ private Regexp alternate() { private void cleanAlt(Regexp re) { switch (re.op) { case CHAR_CLASS: - re.runes = new com.github.aaronshan.functions.regexp.re2j.CharClass(re.runes).cleanClass().toArray(); + re.runes = new CharClass(re.runes).cleanClass().toArray(); if (re.runes.length == 2 && re.runes[0] == 0 && re.runes[1] == Unicode.MAX_RUNE) { @@ -1181,7 +1181,7 @@ private Regexp parseInternal() throws PatternSyntaxException { // Look for Unicode character group like \p{Han} if (t.lookingAt("\\p") || t.lookingAt("\\P")) { - com.github.aaronshan.functions.regexp.re2j.CharClass cc = new com.github.aaronshan.functions.regexp.re2j.CharClass(); + CharClass cc = new CharClass(); if (parseUnicodeClass(t, cc)) { re.runes = cc.toArray(); push(re); @@ -1190,7 +1190,7 @@ private Regexp parseInternal() throws PatternSyntaxException { } // Perl character class escape. - com.github.aaronshan.functions.regexp.re2j.CharClass cc = new com.github.aaronshan.functions.regexp.re2j.CharClass(); + CharClass cc = new CharClass(); if (parsePerlClassEscape(t, cc)) { re.runes = cc.toArray(); push(re); @@ -1420,7 +1420,7 @@ private void parseRightParen() throws PatternSyntaxException { // from the beginning of |t|. If one is present, it appends the characters // to cc and returns true. The iterator is advanced past the escape // on success, undefined on failure, in which case false is returned. - private boolean parsePerlClassEscape(StringIterator t, com.github.aaronshan.functions.regexp.re2j.CharClass cc) { + private boolean parsePerlClassEscape(StringIterator t, CharClass cc) { int beforePos = t.pos(); if ((flags & RE2.PERL_X) == 0 || !t.more() || t.pop() != '\\' || // consume '\\' @@ -1428,7 +1428,7 @@ private boolean parsePerlClassEscape(StringIterator t, com.github.aaronshan.func return false; } t.pop(); // e.g. advance past 'd' in "\\d" - com.github.aaronshan.functions.regexp.re2j.CharGroup g = com.github.aaronshan.functions.regexp.re2j.CharGroup.PERL_GROUPS.get(t.from(beforePos)); + CharGroup g = CharGroup.PERL_GROUPS.get(t.from(beforePos)); if (g == null) { return false; } @@ -1442,7 +1442,7 @@ private boolean parsePerlClassEscape(StringIterator t, com.github.aaronshan.func // Pre: t at "[:". Post: t after ":]". // On failure (no class of than name), throws PatternSyntaxException. // On misparse, returns false; t.pos() is undefined. - private boolean parseNamedClass(StringIterator t, com.github.aaronshan.functions.regexp.re2j.CharClass cc) + private boolean parseNamedClass(StringIterator t, CharClass cc) throws PatternSyntaxException { // (Go precondition check deleted.) String cls = t.rest(); @@ -1452,7 +1452,7 @@ private boolean parseNamedClass(StringIterator t, com.github.aaronshan.functions } String name = cls.substring(0, i + 2); // "[:alnum:]" t.skipString(name); - com.github.aaronshan.functions.regexp.re2j.CharGroup g = com.github.aaronshan.functions.regexp.re2j.CharGroup.POSIX_GROUPS.get(name); + CharGroup g = CharGroup.POSIX_GROUPS.get(name); if (g.sign == 0) { throw new PatternSyntaxException(ERR_INVALID_CHAR_RANGE, name); } @@ -1467,7 +1467,7 @@ private boolean parseNamedClass(StringIterator t, com.github.aaronshan.functions // Returns false if such a pattern is not present or UNICODE_GROUPS // flag is not enabled; |t.pos()| is not advanced in this case. // Indicates error by throwing PatternSyntaxException. - private boolean parseUnicodeClass(StringIterator t, com.github.aaronshan.functions.regexp.re2j.CharClass cc) + private boolean parseUnicodeClass(StringIterator t, CharClass cc) throws PatternSyntaxException { int startPos = t.pos(); if ((flags & RE2.UNICODE_GROUPS) == 0 || @@ -1523,7 +1523,7 @@ private boolean parseUnicodeClass(StringIterator t, com.github.aaronshan.functio // Merge and clean tab and fold in a temporary buffer. // This is necessary for the negative case and just tidy // for the positive case. - int[] tmp = new com.github.aaronshan.functions.regexp.re2j.CharClass(). + int[] tmp = new CharClass(). appendTable(tab). appendTable(fold). cleanClass(). @@ -1543,7 +1543,7 @@ private void parseClass(StringIterator t) throws PatternSyntaxException { t.skip(1); // '[' Regexp re = newRegexp(Regexp.Op.CHAR_CLASS); re.flags = flags; - com.github.aaronshan.functions.regexp.re2j.CharClass cc = new com.github.aaronshan.functions.regexp.re2j.CharClass(); + CharClass cc = new CharClass(); int sign = +1; if (t.more() && t.lookingAt('^')) { diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Pattern.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Pattern.java similarity index 96% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/Pattern.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Pattern.java index b952753..569260d 100644 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Pattern.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Pattern.java @@ -1,13 +1,13 @@ -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; import io.airlift.slice.Slice; import java.io.Serializable; -import static com.github.aaronshan.functions.regexp.re2j.Options.DEFAULT_OPTIONS; -import static com.github.aaronshan.functions.regexp.re2j.RE2.Anchor.ANCHOR_BOTH; -import static com.github.aaronshan.functions.regexp.re2j.RE2.Anchor.UNANCHORED; -import static com.github.aaronshan.functions.regexp.re2j.RE2.MatchKind.FIRST_MATCH; +import static com.chinagoods.bigdata.functions.regexp.re2j.Options.DEFAULT_OPTIONS; +import static com.chinagoods.bigdata.functions.regexp.re2j.RE2.Anchor.ANCHOR_BOTH; +import static com.chinagoods.bigdata.functions.regexp.re2j.RE2.Anchor.UNANCHORED; +import static com.chinagoods.bigdata.functions.regexp.re2j.RE2.MatchKind.FIRST_MATCH; /** * A compiled representation of an RE2 regular expression, mimicking the diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/PatternSyntaxException.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/PatternSyntaxException.java old mode 100755 new mode 100644 similarity index 96% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/PatternSyntaxException.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/PatternSyntaxException.java index fff0f7a..79b3fc0 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/PatternSyntaxException.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/PatternSyntaxException.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; /** * An exception thrown by the parser if the pattern was invalid. diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Prog.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Prog.java old mode 100755 new mode 100644 similarity index 78% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/Prog.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Prog.java index fb29801..c9fa77d --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Prog.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Prog.java @@ -5,7 +5,7 @@ // Original Go source here: // http://code.google.com/p/go/source/browse/src/pkg/regexp/syntax/prog.go -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; import io.airlift.slice.SliceOutput; import io.airlift.slice.Slices; @@ -13,15 +13,15 @@ import java.util.ArrayList; import java.util.List; -import static com.github.aaronshan.functions.regexp.re2j.Inst.Op.BYTE; -import static com.github.aaronshan.functions.regexp.re2j.Inst.Op.MATCH; +import static com.chinagoods.bigdata.functions.regexp.re2j.Inst.Op.BYTE; +import static com.chinagoods.bigdata.functions.regexp.re2j.Inst.Op.MATCH; /** * A Prog is a compiled regular expression program. */ class Prog { - private final List inst = new ArrayList(); + private final List inst = new ArrayList(); int start; // index of start instruction int startUnanchored; // index of unanchored start instruction int numCap = 2; // number of CAPTURE insts in re @@ -33,12 +33,12 @@ class Prog { // Returns the instruction at the specified pc. // Precondition: pc > 0 && pc < numInst(). - com.github.aaronshan.functions.regexp.re2j.Inst getInst(int pc) { + Inst getInst(int pc) { return inst.get(pc); } - com.github.aaronshan.functions.regexp.re2j.Inst[] getInst() { - return inst.toArray(new com.github.aaronshan.functions.regexp.re2j.Inst[inst.size()]); + Inst[] getInst() { + return inst.toArray(new Inst[inst.size()]); } // Returns the number of instructions in this program. @@ -48,15 +48,15 @@ int numInst() { // Adds a new instruction to this program, with operator |op| and |pc| equal // to |numInst()|. - void addInst(com.github.aaronshan.functions.regexp.re2j.Inst.Op op) { - inst.add(new com.github.aaronshan.functions.regexp.re2j.Inst(op)); + void addInst(Inst.Op op) { + inst.add(new Inst(op)); } // skipNop() follows any no-op or capturing instructions and returns the // resulting instruction. - com.github.aaronshan.functions.regexp.re2j.Inst skipNop(int pc) { - com.github.aaronshan.functions.regexp.re2j.Inst i = inst.get(pc); - while (i.op == com.github.aaronshan.functions.regexp.re2j.Inst.Op.NOP || i.op == com.github.aaronshan.functions.regexp.re2j.Inst.Op.CAPTURE) { + Inst skipNop(int pc) { + Inst i = inst.get(pc); + while (i.op == Inst.Op.NOP || i.op == Inst.Op.CAPTURE) { i = inst.get(pc); pc = i.out; } @@ -67,7 +67,7 @@ com.github.aaronshan.functions.regexp.re2j.Inst skipNop(int pc) { // regexp must start with, and a boolean which is true if the prefix is the // entire match. The slice is returned by appending to |prefix|. boolean prefix(SliceOutput prefix) { - com.github.aaronshan.functions.regexp.re2j.Inst i = skipNop(start); + Inst i = skipNop(start); // Avoid allocation of buffer if prefix is empty. if (i.op() != BYTE || i.byteRanges.length != 1) { @@ -102,7 +102,7 @@ int startCond() { int pc = start; loop: for (; ; ) { - com.github.aaronshan.functions.regexp.re2j.Inst i = inst.get(pc); + Inst i = inst.get(pc); switch (i.op) { case EMPTY_WIDTH: flag |= i.arg; @@ -134,7 +134,7 @@ int startCond() { // at its output link. int next(int l) { - com.github.aaronshan.functions.regexp.re2j.Inst i = inst.get(l >> 1); + Inst i = inst.get(l >> 1); if ((l & 1) == 0) { return i.out; } @@ -143,7 +143,7 @@ int next(int l) { void patch(int l, int val) { while (l != 0) { - com.github.aaronshan.functions.regexp.re2j.Inst i = inst.get(l >> 1); + Inst i = inst.get(l >> 1); if ((l & 1) == 0) { l = i.out; i.out = val; @@ -169,7 +169,7 @@ int append(int l1, int l2) { } last = next; } - com.github.aaronshan.functions.regexp.re2j.Inst i = inst.get(last >> 1); + Inst i = inst.get(last >> 1); if ((last & 1) == 0) { i.out = l2; } else { diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/RE2.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/RE2.java old mode 100755 new mode 100644 similarity index 88% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/RE2.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/RE2.java index 2d61601..d9a77b0 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/RE2.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/RE2.java @@ -16,9 +16,8 @@ // the primary input datatype, and the method names have been changed to // reflect this. -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; -import com.github.aaronshan.functions.regexp.re2j.DFA.DFATooManyStatesException; import io.airlift.slice.DynamicSliceOutput; import io.airlift.slice.Slice; import io.airlift.slice.SliceOutput; @@ -30,9 +29,8 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -import static com.github.aaronshan.functions.regexp.re2j.MachineInput.EOF; -import static com.github.aaronshan.functions.regexp.re2j.Options.Algorithm.DFA; -import static com.github.aaronshan.functions.regexp.re2j.Options.Algorithm.DFA_FALLBACK_TO_NFA; +import static com.chinagoods.bigdata.functions.regexp.re2j.Options.Algorithm.DFA; +import static com.chinagoods.bigdata.functions.regexp.re2j.Options.Algorithm.DFA_FALLBACK_TO_NFA; /** * An RE2 class instance is a compiled representation of an RE2 regular @@ -101,10 +99,10 @@ class RE2 { // POSIX syntax. static final int POSIX = 0; final String expr; // as passed to Compile - final com.github.aaronshan.functions.regexp.re2j.Prog prog; // compiled program + final Prog prog; // compiled program //// RE2 instance members. - final com.github.aaronshan.functions.regexp.re2j.Prog reverseProg; // program for matching reversed text + final Prog reverseProg; // program for matching reversed text final int cond; // EMPTY_* bitmask: empty-width conditions // required at start of match final int numSubexp; @@ -128,7 +126,7 @@ protected NFAMachine initialValue() { this(re2.expr, re2.prog, re2.reverseProg, re2.numSubexp, re2.namedGroupIndexes, re2.matchKind, re2.options, re2.prefixComplete, re2.prefixUTF8); } - private RE2(String expr, com.github.aaronshan.functions.regexp.re2j.Prog prog, com.github.aaronshan.functions.regexp.re2j.Prog reverseProg, int numSubexp, + private RE2(String expr, Prog prog, Prog reverseProg, int numSubexp, Map namedGroupIndexes, MatchKind matchKind, Options options, boolean prefixComplete, Slice prefixUTF8) { this.expr = expr; @@ -159,7 +157,7 @@ private RE2(String expr, com.github.aaronshan.functions.regexp.re2j.Prog prog, c * package implements it without the expense of backtracking. * For POSIX leftmost-longest matching, see {@link #compilePOSIX}. */ - static RE2 compile(String expr, Options options) throws com.github.aaronshan.functions.regexp.re2j.PatternSyntaxException { + static RE2 compile(String expr, Options options) throws PatternSyntaxException { return compileImpl(expr, PERL, MatchKind.FIRST_MATCH, options); } @@ -184,18 +182,18 @@ static RE2 compile(String expr, Options options) throws com.github.aaronshan.fun * The POSIX rule is computationally prohibitive and not even well-defined. * See http://swtch.com/~rsc/regexp/regexp2.html#posix */ - static RE2 compilePOSIX(String expr, Options options) throws com.github.aaronshan.functions.regexp.re2j.PatternSyntaxException { + static RE2 compilePOSIX(String expr, Options options) throws PatternSyntaxException { return compileImpl(expr, POSIX, MatchKind.LONGEST_MATCH, options); } // Exposed to ExecTests. static RE2 compileImpl(String expr, int mode, MatchKind matchKind, Options options) - throws com.github.aaronshan.functions.regexp.re2j.PatternSyntaxException { - Regexp re = com.github.aaronshan.functions.regexp.re2j.Parser.parse(expr, mode); + throws PatternSyntaxException { + Regexp re = Parser.parse(expr, mode); int maxCap = re.maxCap(); // (may shrink during simplify) re = Simplify.simplify(re); - com.github.aaronshan.functions.regexp.re2j.Prog prog = com.github.aaronshan.functions.regexp.re2j.Compiler.compileRegexp(re, false); - com.github.aaronshan.functions.regexp.re2j.Prog reverseProg = com.github.aaronshan.functions.regexp.re2j.Compiler.compileRegexp(re, true); + Prog prog = Compiler.compileRegexp(re, false); + Prog reverseProg = Compiler.compileRegexp(re, true); SliceOutput prefixBuilder = new DynamicSliceOutput(prog.numInst()); boolean prefixComplete = prog.prefix(prefixBuilder); Slice prefixUTF8 = prefixBuilder.slice(); @@ -249,26 +247,26 @@ public String toString() { // doExecute() finds the leftmost match in the input and returns // the position of its subexpressions. // Derived from exec.go. - private int[] doExecute(com.github.aaronshan.functions.regexp.re2j.MachineInput in, int pos, Anchor anchor, int ncap) { + private int[] doExecute(MachineInput in, int pos, Anchor anchor, int ncap) { DFAMachine currentDFAMachine = dfaMachine; if (currentDFAMachine == null) { return doExecute(nfaMachine.get(), in, pos, anchor, ncap); } else { try { return doExecute(currentDFAMachine, in, pos, anchor, ncap); - } catch (DFATooManyStatesException e) { + } catch (DFA.DFATooManyStatesException e) { handleTooManyDFAStatesException(e, currentDFAMachine); return doExecute(nfaMachine.get(), in, pos, anchor, ncap); } } } - private int[] doExecute(com.github.aaronshan.functions.regexp.re2j.Machine machine, com.github.aaronshan.functions.regexp.re2j.MachineInput in, int pos, Anchor anchor, int ncap) { + private int[] doExecute(Machine machine, MachineInput in, int pos, Anchor anchor, int ncap) { int[] submatches = new int[ncap]; return machine.match(in, pos, anchor, submatches) ? submatches : null; } - private synchronized void handleTooManyDFAStatesException(DFATooManyStatesException e, DFAMachine currentDFAMachine) { + private synchronized void handleTooManyDFAStatesException(DFA.DFATooManyStatesException e, DFAMachine currentDFAMachine) { // make sure we don't penalize new DFAMachine instance if (currentDFAMachine == dfaMachine) { if (numberOfDFARetriesLeft.decrementAndGet() < 0) { @@ -291,7 +289,7 @@ private synchronized void handleTooManyDFAStatesException(DFATooManyStatesExcept * Returns true iff this regexp matches the string {@code s}. */ boolean match(Slice s) { - return doExecute(com.github.aaronshan.functions.regexp.re2j.MachineInput.fromUTF8(s), 0, Anchor.UNANCHORED, 0) != null; + return doExecute(MachineInput.fromUTF8(s), 0, Anchor.UNANCHORED, 0) != null; } /** @@ -321,7 +319,7 @@ boolean match(Slice input, int start, Anchor anchor, int[] group, // In Russ' own words: // That is, I believe doExecute needs to know the bounds of the whole input // as well as the bounds of the subpiece that is being searched. - int[] groupMatch = doExecute(com.github.aaronshan.functions.regexp.re2j.MachineInput.fromUTF8(input), start, + int[] groupMatch = doExecute(MachineInput.fromUTF8(input), start, anchor, 2 * ngroup); if (groupMatch == null) { @@ -381,7 +379,7 @@ Slice replaceAllFunc(Slice src, ReplaceFunc repl, int maxReplaces) { int lastMatchEnd = 0; // end position of the most recent match int searchPos = 0; // position where we next look for a match SliceOutput buf = new DynamicSliceOutput(src.length()); - com.github.aaronshan.functions.regexp.re2j.MachineInput input = com.github.aaronshan.functions.regexp.re2j.MachineInput.fromUTF8(src); + MachineInput input = MachineInput.fromUTF8(src); int numReplaces = 0; while (searchPos <= src.length()) { int[] a = doExecute(input, searchPos, Anchor.UNANCHORED, 2); @@ -448,7 +446,7 @@ private int[] pad(int[] a) { } // Find matches in input. - private void allMatches(com.github.aaronshan.functions.regexp.re2j.MachineInput input, int n, DeliverFunc deliver) { + private void allMatches(MachineInput input, int n, DeliverFunc deliver) { int end = input.endPos(); if (n < 0) { n = end + 1; @@ -468,7 +466,7 @@ private void allMatches(com.github.aaronshan.functions.regexp.re2j.MachineInput accept = false; } byte b = input.getByte(pos); - if (b == EOF) { + if (b == MachineInput.EOF) { pos = end + 1; } else { pos++; @@ -497,7 +495,7 @@ private void allMatches(com.github.aaronshan.functions.regexp.re2j.MachineInput */ // This is visible for testing. Slice find(Slice s) { - int[] a = doExecute(com.github.aaronshan.functions.regexp.re2j.MachineInput.fromUTF8(s), 0, Anchor.UNANCHORED, 2); + int[] a = doExecute(MachineInput.fromUTF8(s), 0, Anchor.UNANCHORED, 2); if (a == null) { return Slices.EMPTY_SLICE; } @@ -513,7 +511,7 @@ Slice find(Slice s) { */ // This is visible for testing. int[] findIndex(Slice s) { - int[] a = doExecute(com.github.aaronshan.functions.regexp.re2j.MachineInput.fromUTF8(s), 0, Anchor.UNANCHORED, 2); + int[] a = doExecute(MachineInput.fromUTF8(s), 0, Anchor.UNANCHORED, 2); if (a == null) { return null; } @@ -530,7 +528,7 @@ int[] findIndex(Slice s) { */ // This is visible for testing. Slice[] findSubmatch(Slice s) { - int[] a = doExecute(com.github.aaronshan.functions.regexp.re2j.MachineInput.fromUTF8(s), 0, Anchor.UNANCHORED, prog.numCap); + int[] a = doExecute(MachineInput.fromUTF8(s), 0, Anchor.UNANCHORED, prog.numCap); if (a == null) { return null; } @@ -555,7 +553,7 @@ Slice[] findSubmatch(Slice s) { */ // This is visible for testing. int[] findSubmatchIndex(Slice s) { - return pad(doExecute(com.github.aaronshan.functions.regexp.re2j.MachineInput.fromUTF8(s), 0, Anchor.UNANCHORED, prog.numCap)); + return pad(doExecute(MachineInput.fromUTF8(s), 0, Anchor.UNANCHORED, prog.numCap)); } // Legacy Go-style interface; preserved (package-private) for better @@ -605,7 +603,7 @@ int[] findSubmatchIndex(Slice s) { // This is visible for testing. List findAll(final Slice s, int n) { final List result = new ArrayList(); - allMatches(com.github.aaronshan.functions.regexp.re2j.MachineInput.fromUTF8(s), n, new DeliverFunc() { + allMatches(MachineInput.fromUTF8(s), n, new DeliverFunc() { @Override public void deliver(int[] match) { result.add(s.slice(match[0], match[1] - match[0])); @@ -628,7 +626,7 @@ public void deliver(int[] match) { // This is visible for testing. List findAllIndex(Slice s, int n) { final List result = new ArrayList(); - allMatches(com.github.aaronshan.functions.regexp.re2j.MachineInput.fromUTF8(s), n, new DeliverFunc() { + allMatches(MachineInput.fromUTF8(s), n, new DeliverFunc() { @Override public void deliver(int[] match) { result.add(Utils.subarray(match, 0, 2)); @@ -651,7 +649,7 @@ public void deliver(int[] match) { // This is visible for testing. List findAllSubmatch(final Slice s, int n) { final List result = new ArrayList(); - allMatches(com.github.aaronshan.functions.regexp.re2j.MachineInput.fromUTF8(s), n, new DeliverFunc() { + allMatches(MachineInput.fromUTF8(s), n, new DeliverFunc() { @Override public void deliver(int[] match) { Slice[] slice = new Slice[match.length / 2]; @@ -682,7 +680,7 @@ public void deliver(int[] match) { // This is visible for testing. List findAllSubmatchIndex(Slice s, int n) { final List result = new ArrayList(); - allMatches(com.github.aaronshan.functions.regexp.re2j.MachineInput.fromUTF8(s), n, new DeliverFunc() { + allMatches(MachineInput.fromUTF8(s), n, new DeliverFunc() { @Override public void deliver(int[] match) { result.add(match); diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Regexp.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Regexp.java old mode 100755 new mode 100644 similarity index 92% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/Regexp.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Regexp.java index 569ef4a..cf0d24f --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Regexp.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Regexp.java @@ -5,7 +5,7 @@ // Original Go source here: // http://code.google.com/p/go/source/browse/src/pkg/regexp/syntax/regexp.go -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; import java.util.Arrays; import java.util.HashMap; @@ -109,7 +109,7 @@ private void appendTo(StringBuilder out) { out.append('}'); break; } - if ((flags & com.github.aaronshan.functions.regexp.re2j.RE2.NON_GREEDY) != 0) { + if ((flags & RE2.NON_GREEDY) != 0) { out.append('?'); } break; @@ -135,13 +135,13 @@ private void appendTo(StringBuilder out) { break; } case LITERAL: - if ((flags & com.github.aaronshan.functions.regexp.re2j.RE2.FOLD_CASE) != 0) { + if ((flags & RE2.FOLD_CASE) != 0) { out.append("(?i:"); } for (int rune : runes) { Utils.escapeRune(out, rune); } - if ((flags & com.github.aaronshan.functions.regexp.re2j.RE2.FOLD_CASE) != 0) { + if ((flags & RE2.FOLD_CASE) != 0) { out.append(')'); } break; @@ -168,7 +168,7 @@ private void appendTo(StringBuilder out) { out.append("\\A"); break; case END_TEXT: - if ((flags & com.github.aaronshan.functions.regexp.re2j.RE2.WAS_DOLLAR) != 0) { + if ((flags & RE2.WAS_DOLLAR) != 0) { out.append("(?-m:$)"); } else { out.append("\\z"); @@ -280,7 +280,7 @@ public boolean equals(Object that) { switch (x.op) { case END_TEXT: // The parse flags remember whether this is \z or \Z. - if ((x.flags & com.github.aaronshan.functions.regexp.re2j.RE2.WAS_DOLLAR) != (y.flags & com.github.aaronshan.functions.regexp.re2j.RE2.WAS_DOLLAR)) { + if ((x.flags & RE2.WAS_DOLLAR) != (y.flags & RE2.WAS_DOLLAR)) { return false; } break; @@ -304,13 +304,13 @@ public boolean equals(Object that) { case STAR: case PLUS: case QUEST: - if ((x.flags & com.github.aaronshan.functions.regexp.re2j.RE2.NON_GREEDY) != (y.flags & com.github.aaronshan.functions.regexp.re2j.RE2.NON_GREEDY) || + if ((x.flags & RE2.NON_GREEDY) != (y.flags & RE2.NON_GREEDY) || !x.subs[0].equals(y.subs[0])) { return false; } break; case REPEAT: - if ((x.flags & com.github.aaronshan.functions.regexp.re2j.RE2.NON_GREEDY) != (y.flags & com.github.aaronshan.functions.regexp.re2j.RE2.NON_GREEDY) || + if ((x.flags & RE2.NON_GREEDY) != (y.flags & RE2.NON_GREEDY) || x.min != y.min || x.max != y.max || !x.subs[0].equals(y.subs[0])) { return false; } diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Simplify.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Simplify.java old mode 100755 new mode 100644 similarity index 54% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/Simplify.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Simplify.java index a5ea852..fc9c6d7 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Simplify.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Simplify.java @@ -5,7 +5,7 @@ // Original Go source here: // http://code.google.com/p/go/source/browse/src/pkg/regexp/syntax/simplify.go -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; import java.util.ArrayList; @@ -22,7 +22,7 @@ private Simplify() { // or removed. For example, the simplified form for /(x){1,2}/ is // /(x)(x)?/ but both parentheses capture as $1. The returned regexp // may share structure with or be the original. - static com.github.aaronshan.functions.regexp.re2j.Regexp simplify(com.github.aaronshan.functions.regexp.re2j.Regexp re) { + static Regexp simplify(Regexp re) { if (re == null) { return null; } @@ -31,15 +31,15 @@ static com.github.aaronshan.functions.regexp.re2j.Regexp simplify(com.github.aar case CONCAT: case ALTERNATE: { // Simplify children, building new Regexp if children change. - com.github.aaronshan.functions.regexp.re2j.Regexp nre = re; + Regexp nre = re; for (int i = 0; i < re.subs.length; ++i) { - com.github.aaronshan.functions.regexp.re2j.Regexp sub = re.subs[i]; - com.github.aaronshan.functions.regexp.re2j.Regexp nsub = simplify(sub); + Regexp sub = re.subs[i]; + Regexp nsub = simplify(sub); if (nre == re && nsub != sub) { // Start a copy. - nre = new com.github.aaronshan.functions.regexp.re2j.Regexp(re); // shallow copy + nre = new Regexp(re); // shallow copy nre.runes = null; - nre.subs = com.github.aaronshan.functions.regexp.re2j.Parser.subarray(re.subs, 0, re.subs.length); // clone + nre.subs = Parser.subarray(re.subs, 0, re.subs.length); // clone } if (nre != re) { nre.subs[i] = nsub; @@ -50,39 +50,39 @@ static com.github.aaronshan.functions.regexp.re2j.Regexp simplify(com.github.aar case STAR: case PLUS: case QUEST: { - com.github.aaronshan.functions.regexp.re2j.Regexp sub = simplify(re.subs[0]); + Regexp sub = simplify(re.subs[0]); return simplify1(re.op, re.flags, sub, re); } case REPEAT: { // Special special case: x{0} matches the empty string // and doesn't even need to consider x. if (re.min == 0 && re.max == 0) { - return new com.github.aaronshan.functions.regexp.re2j.Regexp(com.github.aaronshan.functions.regexp.re2j.Regexp.Op.EMPTY_MATCH); + return new Regexp(Regexp.Op.EMPTY_MATCH); } // The fun begins. - com.github.aaronshan.functions.regexp.re2j.Regexp sub = simplify(re.subs[0]); + Regexp sub = simplify(re.subs[0]); // x{n,} means at least n matches of x. if (re.max == -1) { // Special case: x{0,} is x*. if (re.min == 0) { - return simplify1(com.github.aaronshan.functions.regexp.re2j.Regexp.Op.STAR, re.flags, sub, null); + return simplify1(Regexp.Op.STAR, re.flags, sub, null); } // Special case: x{1,} is x+. if (re.min == 1) { - return simplify1(com.github.aaronshan.functions.regexp.re2j.Regexp.Op.PLUS, re.flags, sub, null); + return simplify1(Regexp.Op.PLUS, re.flags, sub, null); } // General case: x{4,} is xxxx+. - com.github.aaronshan.functions.regexp.re2j.Regexp nre = new com.github.aaronshan.functions.regexp.re2j.Regexp(com.github.aaronshan.functions.regexp.re2j.Regexp.Op.CONCAT); - ArrayList subs = new ArrayList(); + Regexp nre = new Regexp(Regexp.Op.CONCAT); + ArrayList subs = new ArrayList(); for (int i = 0; i < re.min - 1; i++) { subs.add(sub); } - subs.add(simplify1(com.github.aaronshan.functions.regexp.re2j.Regexp.Op.PLUS, re.flags, sub, null)); - nre.subs = subs.toArray(new com.github.aaronshan.functions.regexp.re2j.Regexp[subs.size()]); + subs.add(simplify1(Regexp.Op.PLUS, re.flags, sub, null)); + nre.subs = subs.toArray(new Regexp[subs.size()]); return nre; } @@ -98,9 +98,9 @@ static com.github.aaronshan.functions.regexp.re2j.Regexp simplify(com.github.aar // so that x{2,5} = xx(x(x(x)?)?)? // Build leading prefix: xx. - ArrayList prefixSubs = null; + ArrayList prefixSubs = null; if (re.min > 0) { - prefixSubs = new ArrayList(); + prefixSubs = new ArrayList(); for (int i = 0; i < re.min; i++) { prefixSubs.add(sub); } @@ -108,11 +108,11 @@ static com.github.aaronshan.functions.regexp.re2j.Regexp simplify(com.github.aar // Build and attach suffix: (x(x(x)?)?)? if (re.max > re.min) { - com.github.aaronshan.functions.regexp.re2j.Regexp suffix = simplify1(com.github.aaronshan.functions.regexp.re2j.Regexp.Op.QUEST, re.flags, sub, null); + Regexp suffix = simplify1(Regexp.Op.QUEST, re.flags, sub, null); for (int i = re.min + 1; i < re.max; i++) { - com.github.aaronshan.functions.regexp.re2j.Regexp nre2 = new com.github.aaronshan.functions.regexp.re2j.Regexp(com.github.aaronshan.functions.regexp.re2j.Regexp.Op.CONCAT); - nre2.subs = new com.github.aaronshan.functions.regexp.re2j.Regexp[]{sub, suffix}; - suffix = simplify1(com.github.aaronshan.functions.regexp.re2j.Regexp.Op.QUEST, re.flags, nre2, null); + Regexp nre2 = new Regexp(Regexp.Op.CONCAT); + nre2.subs = new Regexp[]{sub, suffix}; + suffix = simplify1(Regexp.Op.QUEST, re.flags, nre2, null); } if (prefixSubs == null) { return suffix; @@ -120,14 +120,14 @@ static com.github.aaronshan.functions.regexp.re2j.Regexp simplify(com.github.aar prefixSubs.add(suffix); } if (prefixSubs != null) { - com.github.aaronshan.functions.regexp.re2j.Regexp prefix = new com.github.aaronshan.functions.regexp.re2j.Regexp(com.github.aaronshan.functions.regexp.re2j.Regexp.Op.CONCAT); - prefix.subs = prefixSubs.toArray(new com.github.aaronshan.functions.regexp.re2j.Regexp[prefixSubs.size()]); + Regexp prefix = new Regexp(Regexp.Op.CONCAT); + prefix.subs = prefixSubs.toArray(new Regexp[prefixSubs.size()]); return prefix; } // Some degenerate case like min > max or min < max < 0. // Handle as impossible match. - return new com.github.aaronshan.functions.regexp.re2j.Regexp(com.github.aaronshan.functions.regexp.re2j.Regexp.Op.NO_MATCH); + return new Regexp(Regexp.Op.NO_MATCH); } } @@ -149,27 +149,27 @@ static com.github.aaronshan.functions.regexp.re2j.Regexp simplify(com.github.aar // for other operators generates these unary expressions. // Letting them call simplify1 makes sure the expressions they // generate are simple. - private static com.github.aaronshan.functions.regexp.re2j.Regexp simplify1(com.github.aaronshan.functions.regexp.re2j.Regexp.Op op, int flags, com.github.aaronshan.functions.regexp.re2j.Regexp sub, - com.github.aaronshan.functions.regexp.re2j.Regexp re) { + private static Regexp simplify1(Regexp.Op op, int flags, Regexp sub, + Regexp re) { // Special case: repeat the empty string as much as // you want, but it's still the empty string. - if (sub.op == com.github.aaronshan.functions.regexp.re2j.Regexp.Op.EMPTY_MATCH) { + if (sub.op == Regexp.Op.EMPTY_MATCH) { return sub; } // The operators are idempotent if the flags match. if (op == sub.op && - (flags & com.github.aaronshan.functions.regexp.re2j.RE2.NON_GREEDY) == (sub.flags & com.github.aaronshan.functions.regexp.re2j.RE2.NON_GREEDY)) { + (flags & RE2.NON_GREEDY) == (sub.flags & RE2.NON_GREEDY)) { return sub; } if (re != null && re.op == op && - (re.flags & com.github.aaronshan.functions.regexp.re2j.RE2.NON_GREEDY) == (flags & com.github.aaronshan.functions.regexp.re2j.RE2.NON_GREEDY) && + (re.flags & RE2.NON_GREEDY) == (flags & RE2.NON_GREEDY) && sub == re.subs[0]) { return re; } - re = new com.github.aaronshan.functions.regexp.re2j.Regexp(op); + re = new Regexp(op); re.flags = flags; - re.subs = new com.github.aaronshan.functions.regexp.re2j.Regexp[]{sub}; + re.subs = new Regexp[]{sub}; return re; } diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/SliceUtils.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/SliceUtils.java old mode 100755 new mode 100644 similarity index 98% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/SliceUtils.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/SliceUtils.java index c3900bd..32dae7a --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/SliceUtils.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/SliceUtils.java @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; import io.airlift.slice.Slice; import io.airlift.slice.SliceOutput; diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/SparseSet.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/SparseSet.java old mode 100755 new mode 100644 similarity index 95% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/SparseSet.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/SparseSet.java index 45ce6f1..67c0fde --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/SparseSet.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/SparseSet.java @@ -5,7 +5,7 @@ // Original RE2 source here: // https://github.com/google/re2/blob/master/util/sparse_set.h -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; class SparseSet { private final int[] dense; // may contain stale Entries in slots >= size diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Unicode.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Unicode.java old mode 100755 new mode 100644 similarity index 99% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/Unicode.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Unicode.java index bbe512c..9cd9f87 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Unicode.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Unicode.java @@ -5,7 +5,7 @@ // Many of these were derived from the corresponding Go functions in // http://code.google.com/p/go/source/browse/src/pkg/unicode/letter.go -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; import java.nio.charset.Charset; diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/UnicodeTables.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/UnicodeTables.java old mode 100755 new mode 100644 similarity index 99% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/UnicodeTables.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/UnicodeTables.java index 0350c33..f90c1b2 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/UnicodeTables.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/UnicodeTables.java @@ -2,7 +2,7 @@ // go/src/pkg/unicode/maketables.go. Yes it's awful, but frankly // it's quicker than porting 1300 more lines of Go. -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Utils.java b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Utils.java old mode 100755 new mode 100644 similarity index 97% rename from src/main/java/com/github/aaronshan/functions/regexp/re2j/Utils.java rename to src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Utils.java index 4458990..9e56ac7 --- a/src/main/java/com/github/aaronshan/functions/regexp/re2j/Utils.java +++ b/src/main/java/com/chinagoods/bigdata/functions/regexp/re2j/Utils.java @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package com.github.aaronshan.functions.regexp.re2j; +package com.chinagoods.bigdata.functions.regexp.re2j; import io.airlift.slice.Slice; -import static com.github.aaronshan.functions.regexp.re2j.MachineInput.EOF; +import static com.chinagoods.bigdata.functions.regexp.re2j.MachineInput.EOF; /** * Various constants and helper utilities. @@ -50,7 +50,7 @@ static int unhex(int c) { // Appends a RE2 literal to |out| for rune |rune|, // with regexp metacharacters escaped. static void escapeRune(StringBuilder out, int rune) { - if (com.github.aaronshan.functions.regexp.re2j.Unicode.isPrint(rune)) { + if (Unicode.isPrint(rune)) { if (METACHARACTERS.indexOf((char) rune) >= 0) { out.append('\\'); } diff --git a/src/main/java/com/chinagoods/bigdata/functions/risk/UDFRiskKeywords.java b/src/main/java/com/chinagoods/bigdata/functions/risk/UDFRiskKeywords.java new file mode 100644 index 0000000..c297a6e --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/risk/UDFRiskKeywords.java @@ -0,0 +1,115 @@ +package com.chinagoods.bigdata.functions.risk; + +import com.chinagoods.bigdata.functions.utils.MysqlUtil; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; + +/** + * @author xiaowei.song + * date: 2022-03-23 + * time: 14:48 + */ +@Description(name = "risk_keywords", value = "_FUNC_(str) - Determines whether the keyword is a prohibited word, if it returns comma string, otherwise returns null. " + , extended = "Example:\n" + + " > SELECT _FUNC_(key_word) FROM src LIMIT 1;") +public class UDFRiskKeywords extends GenericUDF { + + private static final Logger logger = LoggerFactory.getLogger(UDFRiskKeywords.class); + + public static final String DB_URL = "jdbc:mysql://172.18.5.22:3306/source?characterEncoding=UTF-8&useSSL=false"; + public static final String DB_USER = "source"; + public static final String DB_PASSWORD = "jP8*dKw,bRjBVos="; + public static final String SELECT_RISK_KEYWORDS_SQL = "select t.key_word\n" + + "from risk_control_keywords t\n" + + "inner join (\n" + + "\tselect key_word\n" + + "\t,max(create_time) max_create_time\n" + + "\tfrom risk_control_keywords\n" + + "\tgroup by key_word\n" + + ") nt on t.create_time = nt.max_create_time and t.key_word = nt.key_word\n" + + "where t.is_deleted = '否'"; + + private ObjectInspectorConverters.Converter[] converters; + + /** + * Number of arguments to this UDF + **/ + private static final int ARG_COUNT = 1; + + /** + * 搜索关键词禁用表 + **/ + public Set riskKeywordsSet = new HashSet(); + + public UDFRiskKeywords() { + } + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + if (arguments.length != ARG_COUNT) { + throw new UDFArgumentLengthException( + "The function search_keywords_sensitive(key_word) takes exactly " + ARG_COUNT + " arguments."); + } + + converters = new ObjectInspectorConverters.Converter[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + converters[i] = ObjectInspectorConverters.getConverter(arguments[i], + PrimitiveObjectInspectorFactory.writableStringObjectInspector); + } + + // 查询现有搜索引擎禁用词 + MysqlUtil mysqlUtil = new MysqlUtil(DB_URL, DB_USER, DB_PASSWORD); + try { + riskKeywordsSet = mysqlUtil.getKeywords(SELECT_RISK_KEYWORDS_SQL); + } catch (SQLException e) { + throw new UDFArgumentException(String.format("Failed to query the set of prohibited words in the risk database, the error details are: %s", e)); + } + + return PrimitiveObjectInspectorFactory.javaStringObjectInspector; + } + + @Override + public Object evaluate(DeferredObject[] arguments) throws HiveException { + assert (arguments.length == ARG_COUNT); + + if (arguments[0].get() == null || StringUtils.isBlank(arguments[0].get().toString())) { + return null; + } + Set hitKeywordSet = new TreeSet<>(); + + String goodName; + try { + goodName = converters[0].convert(arguments[0].get()).toString(); + } catch (Exception e) { + logger.error("Type conversion failed", e); + return null; + } + + for (String keyword : riskKeywordsSet) { + if (StringUtils.contains(goodName, keyword)) { + hitKeywordSet.add(keyword); + } + } + return StringUtils.join(hitKeywordSet, ","); + } + + @Override + public String getDisplayString(String[] strings) { + assert (strings.length == ARG_COUNT); + return "risk_keywords(" + strings[0] + ")"; + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/risk/negative/NegativeStringMatcher.java b/src/main/java/com/chinagoods/bigdata/functions/risk/negative/NegativeStringMatcher.java new file mode 100644 index 0000000..4d59255 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/risk/negative/NegativeStringMatcher.java @@ -0,0 +1,47 @@ +package com.chinagoods.bigdata.functions.risk.negative; + +import java.util.List; + +/** + * @author xiaowei.song + * @version v1.0.0 + * @description 高效负向词匹配,使用trie算法实现,构建负向词词库, + * @date 2023/9/6 10:06 + */ +public class NegativeStringMatcher { + private TrieNode root; + + public NegativeStringMatcher(List negativeStrings) { + root = new TrieNode(); + for (String negativeString : negativeStrings) { + insert(negativeString); + } + } + + public void insert(String word) { + TrieNode current = root; + for (char ch : word.toCharArray()) { + current.children.putIfAbsent(ch, new TrieNode()); + current = current.children.get(ch); + } + current.isEndOfWord = true; + } + + public boolean containsNegativeString(String goodsName) { + TrieNode current = root; + for (char ch : goodsName.toCharArray()) { + if (current.isEndOfWord) { + // 找到匹配的负向字符串 + return true; + } + if (!current.children.containsKey(ch)) { + // 重置到根节点 + current = root; + } else { + current = current.children.get(ch); + } + } + // 检查最后一个字符 + return current.isEndOfWord; + } +} \ No newline at end of file diff --git a/src/main/java/com/chinagoods/bigdata/functions/risk/negative/TrieNode.java b/src/main/java/com/chinagoods/bigdata/functions/risk/negative/TrieNode.java new file mode 100644 index 0000000..b9fef7d --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/risk/negative/TrieNode.java @@ -0,0 +1,20 @@ +package com.chinagoods.bigdata.functions.risk.negative; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author xiaowei.song + * @version v1.0.0 + * @description TODO + * @date 2023/9/6 10:06 + */ +class TrieNode { + Map children; + boolean isEndOfWord; + + public TrieNode() { + children = new HashMap<>(); + isEndOfWord = false; + } +} \ No newline at end of file diff --git a/src/main/java/com/chinagoods/bigdata/functions/risk/negative/UDFNewGoodsNegativeString.java b/src/main/java/com/chinagoods/bigdata/functions/risk/negative/UDFNewGoodsNegativeString.java new file mode 100644 index 0000000..52f62df --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/risk/negative/UDFNewGoodsNegativeString.java @@ -0,0 +1,166 @@ +package com.chinagoods.bigdata.functions.risk.negative; + +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.List; + +/** + * @author xiaowei.song + * date: 2022-03-23 + * time: 14:48 + */ +@Description(name = "new_goods_negative", value = "_FUNC_(str) - To check if the product name contains negative words, return true if it does, and false otherwise. " + , extended = "Example:\n" + + " > SELECT _FUNC_(goods_name) FROM src LIMIT 1;") +public class UDFNewGoodsNegativeString extends GenericUDF { + + private static final Logger logger = LoggerFactory.getLogger(UDFNewGoodsNegativeString.class); + + private ObjectInspectorConverters.Converter[] converters; + + /** + * Number of arguments to this UDF + **/ + private static final int ARG_COUNT = 1; + + private static NegativeStringMatcher negativeStringMatcher; + + /** + * 负向词列表 + **/ + public static final List NEGATIVE_STRING_LIST = Arrays.asList( + "尾货", + "尾单", + "特卖", + "特价", + "清仓", + "反季", + "换季", + "库存", + "亏本", + "超低价", + "尾单", + "清库存", + "折扣", + "促销", + "补差价", + "杂款", + "二手", + "邮费补差", + "补邮费", + "清库存", + "折扣", + "促销", + "福袋", + "临期", + "链接"); + + public UDFNewGoodsNegativeString() { + } + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + if (arguments.length != ARG_COUNT) { + throw new UDFArgumentLengthException( + "The function new_goods_negative(goods_name) takes exactly " + ARG_COUNT + " arguments."); + } + + converters = new ObjectInspectorConverters.Converter[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + converters[i] = ObjectInspectorConverters.getConverter(arguments[i], + PrimitiveObjectInspectorFactory.writableStringObjectInspector); + } + + // 初始化负向词匹配器 + negativeStringMatcher = new NegativeStringMatcher(NEGATIVE_STRING_LIST); + + return PrimitiveObjectInspectorFactory.javaBooleanObjectInspector; + } + + @Override + public Object evaluate(DeferredObject[] arguments) throws HiveException { + assert (arguments.length == ARG_COUNT); + + if (arguments[0].get() == null || StringUtils.isBlank(arguments[0].get().toString())) { + return false; + } + + String goodName; + try { + goodName = converters[0].convert(arguments[0].get()).toString(); + } catch (Exception e) { + logger.error("Type conversion failed", e); + return false; + } + return negativeStringMatcher.containsNegativeString(goodName); + } + + public Object evaluate2(DeferredObject[] arguments) throws HiveException { + assert (arguments.length == ARG_COUNT); + + if (arguments[0].get() == null || StringUtils.isBlank(arguments[0].get().toString())) { + return false; + } + + String goodName; + try { + goodName = converters[0].convert(arguments[0].get()).toString(); + } catch (Exception e) { + logger.error("Type conversion failed", e); + return false; + } + + for (String negativeStr : NEGATIVE_STRING_LIST) { + if (goodName.contains(negativeStr)) { + return true; + } + } + return false; + + } + + @Override + public String getDisplayString(String[] strings) { + assert (strings.length == ARG_COUNT); + return "new_goods_negative(" + strings[0] + ")"; + } + + public static void main(String[] args) throws HiveException { + UDFNewGoodsNegativeString goodsNegativeString = new UDFNewGoodsNegativeString(); + DeferredObject[] deferredObjects = new DeferredObject[2]; + deferredObjects[0] = new DeferredJavaObject("2022爆款仿羊绒格子围巾女冬季加厚保暖围脖哈利波特同款披肩男临期"); + ObjectInspector[] inspectorArr = new ObjectInspector[1]; + inspectorArr[0] = PrimitiveObjectInspectorFactory.javaStringObjectInspector; + goodsNegativeString.initialize(inspectorArr); + + long begin = System.currentTimeMillis(); + boolean latest = false; + + for (int i = 0; i < 3000000; i++) { + Object retArr = goodsNegativeString.evaluate(deferredObjects); + latest = (boolean) retArr; + } + long end = System.currentTimeMillis(); + System.out.println("测试1耗时:" + (end - begin) + "ms,结果为: " + latest); + + long begin2 = System.currentTimeMillis(); + boolean latest2 = false; + for (int i = 0; i < 3000000; i++) { + Object retArr = goodsNegativeString.evaluate2(deferredObjects); + latest2 = (boolean) retArr; + } + long end2 = System.currentTimeMillis(); + System.out.println("测试2耗时:" + (end2 - begin2) + "ms,结果为: " + latest2); + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/search/UDFSearchKeywordsSensitive.java b/src/main/java/com/chinagoods/bigdata/functions/search/UDFSearchKeywordsSensitive.java new file mode 100644 index 0000000..73396b9 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/search/UDFSearchKeywordsSensitive.java @@ -0,0 +1,103 @@ +package com.chinagoods.bigdata.functions.search; + +import com.chinagoods.bigdata.functions.utils.MysqlUtil; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; + +import java.sql.SQLException; +import java.util.HashSet; +import java.util.Set; + +/** + * @author xiaowei.song + * date: 2022-03-07 + * time: 14:48 + */ +@Description(name = "search_keywords_sensitive", value = "_FUNC_(str) - Determines whether the keyword is a prohibited word, if it returns 1, otherwise returns 0. " + , extended = "Example:\n" + + " > SELECT _FUNC_(key_word) FROM src LIMIT 1;") +public class UDFSearchKeywordsSensitive extends GenericUDF { + + public static final String DB_URL = "jdbc:mysql://172.18.7.7:3306/cg_search?characterEncoding=UTF-8&useSSL=false"; + public static final String DB_USER = "cg_search"; + public static final String DB_PASSWORD = "GPuBoTWz3UiMwwLz"; + public static final String SELECT_SENSITIVE_KEYWORDS_SQL = "select words key_word\n" + + "from lexicon_sensitive ls\n" + + "where 1=1\n" + + "and status = 0\n" + + "and is_deleted = 0"; + + private ObjectInspectorConverters.Converter[] converters; + + /** + * Number of arguments to this UDF + **/ + private static final int ARG_COUNT = 1; + + /** + * 搜索关键词禁用表 + **/ + public Set keywordsSensitive = new HashSet(); + + public UDFSearchKeywordsSensitive() { + } + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + if (arguments.length != ARG_COUNT) { + throw new UDFArgumentLengthException( + "The function search_keywords_sensitive(key_word) takes exactly " + ARG_COUNT + " arguments."); + } + + converters = new ObjectInspectorConverters.Converter[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + converters[i] = ObjectInspectorConverters.getConverter(arguments[i], + PrimitiveObjectInspectorFactory.writableStringObjectInspector); + } + + // 查询现有搜索引擎禁用词 + MysqlUtil mysqlUtil = new MysqlUtil(DB_URL, DB_USER, DB_PASSWORD); + try { + keywordsSensitive = mysqlUtil.getKeywords(SELECT_SENSITIVE_KEYWORDS_SQL); + } catch (SQLException e) { + throw new UDFArgumentException(String.format("Failed to query the set of prohibited words in the search engine database, the error details are: %s", e)); + } + + return PrimitiveObjectInspectorFactory + .javaIntObjectInspector; + } + + @Override + public Object evaluate(DeferredObject[] arguments) throws HiveException { + assert (arguments.length == ARG_COUNT); + + if (arguments[0].get() == null || StringUtils.isBlank(arguments[0].get().toString())) { + return 0; + } + + try { + String keywords = converters[0].convert(arguments[0].get()).toString(); + for (String sensitiveKeyword : keywordsSensitive) { + if (StringUtils.contains(keywords, sensitiveKeyword)) { + return 1; + } + } + return 0; + } catch (Exception e) { + return 0; + } + } + + @Override + public String getDisplayString(String[] strings) { + assert (strings.length == ARG_COUNT); + return "search_keywords_sensitive(" + strings[0] + ")"; + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/session/UDFSessionRowSequence.java b/src/main/java/com/chinagoods/bigdata/functions/session/UDFSessionRowSequence.java new file mode 100644 index 0000000..d872937 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/session/UDFSessionRowSequence.java @@ -0,0 +1,94 @@ +package com.chinagoods.bigdata.functions.session; + +import com.chinagoods.bigdata.functions.regexp.Re2JRegexp; +import com.fasterxml.jackson.databind.ObjectWriter; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.UDFType; +import org.apache.hadoop.io.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * UDFSessionRowSequence. + * @author xiaowei.song + */ +@Description(name = "session_row_sequence", + value = "_FUNC_(distinct_id, event, created_at) - Returns a generated row sequence number starting from 1", + extended = "Example:\n" + + " > SELECT session_row_sequence(distinct_id, event, created_at) FROM src LIMIT 100; " + + "Please note that this requires the original table to be in order") +@UDFType(deterministic = false, stateful = true) +public class UDFSessionRowSequence extends UDF { + private static final Logger log = LoggerFactory.getLogger(Re2JRegexp.class); + + // 间隔超过60s,认为会话已结束,重新开始 + public static final Long MAX_SESSION_INTERVAL_SEC = 60 * 1000L; + + public static final String APP_START_NAME = "$AppStart"; + public static final String APP_END_NAME = "$AppEnd"; + + private static volatile Long result = 0L; + private static volatile Long createdAt = 0L; + private static volatile String distinctId = ""; + private static volatile Boolean appEndFlag = Boolean.FALSE; + + public UDFSessionRowSequence() { + appEndFlag = Boolean.FALSE; + } + + public Long evaluate(String distinctIdStr, String eventNameStr, String iCreatedAt) throws HiveException { + + log.debug(String.format("distinctId=%s, event=%s, createdAt=%s", distinctIdStr, eventNameStr, iCreatedAt)); + Long createdAtLong = Long.valueOf(iCreatedAt); + + // 若原表无序,则报错 + if (distinctId.equals(distinctIdStr) && createdAtLong < createdAt) { + log.error("原表无序, lagDistinctId={}, lagCreatedAt={}; distinctId={}, createdAt={}", + distinctId, createdAt, distinctIdStr, iCreatedAt); + throw new HiveException(String.format("原表无序, 此函数必须有序,无序得出结果不正确,请先将表更改成有序表, lagDistinctId=%s, lagCreatedAt=%s; distinctId=%s, createdAt=%s", distinctId, createdAt, distinctIdStr, iCreatedAt)); + } + + if (StringUtils.isBlank(distinctIdStr)) { + distinctIdStr = ""; + } + + if (StringUtils.isBlank(eventNameStr)) { + eventNameStr = ""; + } + + // 起始阶段赋值 + if (result == 0) { + result++; + setLagStatus(distinctIdStr, createdAtLong); + } + + String lagDistinctId = distinctId; + Long lagCreatedAt = createdAt; + + + // 若上一个distinct_id、platformType、platformLang跟此时不一致,则重置row_number + if (!lagDistinctId.equals(distinctIdStr)) { + result = 0L; + result++; + } else if (APP_START_NAME.equals(eventNameStr) || + createdAtLong - lagCreatedAt > MAX_SESSION_INTERVAL_SEC || + appEndFlag) { + appEndFlag = false; + result++; + } + + if (APP_END_NAME.equals(eventNameStr)) { + appEndFlag = true; + } + setLagStatus(distinctIdStr, createdAtLong); + return result; + } + + private void setLagStatus(String distinctIdStr, Long createdAtLong) { + createdAt = createdAtLong; + distinctId = distinctIdStr; + } +} diff --git a/src/main/java/com/github/aaronshan/functions/string/UDFChineseToPinYin.java b/src/main/java/com/chinagoods/bigdata/functions/string/UDFChineseToPinYin.java old mode 100755 new mode 100644 similarity index 97% rename from src/main/java/com/github/aaronshan/functions/string/UDFChineseToPinYin.java rename to src/main/java/com/chinagoods/bigdata/functions/string/UDFChineseToPinYin.java index fa4abe8..23baa2e --- a/src/main/java/com/github/aaronshan/functions/string/UDFChineseToPinYin.java +++ b/src/main/java/com/chinagoods/bigdata/functions/string/UDFChineseToPinYin.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.string; +package com.chinagoods.bigdata.functions.string; import net.sourceforge.pinyin4j.PinyinHelper; import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; diff --git a/src/main/java/com/github/aaronshan/functions/string/UDFCodePoint.java b/src/main/java/com/chinagoods/bigdata/functions/string/UDFCodePoint.java similarity index 84% rename from src/main/java/com/github/aaronshan/functions/string/UDFCodePoint.java rename to src/main/java/com/chinagoods/bigdata/functions/string/UDFCodePoint.java index 6735afe..a4d8630 100644 --- a/src/main/java/com/github/aaronshan/functions/string/UDFCodePoint.java +++ b/src/main/java/com/chinagoods/bigdata/functions/string/UDFCodePoint.java @@ -1,5 +1,6 @@ -package com.github.aaronshan.functions.string; +package com.chinagoods.bigdata.functions.string; +import com.chinagoods.bigdata.functions.utils.Failures; import io.airlift.slice.Slice; import io.airlift.slice.Slices; import org.apache.hadoop.hive.ql.exec.Description; @@ -8,7 +9,6 @@ import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; -import static com.github.aaronshan.functions.utils.Failures.checkCondition; import static io.airlift.slice.SliceUtf8.getCodePointAt; import static io.airlift.slice.SliceUtf8.countCodePoints; @@ -39,7 +39,7 @@ public LongWritable evaluate(Text text) throws HiveException { } Slice slice = Slices.utf8Slice(text.toString()); - checkCondition(countCodePoints(slice) == 1, "Input string must be a single character string"); + Failures.checkCondition(countCodePoints(slice) == 1, "Input string must be a single character string"); result.set(getCodePointAt(slice, 0)); return result; diff --git a/src/main/java/com/chinagoods/bigdata/functions/string/UDFFull2Half.java b/src/main/java/com/chinagoods/bigdata/functions/string/UDFFull2Half.java new file mode 100644 index 0000000..5f0759d --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/string/UDFFull2Half.java @@ -0,0 +1,53 @@ +package com.chinagoods.bigdata.functions.string; + +/** + * @author xiaowei.song + * @version v1.0.0 + * @description TODO + * @date 2021/5/7 16:04 + */ +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; + +@Description( + name = "full2half", + value = "_FUNC_(full_string) - this is a 全角转化半角 util,若为空,则返回空字符串", + extended = "Example:\n > select _FUNC_(full_string) from src;" +) +public class UDFFull2Half extends UDF { + + public UDFFull2Half() { + } + + public String evaluate(String fullStr) throws Exception { + if (StringUtils.isBlank(fullStr)) { + return ""; + } + + StringBuilder outStrBuf = new StringBuilder(""); + String tStr = ""; + byte[] b = null; + for (int i = 0; i < fullStr.length(); i++) { + tStr = fullStr.substring(i, i + 1); + // 全角空格转换成半角空格 + if (tStr.equals(" ")) { + outStrBuf.append(" "); + continue; + } + + b = tStr.getBytes("unicode"); + // 得到 unicode 字节数据 + if (b[2] == -1) { // 表示全角? + b[3] = (byte) (b[3] + 32); + b[2] = 0; + outStrBuf.append(new String(b, "unicode")); + } else { + outStrBuf.append(tStr); + } + } + // end for. + return outStrBuf.toString(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/github/aaronshan/functions/string/UDFMd5.java b/src/main/java/com/chinagoods/bigdata/functions/string/UDFMd5.java similarity index 94% rename from src/main/java/com/github/aaronshan/functions/string/UDFMd5.java rename to src/main/java/com/chinagoods/bigdata/functions/string/UDFMd5.java index ff28507..fe38398 100644 --- a/src/main/java/com/github/aaronshan/functions/string/UDFMd5.java +++ b/src/main/java/com/chinagoods/bigdata/functions/string/UDFMd5.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.string; +package com.chinagoods.bigdata.functions.string; import org.apache.commons.codec.digest.DigestUtils; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/chinagoods/bigdata/functions/string/UDFMessyCodeRecover.java b/src/main/java/com/chinagoods/bigdata/functions/string/UDFMessyCodeRecover.java new file mode 100644 index 0000000..c287b59 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/string/UDFMessyCodeRecover.java @@ -0,0 +1,54 @@ +package com.chinagoods.bigdata.functions.string; + +/** + * @author xiaowei.song + * 乱码恢复 + */ +import com.chinagoods.bigdata.functions.utils.CgStringUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.io.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.StandardCharsets; + +@Description( + name = "messy_code_recover", + value = "_FUNC_(messy_code_str) - this is a 乱码恢复方法", + extended = "Example:\n > select _FUNC_(messy_code_str) from src;" +) +public class UDFMessyCodeRecover extends UDF { + public static final Logger logger = LoggerFactory.getLogger(UDFMessyCodeRecover.class); + + private Text result = new Text(); + + public Text evaluate(String messy_code_str) throws Exception { + if (StringUtils.isBlank(messy_code_str)) { + return null; + } + + // 探测字符串值编码 + String charsetName = CgStringUtils.getEncoding(messy_code_str); + String value = messy_code_str; + switch (charsetName) { + case CgStringUtils.ISO_8859_1: + value = new String(messy_code_str.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); + break; + case CgStringUtils.GBK: + value = new String(messy_code_str.getBytes(CgStringUtils.GBK), StandardCharsets.UTF_8); + } + result.set(value); + return result; + } + + public static void main(String[] args) throws Exception { +// String str = "515æ´»å\u008A¨"; + String str = "515活动"; +// System.out.println(newStr); + System.out.println((new UDFMessyCodeRecover ()).evaluate(str)); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/chinagoods/bigdata/functions/string/UDFRestNameFormat.java b/src/main/java/com/chinagoods/bigdata/functions/string/UDFRestNameFormat.java new file mode 100644 index 0000000..f257131 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/string/UDFRestNameFormat.java @@ -0,0 +1,120 @@ +package com.chinagoods.bigdata.functions.string; + +import com.chinagoods.bigdata.functions.utils.MysqlUtil; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +/** + * @author zyl + * date: 2024-07-29 + * time: 10:30 + * describe: 获取对应时间设备所属食堂rest_name_format + */ +@Description(name = "rest_name_format" + , value = "_FUNC_(string,string) - Return the name of the cafeteria based on the device code and payment time" + , extended = "Example:\n> SELECT _FUNC_(device_no,pay_at) FROM src;") +public class UDFRestNameFormat extends GenericUDF { + private static final Logger logger = LoggerFactory.getLogger(UDFRestNameFormat.class); + private static final String DB_URL = "jdbc:mysql://172.18.5.22:3306/source?characterEncoding=UTF-8&useSSL=false"; + private static final String DB_USER = "source"; + private static final String DB_PASSWORD = "jP8*dKw,bRjBVos="; + /** + * 设备对应食堂有效期 kjt_device_valid_inf + */ + private static final String REST_QUERY_SQL = "select device_no,rest_name,valid_start_at,valid_end_at from kjt_device_valid_inf "; + private ObjectInspectorConverters.Converter[] converters; + private static final int ARG_COUNT = 2; + List> deviceList = new ArrayList>(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + public UDFRestNameFormat() { + } + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + if (arguments.length != ARG_COUNT) { + throw new UDFArgumentException( + "The function rest_name_format takes exactly " + ARG_COUNT + " arguments."); + } + converters = new ObjectInspectorConverters.Converter[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + converters[i] = ObjectInspectorConverters.getConverter(arguments[i], + PrimitiveObjectInspectorFactory.javaStringObjectInspector); + } + queryRestDeviceList(); + return PrimitiveObjectInspectorFactory.javaStringObjectInspector; + } + + @Override + public String evaluate(DeferredObject[] arguments) throws HiveException { + assert (arguments.length == ARG_COUNT); + String deviceNo = converters[0].convert(arguments[0].get()).toString(); + String payAt = converters[0].convert(arguments[1].get()).toString(); + LocalDateTime paramAt = LocalDateTime.parse(payAt, formatter); + for (List subList : deviceList) { + LocalDateTime start = LocalDateTime.parse(subList.get(2), formatter); + LocalDateTime end = LocalDateTime.parse(subList.get(3), formatter); + if (subList.get(0).equals(deviceNo) && paramAt.isAfter(start) && paramAt.isBefore(end)) { + return subList.get(1); + } + } + return null; + } + + /** + * @throws UDFArgumentException 查询mysql异常 + */ + public void queryRestDeviceList() throws UDFArgumentException { + try { + MysqlUtil mysqlUtil = new MysqlUtil(DB_URL, DB_USER, DB_PASSWORD); + deviceList = mysqlUtil.getLists(REST_QUERY_SQL); + } catch (Exception e) { + logger.error("Failed to query the rest name. Procedure, the error details are: ", e); + throw new UDFArgumentException(String.format("Failed to query the rest name. Procedure, the error details are: %s", e)); + } + } + + @Override + public String getDisplayString(String[] strings) { + assert (strings.length == ARG_COUNT); + return "rest_name_format(" + strings[0] + ", " + strings[1] + ")"; + } + + public static void main(String[] args) throws HiveException { + List list = new ArrayList<>(); + list.add("YPT13285"); + list.add("YPT13286"); + list.add("YPT13289"); + list.add("YPT13290"); + UDFRestNameFormat urlFormat = new UDFRestNameFormat(); + for (String dvo : list) { + String restName; + try { + DeferredObject[] deferredObjects = new DeferredObject[2]; + // 设备编码、支付时间 + deferredObjects[0] = new DeferredJavaObject(dvo); + deferredObjects[1] = new DeferredJavaObject("2024-07-16 12:34:23"); + ObjectInspector[] inspectorArr = new ObjectInspector[2]; + inspectorArr[0] = PrimitiveObjectInspectorFactory.javaStringObjectInspector; + inspectorArr[1] = PrimitiveObjectInspectorFactory.javaStringObjectInspector; + urlFormat.initialize(inspectorArr); + restName = urlFormat.evaluate(deferredObjects); + } catch (Exception e) { + throw new RuntimeException(e); + } + System.out.println(restName); + } + } +} diff --git a/src/main/java/com/github/aaronshan/functions/string/UDFSha256.java b/src/main/java/com/chinagoods/bigdata/functions/string/UDFSha256.java similarity index 94% rename from src/main/java/com/github/aaronshan/functions/string/UDFSha256.java rename to src/main/java/com/chinagoods/bigdata/functions/string/UDFSha256.java index 04f86a4..98ef4a4 100644 --- a/src/main/java/com/github/aaronshan/functions/string/UDFSha256.java +++ b/src/main/java/com/chinagoods/bigdata/functions/string/UDFSha256.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.string; +package com.chinagoods.bigdata.functions.string; import org.apache.commons.codec.digest.DigestUtils; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/github/aaronshan/functions/string/UDFStringHammingDistance.java b/src/main/java/com/chinagoods/bigdata/functions/string/UDFStringHammingDistance.java similarity index 91% rename from src/main/java/com/github/aaronshan/functions/string/UDFStringHammingDistance.java rename to src/main/java/com/chinagoods/bigdata/functions/string/UDFStringHammingDistance.java index abbb96a..a61fc27 100644 --- a/src/main/java/com/github/aaronshan/functions/string/UDFStringHammingDistance.java +++ b/src/main/java/com/chinagoods/bigdata/functions/string/UDFStringHammingDistance.java @@ -1,5 +1,6 @@ -package com.github.aaronshan.functions.string; +package com.chinagoods.bigdata.functions.string; +import com.chinagoods.bigdata.functions.utils.Failures; import io.airlift.slice.Slice; import io.airlift.slice.Slices; import org.apache.hadoop.hive.ql.exec.Description; @@ -8,7 +9,6 @@ import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; -import static com.github.aaronshan.functions.utils.Failures.checkCondition; import static io.airlift.slice.SliceUtf8.lengthOfCodePoint; import static io.airlift.slice.SliceUtf8.tryGetCodePointAt; @@ -58,7 +58,7 @@ public LongWritable evaluate(Text leftText, Text rightText) throws HiveException rightPosition += codePointRight > 0 ? lengthOfCodePoint(codePointRight) : -codePointRight; } - checkCondition(leftPosition == left.length() && rightPosition == right.length(), + Failures.checkCondition(leftPosition == left.length() && rightPosition == right.length(), "The input strings to hamming_distance function must have the same length"); result.set(distance); diff --git a/src/main/java/com/github/aaronshan/functions/string/UDFStringLevenshteinDistance.java b/src/main/java/com/chinagoods/bigdata/functions/string/UDFStringLevenshteinDistance.java similarity index 94% rename from src/main/java/com/github/aaronshan/functions/string/UDFStringLevenshteinDistance.java rename to src/main/java/com/chinagoods/bigdata/functions/string/UDFStringLevenshteinDistance.java index 398e905..9525a41 100644 --- a/src/main/java/com/github/aaronshan/functions/string/UDFStringLevenshteinDistance.java +++ b/src/main/java/com/chinagoods/bigdata/functions/string/UDFStringLevenshteinDistance.java @@ -1,5 +1,6 @@ -package com.github.aaronshan.functions.string; +package com.chinagoods.bigdata.functions.string; +import com.chinagoods.bigdata.functions.utils.Failures; import io.airlift.slice.Slice; import io.airlift.slice.Slices; import org.apache.hadoop.hive.ql.exec.Description; @@ -8,7 +9,6 @@ import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; -import static com.github.aaronshan.functions.utils.Failures.checkCondition; import static io.airlift.slice.SliceUtf8.getCodePointAt; import static io.airlift.slice.SliceUtf8.lengthOfCodePoint; import static io.airlift.slice.SliceUtf8.tryGetCodePointAt; @@ -56,7 +56,7 @@ public LongWritable evaluate(Text leftText, Text rightText) throws HiveException return result; } - checkCondition((leftCodePoints.length * (rightCodePoints.length - 1)) <= 1000000, + Failures.checkCondition((leftCodePoints.length * (rightCodePoints.length - 1)) <= 1000000, "The combined inputs for Levenshtein distance are too large"); int[] distances = new int[rightCodePoints.length]; diff --git a/src/main/java/com/github/aaronshan/functions/string/UDFStringNormalize.java b/src/main/java/com/chinagoods/bigdata/functions/string/UDFStringNormalize.java similarity index 95% rename from src/main/java/com/github/aaronshan/functions/string/UDFStringNormalize.java rename to src/main/java/com/chinagoods/bigdata/functions/string/UDFStringNormalize.java index e931a3d..41e9838 100644 --- a/src/main/java/com/github/aaronshan/functions/string/UDFStringNormalize.java +++ b/src/main/java/com/chinagoods/bigdata/functions/string/UDFStringNormalize.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.string; +package com.chinagoods.bigdata.functions.string; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; diff --git a/src/main/java/com/github/aaronshan/functions/string/UDFStringPosition.java b/src/main/java/com/chinagoods/bigdata/functions/string/UDFStringPosition.java similarity index 95% rename from src/main/java/com/github/aaronshan/functions/string/UDFStringPosition.java rename to src/main/java/com/chinagoods/bigdata/functions/string/UDFStringPosition.java index 1cbd2bb..c105a65 100644 --- a/src/main/java/com/github/aaronshan/functions/string/UDFStringPosition.java +++ b/src/main/java/com/chinagoods/bigdata/functions/string/UDFStringPosition.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.string; +package com.chinagoods.bigdata.functions.string; import org.apache.commons.codec.digest.DigestUtils; import org.apache.hadoop.hive.ql.exec.Description; diff --git a/src/main/java/com/github/aaronshan/functions/string/UDFStringSplitToMap.java b/src/main/java/com/chinagoods/bigdata/functions/string/UDFStringSplitToMap.java similarity index 88% rename from src/main/java/com/github/aaronshan/functions/string/UDFStringSplitToMap.java rename to src/main/java/com/chinagoods/bigdata/functions/string/UDFStringSplitToMap.java index b08740f..c818e30 100644 --- a/src/main/java/com/github/aaronshan/functions/string/UDFStringSplitToMap.java +++ b/src/main/java/com/chinagoods/bigdata/functions/string/UDFStringSplitToMap.java @@ -1,5 +1,6 @@ -package com.github.aaronshan.functions.string; +package com.chinagoods.bigdata.functions.string; +import com.chinagoods.bigdata.functions.utils.Failures; import com.google.common.base.Splitter; import java.util.HashMap; import java.util.Map; @@ -14,8 +15,6 @@ import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; -import static com.github.aaronshan.functions.utils.Failures.checkCondition; - /** * @author ruifeng.shan * date: 2018-07-27 @@ -59,9 +58,9 @@ public Object evaluate(DeferredObject[] arguments) throws HiveException { String entryDelimiter = (String) arguments[1].get(); String keyValueDelimiter = (String) arguments[2].get(); - checkCondition(entryDelimiter.length() > 0, "entryDelimiter is empty"); - checkCondition(keyValueDelimiter.length() > 0, "keyValueDelimiter is empty"); - checkCondition(!entryDelimiter.equals(keyValueDelimiter), "entryDelimiter and keyValueDelimiter must not be the same"); + Failures.checkCondition(entryDelimiter.length() > 0, "entryDelimiter is empty"); + Failures.checkCondition(keyValueDelimiter.length() > 0, "keyValueDelimiter is empty"); + Failures.checkCondition(!entryDelimiter.equals(keyValueDelimiter), "entryDelimiter and keyValueDelimiter must not be the same"); if (string == null) { return null; diff --git a/src/main/java/com/github/aaronshan/functions/string/UDFStringSplitToMultimap.java b/src/main/java/com/chinagoods/bigdata/functions/string/UDFStringSplitToMultimap.java similarity index 90% rename from src/main/java/com/github/aaronshan/functions/string/UDFStringSplitToMultimap.java rename to src/main/java/com/chinagoods/bigdata/functions/string/UDFStringSplitToMultimap.java index ab19373..68e112f 100644 --- a/src/main/java/com/github/aaronshan/functions/string/UDFStringSplitToMultimap.java +++ b/src/main/java/com/chinagoods/bigdata/functions/string/UDFStringSplitToMultimap.java @@ -1,5 +1,6 @@ -package com.github.aaronshan.functions.string; +package com.chinagoods.bigdata.functions.string; +import com.chinagoods.bigdata.functions.utils.Failures; import com.google.common.base.Splitter; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Lists; @@ -17,8 +18,6 @@ import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; -import static com.github.aaronshan.functions.utils.Failures.checkCondition; - /** * @author ruifeng.shan * date: 2018-07-27 @@ -62,9 +61,9 @@ public Object evaluate(DeferredObject[] arguments) throws HiveException { String entryDelimiter = (String) arguments[1].get(); String keyValueDelimiter = (String) arguments[2].get(); - checkCondition(entryDelimiter.length() > 0, "entryDelimiter is empty"); - checkCondition(keyValueDelimiter.length() > 0, "keyValueDelimiter is empty"); - checkCondition(!entryDelimiter.equals(keyValueDelimiter), "entryDelimiter and keyValueDelimiter must not be the same"); + Failures.checkCondition(entryDelimiter.length() > 0, "entryDelimiter is empty"); + Failures.checkCondition(keyValueDelimiter.length() > 0, "keyValueDelimiter is empty"); + Failures.checkCondition(!entryDelimiter.equals(keyValueDelimiter), "entryDelimiter and keyValueDelimiter must not be the same"); if (string == null) { return null; diff --git a/src/main/java/com/chinagoods/bigdata/functions/url/UDFAdUrlFormat.java b/src/main/java/com/chinagoods/bigdata/functions/url/UDFAdUrlFormat.java new file mode 100644 index 0000000..65b1bf2 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/url/UDFAdUrlFormat.java @@ -0,0 +1,77 @@ +package com.chinagoods.bigdata.functions.url; + +import com.chinagoods.bigdata.functions.utils.HttpParamUtil; +import com.chinagoods.bigdata.functions.utils.CgStringUtils; +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.*; + +/** + * @author ruifeng.shan + * date: 2016-07-27 + * time: 16:04 + */ +@Description(name = "ad_url_format" + , value = "_FUNC_(value) - Advertising link formatting, Include only advertising parameters" + , extended = "Example:\n > select ad_url_format(value) from src;") +public class UDFAdUrlFormat extends UDF { + public static final Logger logger = LoggerFactory.getLogger(UDFAdUrlFormat.class); + + public static final List AD_PARAM_LIST = Collections.unmodifiableList(Arrays.asList("utm_campaign", + "utm_source", + "utm_medium", + "utm_content" + )); + + public String evaluate(String value) throws MalformedURLException { + if (value == null) { + return null; + } + logger.debug("输入的URL为: {}", value); + // 转义,避免乱码 + value = StringEscapeUtils.unescapeJava(value); + logger.debug("转义之后的URL为: {}", value); + + +// URI adUri = URI.create(value); + URL adUri = null; + try { + adUri = new URL(value); + } catch (Exception e) { + logger.error("解析ad url失败,{}", value, e); + } + Map paramsMap = HttpParamUtil.getParameter(value); + + // Fixed me。 若广告解析为null,则返回null + if (adUri == null) { + return null; + } + + return String.format("%s://%s%s?utm_campaign=%s&utm_source=%s&utm_medium=%s&utm_content=%s", adUri.getProtocol(), adUri.getAuthority(), + adUri.getPath(), + paramsMap.getOrDefault("utm_campaign", ""), + paramsMap.getOrDefault("utm_source", ""), + paramsMap.getOrDefault("utm_medium", ""), + paramsMap.getOrDefault("utm_content", "") + ); + } + + public static void main(String[] args) throws UnsupportedEncodingException, MalformedURLException { + String url = "https://m.chinagoods.com/shop/8002418?utm_campaign=%E58%95%3E&utm_source=4a&utm_medium=cpc&utm_content=4a-F%CE%WAP-%E58%95%3E&custom_ua=novel_webview&fp=a_fake_fp&version_code=7.1.5&tma_jssdk_version=1.31.1.2&app_name=news_article_lite&vid=D98F40E9-DB7D-4678-B4A7-F998DA4A9404&device_id=36725067842&channel=App%20Store&resolution=1242*2208&aid=35&ab_version=1859936,668908,2756108,668907,2756104,668905,2756072,668906,2756080,668904,2756063,668903,2756098,2571776&ab_feature=79452"; + System.out.println((new UDFAdUrlFormat()).evaluate(url)); + +// String str = "515æ´»å\u008A¨"; +// String str = "515活动"; +// String newStr = new String(str.getBytes("ISO8859-1"),"UTF-8"); +//// System.out.println(newStr); +// System.out.println(CgStringUtils.getEncoding(str)); + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/url/UDFNginxLogDecode.java b/src/main/java/com/chinagoods/bigdata/functions/url/UDFNginxLogDecode.java new file mode 100644 index 0000000..6b88e80 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/url/UDFNginxLogDecode.java @@ -0,0 +1,52 @@ +package com.chinagoods.bigdata.functions.url; + +import com.chinagoods.bigdata.functions.json.UDFJsonArray; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.io.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; + +/** + * @author xiaowei.song + * date: 2021-01-04 + */ +@Description(name = "nginx_log_decode" + , value = "_FUNC_(value) - Unescape the nginx log encoded value." + , extended = "Example:\n > select _FUNC_(value) from src;") +public class UDFNginxLogDecode extends UDF { + public static final Logger logger = LoggerFactory.getLogger(UDFNginxLogDecode.class); + + public static final String REPLACE_X_STR = "\\x"; + public static final String REPLACE_PERCENTAGE= "%"; + + private Text result = new Text(); + + public Text evaluate(String value) { + if (value == null) { + return null; + } + String targetStr = value.replace("%", "%25").replace(REPLACE_X_STR, REPLACE_PERCENTAGE); + try { + result.set(URLDecoder.decode(targetStr, StandardCharsets.UTF_8.toString())); + } catch (UnsupportedEncodingException | IllegalArgumentException e) { + logger.error("source value: {}, url decoder error: ", value, e); +// throw new AssertionError(e); + // TODO (解析失败) + // 替换%22为" + result.set(targetStr.replace("%22", "\"")); + } + return result; + } + + public static void main(String[] args) throws UnsupportedEncodingException { +// String str = "{\\x22page\\x22:3,\\x22sort\\x22:11,\\x22q\\x22:\\x22\\xE8\\x8A\\xB1\\xE8\\xBE\\xB9\\xE8\\xBE\\x85\\xE6\\x96\\x99\\x22,\\x22page_size\\x22:20}"; + String str = "{\\x22x_grandpa_product_type_id\\x22:10944,\\x22x_parent_product_type_id\\x22:null,\\x22merchant_type\\x22:\\x22regular\\x22,\\x22page\\x22:1,\\x22page_size\\x22:30,\\x22sort\\x22:1,\\x22q\\x22:\\x22\\x22}"; + String replaceStr = str.replace("\\x", "%"); + System.out.println(URLDecoder.decode(replaceStr, "UTF-8")); + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/url/UDFStandardUrlFormat.java b/src/main/java/com/chinagoods/bigdata/functions/url/UDFStandardUrlFormat.java new file mode 100644 index 0000000..017e17d --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/url/UDFStandardUrlFormat.java @@ -0,0 +1,617 @@ +package com.chinagoods.bigdata.functions.url; + +import com.chinagoods.bigdata.functions.utils.MysqlUtil; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.apache.hadoop.io.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.URL; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @author zyl + * date: 2022-09-24 + * time: 16:30 + * describe: 此函数从基础规则表standard_rule_url,特殊url规则表standard_special_url查询相关规则进行匹配 + * 上述规则数据基于k-v映射表standard_url_param_maping动态生成固定url相关数据,参考见数据库触发器standard_url_param_maping_trigger(依赖于market_industry,sys_map,category,venue,active_meeting,cms_category,cms_article表数据) + * standard_rule_url配置:1.无参url(包含参数在url中,不在问号后的)不用配置正则 + * 2.有参url按照正则替换,正则可多个,用/&/分割,params参数也用/&/分割,空使用NULL字符串代替,其他使用0000代替 + * 3.正则中\\使用\ + * 4.规则配置时,如果原始url符合特殊url表standard_special_url中规则,则正则表达式字段不能为空,否则处理不了 + * standard_special_url配置:1、url,unit,sub_unit必填 + * 2.前置条件param_type为1代表参数替换;fixed_identity代表url包含这个字符串就是按照次规则匹配 + * 3.fixed_param字段参数包含0000,用mapping_key的key中---后的部分替换0000部分;值为fixed_param字符串的,则使用mapping_key的key中---后的部分直接替换fixed_param,如果url_param_keys有值,则按照顺序拼接作为参数直接替换fixed_param(如code=112&active_code=112&id=3) + * 3.前置条件param_type为2代表参数替换;用mapping_key的key中---后的部分替换fixed_param;4.mapping_key的标识必须和standard_url_param_maping中的key_desc的前缀保持一致 + */ +@Description(name = "standard_url_format" + , value = "_FUNC_(string,string) - Normalize the url according to the rule, returning an array of processed urls and a tertiary directory name if present, or an array of default values if absent" + , extended = "Example:\n> SELECT _FUNC_(platform_type,sc_url) FROM src;") +public class UDFStandardUrlFormat extends GenericUDF { + private static final Logger logger = LoggerFactory.getLogger(UDFStandardUrlFormat.class); + private static final String DB_URL = "jdbc:mysql://172.18.5.10:23307/source?characterEncoding=UTF-8&useSSL=false"; + private static final String DB_USER = "source"; + private static final String DB_PASSWORD = "jP8*dKw,bRjBVos="; + /** + * 菜单映射信息,该表是mysql触发器逻辑生成的数据,触发器名称 standard_url_param_maping_trigger + */ + private static final String MENU_MAPPING_SQL = "select key_desc,value_desc from standard_url_param_maping"; + /** + * 特殊URL + */ + private static final String STANDARD_SPECIAL_URL_SQL = "select url,fixed_identity,fixed_param,mapping_key,unit,sub_unit,url_param_keys,param_type,page_link_name from standard_special_url where url_type=%s"; + /** + * 标准url匹配规则信息 + */ + private static final String STANDARD_URL_RULE_SQL = "select platform_type,case when standard_url like '%://h%' then 'Y' else 'N' end is_h5,standard_url, regex, unit,sub_unit,page_name,params from standard_rule_url " + + "where unit is not null and sub_unit is not null and page_name is not null and platform_type is not null and sc_url!='' and regex is not null and regex != ''"; + /** + * 静态URL信息 + */ + private static final String STATIC_URL_SQL = "select standard_url, concat(unit,'---',sub_unit,'---',page_name) url_name from standard_rule_url where (regex is null or regex = '') and standard_url is not null "; + /** + * URL中含菜单信息列表 + **/ + private List> menuUrlList = new ArrayList<>(); + /** + * 特殊URL信息列表 + **/ + private List> specialUrlList = new ArrayList<>(); + /** + * 参数k-v映射信息 + **/ + private Map paramKvMap = new HashMap<>(); + /** + * 汇总规则 + */ + private final Map>> allStandardRuleUrlPlatform2EntityMap = new HashMap<>(); + /** + * 静态url映射表Map + */ + private Map staticUrlMap = new HashMap<>(); + private ObjectInspectorConverters.Converter[] converters; + private static final int ARG_COUNT = 2; + private static final String HTTP_PREFIX = "http:"; + private static final String HTTPS_PREFIX = "https:"; + private static final String HTTPS_H5_PREFIX = "https://h"; + private static final String FLAG_TRUE = "Y"; + private static final String ONE = "1"; + private static final String TWO = "2"; + private static final String EMPTY = ""; + /** + * 约定空字符用NULL替换 + **/ + private static final String PARAM_NULL = "NULL"; + private static final String SEPARATOR = "---"; + private static final String KV_SEPARATOR = "--"; + private static final String KV_VALUE_SEPARATOR = "-"; + /** + * 参数连接分隔符 + **/ + private static final String CONNECTOR_SEPARATOR = "?"; + private static final String REGEX_OR_PARAM_SEPARATOR = "/&/"; + private static final String BACKSLASH = "/"; + private static final String PARAM_SEPARATOR = "&"; + private static final String EQ = "="; + private static final String COMMA = ","; + /** + * 固定参数 + */ + private static final String T = "T--"; + /*导航菜单商品分类中的分类编码*/ + private static final String C = "C--"; + /*导航菜单市场区块中的市场编码*/ + private static final String Z = "Z--"; + /*导航菜单商品分类中的市场编码*/ + private static final String M = "M--"; + /*商品列表实力商家筛选按钮*/ + private static final String EY = "EY--"; + /*商品列表甄选商家筛选按钮*/ + private static final String VL = "VL--"; + /*商品列表生产厂家筛选按钮*/ + private static final String SF = "SF--"; + /*指定的市场id*/ + private static final String LT = "LT--"; + /*商品列表综合,销售、价格、最新、有视频排序按钮*/ + private static final String S = "S--"; + private static final String IMT = "IMT--"; + /*商品列表当前页数*/ + private static final String P = "P--"; + /*商品列表当前页条数*/ + private static final String I = "I--"; + /*商品列表当前页条数*/ + private static final String HR = "HR--"; + /*是否展开全部*/ + private static final String EP = "EP--"; + + private static final String STANDARD_ZERO = "0000"; + private static final String H5 = "h5"; + private static final String MINI_PROGRAMS = "mini_programs"; + + private static final String FIXED_PARAM = "fixed_param"; + /** + * 返回结果list元素 + */ + private volatile String platformType = null; + private volatile String standardUrl = null; + private volatile String unit = null; + private volatile String subUnit = null; + private volatile String pageName = null; + private volatile String regex = null; + private volatile String params = null; + private ArrayList resultPageNameList = new ArrayList<>(4); + public static final String MULTIPLE_URL = "search/categoryProduct"; + + public UDFStandardUrlFormat() { + } + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + if (arguments.length != ARG_COUNT) { + throw new UDFArgumentException( + "The function standard_url_format takes exactly " + ARG_COUNT + " arguments."); + } + converters = new ObjectInspectorConverters.Converter[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + converters[i] = ObjectInspectorConverters.getConverter(arguments[i], + PrimitiveObjectInspectorFactory.javaStringObjectInspector); + } + // 初始化标准化url规则,加载URL规则 + initRules(); + return ObjectInspectorFactory.getStandardListObjectInspector(PrimitiveObjectInspectorFactory.javaStringObjectInspector); + } + + @Override + public ArrayList evaluate(DeferredObject[] arguments) throws HiveException { + assert (arguments.length == ARG_COUNT); + // 初始化参数值 + initParam(); + + String scUrl = converters[0].convert(arguments[1].get()).toString(); + platformType = converters[0].convert(arguments[0].get()).toString(); + + // 针对小程序,由于scUrl=pages/search/categoryProduct类型,添加url前缀进行匹配 + if (platformType.equals(MINI_PROGRAMS)) { + scUrl = String.format("https://www.chinagoods.com/%s", scUrl); + } + + // 若访问地址为空或者客户端名称为空,则直接返回空结果 + if (StringUtils.isBlank(scUrl) || StringUtils.isBlank(platformType)) { + return resultPageNameList; + } + + // 标准化url,将http转换成https + if (scUrl.startsWith(HTTP_PREFIX)) { + scUrl = scUrl.replaceFirst(HTTP_PREFIX, HTTPS_PREFIX); + } + + if (scUrl.contains(HTTPS_PREFIX)) { + // 若scUrl中含?并且不包含=http或=https内容,则针对scUrl进行拼接,保证requestPath以/结尾 + if (scUrl.contains(CONNECTOR_SEPARATOR) && !scUrl.contains(EQ + HTTP_PREFIX) && !scUrl.contains(EQ + HTTPS_PREFIX)) { + String requestUrl = scUrl.substring(0, scUrl.indexOf(CONNECTOR_SEPARATOR)); + String requestUrlParam = scUrl.substring(scUrl.indexOf(CONNECTOR_SEPARATOR)); + scUrl = requestUrl.lastIndexOf(BACKSLASH) + 1 == requestUrl.length() ? scUrl : requestUrl + BACKSLASH + requestUrlParam; + } else if (scUrl.contains(CONNECTOR_SEPARATOR) && (scUrl.contains(EQ + HTTP_PREFIX) || scUrl.contains(EQ + HTTPS_PREFIX))) { + // 截取第一个?位置前字符串内容 + String requestPath = scUrl.substring(0, scUrl.indexOf(CONNECTOR_SEPARATOR)); +// String requestParam = scUrl.substring(scUrl.indexOf(CONNECTOR_SEPARATOR)); + scUrl = requestPath.lastIndexOf(BACKSLASH) + 1 == requestPath.length() ? requestPath : requestPath + BACKSLASH; + } else { + scUrl = scUrl.lastIndexOf(BACKSLASH) + 1 == scUrl.length() ? scUrl : scUrl + BACKSLASH; + } + } + // 处理菜单URL + final AtomicReference scUrlRef = new AtomicReference<>(scUrl); + if (Stream.of(Z, T, M, S, C).anyMatch(e -> StringUtils.contains(scUrlRef.get(), e))) { + resultPageNameList = menuDealUrl(scUrl); + } else { + // 处理特殊参数URL和部分静态原始地址 + resultPageNameList = specialParamDealUrl(scUrl); + } + + // 页面名称列表结果若为空,则进行正则判断处理 + if (resultPageNameList.get(0).equals(STANDARD_ZERO)) { + // 正则处理页面原始url地址 + resultPageNameList = regexDealUrl(scUrl); + } + return resultPageNameList; + } + + /** + * 初始化规则信息 + * + * @throws UDFArgumentException 参数异常 + */ + public void initRules() throws UDFArgumentException { + // 配置信息 + MysqlUtil mysqlUtil = new MysqlUtil(DB_URL, DB_USER, DB_PASSWORD); + try { + paramKvMap = mysqlUtil.getMap(MENU_MAPPING_SQL); + menuUrlList = mysqlUtil.getLists(String.format(STANDARD_SPECIAL_URL_SQL, ONE)); + mysqlUtil.getLists(STANDARD_URL_RULE_SQL).forEach(rules -> { + platformType = rules.get(0); + String h5Key = rules.get(1).equals(FLAG_TRUE) ? H5 : EMPTY; + String fullPlatformType = String.format("%s%s", platformType, h5Key); + // 若allRuleMap中fullPlatformType为为空,则初始化填充空ArrayList + allStandardRuleUrlPlatform2EntityMap.putIfAbsent(fullPlatformType, new ArrayList<>()); + allStandardRuleUrlPlatform2EntityMap.get(fullPlatformType).add(rules); + }); + + staticUrlMap = mysqlUtil.getMap(STATIC_URL_SQL); + // 特殊url动态生成 + specialUrlList = mysqlUtil.getLists(String.format(STANDARD_SPECIAL_URL_SQL, TWO)); + for (List urlList : specialUrlList) { + // 固定参数 + String fixedParam = urlList.get(2); + //参数对应的枚举key前缀 + String mappingKey = urlList.get(3); + unit = urlList.get(4); + subUnit = urlList.get(5); + String paramType = urlList.get(7); + paramKvMap.forEach((key, value) -> { + String url = urlList.get(0); + String paramKeyPre = key.split(KV_SEPARATOR)[0]; + String paramValue = key.split(KV_SEPARATOR)[1]; + // 参数类型为1 + if (paramType.equals(ONE)) { + if (mappingKey.equals(paramKeyPre) && !fixedParam.contains(FIXED_PARAM)) { + url = url.replace(fixedParam, fixedParam.replace(STANDARD_ZERO, paramValue)); + } + if (mappingKey.equals(paramKeyPre) && fixedParam.contains(FIXED_PARAM)) { + url = url.replace(fixedParam, fixedParam.replace(fixedParam, paramValue)); + } + if (!url.contains(STANDARD_ZERO) && !url.contains(FIXED_PARAM)) { + staticUrlMap.put(url, String.join(SEPARATOR, unit, subUnit, value)); + } + } else if (paramType.equals(TWO)) { + // 特殊url类型,贸易咨询中心等 + staticUrlMap.put(paramValue, value); + } + }); + } + //统一转小写 + toLowerMap(staticUrlMap); + toLowerMap(paramKvMap); + } catch (Exception e) { + logger.error("Failed to query the standard rule. Procedure, the error details are: ", e); + throw new UDFArgumentException(String.format("Failed to query the standard rule. Procedure, the error details are: %s", e)); + } + } + + /** + * 处理菜单URL + * + * @param scUrl 原始连接请求地址 + * @return 处理后的菜单URL, 结果对象 + */ + public ArrayList menuDealUrl(String scUrl) throws HiveException { + // 菜单固定参数 + try { + // 遍历菜单URL + // TODO 后续避免遍历,采用性能更高方式,达到O(1)方式获取 + for (List ls : menuUrlList) { + // 特殊url参数列表: url,fixed_identity,fixed_param,mapping_key,unit,sub_unit,url_param_keys,param_type,page_link_name + //当URL是菜单路径 + String specialUrlPath = ls.get(0); + if (StringUtils.contains(scUrl, specialUrlPath)) { + unit = ls.get(4); + subUnit = ls.get(5); + String pageLinkName = ls.get(8); + //当URL包含多个key + int indexStart = scUrl.lastIndexOf(specialUrlPath) + specialUrlPath.length(); + int indexEnd = scUrl.length(); + String menuUrlParam = scUrl.substring(indexStart, indexEnd).toLowerCase(); + if (menuUrlParam.contains(SEPARATOR)) { + // 固定参数 + List nameList = new ArrayList<>(); + // search搜索存在搜索后筛选的情况,给固定格式 + if (menuUrlParam.contains(BACKSLASH)) { + nameList.add(menuUrlParam.substring(0, menuUrlParam.indexOf(BACKSLASH))); + menuUrlParam = menuUrlParam.substring(menuUrlParam.indexOf(BACKSLASH) + 1); + } + String[] keysArr = menuUrlParam.split(SEPARATOR); + for (String specialParam : keysArr) { + String upSpecialParam = specialParam.toUpperCase(); + // 若upKey中包含EY、VL、SF、LT、S、IMT、P、I、HR、EP字符串,则跳过,此为搜索类型key + if (Stream.of(EY, VL, SF, LT, S, IMT, P, I, HR, EP).anyMatch(e -> StringUtils.contains(upSpecialParam, e))) { + continue; + } + boolean isAddNameListFlag = false; + if ((upSpecialParam.contains(C) || upSpecialParam.contains(M)) && scUrl.contains(MULTIPLE_URL)) { + // upSpecialParam举例为T--446 + String mOrCKey = upSpecialParam.split(KV_SEPARATOR)[0]; + String value = EMPTY; + if (upSpecialParam.contains(C)) { + value = upSpecialParam.replaceFirst(C, EMPTY).toLowerCase(); + } else if (upSpecialParam.contains(M)) { + value = upSpecialParam.replaceFirst(M, EMPTY).toLowerCase(); + } + if (value.contains(KV_VALUE_SEPARATOR)) { + isAddNameListFlag = true; + String[] valueArr = value.split(KV_VALUE_SEPARATOR); + String specialParamKeyTpl = "%s" + KV_SEPARATOR + "%s"; + for (String v : valueArr) { + String res = paramKvMap.get(String.format(specialParamKeyTpl, mOrCKey, v).toLowerCase()); + if (StringUtils.isNotBlank(res)) { + nameList.add(res); + } + } + } + } + + if (!isAddNameListFlag) { + nameList.add(paramKvMap.get(specialParam)); + } + } + pageName = String.join(SEPARATOR, nameList); + } else { + pageName = paramKvMap.get(menuUrlParam); + } + + setResultListValue(scUrl, unit, subUnit, pageName, pageLinkName); + break; + } + } + } catch (Exception e) { + logger.error("Menu URL handling error,url is {},error is ", scUrl, e); + throw new HiveException(String.format("Menu URL handling error, url is %s,error is ", scUrl), e); + } + return resultPageNameList; + } + + /** + * 处理特殊固定参数的URL和无正则url处理 + * + * @param scUrl 原始连接请求地址 + * @return 处理后的菜单URL, 结果对象 + */ + public ArrayList specialParamDealUrl(String scUrl) throws HiveException { + try { + // 区分是否特殊URL + // 特殊url参数列表: url,fixed_identity,fixed_param,mapping_key,unit,sub_unit,url_param_keys,param_type,page_link_name + boolean isSpecial = specialUrlList.stream().anyMatch(ls -> scUrl.contains(ls.get(1))); + // 非正则url处理,处理静态URL地址 + if (!isSpecial) { + String scUrlPath = scUrl; + if (scUrl.contains(CONNECTOR_SEPARATOR)) { + scUrlPath = scUrl.substring(0, scUrl.indexOf(CONNECTOR_SEPARATOR)); + } + staticDealUrl(scUrlPath, null); + return resultPageNameList; + } + + // 特殊url处理 + for (List ls : specialUrlList) { + // 特殊url地址中含域名,eg. https://h5.chinagoods.com/venue/?fixed_param + String url = ls.get(0); + String fixedIdentity = ls.get(1); + String urlParamKeys = ls.get(6); + String paramType = ls.get(7); + String pageLinkName = ls.get(8); + + URL urls = new URL(scUrl); + String host = urls.getHost(); + if (scUrl.contains(fixedIdentity) && url.contains(host)) { + standardUrl = scUrl; + int scUrlConnectorSeparatorPos = scUrl.length(); + if (scUrl.indexOf(CONNECTOR_SEPARATOR) > 0) { + scUrlConnectorSeparatorPos = scUrl.indexOf(CONNECTOR_SEPARATOR); + } + // param_type 1: 参数 2: url + if (paramType.equals(ONE)) { + // url中请求参数不为空,进行请求参数解析,获取请求参数对应的值 + if (StringUtils.isNotBlank(urlParamKeys)) { + String[] urlParamKeysArray = urlParamKeys.split(COMMA); + // 获取urlPath和参数列表 + List urlPathAndParams = getUrlPathAndParams(scUrl, urlParamKeysArray); + standardUrl = String.join(CONNECTOR_SEPARATOR, urlPathAndParams.get(0), String.join(PARAM_SEPARATOR, urlPathAndParams.subList(1, urlPathAndParams.size()))); + } else if (!url.contains(CONNECTOR_SEPARATOR)) { + standardUrl = scUrl.substring(0, scUrlConnectorSeparatorPos); + } + } else if (paramType.equals(TWO)) { + if (!url.contains(CONNECTOR_SEPARATOR)) { + standardUrl = scUrl.substring(0, scUrlConnectorSeparatorPos); + } + } + + if (StringUtils.isNotBlank(standardUrl)) { + // 静态url获取三级名称 + staticDealUrl(standardUrl, pageLinkName); + return resultPageNameList; + } + } + } + } catch (Exception e) { + logger.error("Error handling special parameter scUrl, scUrl is {}, error is ", scUrl, e); + throw new HiveException("Error handling special parameter scUrl, scUrl is " + scUrl + ",error is ", e); + } + return resultPageNameList; + } + + /** + * 处理正则匹配的URL + * + * @param scUrl 原始连接请求地址 + * @return 处理后的菜单URL, 结果对象 + */ + public ArrayList regexDealUrl(String scUrl) throws HiveException { + String h5Key = scUrl.startsWith(HTTPS_H5_PREFIX) ? H5 : EMPTY; + String fullPlatformType = String.format("%s%s", platformType, h5Key); + try { + List> platFormRules = allStandardRuleUrlPlatform2EntityMap.get(fullPlatformType); + if (platFormRules != null) { + for (List rules : platFormRules) { + String newScUrl = scUrl; + standardUrl = rules.get(2); + regex = rules.get(3); + unit = rules.get(4); + subUnit = rules.get(5); + pageName = rules.get(6); + params = rules.get(7); + // 多正则匹配 + if (StringUtils.isNotBlank(regex)) { + String[] regexArray = regex.split(REGEX_OR_PARAM_SEPARATOR); + String[] ruleParamsArray = params.split(REGEX_OR_PARAM_SEPARATOR); + String indexRegex, indexRegexParam; + for (int i = 0; i < regexArray.length; i++) { + indexRegex = regexArray[i]; + indexRegexParam = ruleParamsArray[i]; + newScUrl = newScUrl.replaceAll(indexRegex, indexRegexParam.replace(PARAM_NULL, EMPTY)); + } + } + newScUrl = newScUrl.lastIndexOf(BACKSLASH) + 1 == newScUrl.length() ? newScUrl : newScUrl + BACKSLASH; + if (newScUrl.equals(standardUrl)) { + setResultListValue(standardUrl, unit, subUnit, pageName, null); + return resultPageNameList; + } + } + } + } catch (Exception e) { + logger.error("Regular expression rule URL processing error,url is {},error is ", scUrl, e); + throw new HiveException("Regular expression rule URL processing error ,url is " + scUrl + ",error is ", e); + } + return resultPageNameList; + } + + /** + * 从静态url中获取page name + * + * @param standardUrl 标准url + * @param pageLinkName 页面链接名称 + */ + public void staticDealUrl(String standardUrl, String pageLinkName) { + String pageSeparatorName = staticUrlMap.get(standardUrl.toLowerCase()); + if (!StringUtils.isBlank(pageSeparatorName)) { + String[] pageNameArr = pageSeparatorName.split(SEPARATOR); + setResultListValue(standardUrl, pageNameArr[0], pageNameArr[1], pageNameArr[2], pageLinkName); + } + } + + /** + * 初始化变量 + */ + public void initParam() { + platformType = null; + standardUrl = null; + unit = null; + subUnit = null; + pageName = null; + regex = null; + params = null; + resultPageNameList.clear(); + resultPageNameList.add(STANDARD_ZERO); + resultPageNameList.add(STANDARD_ZERO); + resultPageNameList.add(STANDARD_ZERO); + resultPageNameList.add(STANDARD_ZERO); + } + + /** + * 设置返回结果 + * + * @param standardUrl 标准url + * @param unit 一级模块 + * @param subUnit 二级模块 + * @param pageName 页面名称 + * @param pageLinkName 页面链接名 + */ + public void setResultListValue(String standardUrl, String unit, String subUnit, String pageName, String pageLinkName) { + if (StringUtils.isNotBlank(standardUrl) && StringUtils.isNotBlank(unit) && StringUtils.isNotBlank(subUnit) + && StringUtils.isNotBlank(pageName)) { + resultPageNameList.set(0, standardUrl); + resultPageNameList.set(1, unit); + resultPageNameList.set(2, subUnit); + resultPageNameList.set(3, pageName + (pageLinkName == null ? "" : pageLinkName)); + } + } + + /** + * url转小写获取 + * + * @param map 字典map + */ + public void toLowerMap(Map map) { + // 对map的key值进行处理,转小写,再对key进行去重,只保留第一个值 + Map lowerMap = map.entrySet().stream().distinct().collect(Collectors.toMap( + entry -> entry.getKey().toLowerCase(), Map.Entry::getValue, (v1, v2) -> v1 + )); + map.clear(); + map.putAll(lowerMap); + } + + /** + * 提取URL指定参数和请求域名 + * + * @param scUrl 原始请求地址 + * @param keyArr 参数数组 + * @return Map> 请求参数映射表, 返回urlPath, 参数列表 + */ + public static List getUrlPathAndParams(String scUrl, String[] keyArr) { + List urlPathAndParams = new ArrayList<>(4); + + String scUrlPath; + if (StringUtils.isNotBlank(scUrl) && keyArr.length > 0) { + // 处理posIndex + int posIndex = scUrl.indexOf(CONNECTOR_SEPARATOR); + if (posIndex == -1) { + posIndex = scUrl.length(); + } + scUrlPath = scUrl.substring(0, posIndex); + urlPathAndParams.add(scUrlPath); + for (String key : keyArr) { + Pattern pattern = Pattern.compile(key + "=([^&]*)"); + Matcher matcher = pattern.matcher(scUrl); + if (matcher.find()) { + // 提取关键字和关键字值 + String keyVal = matcher.group(0); + String[] keyValArr = keyVal.split(EQ); + String value = EMPTY; + if (keyValArr.length == 2) { + value = keyValArr[1].replace(PARAM_SEPARATOR, EMPTY); + } + urlPathAndParams.add(String.format("%s=%s", key, value)); + } + } + } + return urlPathAndParams; + } + + @Override + public String getDisplayString(String[] strings) { + assert (strings.length == ARG_COUNT); + return "standard_url_format(" + strings[0] + ", " + strings[1] + ")"; + } + + public static void main(String[] args) throws HiveException { + String url = "https://www.chinagoods.com/login?return_url=https://www.chinagoods.com/search/categoryProduct/T--401---C--402---S--1---P--3---I--20"; +// String url = "https://h5.chinagoods.com/enterYiwu/venue/"; + ArrayList retArr; + try (UDFStandardUrlFormat urlFormat = new UDFStandardUrlFormat()) { + DeferredObject[] deferredObjects = new DeferredObject[2]; + // 平台类型、sc_url + deferredObjects[0] = new DeferredJavaObject("pc"); + deferredObjects[1] = new DeferredJavaObject(url); + ObjectInspector[] inspectorArr = new ObjectInspector[2]; + inspectorArr[0] = PrimitiveObjectInspectorFactory.javaStringObjectInspector; + inspectorArr[1] = PrimitiveObjectInspectorFactory.javaStringObjectInspector; + urlFormat.initialize(inspectorArr); + retArr = urlFormat.evaluate(deferredObjects); + } catch (IOException e) { + throw new RuntimeException(e); + } + System.out.println(retArr); + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/url/UDFUrlDecode.java b/src/main/java/com/chinagoods/bigdata/functions/url/UDFUrlDecode.java new file mode 100644 index 0000000..99eb3f9 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/url/UDFUrlDecode.java @@ -0,0 +1,60 @@ +package com.chinagoods.bigdata.functions.url; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.chinagoods.bigdata.functions.json.UDFJsonArray; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDF; +import org.apache.hadoop.io.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author ruifeng.shan + * date: 2016-07-27 + * time: 16:04 + */ +@Description(name = "url_decode" + , value = "_FUNC_(value) - Unescape the URL encoded value. This function is the inverse of url_encode()" + , extended = "Example:\n > select _FUNC_(value) from src;") +public class UDFUrlDecode extends UDF { + public static final Logger logger = LoggerFactory.getLogger(UDFUrlDecode.class); + + private Text result = new Text(); + /** + * 正则表达式,匹配结尾为%\d或%$字符 + **/ + public static final String INCOMPLETE_PATTERN_STR = "%[\\w+\\\\]?$"; + + // 创建 Pattern 对象 + public static final Pattern INCOMPLETE_PATTERN = Pattern.compile(INCOMPLETE_PATTERN_STR); + + public Text evaluate(String value) { + if (value == null) { + return null; + } + try { + Matcher m = INCOMPLETE_PATTERN.matcher(value); + if (m.find( )) { + value = value.replaceAll(INCOMPLETE_PATTERN_STR, ""); + } + + result.set(URLDecoder.decode(value, "UTF-8")); + return result; + } catch (UnsupportedEncodingException | IllegalArgumentException e) { + logger.error("url_decode转码失败,此字符串无法转码: {}", value, e); + result.set(value); + return result; +// throw new AssertionError(e); + } + } + + public static void main(String[] args) { + String url = "http://m.chinagoods.com/callApp/buyer?code=AI#mCHMv5C%dqMJ0"; + System.out.println((new UDFUrlDecode()).evaluate(url)); + } +} diff --git a/src/main/java/com/github/aaronshan/functions/url/UDFUrlEncode.java b/src/main/java/com/chinagoods/bigdata/functions/url/UDFUrlEncode.java similarity index 96% rename from src/main/java/com/github/aaronshan/functions/url/UDFUrlEncode.java rename to src/main/java/com/chinagoods/bigdata/functions/url/UDFUrlEncode.java index 0768da4..6ff3c65 100644 --- a/src/main/java/com/github/aaronshan/functions/url/UDFUrlEncode.java +++ b/src/main/java/com/chinagoods/bigdata/functions/url/UDFUrlEncode.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.url; +package com.chinagoods.bigdata.functions.url; import com.google.common.escape.Escaper; import com.google.common.net.UrlEscapers; diff --git a/src/main/java/com/github/aaronshan/functions/utils/ArrayUtils.java b/src/main/java/com/chinagoods/bigdata/functions/utils/ArrayUtils.java similarity index 92% rename from src/main/java/com/github/aaronshan/functions/utils/ArrayUtils.java rename to src/main/java/com/chinagoods/bigdata/functions/utils/ArrayUtils.java index c46d95c..3e58c94 100644 --- a/src/main/java/com/github/aaronshan/functions/utils/ArrayUtils.java +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/ArrayUtils.java @@ -1,7 +1,7 @@ -package com.github.aaronshan.functions.utils; +package com.chinagoods.bigdata.functions.utils; -import com.github.aaronshan.functions.fastuitl.ints.AbstractIntComparator; -import com.github.aaronshan.functions.fastuitl.ints.IntComparator; +import com.chinagoods.bigdata.functions.fastuitl.ints.AbstractIntComparator; +import com.chinagoods.bigdata.functions.fastuitl.ints.IntComparator; import org.apache.hadoop.hive.serde2.objectinspector.ListObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; diff --git a/src/main/java/com/github/aaronshan/functions/utils/CardUtils.java b/src/main/java/com/chinagoods/bigdata/functions/utils/CardUtils.java similarity index 74% rename from src/main/java/com/github/aaronshan/functions/utils/CardUtils.java rename to src/main/java/com/chinagoods/bigdata/functions/utils/CardUtils.java index 891a189..affe896 100644 --- a/src/main/java/com/github/aaronshan/functions/utils/CardUtils.java +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/CardUtils.java @@ -1,10 +1,18 @@ -package com.github.aaronshan.functions.utils; +package com.chinagoods.bigdata.functions.utils; -import com.github.aaronshan.functions.model.ChinaIdArea; +import com.chinagoods.bigdata.functions.array.UDFArraySum; +import com.chinagoods.bigdata.functions.model.ChinaIdArea; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Strings; import com.google.common.collect.Maps; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; import java.util.Map; /** @@ -13,6 +21,7 @@ * time: 19:35 */ public class CardUtils { + private static final Logger LOG = LoggerFactory.getLogger(CardUtils.class); private static final Map chinaIdAreaMap = ConfigUtils.getIdCardMap(); private static int[] weight = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; //十七位数字本体码权重 private static char[] validate = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}; //mod11,对应校验码字符值 @@ -63,6 +72,37 @@ public static String getIdCardArea(String card) { return null; } + public static int getIdCardAge(String card, String ds) throws ParseException { + if (isValidIdCard(card)) { + int cardLength = card.length(); + String birthday = card.substring(6, 14); + if (cardLength == 15) { + birthday = "19" + card.substring(6, 12); + } + SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd"); + Calendar dsCal = Calendar.getInstance(); + Date dsDate = df.parse(ds); + dsCal.setTime(dsDate); + + Date birth = df.parse(birthday); + Calendar born = Calendar.getInstance(); + born.setTime(birth); + + if(born.after(dsDate)){ + LOG.error("Can't be born in the future"); + return -1; + } + + int age = dsCal.get(Calendar.YEAR) - born.get(Calendar.YEAR); + if(dsCal.get(Calendar.DAY_OF_YEAR) < born.get(Calendar.DAY_OF_YEAR)) { + age -= 1; + } + return age; + + } + return -2; + } + public static String getIdCardBirthday(String card) { if (isValidIdCard(card)) { int cardLength = card.length(); @@ -72,7 +112,6 @@ public static String getIdCardBirthday(String card) { return card.substring(6, 14); } } - return null; } @@ -81,9 +120,9 @@ public static String getIdCardGender(String card) { int cardLength = card.length(); int genderValue; if (cardLength == 15) { - genderValue = card.charAt(15) - 48; + genderValue = card.charAt(14) - 48; } else { - genderValue = card.charAt(17) - 48; + genderValue = card.charAt(16) - 48; } if (genderValue % 2 == 0) { @@ -113,7 +152,7 @@ public static boolean isValidIdCard(String card) { return false; } char validateCode = getValidateCode(card17); - if (validateCode == card.charAt(17)) { + if (validateCode == card.charAt(17) && getCardValue(card) != null) { return true; } } else if (cardLength == 15) { diff --git a/src/main/java/com/chinagoods/bigdata/functions/utils/CgStringUtils.java b/src/main/java/com/chinagoods/bigdata/functions/utils/CgStringUtils.java new file mode 100644 index 0000000..6d5e97b --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/CgStringUtils.java @@ -0,0 +1,52 @@ +package com.chinagoods.bigdata.functions.utils; + +import java.nio.charset.StandardCharsets; + +/** + * @author xiaowei.song + * 字符串编码探测,返回相应编码 + */ +public class CgStringUtils { + public static final String ISO_8859_1 = "ISO-8859-1"; + public static final String GB2312 = "GB2312"; + public static final String GBK = "GBK"; + + /** + * 探测字符串编码 + **/ + public static String getEncoding(String str) { + String encode = GB2312; + try { + if (str.equals(new String(str.getBytes(encode), encode))) { + String s = encode; + return s; + } + } catch (Exception exception) { + } + encode = ISO_8859_1; + try { + if (str.equals(new String(str.getBytes(encode), encode))) { + String s1 = encode; + return s1; + } + } catch (Exception exception1) { + } + encode = StandardCharsets.UTF_8.name(); + try { + if (str.equals(new String(str.getBytes(encode), encode))) { + String s2 = encode; + return s2; + } + } catch (Exception exception2) { + } + encode = GBK; + try { + if (str.equals(new String(str.getBytes(encode), encode))) { + String s3 = encode; + return s3; + } + } catch (Exception exception3) { + } + return ""; + } +} diff --git a/src/main/java/com/github/aaronshan/functions/utils/ConfigUtils.java b/src/main/java/com/chinagoods/bigdata/functions/utils/ConfigUtils.java similarity index 50% rename from src/main/java/com/github/aaronshan/functions/utils/ConfigUtils.java rename to src/main/java/com/chinagoods/bigdata/functions/utils/ConfigUtils.java index a48fb18..508ccf0 100644 --- a/src/main/java/com/github/aaronshan/functions/utils/ConfigUtils.java +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/ConfigUtils.java @@ -1,17 +1,19 @@ -package com.github.aaronshan.functions.utils; +package com.chinagoods.bigdata.functions.utils; -import com.github.aaronshan.functions.model.ChinaIdArea; +import com.chinagoods.bigdata.functions.model.ChinaIdArea; +import com.google.common.base.Charsets; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.io.Closer; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.*; + +import java.io.*; import java.util.ArrayList; import java.util.List; import java.util.Map; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,13 +24,14 @@ */ public class ConfigUtils { private static Logger logger = LoggerFactory.getLogger(ConfigUtils.class); + public static Configuration conf = null; public static List loadFile(String fileName) throws IOException { ArrayList strings = Lists.newArrayList(); Closer closer = Closer.create(); try { InputStream inputStream = ConfigUtils.class.getResourceAsStream(fileName); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, Charsets.UTF_8)); closer.register(bufferedReader); String line; while ((line = bufferedReader.readLine()) != null) { @@ -47,6 +50,61 @@ public static List loadFile(String fileName) throws IOException { return strings; } + public static Configuration getHDFSConf(){ + if (conf == null){ + //这里的路径是在hdfs上的存放路径,但是事先需将hdfs-site.xml文件放在工程的source文件下,这样才能找到hdfs + conf = new Configuration(); + } + return conf; + } + + public static byte[] loadBinFile(String fileName) throws IOException { +// ByteBuffer bbf = ByteBuffer.allocateDirect(8_733_094 + 1024); +// byte[] bytes = null; + ByteArrayOutputStream output = new ByteArrayOutputStream(); + Closer closer = Closer.create(); + try { +// // 一次性载入,速度最快 +// InputStream is = ConfigUtils.class.getResourceAsStream(fileName); +// closer.register(is); +// bytes = new byte[is.available()]; +// is.read(bytes); + +// FileSystem fs = FileSystem.newInstance(getHDFSConf()); +// Path remotePath = new Path(fileName); +// FSDataInputStream in = fs.open(remotePath); +// closer.register(in); +// byte[] buffer = new byte[4096]; +// int n = 0; +// while (-1 != (n = in.read(buffer))) { +// output.write(buffer, 0, n); +// } +// bytes = new byte[in.available()]; +// in.read(bytes); + + // 设置缓冲器大小, 4k + final int buffSize = 4096; + byte[] bf = new byte[buffSize]; + InputStream in = ConfigUtils.class.getResourceAsStream(fileName); + closer.register(in); + byte[] buffer = new byte[buffSize]; + int n = 0; + while (-1 != (n = in.read(buffer))) { + output.write(buffer, 0, n); + } + } catch (IOException e) { + logger.error("loadFile {} error. error is {}.", fileName, e); + throw e; + } finally { + closer.close(); + } + // 转换模式 +// bbf.flip(); +// byte[] bytes = new byte[bbf.remaining()]; +// bbf.get(bytes); + return output.toByteArray(); + } + public static Map getIdCardMap() { String fileName = "/china_p_c_a.config"; Map map = Maps.newHashMap(); diff --git a/src/main/java/com/chinagoods/bigdata/functions/utils/DateUtil.java b/src/main/java/com/chinagoods/bigdata/functions/utils/DateUtil.java new file mode 100644 index 0000000..f06ab99 --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/DateUtil.java @@ -0,0 +1,256 @@ +package com.chinagoods.bigdata.functions.utils; + +import com.google.common.collect.ImmutableMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 日期帮助类 + * + * @author xiaowei.song + */ +public class DateUtil { + public static final Logger logger = LoggerFactory.getLogger(DateUtil.class); + + public static final String DEFAULT_UTC_DATE_TIME = "1970-01-01 00:00:00"; + + public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; + public static final String US_DATE_TIME_FORMAT = "MM/dd/yyyy HH:mm:ss"; + //09/Nov/2020:16:11:31 +0800 + public static final String GMT_DATE_TIME_FORMAT = "dd/MMM/yyyy:HH:mm:ss Z"; + /** + * 2022-02-11T09:12:15+08:00 + **/ + public static final String UTC_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ssXXX"; + public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd"; + public static final String DATE_DS_FORMAT = "yyyyMMdd"; + + public static final String US_DATE_FORMAT = "MM/dd/yyyy"; + + public static final String TIME_FORMAT = "HH:mm:ss"; + + public static final Pattern US_DATE_PATTERN = Pattern.compile("[0-1][0-9]/[0-3][0-9]/20[0-9][0-9]"); + + public static final Pattern TIME_PATTERN = Pattern.compile("[0-2][0-9]:[0-5][0-9]:[0-5][0-9]"); + + public static final long[] TIME_RATION = {1L, 60L, 3600L}; + + public static final DateTimeFormatter DEFAULT_DTF = DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT); + public static final DateTimeFormatter DEFAULT_DATE_DTF = DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT); + public static final DateTimeFormatter DATE_DS_DTF = DateTimeFormatter.ofPattern(DATE_DS_FORMAT); + public static final DateTimeFormatter US_DATE_DTF = DateTimeFormatter.ofPattern(US_DATE_FORMAT); + public static final DateTimeFormatter GMT_DATE_DTF = DateTimeFormatter.ofPattern(GMT_DATE_TIME_FORMAT, Locale.ENGLISH); + public static final DateTimeFormatter UTC_DATE_TIME_DTF = DateTimeFormatter.ofPattern(UTC_DATE_TIME_FORMAT, Locale.CHINA); + public static final DateTimeFormatter US_DATE_TIME_DTF = DateTimeFormatter.ofPattern(US_DATE_TIME_FORMAT); + public static final DateTimeFormatter DEFAULT_TIME_DTF = DateTimeFormatter.ofPattern(TIME_FORMAT); + public static final Map FORMATTER_DTF_MAP = ImmutableMap.builder() + .put(DEFAULT_DATE_TIME_FORMAT, DEFAULT_DTF) + .put(DEFAULT_DATE_FORMAT, DEFAULT_DATE_DTF) + .put(US_DATE_FORMAT, US_DATE_DTF) + .put(GMT_DATE_TIME_FORMAT, GMT_DATE_DTF) + .put(US_DATE_TIME_FORMAT, US_DATE_TIME_DTF) + .put(TIME_FORMAT, DEFAULT_TIME_DTF) + .put(UTC_DATE_TIME_FORMAT, UTC_DATE_TIME_DTF) + .put(DATE_DS_FORMAT, DATE_DS_DTF) + .build(); + + public static final ZoneOffset DEFAULT_ZONE_OFFSET = ZoneOffset.of("+8"); + + /** + * 给定日期时间格式,返回班次信息 + * + * @param dateTimeStr 日期时间字符串 + * @return shift 班次 + **/ + public static String calcShift(String dateTimeStr) { + LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, DEFAULT_DTF); + return calcShift(dateTime, false); + } + + /** + * 给定日期时间格式,返回班次信息 + * + * @param dateTimeStr 日期时间字符串 + * @return shift 班次 + **/ + public static String calcShift(String dateTimeStr, boolean dayDate) { + LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, DEFAULT_DTF); + return calcShift(dateTime, dayDate); + } + + /** + * 给定日期时间格式,返回班次信息 + * + * @param dateTime 日期时间 + * @param dayDate 是否是班次时间,若是,则不减8,反之,减8 + * @return shift 班次 + **/ + public static String calcShift(LocalDateTime dateTime, boolean dayDate) { + if (!dayDate) { + dateTime = dateTime.plusHours(-8); + } + String shift; + String dateStr = DEFAULT_DATE_DTF.format(dateTime); + if (dateTime.getHour() < 12) { + shift = String.format("%s-D", dateStr); + } else { + shift = String.format("%s-N", dateStr); + } + return shift; + } + + /** + * 给定日期时间格式,返回day date信息 + * + * @param dateTimeStr 日期时间字符串 + * @return day date 工作日期 + **/ + public static String calcDayDate(String dateTimeStr) { + LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, DEFAULT_DTF); + dateTime = calcDayDate(dateTime); + return DEFAULT_DATE_DTF.format(dateTime); + } + + /** + * 给定日期时间格式,返回day date信息 + * + * @param dateTimeStr 日期时间字符串 + * @return LocalDateTime dayDate 工作日期时间格式 + **/ + public static LocalDateTime calcDayDate2DateTime(String dateTimeStr) { + LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, DEFAULT_DTF); + dateTime = calcDayDate(dateTime); + return dateTime; + } + + public static LocalDateTime calcDayDate(LocalDateTime dateTime) { + return dateTime.plusHours(-8); + } + + /** + * 将日期时间格式字符串转换成日期对象 + * + * @param dateTimeStr 日期时间字符串 + * @return date 日期实例 + **/ + public static LocalDateTime parse(String dateTimeStr) { + return parse(dateTimeStr, DEFAULT_DATE_TIME_FORMAT); + } + + /** + * 将日期格式字符串按照指定格式转换成日期对象 + * + * @param dateTimeStr 日期时间字符串 + * @param format 日期格式 + * @return date 日期实例 + **/ + public static LocalDateTime parse(final String dateTimeStr, final String format) { + DateTimeFormatter formatter = null; + if (FORMATTER_DTF_MAP.containsKey(format)) { + formatter = FORMATTER_DTF_MAP.get(format); + } else { + formatter = DateTimeFormatter.ofPattern(format); + } + return LocalDateTime.parse(dateTimeStr, formatter); + } + + /** + * 将日期格式化成字符串 + * + * @param dateTime 日期时间 + * @param format 日期格式 + * @return dateTimeStr String + **/ + public static String format(LocalDateTime dateTime, String format) { + DateTimeFormatter formatter = null; + if (FORMATTER_DTF_MAP.containsKey(format)) { + formatter = FORMATTER_DTF_MAP.get(format); + } else { + formatter = DateTimeFormatter.ofPattern(format); + } + return dateTime.format(formatter); + } + + /** + * 将日期格式化成字符串 + * + * @param dateTime 日期时间 + * @return dateTimeStr String + **/ + public static String format(LocalDateTime dateTime) { + return format(dateTime, DEFAULT_DATE_TIME_FORMAT); + } + + /** + * 从字符串中提取日期字符串 + * 08/20/2020->08/20/2020 + * 若数据错误,则忽略,填写默认值 + **/ + public static String getDateStr(String dateStr) { + Matcher matcher = US_DATE_PATTERN.matcher(dateStr); + matcher.reset(); + if (matcher.find()) { + return matcher.group(0); + } + return format(LocalDateTime.now(), US_DATE_FORMAT); + } + + /** + * 从字符串中提取日期字符串 + * 08/20/2020->08/20/2020 + * 若数据错误,则忽略,填写默认值 + **/ + public static String getTimeStr(String str) { + Matcher matcher = TIME_PATTERN.matcher(str); + matcher.reset(); + if (matcher.find()) { + return matcher.group(0); + } + return format(LocalDateTime.now(), TIME_FORMAT); + } + + /** + * 13位时间戳转换成ds字符串 + * @param timestamp13 13位时间戳 + **/ + public static String getDate2DSString(long timestamp13) { + return parse(timestamp13, DATE_DS_FORMAT); + } + + /** + * 13位时间戳转换成字符串 + * @param timestamp13 13位时间戳 + * @param format 格式化 + **/ + public static String parse(long timestamp13, String format) { + Instant instant = Instant.ofEpochMilli(timestamp13); + return format(LocalDateTime.ofInstant(instant, DEFAULT_ZONE_OFFSET), format); + } + + + public static void main(String[] args) { +// String dateTime = "2020-08-27 19:58:00"; +// String usDateTime = "08/27/2020 22:58:00"; +// System.out.println(parse(dateTime)); +// System.out.println(format(parse(dateTime))); +// +// System.out.println(parse(usDateTime, US_DATE_TIME_FORMAT)); +// +// System.out.println(calcDayDate(dateTime)); +// +// System.out.println(calcShift(dateTime)); + +// String dateStr = "01/Nov/2020:13:57:29 +0800"; +// System.out.println(parse(dateStr, GMT_DATE_TIME_FORMAT)); + System.out.println(DateUtil.format(DateUtil.parse("2022-02-11T09:12:15+08:00", UTC_DATE_TIME_FORMAT))); + } +} diff --git a/src/main/java/com/github/aaronshan/functions/utils/Failures.java b/src/main/java/com/chinagoods/bigdata/functions/utils/Failures.java similarity index 90% rename from src/main/java/com/github/aaronshan/functions/utils/Failures.java rename to src/main/java/com/chinagoods/bigdata/functions/utils/Failures.java index 6437bea..be914c0 100644 --- a/src/main/java/com/github/aaronshan/functions/utils/Failures.java +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/Failures.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.utils; +package com.chinagoods.bigdata.functions.utils; import org.apache.hadoop.hive.ql.metadata.HiveException; diff --git a/src/main/java/com/github/aaronshan/functions/utils/GeoUtils.java b/src/main/java/com/chinagoods/bigdata/functions/utils/GeoUtils.java similarity index 99% rename from src/main/java/com/github/aaronshan/functions/utils/GeoUtils.java rename to src/main/java/com/chinagoods/bigdata/functions/utils/GeoUtils.java index f8be22a..63c0752 100644 --- a/src/main/java/com/github/aaronshan/functions/utils/GeoUtils.java +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/GeoUtils.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.utils; +package com.chinagoods.bigdata.functions.utils; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/src/main/java/com/chinagoods/bigdata/functions/utils/HttpParamUtil.java b/src/main/java/com/chinagoods/bigdata/functions/utils/HttpParamUtil.java new file mode 100644 index 0000000..f374b4d --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/HttpParamUtil.java @@ -0,0 +1,55 @@ +package com.chinagoods.bigdata.functions.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +/** + * @author xiaowei.song + */ +public class HttpParamUtil { + public static final Logger logger = LoggerFactory.getLogger(HttpParamUtil.class); + + /** + * 获得url中参数 + * @param url url链接 + * @return url中参数map + */ + public static Map getParameter(String url) { + Map map = new HashMap(); + try { + url = URLDecoder.decode(url, StandardCharsets.UTF_8.name()); + } catch (Exception e) { + logger.error("url解码异常: {}", url, e); + } + if (url.indexOf('?') != -1) { + final String contents = url.substring(url.indexOf('?') + 1); + String[] keyValues = contents.split("[&#]"); + for (int i = 0; i < keyValues.length; i++) { + // url结尾为/非标准k=v格式,跳过 + if (!keyValues[i].contains("=")) { + continue; + } + String key = keyValues[i].substring(0, keyValues[i].indexOf("=")); + String value = keyValues[i].substring(keyValues[i].indexOf("=") + 1); + // value去除特殊字符 + value = value.replaceAll("[.、']", ""); + map.put(key, value); + } + } + return map; + } + /** + * 测试 + * @param args main方法参数列表 + */ + public static void main(String[] args) { + String url = "https://www.chinagoods.com/activies/special?code=202107131418516200819335&active_code=202107131418516200819335&id=545?utm_campaign=????&utm_source=??&utm_medium=cpc&utm_content=??-????WAP-????#/"; + Map map = getParameter(url); + System.out.println(map); + } +} \ No newline at end of file diff --git a/src/main/java/com/chinagoods/bigdata/functions/utils/JacksonBuilder.java b/src/main/java/com/chinagoods/bigdata/functions/utils/JacksonBuilder.java new file mode 100644 index 0000000..aeb063e --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/JacksonBuilder.java @@ -0,0 +1,47 @@ +package com.chinagoods.bigdata.functions.utils; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.apache.commons.lang3.StringEscapeUtils; + +import java.io.IOException; +import java.text.SimpleDateFormat; + +/** + * Jackson builder mapper + */ +public final class JacksonBuilder { + public static final ObjectMapper mapper = new ObjectMapper(); + + /** + * 配置jackson配置 + **/ + static { + // 该特性决定了当遇到未知属性(没有映射到属性,没有任何setter或者任何可以处理它的handler),是否应该抛出一个JsonMappingException异常 + mapper.configure(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS, false); + //在序列化时日期格式默认为 yyyy-MM-dd'T'HH:mm:ss.SSSZ + mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + //在序列化时忽略值为 null 的属性 + mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS); + //忽略值为默认值的属性 + mapper.setDefaultPropertyInclusion(JsonInclude.Include.ALWAYS); + //设置JSON时间格式 + mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); + mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); + + // 声明一个简单Module 对象 + SimpleModule httpCodeEnumModule = new SimpleModule(); + mapper.registerModule(httpCodeEnumModule); + } + + public static void main(String[] args) throws IOException { + String requestBody = "{\\x22unitSystem\\x22:\\x22iOS\\x22,\\x22type\\x22:1,\\x22token\\x22:\\x22031f88c99c601d614633c6ba84825d5e763c\\x22,\\x22unitType\\x22:\\x22iPhone 7 Plus\\x22,\\x22unitName\\x22:\\x22iPhone\\x22}"; + requestBody = StringEscapeUtils.unescapeJava(requestBody.replaceAll("\\\\x", "\\\\u00")); + JsonNode jsonNode = JacksonBuilder.mapper.readTree(requestBody); + System.out.println(jsonNode); + } +} diff --git a/src/main/java/com/github/aaronshan/functions/utils/MapUtils.java b/src/main/java/com/chinagoods/bigdata/functions/utils/MapUtils.java similarity index 96% rename from src/main/java/com/github/aaronshan/functions/utils/MapUtils.java rename to src/main/java/com/chinagoods/bigdata/functions/utils/MapUtils.java index ac74750..940b2e9 100644 --- a/src/main/java/com/github/aaronshan/functions/utils/MapUtils.java +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/MapUtils.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.utils; +package com.chinagoods.bigdata.functions.utils; import java.util.Map; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; diff --git a/src/main/java/com/github/aaronshan/functions/utils/MathUtils.java b/src/main/java/com/chinagoods/bigdata/functions/utils/MathUtils.java similarity index 50% rename from src/main/java/com/github/aaronshan/functions/utils/MathUtils.java rename to src/main/java/com/chinagoods/bigdata/functions/utils/MathUtils.java index 4adb505..2de76f6 100644 --- a/src/main/java/com/github/aaronshan/functions/utils/MathUtils.java +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/MathUtils.java @@ -1,14 +1,13 @@ -package com.github.aaronshan.functions.utils; +package com.chinagoods.bigdata.functions.utils; import org.apache.hadoop.hive.ql.metadata.HiveException; -import static com.github.aaronshan.functions.utils.Failures.checkCondition; import static java.lang.Character.MAX_RADIX; import static java.lang.Character.MIN_RADIX; public class MathUtils { public static void checkRadix(long radix) throws HiveException { - checkCondition(radix >= MIN_RADIX && radix <= MAX_RADIX, "Radix must be between %d and %d", MIN_RADIX, MAX_RADIX); + Failures.checkCondition(radix >= MIN_RADIX && radix <= MAX_RADIX, "Radix must be between %d and %d", MIN_RADIX, MAX_RADIX); } } diff --git a/src/main/java/com/chinagoods/bigdata/functions/utils/MysqlUtil.java b/src/main/java/com/chinagoods/bigdata/functions/utils/MysqlUtil.java new file mode 100644 index 0000000..8db00fa --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/MysqlUtil.java @@ -0,0 +1,148 @@ +package com.chinagoods.bigdata.functions.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.*; +import java.util.*; + +/** + * @author xiaowei.song + */ +final public class MysqlUtil { + private static final Logger logger = LoggerFactory.getLogger(MysqlUtil.class); + private Connection connection; + private String dbUrl; + private String dbUser; + private String dbPassword; + + /** + * MySQL 8.0 以下版本 - JDBC 驱动名及数据库 URL + **/ + private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; + + public MysqlUtil(String dbUrl, String dbUser, String dbPassword) { + this.dbUrl = dbUrl; + this.dbUser = dbUser; + this.dbPassword = dbPassword; + connection = getConnection(); + } + + public Connection getConnection(){ + Connection conn = null; + try { + Class.forName(JDBC_DRIVER); + conn = DriverManager.getConnection(this.dbUrl, this.dbUser, this.dbPassword); + }catch (Exception e) { + logger.error("获取mysql连接失败, dbUrl: {}, username: {}, password: {}", dbUrl, dbUser, dbPassword, e); + System.exit(1); + } + return conn; + } + + /** + * 查询表中关键词 + * @return keywords sensitive set违禁词集合 + * @throws SQLException 查詢異常 + */ + public Set getKeywords(String sql) throws SQLException { + Set keywordsSet = new HashSet<>(3000); + // 重建mysql连接信息 + if (connection == null || connection.isClosed()) { + connection = getConnection(); + } + Statement stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery(sql); + // 展开结果集数据库 + while(rs.next()) { + for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) { + keywordsSet.add((String) rs.getObject(i + 1)); + } + } + // 完成后关闭 + rs.close(); + stmt.close(); + return keywordsSet; + } + + public Set getSet(String sql) throws SQLException { + Set set = new HashSet<>(); + // 重建mysql连接信息 + if (connection == null || connection.isClosed()) { + connection = getConnection(); + } + Statement stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery(sql); + // 展开结果集数据库 + while(rs.next()) { + for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) { + set.add((String) rs.getObject(i + 1)); + } + } + // 完成后关闭 + rs.close(); + stmt.close(); + return set; + } + + public List> getLists(String sql) throws SQLException { + List> resultlist = new ArrayList<>(); + // 重建mysql连接信息 + if (connection == null || connection.isClosed()) { + connection = getConnection(); + } + Statement stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery(sql); + // 展开结果集数据库 + while(rs.next()) { + List list = new ArrayList<>(); + for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) { + list.add((String) rs.getObject(i + 1)); + } + resultlist.add(list); + } + // 完成后关闭 + rs.close(); + stmt.close(); + return resultlist; + } + + public Map getMap(String sql) throws SQLException { + Map map = new HashMap<>(); + // 重建mysql连接信息 + if (connection == null || connection.isClosed()) { + connection = getConnection(); + } + Statement stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery(sql); + // 展开结果集数据库 + while(rs.next()) { + map.put((String) rs.getObject(1),(String) rs.getObject(2)); + } + // 完成后关闭 + rs.close(); + stmt.close(); + return map; + } + + public void close() throws SQLException { + if (connection != null && !connection.isClosed()) { + connection.close(); + } + } + + public static void main(String[] args) throws SQLException { + MysqlUtil mysqlUtil = new MysqlUtil("jdbc:mysql://172.18.5.22:3306/source?characterEncoding=UTF-8&useSSL=false", + "source", + "jP8*dKw,bRjBVos="); + System.out.println(mysqlUtil.getKeywords("select t.key_word\n" + + "from risk_control_keywords t\n" + + "inner join (\n" + + "\tselect key_word\n" + + "\t,max(create_time) max_create_time\n" + + "\tfrom risk_control_keywords\n" + + "\tgroup by key_word\n" + + ") nt on t.create_time = nt.max_create_time and t.key_word = nt.key_word\n" + + "where t.is_deleted = '否'")); + } +} diff --git a/src/main/java/com/chinagoods/bigdata/functions/utils/img/PHash.java b/src/main/java/com/chinagoods/bigdata/functions/utils/img/PHash.java new file mode 100644 index 0000000..2d2468d --- /dev/null +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/img/PHash.java @@ -0,0 +1,229 @@ +package com.chinagoods.bigdata.functions.utils.img; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +/** + * Phash 算法实现 + * @author luoweifu + **/ +public class PHash { + public static final Logger logger = LoggerFactory.getLogger(PHash.class); + + public static final Integer DEFAULT_N = 180; + + public static final Integer DCT_N = 16; + + public PHash() { + } + + /** + * 获得图像特征值 + * @param imagePath 图像路径 + * @return 返回图像phash特征值 + */ + public static String getFeatureValue(String imagePath) { + logger.debug("获取特征图片路径为: {}, 图片宽: {}, 图片高: {}", imagePath, DEFAULT_N, DEFAULT_N); + // 缩小尺寸,简化色彩 + int[][] grayMatrix = PHash.getGrayPixel(imagePath, DEFAULT_N, DEFAULT_N); + if (grayMatrix == null) { + return null; + } + // 计算DCT + dct(grayMatrix, DEFAULT_N); + // 缩小DCT,计算平均值 + int[][] newMatrix = new int[DCT_N][DCT_N]; + double average = 0; + for(int i = 0; i < DCT_N; i++){ + for(int j = 0; j < DCT_N; j++){ + newMatrix[i][j] = grayMatrix[i][j]; + average += grayMatrix[i][j]; + } + } + average /= (DCT_N * DCT_N); + + // 计算hash值 + StringBuilder sb = new StringBuilder(); + int pos4Sum = 0; + for(int i = 0; i < DCT_N; i++) { + for(int j = 0; j < DCT_N; j++){ + // 若当前位置为4的倍数,则将数值转换为16进制字符 + if (j > 0 && j % 4 == 0) { + sb.append(Integer.toHexString(pos4Sum)); + pos4Sum = 0; + } + if(newMatrix[i][j] < average){ + pos4Sum<<=1; + } else{ + pos4Sum = (pos4Sum << 1) + 1; + } + } + sb.append(Integer.toHexString(pos4Sum)); + pos4Sum = 0; + } + return sb.toString(); + } + + /** + * 得到灰度像素图矩阵 + * @param imagePath 图像路径 + * @param width 宽 + * @param height 高 + * @return 返回图像灰度化矩阵 + */ + public static int[][] getGrayPixel(String imagePath, int width, int height) { + logger.debug("获取特征图片路径为: {}, 宽: {}, 高: {}", imagePath, width, height); + BufferedImage bi; + try { + bi = resizeImage(imagePath, width, height, BufferedImage.TYPE_INT_RGB); + } catch (Exception e) { + e.printStackTrace(); + logger.error("{}图片缩放失败, 错误原因为: ", imagePath, e); + return null; + } + int minx = bi.getMinX(); + int miny = bi.getMinY(); + int[][] matrix = new int[width - minx][height - miny]; + for (int i = minx; i < width; i++) { + for (int j = miny; j < height; j++) { + int pixel = bi.getRGB(i, j); + int red = (pixel & 0xff0000) >> 16; + int green = (pixel & 0xff00) >> 8; + int blue = (pixel & 0xff); + int gray = (int) (red * 0.3 + green * 0.59 + blue * 0.11); + matrix[i][j] = gray; + } + } + return matrix; + } + + /** + * 缩放图片大小,将图片缩放成指定格式和指定宽高图片 + * @param srcImgPath 原始图片路径 + * @param width 转换的宽 + * @param height 转换的高 + * @param imageType 图片类型 + * @return 图片缓存内容 + */ + public static BufferedImage resizeImage(String srcImgPath, int width, int height, int imageType) + throws IOException { + File srcFile = new File(srcImgPath); + BufferedImage srcImg = ImageIO.read(srcFile); + BufferedImage buffImg; + buffImg = new BufferedImage(width, height, imageType); + buffImg.getGraphics().drawImage(srcImg.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null); + return buffImg; + } + + /** + * 用于计算pHash的相似度
+ * 相似度为1时,图片最相似 + * @param phashCode1 图像1 phash code值 + * @param phashCode2 图像2 phash code值 + * @return 两者相似度,若返回1,则说明图片一样 + */ + public static double calculateSimilarity(String phashCode1, String phashCode2) { + int num = 0; + for(int i = 0; i < DCT_N * DCT_N; i++){ + if(phashCode1.charAt(i) == phashCode2.charAt(i)){ + num++; + } + } + return ((double)num) / (DCT_N * DCT_N * 1.0); + } + + /** + * 离散余弦变换 + * @author luoweifu + * @param pix 原图像的数据矩阵 + * @param matrixN 原图像(n*n)的高或宽 + */ + public static void dct(int[][] pix, int matrixN) { + double[][] iMatrix = new double[matrixN][matrixN]; + for (int i = 0; i < matrixN; i++) { + for (int j = 0; j < matrixN; j++) { + iMatrix[i][j] = pix[i][j]; + } + } + // 求系数矩阵 + double[][] quotient = coefficient(matrixN); + // 转置系数矩阵 + double[][] quotientT = transposingMatrix(quotient, matrixN); + + double[][] temp; + temp = matrixMultiply(quotient, iMatrix, matrixN); + iMatrix = matrixMultiply(temp, quotientT, matrixN); + + for (int i = 0; i < matrixN; i++) { + for (int j = 0; j < matrixN; j++) { + pix[i][j] = (int) (iMatrix[i][j]); + } + } + } + + /** + * 求离散余弦变换的系数矩阵 + * @author luoweifu + * @param matrixN n*n矩阵的大小 + * @return 系数矩阵 + */ + private static double[][] coefficient(int matrixN) { + double[][] coeff = new double[matrixN][matrixN]; + double sqrt = 1.0 / Math.sqrt(matrixN); + for (int i = 0; i < matrixN; i++) { + coeff[0][i] = sqrt; + } + for (int i = 1; i < matrixN; i++) { + for (int j = 0; j < matrixN; j++) { + coeff[i][j] = Math.sqrt(2.0 / matrixN) * Math.cos(i * Math.PI * (j + 0.5) / (double) matrixN); + } + } + return coeff; + } + + /** + * 矩阵转置 + * @author luoweifu + * @param matrix 原矩阵 + * @param matrixN 矩阵(n*n)的高或宽 + * @return 转置后的矩阵 + */ + private static double[][] transposingMatrix(double[][] matrix, int matrixN) { + double[][] nMatrix = new double[matrixN][matrixN]; + for (int i = 0; i < matrixN; i++) { + for (int j = 0; j < matrixN; j++) { + nMatrix[i][j] = matrix[j][i]; + } + } + return nMatrix; + } + + /** + * 矩阵相乘 + * @author luoweifu + * @param matrixA 矩阵A + * @param matrixB 矩阵B + * @param matrixN 矩阵的大小n*n + * @return 结果矩阵 + */ + private static double[][] matrixMultiply(double[][] matrixA, double[][] matrixB, int matrixN) { + double[][] nMatrix = new double[matrixN][matrixN]; + int t; + for (int i = 0; i < matrixN; i++) { + for (int j = 0; j < matrixN; j++) { + t = 0; + for (int k = 0; k < matrixN; k++) { + t += matrixA[i][k] * matrixB[k][j]; + } + nMatrix[i][j] = t; + } + } + return nMatrix; + } +} diff --git a/src/main/java/com/github/aaronshan/functions/utils/json/JsonExtract.java b/src/main/java/com/chinagoods/bigdata/functions/utils/json/JsonExtract.java similarity index 99% rename from src/main/java/com/github/aaronshan/functions/utils/json/JsonExtract.java rename to src/main/java/com/chinagoods/bigdata/functions/utils/json/JsonExtract.java index 2cae95c..e17941d 100644 --- a/src/main/java/com/github/aaronshan/functions/utils/json/JsonExtract.java +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/json/JsonExtract.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.utils.json; +package com.chinagoods.bigdata.functions.utils.json; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.SerializedString; diff --git a/src/main/java/com/github/aaronshan/functions/utils/json/JsonPath.java b/src/main/java/com/chinagoods/bigdata/functions/utils/json/JsonPath.java similarity index 94% rename from src/main/java/com/github/aaronshan/functions/utils/json/JsonPath.java rename to src/main/java/com/chinagoods/bigdata/functions/utils/json/JsonPath.java index 648039c..2933b1c 100644 --- a/src/main/java/com/github/aaronshan/functions/utils/json/JsonPath.java +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/json/JsonPath.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.utils.json; +package com.chinagoods.bigdata.functions.utils.json; /** * @author ruifeng.shan diff --git a/src/main/java/com/github/aaronshan/functions/utils/json/JsonPathTokenizer.java b/src/main/java/com/chinagoods/bigdata/functions/utils/json/JsonPathTokenizer.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/utils/json/JsonPathTokenizer.java rename to src/main/java/com/chinagoods/bigdata/functions/utils/json/JsonPathTokenizer.java index 58270a6..9e6f3e9 100644 --- a/src/main/java/com/github/aaronshan/functions/utils/json/JsonPathTokenizer.java +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/json/JsonPathTokenizer.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.utils.json; +package com.chinagoods.bigdata.functions.utils.json; import com.google.common.collect.AbstractIterator; diff --git a/src/main/java/com/github/aaronshan/functions/utils/json/JsonUtils.java b/src/main/java/com/chinagoods/bigdata/functions/utils/json/JsonUtils.java similarity index 98% rename from src/main/java/com/github/aaronshan/functions/utils/json/JsonUtils.java rename to src/main/java/com/chinagoods/bigdata/functions/utils/json/JsonUtils.java index 26cc15d..48e935c 100644 --- a/src/main/java/com/github/aaronshan/functions/utils/json/JsonUtils.java +++ b/src/main/java/com/chinagoods/bigdata/functions/utils/json/JsonUtils.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.utils.json; +package com.chinagoods.bigdata.functions.utils.json; import com.fasterxml.jackson.core.JsonFactory; @@ -6,6 +6,7 @@ import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.MappingJsonFactory; import com.google.common.collect.Lists; + import java.io.IOException; import java.util.List; diff --git a/src/main/java/com/github/aaronshan/functions/array/UDFSequence.java b/src/main/java/com/github/aaronshan/functions/array/UDFSequence.java deleted file mode 100644 index 220d0c2..0000000 --- a/src/main/java/com/github/aaronshan/functions/array/UDFSequence.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.github.aaronshan.functions.array; - -import com.google.common.collect.Lists; -import org.apache.hadoop.hive.ql.exec.Description; -import org.apache.hadoop.hive.ql.exec.UDF; -import org.apache.hadoop.hive.ql.metadata.HiveException; -import org.apache.hadoop.io.LongWritable; -import org.apache.hadoop.io.Text; -import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; - -import java.util.List; - -import static com.github.aaronshan.functions.utils.Failures.checkCondition; -/** - * @author aaron02 - * date: 2018-08-18 上午9:23 - */ -@Description(name = "sequence" - , value = "_FUNC_(start, stop) - Generate a sequence of integers from start to stop.\n" + - "_FUNC_(start, stop, step) - Generate a sequence of integers from start to stop, incrementing by step." - , extended = "Example:\n > select _FUNC_(1, 5) from src;\n > select _FUNC_(1, 9, 4) from src;\n" + - " > select _FUNC_('2016-04-12', '2016-04-14') from src;") -public class UDFSequence extends UDF { - public final static DateTimeFormatter DEFAULT_DATE_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"); - private static final long MAX_RESULT_ENTRIES = 10000; - - public UDFSequence() { - - } - - public Object evaluate(LongWritable start, LongWritable stop) throws HiveException { - return fixedWidthSequence(start.get(), stop.get(), stop.get() >= start.get() ? 1 : -1, Long.class); - } - - public Object evaluate(LongWritable start, LongWritable stop, LongWritable step) throws HiveException { - return fixedWidthSequence(start.get(), stop.get(), step.get(), Long.class); - } - - public Object evaluate(Text start, Text stop, long step) throws HiveException { - long startMillis = DateTime.parse(start.toString(), DEFAULT_DATE_FORMATTER).getMillis(); - long stopMillis = DateTime.parse(stop.toString(), DEFAULT_DATE_FORMATTER).getMillis(); - return fixedWidthSequence(startMillis, stopMillis, step, String.class); - } - - public static int toIntExact(long value) { - if ((int)value != value) { - throw new ArithmeticException("integer overflow"); - } - return (int)value; - } - - private static Object fixedWidthSequence(long start, long stop, long step, Class type) throws HiveException { - checkValidStep(start, stop, step); - - int length = toIntExact((stop - start) / step + 1L); - checkMaxEntry(length); - - if (type == long.class || type == Long.class) { - List result = Lists.newArrayList(); - for (long i = 0, value = start; i < length; ++i, value += step) { - result.add(value); - } - return result; - } else if (type == String.class){ - List result = Lists.newArrayList(); - for (long i = 0, value = start; i < length; ++i, value += step) { - DateTime dateTime = new DateTime(value); - result.add(dateTime.toString(DEFAULT_DATE_FORMATTER)); - } - return result; - } else { - throw new HiveException("Don't support this class type!" + type); - } - } - - private static void checkValidStep(long start, long stop, long step) throws HiveException { - checkCondition( - step != 0, - "step must not be zero"); - checkCondition( - step > 0 ? stop >= start : stop <= start, - "sequence stop value should be greater than or equal to start value if step is greater than zero otherwise stop should be less than or equal to start"); - } - - private static void checkMaxEntry(int length) throws HiveException { - checkCondition( - length <= MAX_RESULT_ENTRIES, - "result of sequence function must not have more than 10000 entries"); - } -} diff --git a/src/main/java/com/github/aaronshan/functions/url/UDFUrlDecode.java b/src/main/java/com/github/aaronshan/functions/url/UDFUrlDecode.java deleted file mode 100644 index e991f24..0000000 --- a/src/main/java/com/github/aaronshan/functions/url/UDFUrlDecode.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.github.aaronshan.functions.url; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import org.apache.hadoop.hive.ql.exec.Description; -import org.apache.hadoop.hive.ql.exec.UDF; -import org.apache.hadoop.io.Text; - -/** - * @author ruifeng.shan - * date: 2016-07-27 - * time: 16:04 - */ -@Description(name = "url_decode" - , value = "_FUNC_(value) - Unescape the URL encoded value. This function is the inverse of url_encode()" - , extended = "Example:\n > select _FUNC_(value) from src;") -public class UDFUrlDecode extends UDF { - private Text result = new Text(); - - public Text evaluate(String value) { - if (value == null) { - return null; - } - try { - result.set(URLDecoder.decode(value, "UTF-8")); - return result; - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); - } - } -} diff --git a/src/main/resources/china_p_c_a.config b/src/main/resources/china_p_c_a.config index 874bd9f..57beb2d 100644 --- a/src/main/resources/china_p_c_a.config +++ b/src/main/resources/china_p_c_a.config @@ -1,14 +1,14 @@ # come from http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/201504/t20150415_712722.html 110101 北京市 北京市 东城区 110102 北京市 北京市 西城区 -#110103 北京市 北京市 崇文区 -#110104 北京市 北京市 宣武区 +110103 北京市 北京城区 东城区 +110104 北京市 北京城区 西城区 110105 北京市 北京市 朝阳区 110106 北京市 北京市 丰台区 110107 北京市 北京市 石景山区 110108 北京市 北京市 海淀区 110109 北京市 北京市 门头沟区 -#110110 北京市 北京市 燕山区 +110110 北京市 北京城区 房山区 110111 北京市 北京市 房山区 110112 北京市 北京市 通州区 110113 北京市 北京市 顺义区 @@ -16,8 +16,8 @@ 110115 北京市 北京市 大兴区 110116 北京市 北京市 怀柔区 110117 北京市 北京市 平谷区 -110228 北京市 北京市 密云县 -110229 北京市 北京市 延庆县 +110228 北京市 北京城区 密云区 +110229 北京市 北京城区 延庆区 120101 天津市 天津市 和平区 120102 天津市 天津市 河东区 120103 天津市 天津市 河西区 @@ -31,13 +31,13 @@ 120114 天津市 天津市 武清区 120115 天津市 天津市 宝坻区 120116 天津市 天津市 滨海新区 -120221 天津市 天津市 宁河区 -120223 天津市 天津市 静海区 -120225 天津市 天津市 蓟县 +120221 天津市 天津城区 宁河区 +120223 天津市 天津城区 静海区 +120225 天津市 天津城区 蓟州区 130100 河北省 石家庄市 石家庄市 130101 河北省 石家庄市 石家庄市 130102 河北省 石家庄市 长安区 -130103 河北省 石家庄市 桥东区 +130103 河北省 张家口市 桥东区 130104 河北省 石家庄市 桥西区 130105 河北省 石家庄市 新华区 130107 河北省 石家庄市 井陉矿区 @@ -73,7 +73,7 @@ 130225 河北省 唐山市 乐亭县 130227 河北省 唐山市 迁西县 130229 河北省 唐山市 玉田县 -#130230 河北省 唐山市 唐海县 +130230 河北省 唐山市 唐山市 130281 河北省 唐山市 遵化市 130283 河北省 唐山市 迁安市 130300 河北省 秦皇岛市 秦皇岛市 @@ -83,7 +83,7 @@ 130304 河北省 秦皇岛市 北戴河区 130321 河北省 秦皇岛市 青龙满族自治县 130322 河北省 秦皇岛市 昌黎县 -130323 河北省 秦皇岛市 抚宁县 +130323 河北省 秦皇岛市 抚宁区 130324 河北省 秦皇岛市 卢龙县 130400 河北省 邯郸市 邯郸市 130401 河北省 邯郸市 邯郸市 @@ -91,14 +91,14 @@ 130403 河北省 邯郸市 丛台区 130404 河北省 邯郸市 复兴区 130406 河北省 邯郸市 峰峰矿区 -130421 河北省 邯郸市 邯郸县 +130421 河北省 邯郸市 邯郸市 130423 河北省 邯郸市 临漳县 130424 河北省 邯郸市 成安县 130425 河北省 邯郸市 大名县 130426 河北省 邯郸市 涉县 130427 河北省 邯郸市 磁县 -130428 河北省 邯郸市 肥乡县 -130429 河北省 邯郸市 永年县 +130428 河北省 邯郸市 肥乡区 +130429 河北省 邯郸市 永年区 130430 河北省 邯郸市 邱县 130431 河北省 邯郸市 鸡泽县 130432 河北省 邯郸市 广平县 @@ -131,7 +131,7 @@ 130601 河北省 保定市 保定市 130602 河北省 保定市 竞秀区 130603 河北省 保定市 莲池区 -130604 河北省 保定市 南市区 +130604 河北省 保定市 莲池区 130621 河北省 保定市 满城区 130622 河北省 保定市 清苑区 130623 河北省 保定市 涞水县 @@ -160,7 +160,7 @@ 130703 河北省 张家口市 桥西区 130705 河北省 张家口市 宣化区 130706 河北省 张家口市 下花园区 -130721 河北省 张家口市 宣化县 +130721 河北省 张家口市 宣化区 130722 河北省 张家口市 张北县 130723 河北省 张家口市 康保县 130724 河北省 张家口市 沽源县 @@ -168,11 +168,11 @@ 130726 河北省 张家口市 蔚县 130727 河北省 张家口市 阳原县 130728 河北省 张家口市 怀安县 -130729 河北省 张家口市 万全县 +130729 河北省 张家口市 万全区 130730 河北省 张家口市 怀来县 130731 河北省 张家口市 涿鹿县 130732 河北省 张家口市 赤城县 -130733 河北省 张家口市 崇礼县 +130733 河北省 张家口市 崇礼区 130800 河北省 承德市 承德市 130801 河北省 承德市 承德市 130802 河北省 承德市 双桥区 @@ -180,7 +180,7 @@ 130804 河北省 承德市 鹰手营子矿区 130821 河北省 承德市 承德县 130822 河北省 承德市 兴隆县 -130823 河北省 承德市 平泉县 +130823 河北省 承德市 平泉市 130824 河北省 承德市 滦平县 130825 河北省 承德市 隆化县 130826 河北省 承德市 丰宁满族自治县 @@ -227,7 +227,7 @@ 131126 河北省 衡水市 故城县 131127 河北省 衡水市 景县 131128 河北省 衡水市 阜城县 -131181 河北省 衡水市 冀州市 +131181 河北省 衡水市 冀州区 131182 河北省 衡水市 深州市 140100 山西省 太原市 太原市 140101 山西省 太原市 太原市 @@ -442,7 +442,7 @@ 150725 内蒙古自治区 呼伦贝尔市 陈巴尔虎旗 150726 内蒙古自治区 呼伦贝尔市 新巴尔虎左旗 150727 内蒙古自治区 呼伦贝尔市 新巴尔虎右旗 -150781 内蒙古自治区 呼伦贝尔市 满洲里 +150781 内蒙古自治区 呼伦贝尔市 满洲里市 150782 内蒙古自治区 呼伦贝尔市 牙克石市 150783 内蒙古自治区 呼伦贝尔市 扎兰屯市 150784 内蒙古自治区 呼伦贝尔市 额尔古纳市 @@ -483,7 +483,7 @@ 152523 内蒙古自治区 锡林郭勒盟 苏尼特左旗 152524 内蒙古自治区 锡林郭勒盟 苏尼特右旗 152525 内蒙古自治区 锡林郭勒盟 东乌珠穆沁旗 -152526 内蒙古自治区 锡林郭勒盟 西乌珠穆沁 +152526 内蒙古自治区 锡林郭勒盟 西乌珠穆沁旗 152527 内蒙古自治区 锡林郭勒盟 太仆寺旗 152528 内蒙古自治区 锡林郭勒盟 镶黄旗 152529 内蒙古自治区 锡林郭勒盟 正镶白旗 @@ -504,7 +504,7 @@ 210112 辽宁省 沈阳市 浑南区 210113 辽宁省 沈阳市 沈北新区 210114 辽宁省 沈阳市 于洪区 -210122 辽宁省 沈阳市 辽中县 +210122 辽宁省 沈阳市 辽中区 210123 辽宁省 沈阳市 康平县 210124 辽宁省 沈阳市 法库县 210181 辽宁省 沈阳市 新民市 @@ -518,7 +518,7 @@ 210213 辽宁省 大连市 金州区 210224 辽宁省 大连市 长海县 210281 辽宁省 大连市 瓦房店市 -210282 辽宁省 大连市 普兰店市 +210282 辽宁省 大连市 普兰店区 210283 辽宁省 大连市 庄河市 210300 辽宁省 鞍山市 鞍山市 210301 辽宁省 鞍山市 鞍山市 @@ -593,13 +593,13 @@ 211101 辽宁省 盘锦市 盘锦市 211102 辽宁省 盘锦市 双台子区 211103 辽宁省 盘锦市 兴隆台区 -211121 辽宁省 盘锦市 大洼县 +211121 辽宁省 盘锦市 大洼区 211122 辽宁省 盘锦市 盘山县 211200 辽宁省 铁岭市 铁岭市 211201 辽宁省 铁岭市 铁岭市 211202 辽宁省 铁岭市 银州区 211204 辽宁省 铁岭市 清河区 -211221 辽宁省 铁岭市 铁岭市县 +211221 辽宁省 铁岭市 铁岭县 211223 辽宁省 铁岭市 西丰县 211224 辽宁省 铁岭市 昌图县 211281 辽宁省 铁岭市 调兵山市 @@ -739,7 +739,7 @@ 230300 黑龙江省 鸡西市 鸡西市 230301 黑龙江省 鸡西市 鸡西市 230302 黑龙江省 鸡西市 鸡冠区 -230303 黑龙江省 鸡西市 恒山市 +230303 黑龙江省 鸡西市 恒山区 230304 黑龙江省 鸡西市 滴道区 230305 黑龙江省 鸡西市 梨树区 230306 黑龙江省 鸡西市 城子河区 @@ -806,13 +806,13 @@ 230822 黑龙江省 佳木斯市 桦南县 230826 黑龙江省 佳木斯市 桦川县 230828 黑龙江省 佳木斯市 汤原县 -230833 黑龙江省 佳木斯市 抚远县 +230833 黑龙江省 佳木斯市 抚远市 230881 黑龙江省 佳木斯市 同江市 230882 黑龙江省 佳木斯市 富锦市 230900 黑龙江省 七台河市 七台河市 230901 黑龙江省 七台河市 七台河市 230902 黑龙江省 七台河市 新兴区 -230903 黑龙江省 七台河市 桃山市 +230903 黑龙江省 七台河市 桃山区 230904 黑龙江省 七台河市 茄子河区 230921 黑龙江省 七台河市 勃利县 231000 黑龙江省 牡丹江市 牡丹江市 @@ -821,7 +821,7 @@ 231003 黑龙江省 牡丹江市 阳明区 231004 黑龙江省 牡丹江市 爱民区 231005 黑龙江省 牡丹江市 西安区 -231024 黑龙江省 牡丹江市 东宁县 +231024 黑龙江省 牡丹江市 东宁市 231025 黑龙江省 牡丹江市 林口县 231081 黑龙江省 牡丹江市 绥芬河市 231083 黑龙江省 牡丹江市 海林市 @@ -847,8 +847,8 @@ 231281 黑龙江省 绥化市 安达市 231282 黑龙江省 绥化市 肇东市 231283 黑龙江省 绥化市 海伦市 -232700 黑龙江省 大兴安岭地区 大兴安岭地区 -232701 黑龙江省 大兴安岭地区 加格达奇区 +232700 黑龙江省 呼中区* 呼中区* +232701 黑龙江省 大兴安岭地区 漠河市 232702 黑龙江省 大兴安岭地区 松岭区 232703 黑龙江省 大兴安岭地区 新林区 232704 黑龙江省 大兴安岭地区 呼中区 @@ -860,7 +860,7 @@ 310105 上海市 上海市 长宁区 310106 上海市 上海市 静安区 310107 上海市 上海市 普陀区 -310108 上海市 上海市 闸北区 +310108 上海市 上海城区 静安区 310109 上海市 上海市 虹口区 310110 上海市 上海市 杨浦区 310112 上海市 上海市 闵行区 @@ -871,7 +871,7 @@ 310117 上海市 上海市 松江区 310118 上海市 上海市 青浦区 310120 上海市 上海市 奉贤区 -310230 上海市 上海市 崇明县 +310230 上海市 上海城区 崇明区 320100 江苏省 南京市 南京市 320101 江苏省 南京市 南京市 320102 江苏省 南京市 玄武区 @@ -887,9 +887,9 @@ 320125 江苏省 南京市 高淳区 320200 江苏省 无锡市 无锡市 320201 江苏省 无锡市 无锡市 -320202 江苏省 无锡市 崇安区 -320203 江苏省 无锡市 南长区 -320204 江苏省 无锡市 北塘区 +320202 江苏省 无锡市 梁溪区 +320203 江苏省 无锡市 梁溪区 +320204 江苏省 无锡市 梁溪区 320205 江苏省 无锡市 锡山区 320206 江苏省 无锡市 惠山区 320211 江苏省 无锡市 滨湖区 @@ -911,7 +911,7 @@ 320401 江苏省 常州市 常州市 320402 江苏省 常州市 天宁区 320404 江苏省 常州市 钟楼区 -320405 江苏省 常州市 戚墅堰区 +320405 江苏省 常州市 武进区 320411 江苏省 常州市 新北区 320412 江苏省 常州市 武进区 320481 江苏省 常州市 溧阳市 @@ -940,7 +940,7 @@ 320700 江苏省 连云港市 连云港市 320701 江苏省 连云港市 连云港市 320703 江苏省 连云港市 连云区 -320705 江苏省 连云港市 新浦区 +320705 辽宁省 阜新市 海州区 320706 江苏省 连云港市 海州区 320721 江苏省 连云港市 赣榆区 320722 江苏省 连云港市 东海县 @@ -948,12 +948,12 @@ 320724 江苏省 连云港市 灌南县 320800 江苏省 淮安市 淮安市 320801 江苏省 淮安市 淮安市 -320802 江苏省 淮安市 清河区 -320803 江苏省 淮安市 淮安市区 +320802 江苏省 淮安市 清江浦区 +320803 江苏省 淮安市 淮安区 320804 江苏省 淮安市 淮阴区 -320811 江苏省 淮安市 清浦区 +320811 江苏省 淮安市 清江浦区 320826 江苏省 淮安市 涟水县 -320829 江苏省 淮安市 洪泽县 +320829 江苏省 淮安市 洪泽区 320830 江苏省 淮安市 盱眙县 320831 江苏省 淮安市 金湖县 320900 江苏省 盐城市 盐城市 @@ -966,7 +966,7 @@ 320924 江苏省 盐城市 射阳县 320925 江苏省 盐城市 建湖县 320981 江苏省 盐城市 东台市 -320982 江苏省 盐城市 大丰市 +320982 江苏省 盐城市 大丰区 321000 江苏省 扬州市 扬州市 321001 江苏省 扬州市 扬州市 321002 江苏省 扬州市 广陵区 @@ -1007,15 +1007,16 @@ 330108 浙江省 杭州市 滨江区 330109 浙江省 杭州市 萧山区 330110 浙江省 杭州市 余杭区 +330121 浙江省 杭州市 萧山区 330122 浙江省 杭州市 桐庐县 330127 浙江省 杭州市 淳安县 330182 浙江省 杭州市 建德市 330183 浙江省 杭州市 富阳区 -330185 浙江省 杭州市 临安市 +330185 浙江省 杭州市 临安区 330200 浙江省 宁波市 宁波市 330201 浙江省 宁波市 宁波市 330203 浙江省 宁波市 海曙区 -330204 浙江省 宁波市 江东区 +330204 浙江省 宁波市 鄞州区 330205 浙江省 宁波市 江北区 330206 浙江省 宁波市 北仑区 330211 浙江省 宁波市 镇海区 @@ -1024,7 +1025,7 @@ 330226 浙江省 宁波市 宁海县 330281 浙江省 宁波市 余姚市 330282 浙江省 宁波市 慈溪市 -330283 浙江省 宁波市 奉化市 +330283 浙江省 宁波市 奉化区 330300 浙江省 温州市 温州市 330301 浙江省 温州市 温州市 330302 浙江省 温州市 鹿城区 @@ -1057,7 +1058,7 @@ 330600 浙江省 绍兴市 绍兴市 330601 浙江省 绍兴市 绍兴市 330602 浙江省 绍兴市 越城区 -330621 浙江省 绍兴市 柯桥区 +330621 浙江省 绍兴市 绍兴市 330624 浙江省 绍兴市 新昌县 330681 浙江省 绍兴市 诸暨市 330682 浙江省 绍兴市 上虞区 @@ -1067,6 +1068,7 @@ 330702 浙江省 金华市 婺城区 330703 浙江省 金华市 金东区 330723 浙江省 金华市 武义县 +330725 浙江省 金华市 义乌市 330726 浙江省 金华市 浦江县 330727 浙江省 金华市 磐安县 330781 浙江省 金华市 兰溪市 @@ -1092,7 +1094,7 @@ 331002 浙江省 台州市 椒江区 331003 浙江省 台州市 黄岩区 331004 浙江省 台州市 路桥区 -331021 浙江省 台州市 玉环县 +331021 浙江省 台州市 玉环市 331022 浙江省 台州市 三门县 331023 浙江省 台州市 天台县 331024 浙江省 台州市 仙居县 @@ -1148,10 +1150,10 @@ 340421 安徽省 淮南市 凤台县 340500 安徽省 马鞍山市 马鞍山市 340501 安徽省 马鞍山市 马鞍山市 -340502 安徽省 马鞍山市 金家庄区 +340502 安徽省 马鞍山市 花山区 340503 安徽省 马鞍山市 花山区 340504 安徽省 马鞍山市 雨山区 -340505 安徽省 马鞍山市 向山区 +340505 安徽省 马鞍山市 花山区 340506 安徽省 马鞍山市 博望区 340521 安徽省 马鞍山市 当涂县 340522 安徽省 马鞍山市 含山县 @@ -1163,17 +1165,17 @@ 340621 安徽省 淮北市 濉溪县 340700 安徽省 铜陵市 铜陵市 340701 安徽省 铜陵市 铜陵市 -340702 安徽省 铜陵市 铜官山区 -340703 安徽省 铜陵市 狮子山区 +340702 安徽省 铜陵市 铜官区 +340703 安徽省 铜陵市 铜官区 340711 安徽省 铜陵市 郊区 -340721 安徽省 铜陵市 铜陵县 +340721 安徽省 铜陵市 铜陵市 340800 安徽省 安庆市 安庆市 340801 安徽省 安庆市 安庆市 340802 安徽省 安庆市 迎江区 340803 安徽省 安庆市 大观区 340811 安徽省 安庆市 宜秀区 340822 安徽省 安庆市 怀宁县 -340823 安徽省 安庆市 枞阳县 +340823 安徽省 铜陵市 枞阳县 340824 安徽省 安庆市 潜山县 340825 安徽省 安庆市 太湖县 340826 安徽省 安庆市 宿松县 @@ -1262,7 +1264,7 @@ 350125 福建省 福州市 永泰县 350128 福建省 福州市 平潭县 350181 福建省 福州市 福清市 -350182 福建省 福州市 长乐市 +350182 福建省 福州市 长乐区 350200 福建省 厦门市 厦门市 350201 福建省 厦门市 厦门市 350203 福建省 厦门市 思明区 @@ -1358,7 +1360,7 @@ 360104 江西省 南昌市 青云谱区 360105 江西省 南昌市 湾里区 360111 江西省 南昌市 青山湖区 -360121 江西省 南昌市 南昌市县 +360121 江西省 南昌市 南昌县 360122 江西省 南昌市 新建区 360123 江西省 南昌市 安义县 360124 江西省 南昌市 进贤县 @@ -1377,14 +1379,14 @@ 360323 江西省 萍乡市 芦溪县 360400 江西省 九江市 九江市 360401 江西省 九江市 九江市 -360402 江西省 九江市 庐山区 +360402 江西省 九江市 濂溪区 360403 江西省 九江市 浔阳区 -360421 江西省 九江市 九江县 +360421 江西省 九江市 九江市 360423 江西省 九江市 武宁县 360424 江西省 九江市 修水县 360425 江西省 九江市 永修县 360426 江西省 九江市 德安县 -360427 江西省 九江市 星子县 +360427 江西省 九江市 庐山市 360428 江西省 九江市 都昌县 360429 江西省 九江市 湖口县 360430 江西省 九江市 彭泽县 @@ -1402,7 +1404,7 @@ 360700 江西省 赣州市 赣州市 360701 江西省 赣州市 赣州市 360702 江西省 赣州市 章贡区 -360721 江西省 赣州市 赣县 +360721 江西省 赣州市 赣县区 360722 江西省 赣州市 信丰县 360723 江西省 赣州市 大余县 360724 江西省 赣州市 上犹县 @@ -1484,7 +1486,7 @@ 370124 山东省 济南市 平阴县 370125 山东省 济南市 济阳县 370126 山东省 济南市 商河县 -370181 山东省 济南市 章丘市 +370181 山东省 济南市 章丘区(章邱区) 370200 山东省 青岛市 青岛市 370201 山东省 青岛市 青岛市 370202 山东省 青岛市 市南区 @@ -1494,7 +1496,7 @@ 370213 山东省 青岛市 李沧区 370214 山东省 青岛市 城阳区 370281 山东省 青岛市 胶州市 -370282 山东省 青岛市 即墨市 +370282 山东省 青岛市 即墨区 370283 山东省 青岛市 平度市 370285 山东省 青岛市 莱西市 370300 山东省 淄博市 淄博市 @@ -1517,9 +1519,9 @@ 370481 山东省 枣庄市 滕州市 370500 山东省 东营市 东营市 370501 山东省 东营市 东营市 -370502 山东省 东营市 东营市区 +370502 山东省 东营市 东营区 370503 山东省 东营市 河口区 -370521 山东省 东营市 垦利县 +370521 山东省 东营市 垦利区 370522 山东省 东营市 利津县 370523 山东省 东营市 广饶县 370600 山东省 烟台市 烟台市 @@ -1552,7 +1554,7 @@ 370786 山东省 潍坊市 昌邑市 370800 山东省 济宁市 济宁市 370801 山东省 济宁市 济宁市 -370802 山东省 济宁市 市中区 +370802 山东省 济南市 市中区 370811 山东省 济宁市 任城区 370812 山东省 济宁市 兖州区 370826 山东省 济宁市 微山县 @@ -1665,7 +1667,7 @@ 410203 河南省 开封市 顺河回族区 410204 河南省 开封市 鼓楼区 410205 河南省 开封市 禹王台区 -410211 河南省 开封市 金明区 +410211 河南省 开封市 龙亭区 410212 河南省 开封市 祥符区 410221 河南省 开封市 杞县 410222 河南省 开封市 通许县 @@ -1706,7 +1708,7 @@ 410503 河南省 安阳市 北关区 410505 河南省 安阳市 殷都区 410506 河南省 安阳市 龙安区 -410522 河南省 安阳市 安阳市县 +410522 河南省 安阳市 安阳县 410523 河南省 安阳市 汤阴县 410526 河南省 安阳市 滑县 410527 河南省 安阳市 内黄县 @@ -1755,7 +1757,7 @@ 411000 河南省 许昌市 许昌市 411001 河南省 许昌市 许昌市 411002 河南省 许昌市 魏都区 -411023 河南省 许昌市 许昌县 +411023 河南省 许昌市 许昌市 411024 河南省 许昌市 鄢陵县 411025 河南省 许昌市 襄城县 411081 河南省 许昌市 禹州市 @@ -1837,7 +1839,7 @@ 411727 河南省 驻马店市 汝南县 411728 河南省 驻马店市 遂平县 411729 河南省 驻马店市 新蔡县 -419001 河南省 济源市 济源市 +419001 河南省 河南省 济源市 420100 湖北省 武汉市 武汉市 420101 湖北省 武汉市 武汉市 420102 湖北省 武汉市 江岸区 @@ -1962,10 +1964,10 @@ 422826 湖北省 恩施土家族苗族自治州 咸丰县 422827 湖北省 恩施土家族苗族自治州 来凤县 422828 湖北省 恩施土家族苗族自治州 鹤峰县 -429004 湖北省 仙桃市 仙桃市 -429005 湖北省 潜江市 潜江市 -429006 湖北省 天门市 天门市 -429021 湖北省 神农架林区 神农架林区 +429004 湖北省 湖北省 仙桃市 +429005 湖北省 湖北省 潜江市 +429006 湖北省 湖北省 天门市 +429021 湖北省 湖北省 神农架林区 430100 湖南省 长沙市 长沙市 430101 湖南省 长沙市 长沙市 430102 湖南省 长沙市 芙蓉区 @@ -1975,7 +1977,7 @@ 430111 湖南省 长沙市 雨花区 430112 湖南省 长沙市 望城区 430121 湖南省 长沙市 长沙县 -430124 湖南省 长沙市 宁乡县 +430124 湖南省 长沙市 宁乡市 430181 湖南省 长沙市 浏阳市 430200 湖南省 株洲市 株洲市 430201 湖南省 株洲市 株洲市 @@ -2053,7 +2055,7 @@ 430822 湖南省 张家界市 桑植县 430900 湖南省 益阳市 益阳市 430901 湖南省 益阳市 益阳市 -430902 湖南省 益阳市 资阳市区 +430902 湖南省 益阳市 资阳区 430903 湖南省 益阳市 赫山区 430921 湖南省 益阳市 南县 430922 湖南省 益阳市 桃江县 @@ -2252,7 +2254,7 @@ 441823 广东省 清远市 阳山县 441825 广东省 清远市 连山壮族瑶族自治县 441826 广东省 清远市 连南瑶族自治县 -441827 广东省 清远市 清新县 +441827 广东省 清远市 清新区 441881 广东省 清远市 英德市 441882 广东省 清远市 连州市 441900 广东省 东莞市 东莞市 @@ -2296,7 +2298,7 @@ 450203 广西壮族自治区 柳州市 鱼峰区 450204 广西壮族自治区 柳州市 柳南区 450205 广西壮族自治区 柳州市 柳北区 -450221 广西壮族自治区 柳州市 柳江县 +450221 广西壮族自治区 柳州市 柳江区 450222 广西壮族自治区 柳州市 柳城县 450223 广西壮族自治区 柳州市 鹿寨县 450224 广西壮族自治区 柳州市 融安县 @@ -2324,7 +2326,7 @@ 450400 广西壮族自治区 梧州市 梧州市 450401 广西壮族自治区 梧州市 梧州市 450403 广西壮族自治区 梧州市 万秀区 -450404 广西壮族自治区 梧州市 龙圩区 +450404 广西壮族自治区 梧州市 万秀区 450405 广西壮族自治区 梧州市 长洲区 450421 广西壮族自治区 梧州市 苍梧县 450422 广西壮族自治区 梧州市 藤县 @@ -2347,7 +2349,7 @@ 450702 广西壮族自治区 钦州市 钦南区 450703 广西壮族自治区 钦州市 钦北区 450721 广西壮族自治区 钦州市 灵山县 -450722 广西壮族自治区 钦州市 浦北区 +450722 广西壮族自治区 钦州市 浦北县 450800 广西壮族自治区 贵港市 贵港市 450801 广西壮族自治区 贵港市 贵港市 450802 广西壮族自治区 贵港市 港北区 @@ -2387,7 +2389,7 @@ 451201 广西壮族自治区 河池市 河池市 451202 广西壮族自治区 河池市 金城江区 451221 广西壮族自治区 河池市 南丹县 -451222 广西壮族自治区 河池市 天蛾县 +451222 广西壮族自治区 河池市 天峨县 451223 广西壮族自治区 河池市 凤山县 451224 广西壮族自治区 河池市 东兰县 451225 广西壮族自治区 河池市 罗城仫佬族自治县 @@ -2395,7 +2397,7 @@ 451227 广西壮族自治区 河池市 巴马瑶族自治县 451228 广西壮族自治区 河池市 都安瑶族自治县 451229 广西壮族自治区 河池市 大化瑶族自治县 -451281 广西壮族自治区 河池市 宜州市 +451281 广西壮族自治区 河池市 宜州区 451300 广西壮族自治区 来宾市 来宾市 451301 广西壮族自治区 来宾市 来宾市 451302 广西壮族自治区 来宾市 兴宾区 @@ -2425,21 +2427,21 @@ 460203 海南省 三亚市 吉阳区 460204 海南省 三亚市 天涯区 460205 海南省 三亚市 崖州区 -469001 海南省 五指山市 五指山市 -469002 海南省 琼海市 琼海市 +469001 海南省 海南省 五指山市 +469002 海南省 海南省 琼海市 469003 海南省 儋州市 儋州市 -469005 海南省 文昌市 文昌市 -469006 海南省 万宁市 万宁市 -469007 海南省 东方市 东方市 -469021 海南省 定安县 定安县 -469022 海南省 屯昌县 屯昌县 -469023 海南省 澄迈县 澄迈县 -469024 海南省 临高县 临高县 -469025 海南省 白沙黎族自治县 白沙黎族自治县 -469026 海南省 昌江黎族自治县 昌江黎族自治县 -469027 海南省 乐东黎族自治县 乐东黎族自治县 -469028 海南省 陵水黎族自治县 陵水黎族自治县 -469029 海南省 保亭黎族苗族自治县 保亭黎族苗族自治县 +469005 海南省 海南省 文昌市 +469006 海南省 海南省 万宁市 +469007 海南省 海南省 东方市 +469021 海南省 海南省 定安县 +469022 海南省 海南省 屯昌县 +469023 海南省 海南省 澄迈县 +469024 海南省 海南省 临高县 +469025 海南省 海南省 白沙黎族自治县 +469026 海南省 海南省 昌江黎族自治县 +469027 海南省 海南省 乐东黎族自治县 +469028 海南省 海南省 陵水黎族自治县 +469029 海南省 海南省 保亭黎族苗族自治县 469030 海南省 琼中黎族苗族自治县 琼中黎族苗族自治县 469031 海南省 三沙市 三沙市 469031 海南省 西沙群岛 西沙群岛 @@ -2456,7 +2458,7 @@ 500109 重庆市 重庆市 北碚区 500110 重庆市 重庆市 万盛区 500110 重庆市 重庆市 綦江区 -500111 重庆市 重庆市 双桥区 +500111 重庆市 重庆市 大足区 500111 重庆市 重庆市 大足区 500112 重庆市 重庆市 渝北区 500113 重庆市 重庆市 巴南区 @@ -2468,15 +2470,15 @@ 500119 重庆市 重庆市 南川区 500120 重庆市 重庆市 铜梁区 500121 重庆市 重庆市 璧山区 -500223 重庆市 重庆市 潼南区 -500226 重庆市 重庆市 荣昌区 -500228 重庆市 重庆市 梁平县 +500223 重庆市 重庆城区 潼南区 +500226 重庆市 重庆城区 荣昌区 +500228 重庆市 重庆城区 梁平区 500229 重庆市 重庆市 城口县 500230 重庆市 重庆市 丰都县 500231 重庆市 重庆市 垫江县 -500232 重庆市 重庆市 武隆县 +500232 重庆市 重庆城区 武隆区 500233 重庆市 重庆市 忠县 -500234 重庆市 重庆市 开县 +500234 重庆市 重庆城区 开州区 500235 重庆市 重庆市 云阳县 500236 重庆市 重庆市 奉节县 500237 重庆市 重庆市 巫山县 @@ -2497,8 +2499,8 @@ 510114 四川省 成都市 新都区 510115 四川省 成都市 温江区 510121 四川省 成都市 金堂县 -510122 四川省 成都市 双流县 -510124 四川省 成都市 郫县 +510122 四川省 成都市 双流区 +510124 四川省 成都市 郫都区 510129 四川省 成都市 大邑县 510131 四川省 成都市 蒲江县 510132 四川省 成都市 新津县 @@ -2544,7 +2546,7 @@ 510704 四川省 绵阳市 游仙区 510722 四川省 绵阳市 三台县 510723 四川省 绵阳市 盐亭县 -510724 四川省 绵阳市 安县 +510724 四川省 绵阳市 安州区 510725 四川省 绵阳市 梓潼县 510726 四川省 绵阳市 北川羌族自治县 510727 四川省 绵阳市 平武县 @@ -2571,7 +2573,7 @@ 511011 四川省 内江市 东兴区 511024 四川省 内江市 威远县 511025 四川省 内江市 资中县 -511028 四川省 内江市 隆昌县 +511028 四川省 内江市 隆昌市 511100 四川省 乐山市 乐山市 511101 四川省 乐山市 乐山市 511102 四川省 乐山市 市中区 @@ -2584,7 +2586,7 @@ 511129 四川省 乐山市 沐川县 511132 四川省 乐山市 峨边彝族自治县 511133 四川省 乐山市 马边彝族自治县 -511181 四川省 乐山市 峨眉山市市 +511181 四川省 乐山市 峨眉山市 511300 四川省 南充市 南充市 511301 四川省 南充市 南充市 511302 四川省 南充市 顺庆区 @@ -2655,13 +2657,13 @@ 512002 四川省 资阳市 雁江区 512021 四川省 资阳市 安岳县 512022 四川省 资阳市 乐至县 -512081 四川省 资阳市 简阳市 +512081 四川省 成都市 简阳市 513200 四川省 阿坝藏族羌族自治州 阿坝藏族羌族自治州 513221 四川省 阿坝藏族羌族自治州 汶川县 513222 四川省 阿坝藏族羌族自治州 理县 513223 四川省 阿坝藏族羌族自治州 茂县 513224 四川省 阿坝藏族羌族自治州 松潘县 -513225 四川省 阿坝藏族羌族自治州 九寨沟 +513225 四川省 阿坝藏族羌族自治州 九寨沟县 513226 四川省 阿坝藏族羌族自治州 金川县 513227 四川省 阿坝藏族羌族自治州 小金县 513228 四川省 阿坝藏族羌族自治州 黑水县 @@ -2721,7 +2723,7 @@ 520181 贵州省 贵阳市 清镇市 520200 贵州省 六盘水市 六盘水市 520201 贵州省 六盘水市 钟山区 -520202 贵州省 六盘水市 盘县特区 +520202 贵州省 六盘水市 盘州市 520203 贵州省 六盘水市 六枝特区 520221 贵州省 六盘水市 水城县 520222 贵州省 六盘水市 盘县 @@ -2781,21 +2783,21 @@ 522327 贵州省 黔西南布依族苗族自治州 册亨县 522328 贵州省 黔西南布依族苗族自治州 安龙县 522600 贵州省 黔东南布依族苗族自治州 黔东南布依族苗族自治州 -522601 贵州省 黔东南布依族苗族自治州 凯里市 -522622 贵州省 黔东南布依族苗族自治州 黄平县 -522623 贵州省 黔东南布依族苗族自治州 施秉县 -522624 贵州省 黔东南布依族苗族自治州 三穗县 -522626 贵州省 黔东南布依族苗族自治州 岑巩县 -522627 贵州省 黔东南布依族苗族自治州 天柱县 -522628 贵州省 黔东南布依族苗族自治州 锦屏县 -522629 贵州省 黔东南布依族苗族自治州 剑河县 +522601 贵州省 黔东南苗族侗族自治州 凯里市 +522622 贵州省 黔东南苗族侗族自治州 黄平县 +522623 贵州省 黔东南苗族侗族自治州 施秉县 +522624 贵州省 黔东南苗族侗族自治州 三穗县 +522626 贵州省 黔东南苗族侗族自治州 岑巩县 +522627 贵州省 黔东南苗族侗族自治州 天柱县 +522628 贵州省 黔东南苗族侗族自治州 锦屏县 +522629 贵州省 黔东南苗族侗族自治州 剑河县 522630 贵州省 黔东南布依族苗族自治州 台江县 -522631 贵州省 黔东南布依族苗族自治州 黎平县 -522632 贵州省 黔东南布依族苗族自治州 榕江县 -522633 贵州省 黔东南布依族苗族自治州 从江县 -522634 贵州省 黔东南布依族苗族自治州 雷山县 -522635 贵州省 黔东南布依族苗族自治州 麻江县 -522636 贵州省 黔东南布依族苗族自治州 丹寨县 +522631 贵州省 黔东南苗族侗族自治州 黎平县 +522632 贵州省 黔东南苗族侗族自治州 榕江县 +522633 贵州省 黔东南苗族侗族自治州 从江县 +522634 贵州省 黔东南苗族侗族自治州 雷山县 +522635 贵州省 黔东南苗族侗族自治州 麻江县 +522636 贵州省 黔东南苗族侗族自治州 丹寨县 522700 贵州省 黔南布依族苗族自治州 黔南布依族苗族自治州 522701 贵州省 黔南布依族苗族自治州 都匀市 522702 贵州省 黔南布依族苗族自治州 福泉市 @@ -2817,7 +2819,7 @@ 530112 云南省 昆明市 西山区 530113 云南省 昆明市 东川区 530121 云南省 昆明市 呈贡区 -530122 云南省 昆明市 晋宁县 +530122 云南省 昆明市 晋宁区 530124 云南省 昆明市 富民县 530125 云南省 昆明市 宜良县 530126 云南省 昆明市 石林彝族自治县 @@ -2834,7 +2836,7 @@ 530324 云南省 曲靖市 罗平县 530325 云南省 曲靖市 富源县 530326 云南省 曲靖市 会泽县 -530328 云南省 曲靖市 沾益县 +530328 云南省 曲靖市 沾益区 530381 云南省 曲靖市 宣威市 530400 云南省 玉溪市 玉溪市 530401 云南省 玉溪市 玉溪市 @@ -2922,8 +2924,8 @@ 532531 云南省 红河哈尼族彝族自治州 绿春县 532532 云南省 红河哈尼族彝族自治州 河口瑶族自治县 532600 云南省 文山壮族苗族自治州 文山壮族苗族自治州 -532601 云南省 文山壮族苗族自治州 文山壮族苗族自治州 -532621 云南省 文山壮族苗族自治州 文山县 +532601 云南省 文山壮族苗族自治州 文山市 +532621 云南省 文山壮族苗族自治州 文山市 532622 云南省 文山壮族苗族自治州 砚山县 532623 云南省 文山壮族苗族自治州 西畴县 532624 云南省 文山壮族苗族自治州 麻栗坡县 @@ -2955,7 +2957,7 @@ 533123 云南省 德宏傣族景颇族自治州 盈江县 533124 云南省 德宏傣族景颇族自治州 陇川县 533300 云南省 怒江傈僳族自治州 怒江傈僳族自治州 -533321 云南省 怒江傈僳族自治州 泸水县 +533321 云南省 怒江傈僳族自治州 泸水市 533323 云南省 怒江傈僳族自治州 福贡县 533324 云南省 怒江傈僳族自治州 贡山独龙族怒族自治县 533325 云南省 怒江傈僳族自治州 兰坪白族普米族自治县 @@ -2994,7 +2996,7 @@ 542226 西藏自治区 山南地区 曲松县 542227 西藏自治区 山南地区 措美县 542228 西藏自治区 山南地区 洛扎县 -542229 西藏自治区 山南地区 加查县 +542229 西藏自治区 山南市 加查县 542231 西藏自治区 山南地区 隆子县 542232 西藏自治区 山南地区 错那县 542233 西藏自治区 山南地区 浪卡子县 @@ -3024,7 +3026,7 @@ 542424 西藏自治区 那曲地区 聂荣县 542425 西藏自治区 那曲地区 安多县 542426 西藏自治区 那曲地区 申扎县 -542427 西藏自治区 那曲地区 索县 +542427 西藏自治区 那曲市 索县 542428 西藏自治区 那曲地区 班戈县 542429 西藏自治区 那曲地区 巴青县 542430 西藏自治区 那曲地区 尼玛县 @@ -3037,11 +3039,11 @@ 542526 西藏自治区 阿里地区 改则县 542527 西藏自治区 阿里地区 措勤县 542600 西藏自治区 林芝地区 林芝 -542621 西藏自治区 林芝地区 林芝县 +542621 西藏自治区 林芝市 林芝市 542622 西藏自治区 林芝地区 工布江达县 542623 西藏自治区 林芝地区 米林县 542624 西藏自治区 林芝地区 墨脱县 -542625 西藏自治区 林芝地区 波密县 +542625 西藏自治区 林芝市 波密县 542626 西藏自治区 林芝地区 察隅县 542627 西藏自治区 林芝地区 朗县 610100 陕西省 西安市 西安市 @@ -3057,7 +3059,7 @@ 610116 陕西省 西安市 长安区 610122 陕西省 西安市 蓝田县 610124 陕西省 西安市 周至县 -610125 陕西省 西安市 户县 +610125 陕西省 西安市 鄠邑区 610126 陕西省 西安市 高陵区 610200 陕西省 铜川市 铜川市 610201 陕西省 铜川市 铜川市 @@ -3098,7 +3100,7 @@ 610500 陕西省 渭南市 渭南市 610501 陕西省 渭南市 渭南市 610502 陕西省 渭南市 临渭区 -610521 陕西省 渭南市 华县 +610521 陕西省 渭南市 华州区 610522 陕西省 渭南市 潼关县 610523 陕西省 渭南市 大荔县 610524 陕西省 渭南市 合阳县 @@ -3114,7 +3116,7 @@ 610621 陕西省 延安市 延长县 610622 陕西省 延安市 延川县 610623 陕西省 延安市 子长县 -610624 陕西省 延安市 安塞县 +610624 陕西省 延安市 安塞区 610625 陕西省 延安市 志丹县 610626 陕西省 延安市 吴起县 610627 陕西省 延安市 甘泉县 @@ -3387,11 +3389,11 @@ 650204 新疆维吾尔自治区 克拉玛依市 白碱滩区 650205 新疆维吾尔自治区 克拉玛依市 乌尔禾区 652100 新疆维吾尔自治区 吐鲁番市 吐鲁番市 -652101 新疆维吾尔自治区 吐鲁番市 高昌区 +652101 新疆维吾尔自治区 吐鲁番市 吐鲁番市 652122 新疆维吾尔自治区 吐鲁番市 鄯善县 652123 新疆维吾尔自治区 吐鲁番市 托克逊县 652200 新疆维吾尔自治区 哈密地区 哈密地区 -652201 新疆维吾尔自治区 哈密地区 哈密市 +652201 新疆维吾尔自治区 哈密市 哈密市 652222 新疆维吾尔自治区 哈密地区 巴里坤哈萨克自治县 652223 新疆维吾尔自治区 哈密地区 伊吾县 652300 新疆维吾尔自治区 昌吉回族自治州 昌吉回族自治州 @@ -3418,70 +3420,1808 @@ 652828 新疆维吾尔自治区 巴音郭楞蒙古自治州 和硕县 652829 新疆维吾尔自治区 巴音郭楞蒙古自治州 博湖县 652900 新疆维吾尔自治区 阿克苏地区 阿克苏地区 -652901 新疆维吾尔自治区 阿克苏地区 阿克苏市 -652922 新疆维吾尔自治区 阿克苏地区 温宿县 +652901 新疆维吾尔自治区 阿克苏地区 阿克苏市 +652922 新疆维吾尔自治区 阿克苏地区 温宿县 652923 新疆维吾尔自治区 阿克苏地区 库车县 -652924 新疆维吾尔自治区 阿克苏地区 沙雅县 -652925 新疆维吾尔自治区 阿克苏地区 新和县 -652926 新疆维吾尔自治区 阿克苏地区 拜城县 -652927 新疆维吾尔自治区 阿克苏地区 乌什县 -652928 新疆维吾尔自治区 阿克苏地区 阿瓦提县 -652929 新疆维吾尔自治区 阿克苏地区 柯坪县 +652924 新疆维吾尔自治区 阿克苏地区 沙雅县 +652925 新疆维吾尔自治区 阿克苏地区 新和县 +652926 新疆维吾尔自治区 阿克苏地区 拜城县 +652927 新疆维吾尔自治区 阿克苏地区 乌什县 +652928 新疆维吾尔自治区 阿克苏地区 阿瓦提县 +652929 新疆维吾尔自治区 阿克苏地区 柯坪县 653000 新疆维吾尔自治区 克孜勒苏柯尔克孜自治州 克孜勒苏柯尔克孜自治州 -653001 新疆维吾尔自治区 克孜勒苏柯尔克孜自治州 阿图什市 -653022 新疆维吾尔自治区 克孜勒苏柯尔克孜自治州 阿克陶县 -653023 新疆维吾尔自治区 克孜勒苏柯尔克孜自治州 阿合奇县 -653024 新疆维吾尔自治区 克孜勒苏柯尔克孜自治州 乌恰县 +653001 新疆维吾尔自治区 克孜勒苏柯尔克孜自治州 阿图什市 +653022 新疆维吾尔自治区 克孜勒苏柯尔克孜自治州 阿克陶县 +653023 新疆维吾尔自治区 克孜勒苏柯尔克孜自治州 阿合奇县 +653024 新疆维吾尔自治区 克孜勒苏柯尔克孜自治州 乌恰县 653100 新疆维吾尔自治区 喀什地区 喀什地区 -653101 新疆维吾尔自治区 喀什地区 喀什市 -653121 新疆维吾尔自治区 喀什地区 疏附县 -653122 新疆维吾尔自治区 喀什地区 疏勒县 -653123 新疆维吾尔自治区 喀什地区 英吉沙县 -653124 新疆维吾尔自治区 喀什地区 泽普县 -653125 新疆维吾尔自治区 喀什地区 莎车县 -653126 新疆维吾尔自治区 喀什地区 叶城县 -653127 新疆维吾尔自治区 喀什地区 麦盖提县 -653128 新疆维吾尔自治区 喀什地区 岳普湖县 -653129 新疆维吾尔自治区 喀什地区 伽师县 +653101 新疆维吾尔自治区 喀什地区 喀什市 +653121 新疆维吾尔自治区 喀什地区 疏附县 +653122 新疆维吾尔自治区 喀什地区 疏勒县 +653123 新疆维吾尔自治区 喀什地区 英吉沙县 +653124 新疆维吾尔自治区 喀什地区 泽普县 +653125 新疆维吾尔自治区 喀什地区 莎车县 +653126 新疆维吾尔自治区 喀什地区 叶城县 +653127 新疆维吾尔自治区 喀什地区 麦盖提县 +653128 新疆维吾尔自治区 喀什地区 岳普湖县 +653129 新疆维吾尔自治区 喀什地区 伽师县 653130 新疆维吾尔自治区 喀什地区 巴楚县 -653131 新疆维吾尔自治区 喀什地区 塔什库尔干塔吉克自治县 +653131 新疆维吾尔自治区 喀什地区 塔什库尔干塔吉克自治县 653200 新疆维吾尔自治区 和田地区 和田地区 -653201 新疆维吾尔自治区 和田地区 和田市 -653221 新疆维吾尔自治区 和田地区 和田县 -653222 新疆维吾尔自治区 和田地区 墨玉县 -653223 新疆维吾尔自治区 和田地区 皮山县 -653224 新疆维吾尔自治区 和田地区 洛浦县 -653225 新疆维吾尔自治区 和田地区 策勒县 -653226 新疆维吾尔自治区 和田地区 于田县 -653227 新疆维吾尔自治区 和田地区 民丰县 +653201 新疆维吾尔自治区 和田地区 和田市 +653221 新疆维吾尔自治区 和田地区 和田县 +653222 新疆维吾尔自治区 和田地区 墨玉县 +653223 新疆维吾尔自治区 和田地区 皮山县 +653224 新疆维吾尔自治区 和田地区 洛浦县 +653225 新疆维吾尔自治区 和田地区 策勒县 +653226 新疆维吾尔自治区 和田地区 于田县 +653227 新疆维吾尔自治区 和田地区 民丰县 654000 新疆维吾尔自治区 伊犁哈萨克自治州 伊犁哈萨克自治州 -654002 新疆维吾尔自治区 伊犁哈萨克自治州 伊宁市 -654003 新疆维吾尔自治区 伊犁哈萨克自治州 奎屯市 -654021 新疆维吾尔自治区 伊犁哈萨克自治州 伊宁县 -654022 新疆维吾尔自治区 伊犁哈萨克自治州 察布查尔锡伯自治县 -654023 新疆维吾尔自治区 伊犁哈萨克自治州 霍城县 -654024 新疆维吾尔自治区 伊犁哈萨克自治州 巩留县 -654025 新疆维吾尔自治区 伊犁哈萨克自治州 新源县 -654026 新疆维吾尔自治区 伊犁哈萨克自治州 昭苏县 -654027 新疆维吾尔自治区 伊犁哈萨克自治州 特克斯县 -654028 新疆维吾尔自治区 伊犁哈萨克自治州 尼勒克县 +654002 新疆维吾尔自治区 伊犁哈萨克自治州 伊宁市 +654003 新疆维吾尔自治区 伊犁哈萨克自治州 奎屯市 +654021 新疆维吾尔自治区 伊犁哈萨克自治州 伊宁县 +654022 新疆维吾尔自治区 伊犁哈萨克自治州 察布查尔锡伯自治县 +654023 新疆维吾尔自治区 伊犁哈萨克自治州 霍城县 +654024 新疆维吾尔自治区 伊犁哈萨克自治州 巩留县 +654025 新疆维吾尔自治区 伊犁哈萨克自治州 新源县 +654026 新疆维吾尔自治区 伊犁哈萨克自治州 昭苏县 +654027 新疆维吾尔自治区 伊犁哈萨克自治州 特克斯县 +654028 新疆维吾尔自治区 伊犁哈萨克自治州 尼勒克县 654200 新疆维吾尔自治区 塔城地区 塔城地区 -654201 新疆维吾尔自治区 塔城地区 塔城市 -654202 新疆维吾尔自治区 塔城地区 乌苏市 -654221 新疆维吾尔自治区 塔城地区 额敏县 -654223 新疆维吾尔自治区 塔城地区 沙湾县 -654224 新疆维吾尔自治区 塔城地区 托里县 -654225 新疆维吾尔自治区 塔城地区 裕民县 -654226 新疆维吾尔自治区 塔城地区 和布克赛尔蒙古自治县 +654201 新疆维吾尔自治区 塔城地区 塔城市 +654202 新疆维吾尔自治区 塔城地区 乌苏市 +654221 新疆维吾尔自治区 塔城地区 额敏县 +654223 新疆维吾尔自治区 塔城地区 沙湾县 +654224 新疆维吾尔自治区 塔城地区 托里县 +654225 新疆维吾尔自治区 塔城地区 裕民县 +654226 新疆维吾尔自治区 塔城地区 和布克赛尔蒙古自治县 654300 新疆维吾尔自治区 阿勒泰地区 阿勒泰地区 -654301 新疆维吾尔自治区 阿勒泰地区 阿勒泰市 -654321 新疆维吾尔自治区 阿勒泰地区 布尔津县 -654322 新疆维吾尔自治区 阿勒泰地区 富蕴县 -654323 新疆维吾尔自治区 阿勒泰地区 福海县 -654324 新疆维吾尔自治区 阿勒泰地区 哈巴河县 -654325 新疆维吾尔自治区 阿勒泰地区 青河县 -654326 新疆维吾尔自治区 阿勒泰地区 吉木乃县 -659001 新疆维吾尔自治区 石河子市 石河子市 -659002 新疆维吾尔自治区 阿拉尔市 阿拉尔市 -659003 新疆维吾尔自治区 图木舒克市 图木舒克市 -659004 新疆维吾尔自治区 五家渠市 五家渠市 \ No newline at end of file +654301 新疆维吾尔自治区 阿勒泰地区 阿勒泰市 +654321 新疆维吾尔自治区 阿勒泰地区 布尔津县 +654322 新疆维吾尔自治区 阿勒泰地区 富蕴县 +654323 新疆维吾尔自治区 阿勒泰地区 福海县 +654324 新疆维吾尔自治区 阿勒泰地区 哈巴河县 +654325 新疆维吾尔自治区 阿勒泰地区 青河县 +654326 新疆维吾尔自治区 阿勒泰地区 吉木乃县 +659001 新疆维吾尔自治区 新疆维吾尔自治区 石河子市 +659002 新疆维吾尔自治区 新疆维吾尔自治区 阿拉尔市 +659003 新疆维吾尔自治区 新疆维吾尔自治区 图木舒克市 +659004 新疆维吾尔自治区 新疆维吾尔自治区 五家渠市 +110118 北京市 北京市 密云区 +110119 北京市 北京市 延庆区 +120117 天津市 天津市 宁河区 +120118 天津市 天津市 静海区 +120119 天津市 天津市 蓟州区 +130284 河北省 唐山市 滦州市 +130306 河北省 秦皇岛市 抚宁区 +130407 河北省 邯郸市 肥乡区 +130408 河北省 邯郸市 永年区 +130606 河北省 保定市 莲池区 +130607 河北省 保定市 满城区 +130608 河北省 保定市 清苑区 +130609 河北省 保定市 徐水区 +130708 河北省 张家口市 万全区 +130709 河北省 张家口市 崇礼区 +130881 河北省 承德市 平泉市 +131103 河北省 衡水市 冀州区 +140213 山西省 大同市 平城区 +140214 山西省 大同市 云冈区 +140215 山西省 大同市 云州区 +140403 山西省 长治市 潞州区 +140404 山西省 长治市 上党区 +140405 山西省 长治市 屯留区 +140406 山西省 长治市 潞城区 +140681 山西省 朔州市 怀仁市 +140703 山西省 晋中市 太谷区 +150603 内蒙古自治区 鄂尔多斯市 康巴什区 +210115 辽宁省 沈阳市 辽中区 +210214 辽宁省 大连市 普兰店区 +211104 辽宁省 盘锦市 大洼区 +220113 吉林省 长春市 九台区 +220781 吉林省 松原市 扶余市 +230717 黑龙江省 伊春市 伊美区 +230718 黑龙江省 伊春市 乌翠区 +230719 黑龙江省 伊春市 友好区 +230723 黑龙江省 伊春市 汤旺县 +230724 黑龙江省 伊春市 丰林县 +230725 黑龙江省 伊春市 大箐山县 +230726 黑龙江省 伊春市 南岔县 +230751 黑龙江省 伊春市 金林区 +230883 黑龙江省 佳木斯市 抚远市 +231086 黑龙江省 牡丹江市 东宁市 +231183 黑龙江省 黑河市 嫩江市 +310151 上海市 上海市 崇明区 +320117 江苏省 南京市 溧水区 +320118 江苏省 南京市 高淳区 +320213 江苏省 无锡市 梁溪区 +320214 江苏省 无锡市 新吴区 +320413 江苏省 常州市 金坛区 +320685 江苏省 南通市 海安市 +320707 江苏省 连云港市 赣榆区 +320812 江苏省 淮安市 清江浦区 +320813 江苏省 淮安市 洪泽区 +320904 江苏省 盐城市 大丰区 +321204 江苏省 泰州市 姜堰区 +330111 浙江省 杭州市 富阳区 +330112 浙江省 杭州市 临安区 +330213 浙江省 宁波市 奉化区 +330305 浙江省 温州市 洞头区 +330383 浙江省 温州市 龙港市 +330603 浙江省 绍兴市 柯桥区 +330604 浙江省 绍兴市 上虞区 +331083 浙江省 台州市 玉环市 +340281 安徽省 芜湖市 无为市 +340422 安徽省 淮南市 寿县 +340523 安徽省 马鞍山市 和县 +340705 安徽省 铜陵市 铜官区 +340706 安徽省 铜陵市 义安区 +340722 安徽省 铜陵市 枞阳县 +340882 安徽省 安庆市 潜山市 +341504 安徽省 六安市 叶集区 +341882 安徽省 宣城市 广德市 +350112 福建省 福州市 长乐区 +350803 福建省 龙岩市 永定区 +360112 江西省 南昌市 新建区 +360113 江西省 南昌市 红谷滩区 +360404 江西省 九江市 柴桑区 +360483 江西省 九江市 庐山市 +360603 江西省 鹰潭市 余江区 +360703 江西省 赣州市 南康区 +360704 江西省 赣州市 赣县区 +361003 江西省 抚州市 东乡区 +361103 江西省 上饶市 广丰区 +361104 江西省 上饶市 广信区 +370114 山东省 济南市 章丘区 +370115 山东省 济南市 济阳区 +370116 山东省 济南市 莱芜区 +370117 山东省 济南市 钢城区 +370215 山东省 青岛市 即墨区 +370505 山东省 东营市 垦利区 +371003 山东省 威海市 文登区 +371503 山东省 聊城市 茌平区 +371681 山东省 滨州市 邹平市 +371703 山东省 菏泽市 定陶区 +410783 河南省 新乡市 长垣市 +411003 河南省 许昌市 建安区 +411203 河南省 三门峡市 陕州区 +411603 河南省 周口市 淮阳区 +420304 湖北省 十堰市 郧阳区 +420882 湖北省 荆门市 京山市 +421303 湖北省 随州市 曾都区 +430182 湖南省 长沙市 宁乡市 +430212 湖南省 株洲市 渌口区 +430582 湖南省 邵阳市 邵东市 +440117 广东省 广州市 从化区 +440118 广东省 广州市 增城区 +440309 广东省 深圳市 龙华区 +440311 广东省 深圳市 光明区 +440904 广东省 茂名市 电白区 +441204 广东省 肇庆市 高要区 +441403 广东省 梅州市 梅县区 +441704 广东省 阳江市 阳东区 +441803 广东省 清远市 清新区 +445203 广东省 揭阳市 揭东区 +450206 广西壮族自治区 柳州市 柳江区 +450381 广西壮族自治区 桂林市 荔浦市 +450406 广西壮族自治区 梧州市 龙圩区 +450903 广西壮族自治区 玉林市 福绵区 +451003 广西壮族自治区 百色市 田阳区 +451081 广西壮族自治区 百色市 靖西市 +451082 广西壮族自治区 百色市 平果市 +451103 广西壮族自治区 贺州市 平桂区 +451203 广西壮族自治区 河池市 宜州区 +500151 重庆市 重庆市 铜梁区 +500152 重庆市 重庆市 潼南区 +500153 重庆市 重庆市 荣昌区 +500154 重庆市 重庆市 开州区 +500155 重庆市 重庆市 梁平区 +500156 重庆市 重庆市 武隆区 +510116 四川省 成都市 双流区 +510117 四川省 成都市 郫都区 +510185 四川省 成都市 简阳市 +510604 四川省 德阳市 罗江区 +510705 四川省 绵阳市 安州区 +510981 四川省 遂宁市 射洪市 +511083 四川省 内江市 隆昌市 +511504 四川省 宜宾市 叙州区 +511803 四川省 雅安市 名山区 +513201 四川省 阿坝藏族羌族自治州 马尔康市 +513301 四川省 甘孜藏族自治州 康定市 +520115 贵州省 贵阳市 观山湖区 +520281 贵州省 六盘水市 盘州市 +520304 贵州省 遵义市 播州区 +520403 贵州省 安顺市 平坝区 +522302 贵州省 黔西南布依族苗族自治州 兴仁市 +522625 贵州省 黔东南苗族侗族自治州 镇远县 +530114 云南省 昆明市 呈贡区 +530115 云南省 昆明市 晋宁区 +530303 云南省 曲靖市 沾益区 +530304 云南省 曲靖市 马龙区 +530403 云南省 玉溪市 江川区 +530481 云南省 玉溪市 澄江市 +530581 云南省 保山市 腾冲市 +530681 云南省 昭通市 水富市 +532504 云南省 红河哈尼族彝族自治州 弥勒市 +533301 云南省 怒江傈僳族自治州 泸水市 +533401 云南省 迪庆藏族自治州 香格里拉市 +540103 西藏自治区 拉萨市 堆龙德庆区 +540104 西藏自治区 拉萨市 达孜区 +540202 西藏自治区 日喀则市 桑珠孜区 +540221 西藏自治区 日喀则市 南木林县 +540222 西藏自治区 日喀则市 江孜县 +540223 西藏自治区 日喀则市 定日县 +540224 西藏自治区 日喀则市 萨迦县 +540225 西藏自治区 日喀则市 拉孜县 +540226 西藏自治区 日喀则市 昂仁县 +540227 西藏自治区 日喀则市 谢通门县 +540228 西藏自治区 日喀则市 白朗县 +540229 西藏自治区 日喀则市 仁布县 +540231 西藏自治区 日喀则市 定结县 +540232 西藏自治区 日喀则市 仲巴县 +540233 西藏自治区 日喀则市 亚东县 +540234 西藏自治区 日喀则市 吉隆县 +540235 西藏自治区 日喀则市 聂拉木县 +540236 西藏自治区 日喀则市 萨嘎县 +540237 西藏自治区 日喀则市 岗巴县 +540302 西藏自治区 昌都市 卡若区 +540321 西藏自治区 昌都市 江达县 +540322 西藏自治区 昌都市 贡觉县 +540323 西藏自治区 昌都市 类乌齐县 +540324 西藏自治区 昌都市 丁青县 +540325 西藏自治区 昌都市 察雅县 +540326 西藏自治区 昌都市 八宿县 +540327 西藏自治区 昌都市 左贡县 +540328 西藏自治区 昌都市 芒康县 +540329 西藏自治区 昌都市 洛隆县 +540402 西藏自治区 林芝市 巴宜区 +540421 西藏自治区 林芝市 工布江达县 +540422 西藏自治区 林芝市 米林县 +540423 西藏自治区 林芝市 墨脱县 +540424 西藏自治区 林芝市 波密县 +540425 西藏自治区 林芝市 察隅县 +540426 西藏自治区 林芝市 朗县 +540502 西藏自治区 山南市 乃东区 +540521 西藏自治区 山南市 扎囊县 +540522 西藏自治区 山南市 贡嘎县 +540523 西藏自治区 山南市 桑日县 +540524 西藏自治区 山南市 琼结县 +540525 西藏自治区 山南市 曲松县 +540526 西藏自治区 山南市 措美县 +540527 西藏自治区 山南市 洛扎县 +540528 西藏自治区 山南市 加查县 +540529 西藏自治区 山南市 隆子县 +540531 西藏自治区 山南市 浪卡子县 +540602 西藏自治区 那曲市 色尼区 +540621 西藏自治区 那曲市 嘉黎县 +540622 西藏自治区 那曲市 比如县 +540623 西藏自治区 那曲市 聂荣县 +540624 西藏自治区 那曲市 安多县 +540625 西藏自治区 那曲市 申扎县 +540626 西藏自治区 那曲市 索县 +540627 西藏自治区 那曲市 班戈县 +540628 西藏自治区 那曲市 巴青县 +540629 西藏自治区 那曲市 尼玛县 +610117 陕西省 西安市 高陵区 +610118 陕西省 西安市 鄠邑区 +610482 陕西省 咸阳市 彬州市 +610503 陕西省 渭南市 华州区 +610603 陕西省 延安市 安塞区 +610681 陕西省 延安市 子长市 +610703 陕西省 汉中市 南郑区 +610803 陕西省 榆林市 横山区 +610881 陕西省 榆林市 神木市 +620881 甘肃省 平凉市 华亭市 +630106 青海省 西宁市 湟中区 +630202 青海省 海东市 乐都区 +630203 青海省 海东市 平安区 +630222 青海省 海东市 民和回族土族自治县 +630223 青海省 海东市 互助土族自治县 +630224 青海省 海东市 化隆回族自治县 +630225 青海省 海东市 循化撒拉族自治县 +632803 青海省 海西蒙古族藏族自治州 茫崖市 +650402 新疆维吾尔自治区 吐鲁番市 高昌区 +650421 新疆维吾尔自治区 吐鲁番市 鄯善县 +650422 新疆维吾尔自治区 吐鲁番市 托克逊县 +650502 新疆维吾尔自治区 哈密市 伊州区 +650521 新疆维吾尔自治区 哈密市 巴里坤哈萨克自治县 +650522 新疆维吾尔自治区 哈密市 伊吾县 +652902 新疆维吾尔自治区 阿克苏地区 库车市 +654004 新疆维吾尔自治区 伊犁哈萨克自治州 霍尔果斯市 +659005 新疆维吾尔自治区 新疆维吾尔自治区 北屯市 +659006 新疆维吾尔自治区 新疆维吾尔自治区 铁门关市 +659007 新疆维吾尔自治区 新疆维吾尔自治区 双河市 +659008 新疆维吾尔自治区 新疆维吾尔自治区 可克达拉市 +659009 新疆维吾尔自治区 新疆维吾尔自治区 昆玉市 +152823 内蒙古自治区 巴彦淖尔市 磴口县 +830000 台湾省(非国标,用于身份证) 台湾省(非国标,用于身份证) 台湾省(非国标,用于身份证) +810000 香港特别行政区 香港特别行政区 香港特别行政区 +513525 重庆市 重庆市区 酉阳土家族苗族自治县 +513524 重庆市 重庆市区 酉阳土家族苗族自治县 +513522 重庆市 重庆市区 秀山土家族苗族自治县 +512323 重庆市 重庆市区 南川区 +512301 重庆市 重庆市区 涪陵区 +510229 重庆市 县 永川区 +510226 重庆市 县 合川区 +510225 重庆市 县 江津区 +510219 重庆市 县 巴南区 +450106 广西壮族自治区 南宁市 南宁市 +450000 广西壮族自治区 广西壮族自治区 广西壮族自治区 +440505 广东省 汕头市 汕头市 +440503 广东省 汕头市 汕头市 +419003 河南省 省直辖县级行政区划 省直辖县级行政区划 +410881 河南省 焦作市 焦作市 +320503 江苏省 苏州市 苏州市 +140102 山西省 太原市 太原市 +130206 河北省 唐山市 唐山市 +620202 甘肃省 嘉峪关市 嘉峪关市 +511237 四川省 万州区 万州区 +510925 四川省 遂宁市 遂宁市 +500215 重庆市 县 县 +450525 广西壮族自治区 北海市 北海市 +411008 河南省 许昌市 许昌市 +363529 江西省 江西省 江西省 +360527 江西省 新余市(新渝市) 新余市(新渝市) +360181 江西省 南昌市 南昌市 +342628 安徽省 合肥市 合肥市 +332326 浙江省 绍兴市 绍兴市 +330709 浙江省 金华市 金华市 +330705 浙江省 金华市 金华市 +330524 浙江省 湖州市 湖州市 +224017 吉林省 吉林省 吉林省 +120164 天津市 市辖区 市辖区 +654222 新疆维吾尔自治区 伊犁哈萨克自治州 乌苏市 +654127 新疆维吾尔自治区 伊犁哈萨克自治州 特克斯县 +652427 新疆维吾尔自治区 伊犁哈萨克自治州 特克斯县 +654128 新疆维吾尔自治区 伊犁哈萨克自治州 尼勒克县 +654123 新疆维吾尔自治区 伊犁哈萨克自治州 霍城县 +654122 新疆维吾尔自治区 伊犁哈萨克自治州 察布查尔锡伯自治县 +654121 新疆维吾尔自治区 伊犁哈萨克自治州 伊宁市 +654101 新疆维吾尔自治区 伊犁哈萨克自治州 伊宁市 +652523 新疆维吾尔自治区 伊犁哈萨克自治州 乌苏市 +652428 新疆维吾尔自治区 伊犁哈萨克自治州 尼勒克县 +652423 新疆维吾尔自治区 伊犁哈萨克自治州 霍城县 +652422 新疆维吾尔自治区 伊犁哈萨克自治州 察布查尔锡伯自治县 +652421 新疆维吾尔自治区 伊犁哈萨克自治州 伊宁市 +652401 新疆维吾尔自治区 伊犁哈萨克自治州 伊宁市 +652322 新疆维吾尔自治区 乌鲁木齐市 米东区 +650108 新疆维吾尔自治区 乌鲁木齐市 米东区 +642124 宁夏回族自治区 中卫市 中宁县 +642123 宁夏回族自治区 中卫市 沙坡头区 +642103 宁夏回族自治区 银川市 灵武市 +640382 宁夏回族自治区 银川市 灵武市 +640322 宁夏回族自治区 中卫市 中宁县 +640321 宁夏回族自治区 中卫市 沙坡头区 +640222 宁夏回族自治区 石嘴山市 平罗县 +640211 宁夏回族自治区 石嘴山市 惠农区 +640204 宁夏回族自治区 石嘴山市 大武口区 +640111 宁夏回族自治区 银川市 兴庆区 +640103 宁夏回族自治区 银川市 金凤区 +640102 宁夏回族自治区 银川市 西夏区 +612729 陕西省 榆林市 佳县(葭县) +612525 陕西省 商洛市(商雒市) 山阳县 +612522 陕西省 商洛市(商雒市) 洛南县(雒南县) +612429 陕西省 安康市 旬阳县(洵阳县) +612325 陕西省 汉中市 勉县(沔县) +610221 陕西省 铜川市 耀州区 +610121 河北省 石家庄市 长安区 +533221 云南省 丽江市 古城区 +530123 云南省 昆明市 安宁市 +522526 贵州省 安顺市 平坝区 +522132 贵州省 遵义市 习水县(鳛水县) +522126 贵州省 遵义市 务川仡佬族苗族自治县(婺川仡佬族苗族自治县) +513922 四川省 资阳市 乐至县 +513921 四川省 资阳市 安岳县 +513902 四川省 成都市 简阳市 +513901 四川省 资阳市 资阳市 +513824 四川省 眉山市 洪雅县 +513823 四川省 眉山市 彭山区 +513822 四川省 眉山市 仁寿县 +513821 四川省 眉山市 东坡区 +513723 四川省 巴中市 平昌县 +513722 四川省 巴中市 南江县 +513721 四川省 巴中市 通江县 +513624 四川省 广安市 邻水县 +513623 四川省 广安市 武胜县 +513622 四川省 广安市 岳池县 +513621 四川省 广安市 广安区 +513601 四川省 广安市 华蓥市 +513523 重庆市 重庆城区 黔江区 +513521 重庆市 县 石柱土家族自治县(石砫土家族自治县) +513031 四川省 广安市 邻水县 +513028 四川省 巴中市 平昌县 +513026 四川省 巴中市 南江县 +513025 四川省 巴中市 通江县 +513021 四川省 达州市 达川区 +512928 四川省 广安市 武胜县 +512925 四川省 广安市 广安区 +512923 四川省 广安市 岳池县 +512902 四川省 广安市 华蓥市 +512528 四川省 宜宾市 南溪区 +512326 重庆市 重庆城区 武隆区 +512324 重庆市 县 丰都县(酆都县) +512228 重庆市 县 巫溪县 +512227 重庆市 县 巫山县 +512226 重庆市 县 奉节县 +512225 重庆市 县 云阳县 +512224 重庆市 重庆城区 梁平区 +512223 重庆市 县 忠县 +512222 重庆市 重庆城区 开州区 +512221 重庆市 重庆城区 万州区 +512201 重庆市 重庆城区 万州区 +512327 重庆市 县 彭水苗族土家族自治县 +512329 重庆市 县 酉阳土家族苗族自治县 +512330 重庆市 县 秀山土家族苗族自治县 +512322 重庆市 县 垫江县 +511228 重庆市 县 城口县 +511522 四川省 宜宾市 南溪区 +511227 重庆市 县 巫溪县 +511226 重庆市 县 巫山县 +511225 重庆市 县 奉节县 +511224 重庆市 县 云阳县 +511223 重庆市 重庆城区 梁平区 +511222 重庆市 县 忠县 +511221 重庆市 重庆城区 开州区 +511204 重庆市 重庆城区 万州区 +511203 重庆市 重庆城区 万州区 +511202 重庆市 重庆城区 万州区 +511128 四川省 眉山市 彭山区 +511127 四川省 眉山市 洪雅县 +511122 四川省 眉山市 东坡区 +511121 四川省 眉山市 仁寿县 +511081 四川省 资阳市 资阳市 +511026 四川省 资阳市 雁江区 +511023 四川省 资阳市 安岳县 +511022 四川省 资阳市 乐至县 +510902 四川省 遂宁市 船山区 +510702 四川省 绵阳市 涪城区 +510602 四川省 德阳市 旌阳区 +510283 重庆市 重庆城区 合川区 +510282 重庆市 重庆城区 江津区 +510281 重庆市 重庆城区 永川区 +510232 重庆市 重庆城区 璧山区 +510231 重庆市 重庆城区 荣昌区 +510230 重庆市 重庆城区 大足区 +510228 重庆市 重庆城区 铜梁区 +510227 重庆市 重庆城区 潼南区 +510224 浙江省 宁波市 江北区 +510223 重庆市 重庆城区 綦江区 +510222 重庆市 重庆城区 巴南区 +510221 重庆市 重庆城区 长寿区 +510216 重庆市 重庆城区 綦江区 +510215 重庆市 重庆城区 北碚区 +510214 重庆市 重庆城区 南岸区 +510213 重庆市 重庆城区 九龙坡区 +510212 重庆市 重庆城区 沙坪坝区 +510202 重庆市 重庆城区 渝中区 +510211 浙江省 宁波市 江北区 +510103 四川省 成都市 青羊区 +510102 四川省 成都市 锦江区 +510128 四川省 成都市 崇州市 +510126 四川省 成都市 彭州市 +500383 重庆市 重庆城区 永川区 +500382 重庆市 重庆城区 合川区 +500381 重庆市 重庆城区 江津区 +500239 重庆市 重庆城区 黔江区 +500227 重庆市 重庆城区 璧山区 +500225 重庆市 重庆城区 大足区 +500224 重庆市 重庆城区 铜梁区 +500222 重庆市 重庆城区 綦江区 +500221 重庆市 重庆城区 长寿区 +460102 海南省 海口市 美兰区 +460029 海南省 儋州市 儋州市 +460001 海南省 儋州市 五指山市 +452722 广西壮族自治区 河池市 宜州区 +452702 广西壮族自治区 河池市 宜州区 +452522 广西壮族自治区 贵港市 贵港市 +452501 广西壮族自治区 玉林市(鬱林市/郁林市) 玉林市(鬱林市/郁林市) +452427 广西壮族自治区 贺州市 钟山县(锺山县) +452426 广西壮族自治区 贺州市 八步区 +452324 广西壮族自治区 桂林市 兴安县 +450211 广西壮族自治区 柳州市 城中区 +450104 广西壮族自治区 南宁市 西乡塘区 +445223 广东省 揭阳市 普宁市 +442830 广东省 云浮市 罗定市 +442821 广东省 肇庆市 高要区 +441824 广东省 清远市 连州市 +441722 广东省 阳江市 阳春市 +441611 广东省 河源市 东源县 +441425 广东省 梅州市 兴宁市 +441230 广东省 云浮市 罗定市 +441228 广东省 云浮市 新兴县 +441221 广东省 肇庆市 高要区 +440824 广东省 湛江市 雷州市 +440727 广东省 阳江市 阳春市 +440725 广东省 江门市 鹤山市 +440724 广东省 江门市 开平市 +440620 广东省 东莞市 中山市 +440603 广东省 佛山市 禅城区 +440602 广东省 佛山市 禅城区 +440527 广东省 揭阳市 普宁市 +440510 广东省 汕头市 濠江区 +440509 广东省 汕头市 金平区 +440508 广东省 汕头市 金平区 +440506 广东省 汕头市 濠江区 +440504 广东省 汕头市 金平区 +440502 广东省 汕头市 金平区 +440202 广东省 韶关市 浈江区 +440121 广东省 广州市 花都区 +440102 广东省 广州市 越秀区 +432222 湖南省 岳阳市 平江县 +433021 湖南省 怀化市 洪江市 +432922 湖南省 永州市 东安县 +432623 湖南省 邵阳市 武冈市 +432621 湖南省 邵阳市 邵阳县 +430526 湖南省 邵阳市 武冈市 +430411 湖南省 衡阳市 蒸湘区 +430404 湖南省 衡阳市 石鼓区 +430403 湖南省 衡阳市 雁峰区 +430402 湖南省 衡阳市 珠晖区 +430303 湖南省 湘潭市 雨湖区 +429001 湖北省 随州市 随州市 +422726 湖北省 宜昌市 兴山县 +422723 湖北省 宜昌市 枝江市 +422721 湖北省 宜昌市 夷陵区 +422701 湖北省 宜昌市 宜都市 +422622 湖北省 十堰市 郧阳区 +422431 湖北省 荆门市 钟祥市(锺祥市) +422427 湖北省 省直辖县级行政区划_恩施土家族苗族自治州 仙桃市 +422421 湖北省 荆州市 江陵县 +422406 湖北省 荆门市 钟祥市(锺祥市) +422400 湖北省 荆州市 荆州市 +422323 湖北省 咸宁市 赤壁市 +422302 湖北省 咸宁市 赤壁市 +422224 湖北省 随州市 广水市 +422204 湖北省 随州市 广水市 +422129 湖北省 黄冈市 武穴市 +421004 湖北省 荆州市 江陵县 +420983 湖北省 随州市 广水市 +420619 湖北省 随州市 随州市 +420605 湖北省 襄阳市 襄城区 +420603 湖北省 襄阳市 襄城区 +420523 湖北省 宜昌市 枝江市 +420521 湖北省 宜昌市 夷陵区 +412930 河南省 南阳市 邓州市 +412728 河南省 周口市 沈丘县(沈邱县) +412322 河南省 商丘市(商邱市) 商丘市(商邱市) +412301 河南省 商丘市(商邱市) 商丘市(商邱市) +410826 河南省 焦作市 孟州市 +410521 河南省 安阳市 林州市 +410511 河南省 安阳市 龙安区 +410504 河南省 安阳市 殷都区 +410426 河南省 许昌市 襄城县 +410424 江西省 抚州市 临川区 +410112 河南省 郑州市 金水区 +372823 山东省 临沂市 兰陵县 +371421 山东省 德州市 陵城区 +371021 山东省 威海市 乳山市 +370825 山东省 济宁市 邹城市 +370722 山东省 潍坊市 安丘市(安邱市) +370721 山东省 潍坊市 青州市 +370630 山东省 威海市 乳山市 +370628 山东省 烟台市 栖霞市 +370623 山东省 烟台市 龙口市 +370421 山东省 枣庄市 滕州市 +370284 山东省 青岛市 黄岛区 +370224 山东省 青岛市 胶州市 +370206 山东省 青岛市 李沧区 +370205 山东省 青岛市 市北区 +370122 山东省 济南市 章丘区(章邱区) +370111 山东省 济南市 历城区 +362432 江西省 吉安市 井冈山市 +362424 江西省 吉安市 新干县(新淦县) +362421 江西省 吉安市 吉安县 +362401 江西省 吉安市 吉安市 +362330 江西省 上饶市 鄱阳县 +362327 江西省 鹰潭市 贵溪市 +362223 江西省 宜春市 樟树市 +362132 江西省 赣州市 于都县(雩都县) +362130 江西省 赣州市 全南县(虔南县) +362124 江西省 赣州市 大余县(大庾县) +362121 江西省 赣州市 赣县区 +362103 江西省 赣州市 南康区 +360621 江西省 鹰潭市 贵溪市 +360212 江西省 景德镇市 浮梁县 +360211 江西省 景德镇市 浮梁县 +359001 福建省 三明市 永安市 +352623 福建省 龙岩市 永定区 +352100 福建省 南平市 南平市 +350420 福建省 三明市 永安市 +350204 福建省 厦门市 思明区 +342923 安徽省 池州市 青阳县 +342922 安徽省 池州市 石台县(石埭县) +342921 安徽省 池州市 东至县 +342829 安徽省 池州市 东至县 +342823 安徽省 铜陵市 枞阳县 +342822 安徽省 安庆市 桐城市 +342728 安徽省 池州市 石台县(石埭县) +342721 安徽省 宣城市 绩溪县 +342700 安徽省 黄山市 黄山市 +342531 安徽省 宣城市 绩溪县 +342327 安徽省 滁州市 明光市 +342223 安徽省 宿州市 埇桥区 +342130 安徽省 亳州市 利辛县 +342126 安徽省 亳州市 亳州市 +342125 安徽省 亳州市 蒙城县 +342124 安徽省 亳州市 涡阳县 +342123 安徽省 阜阳市 太和县 +341227 安徽省 亳州市 利辛县 +341224 安徽省 亳州市 蒙城县 +341223 安徽省 亳州市 涡阳县 +341127 安徽省 滁州市 明光市 +340821 安徽省 安庆市 桐城市 +340224 安徽省 池州市 青阳县 +340211 安徽省 芜湖市 镜湖区 +340205 安徽省 芜湖市 鸠江区 +340204 安徽省 芜湖市 镜湖区 +332627 浙江省 台州市 玉环市 +330821 浙江省 衢州市 衢江区 +330623 浙江省 绍兴市 嵊州市 +330511 浙江省 湖州市 湖州市 +330227 浙江省 宁波市 鄞州区 +330107 浙江省 杭州市 拱墅区 +321087 江苏省 泰州市 姜堰区 +321082 江苏省 泰州市 泰州市 +321028 江苏省 泰州市 姜堰区 +321020 江苏省 泰州市 泰州市 +321011 江苏省 扬州市 邗江区 +320911 江苏省 盐城市 盐都区 +320882 江苏省 淮安市 淮安市 +320881 江苏省 宿迁市 宿迁市 +320828 江苏省 淮安市 淮安区 +320819 江苏省 宿迁市 宿迁市 +320704 江苏省 连云港市 连云区 +320683 北京市 北京城区 通州区 +320586 江苏省 苏州市 吴中区 +320524 江苏省 苏州市 吴中区 +320521 江苏省 苏州市 张家港市 +320511 江苏省 苏州市 虎丘区 +320504 江苏省 苏州市 姑苏区 +320502 江苏省 苏州市 姑苏区 +320325 江苏省 徐州市 邳州市 +320304 江苏省 徐州市 铜山区 +320122 江苏省 南京市 浦口区 +320112 江苏省 南京市 六合区 +320107 江苏省 南京市 鼓楼区 +320103 江苏省 南京市 秦淮区 +310225 上海市 上海城区 浦东新区 +310224 上海市 上海城区 浦东新区 +310223 黑龙江省 双鸭山市 宝山区 +310111 黑龙江省 双鸭山市 宝山区 +310103 上海市 上海城区 黄浦区 +310102 上海市 上海城区 黄浦区 +239005 黑龙江省 伊春市 铁力市(铁骊市) +232724 黑龙江省 大兴安岭地区 漠河市 +232623 黑龙江省 黑河市 五大连池市 +232101 黑龙江省 哈尔滨市 双城区 +231011 黑龙江省 牡丹江市 东安区 +230802 山西省 阳泉市 郊区 +230105 黑龙江省 哈尔滨市 道外区 +230182 黑龙江省 哈尔滨市 双城区 +230181 黑龙江省 哈尔滨市 阿城区 +230119 黑龙江省 哈尔滨市 阿城区 +230107 黑龙江省 哈尔滨市 香坊区 +229005 吉林省 长春市 九台区 +229002 吉林省 通化市 梅河口市 +222304 吉林省 白城市 大安市 +220603 吉林省 白山市 江源区 +220519 吉林省 通化市 梅河口市 +220111 吉林省 长春市 绿园区 +211203 辽宁省 铁岭市 调兵山市 +211111 辽宁省 盘锦市 盘山县 +210824 辽宁省 营口市 盖州市 +210724 辽宁省 锦州市 凌海市 +210623 辽宁省 丹东市 东港市 +210621 辽宁省 丹东市 凤城市 +210319 辽宁省 鞍山市 海城市 +210222 辽宁省 大连市 普兰店区 +210221 辽宁省 大连市 金州区 +152126 内蒙古自治区 呼伦贝尔市 根河市 +152125 内蒙古自治区 呼伦贝尔市 额尔古纳市 +142128 山西省 朔州市 朔城区 +140511 山西省 晋城市 泽州县 +140104 山西省 太原市 万柏林区 +140103 山西省 太原市 杏花岭区 +133025 河北省 衡水市 深州市 +133022 河北省 衡水市 冀州区 +132903 河北省 沧州市 任丘市(任邱市) +132827 河北省 廊坊市 霸州市 +132624 河北省 承德市 平泉市 +132531 河北省 张家口市 宣化区 +132528 河北省 张家口市 万全区 +132439 河北省 保定市 定州市 +132423 河北省 保定市 徐水区 +132322 河北省 石家庄市 晋州市 +132321 河北省 石家庄市 辛集市 +132302 河北省 石家庄市 藁城区 +132227 河北省 邢台市 任泽区 +132133 河北省 邯郸市 永年区 +132126 河北省 邯郸市 肥乡区 +132124 河北省 邯郸市 邱县 +130904 河北省 沧州市 运河区 +130605 河北省 保定市 莲池区 +130182 河北省 石家庄市 藁城区 +130122 河北省 石家庄市 鹿泉区 +130106 河北省 张家口市 桥东区 +120109 天津市 天津城区 滨海新区 +120107 天津市 天津城区 滨海新区 +110223 北京市 北京城区 通州区 +654126 新疆维吾尔自治区 伊犁哈萨克自治州 昭苏县 +654125 新疆维吾尔自治区 伊犁哈萨克自治州 新源县 +654124 新疆维吾尔自治区 伊犁哈萨克自治州 巩留县 +654001 新疆维吾尔自治区 伊犁哈萨克自治州 奎屯市 +653021 新疆维吾尔自治区 克孜勒苏柯尔克孜自治州 阿图什市 +652721 新疆维吾尔自治区 博尔塔拉蒙古自治州 博乐市 +652522 新疆维吾尔自治区 伊犁哈萨克自治州 额敏县 +652326 新疆维吾尔自治区 昌吉回族自治州 阜康市 +650300 新疆维吾尔自治区 自治区直辖县级行政区划 石河子市 +642226 宁夏回族自治区 固原市 彭阳县 +642225 宁夏回族自治区 固原市 泾源县 +642224 宁夏回族自治区 固原市 隆德县 +642223 宁夏回族自治区 固原市 西吉县 +642222 宁夏回族自治区 中卫市 海原县 +642221 宁夏回族自治区 固原市 固原市 +642127 宁夏回族自治区 吴忠市 同心县 +642125 宁夏回族自治区 银川市 灵武市 +642102 宁夏回族自治区 吴忠市 青铜峡市 +642101 宁夏回族自治区 吴忠市 吴忠市 +640223 宁夏回族自治区 石嘴山市 惠农区 +640203 宁夏回族自治区 石嘴山市 石嘴山市 +632421 青海省 黄南藏族自治州 河南蒙古族自治县 +632124 青海省 西宁市 湟中区 +632123 青海省 海东市 乐都区 +622827 甘肃省 庆阳市 镇原县 +622826 甘肃省 庆阳市 宁县 +622825 甘肃省 庆阳市 正宁县 +622824 甘肃省 庆阳市 合水县 +622823 甘肃省 庆阳市 华池县 +622822 甘肃省 庆阳市 环县 +622821 甘肃省 庆阳市 庆阳市 +622801 甘肃省 庆阳市 西峰区 +622727 甘肃省 平凉市 静宁县 +622726 甘肃省 平凉市 庄浪县 +622725 甘肃省 平凉市 华亭市 +622724 甘肃省 平凉市 崇信县 +622723 甘肃省 平凉市 灵台县 +622722 甘肃省 平凉市 泾川县 +622701 甘肃省 平凉市 平凉市 +622630 甘肃省 陇南市 徽县 +622629 甘肃省 陇南市 两当县 +622628 甘肃省 陇南市 礼县 +622627 甘肃省 陇南市 西和县 +622625 甘肃省 陇南市 康县 +622624 甘肃省 陇南市 成县 +622623 甘肃省 陇南市 宕昌县 +622621 甘肃省 陇南市 武都区 +622429 甘肃省 定西市 岷县 +622428 甘肃省 定西市 漳县 +622427 甘肃省 定西市 临洮县 +622426 甘肃省 定西市 渭源县 +622425 甘肃省 定西市 陇西县 +622424 甘肃省 定西市 通渭县 +622421 甘肃省 定西市 定西市 +622326 甘肃省 武威市 天祝藏族自治县 +622323 甘肃省 武威市 古浪县 +622322 甘肃省 武威市 民勤县 +622301 甘肃省 武威市 武威市 +622226 甘肃省 张掖市 山丹县 +622225 甘肃省 张掖市 高台县 +622223 甘肃省 张掖市 民乐县 +622201 甘肃省 张掖市 张掖市 +622123 甘肃省 酒泉市 金塔县 +622103 甘肃省 酒泉市 敦煌市 +622102 甘肃省 酒泉市 酒泉市 +612732 陕西省 榆林市 子洲县 +612731 陕西省 榆林市 清涧县 +612730 陕西省 榆林市 吴堡县 +612727 陕西省 榆林市 绥德县 +612726 陕西省 榆林市 定边县 +612725 陕西省 榆林市 靖边县 +612724 陕西省 榆林市 横山区 +612722 陕西省 榆林市 神木市 +612701 陕西省 榆林市 榆林市 +612601 陕西省 延安市 延安市 +612527 陕西省 商洛市(商雒市) 柞水县 +612526 陕西省 商洛市(商雒市) 镇安县 +612524 陕西省 商洛市(商雒市) 商南县 +612523 陕西省 商洛市(商雒市) 丹凤县 +612501 陕西省 商洛市(商雒市) 商州区 +612430 陕西省 安康市 白河县 +612428 陕西省 安康市 镇坪县 +612427 陕西省 安康市 平利县 +612426 陕西省 安康市 岚皋县 +612425 陕西省 安康市 紫阳县 +612424 陕西省 安康市 宁陕县 +612423 陕西省 安康市 石泉县 +612422 陕西省 安康市 汉阴县 +612401 陕西省 安康市 安康市 +612328 陕西省 汉中市 镇巴县 +612326 陕西省 汉中市 宁强县 +612324 陕西省 汉中市 西乡县 +612323 陕西省 汉中市 洋县 +612322 陕西省 汉中市 城固县 +612321 陕西省 汉中市 南郑区 +612301 陕西省 汉中市 汉中市 +612133 陕西省 渭南市 富平县 +612129 陕西省 渭南市 澄城县 +612128 陕西省 渭南市 蒲城县 +612127 陕西省 渭南市 大荔县 +612102 陕西省 渭南市 韩城市 +612101 陕西省 渭南市 渭南市 +610421 陕西省 咸阳市 兴平市 +610321 陕西省 宝鸡市 宝鸡市 +610123 陕西省 西安市 临潼区 +533526 云南省 临沧市 双江拉祜族佤族布朗族傣族自治县 +533524 云南省 临沧市 永德县 +533523 云南省 临沧市 云县 +533522 云南省 临沧市 凤庆县 +533223 云南省 丽江市 华坪县 +533222 云南省 丽江市 永胜县 +533025 云南省 保山市 昌宁县 +533023 云南省 保山市 腾冲市 +533022 云南省 保山市 施甸县 +533001 云南省 保山市 保山市 +532729 云南省 普洱市 澜沧拉祜族自治县 +532727 云南省 普洱市 江城哈尼族彝族自治县 +532724 云南省 普洱市 景东彝族自治县 +532721 云南省 普洱市 思茅区 +532701 云南省 普洱市 思茅区 +532428 云南省 玉溪市 新平彝族傣族自治县 +532423 云南省 玉溪市 澄江市 +532231 云南省 昆明市 寻甸回族彝族自治县 +532228 云南省 曲靖市 陆良县 +532226 云南省 曲靖市 罗平县 +532225 云南省 曲靖市 富源县 +532201 云南省 曲靖市 曲靖市 +532131 云南省 昭通市 水富市 +532130 云南省 昭通市 威信县 +532129 云南省 昭通市 彝良县 +532128 云南省 昭通市 镇雄县 +532127 云南省 昭通市 绥江县 +532125 云南省 昭通市 大关县 +532124 云南省 昭通市 盐津县 +532123 云南省 昭通市 巧家县 +532122 云南省 昭通市 鲁甸县 +532101 云南省 昭通市 昭通市 +522724 贵州省 黔南布依族苗族自治州 福泉市 +522530 贵州省 安顺市 紫云苗族布依族自治县 +522529 贵州省 安顺市 镇宁布依族苗族自治县 +522528 贵州省 安顺市 关岭布依族苗族自治县 +522527 贵州省 安顺市 普定县 +522524 贵州省 贵阳市 修文县 +522523 贵州省 贵阳市 息烽县 +522522 贵州省 贵阳市 开阳县 +522502 贵州省 贵阳市 清镇市 +522501 贵州省 安顺市 安顺市 +522428 贵州省 毕节市 赫章县 +522427 贵州省 毕节市 威宁彝族回族苗族自治县 +522426 贵州省 毕节市 纳雍县 +522425 贵州省 毕节市 织金县 +522424 贵州省 毕节市 金沙县 +522423 贵州省 毕节市 黔西县 +522422 贵州省 毕节市 大方县 +522421 贵州省 毕节市 毕节市 +522401 贵州省 毕节市 毕节市 +522321 贵州省 黔西南布依族苗族自治州 兴义市 +522229 贵州省 铜仁市 松桃苗族自治县 +522228 贵州省 铜仁市 沿河土家族自治县 +522227 贵州省 铜仁市 德江县 +522226 贵州省 铜仁市 印江土家族苗族自治县 +522225 贵州省 铜仁市 思南县 +522224 贵州省 铜仁市 石阡县 +522223 贵州省 铜仁市 玉屏侗族自治县 +522222 贵州省 铜仁市 江口县 +522221 贵州省 铜仁市 铜仁市 +522131 贵州省 遵义市 赤水市 +522130 贵州省 遵义市 仁怀市 +522129 贵州省 遵义市 余庆县 +522128 贵州省 遵义市 湄潭县 +522127 贵州省 遵义市 凤冈县 +522125 贵州省 遵义市 道真仡佬族苗族自治县 +522124 贵州省 遵义市 正安县 +522123 贵州省 遵义市 绥阳县 +522122 贵州省 遵义市 桐梓县 +522121 贵州省 遵义市 遵义市 +522101 贵州省 遵义市 遵义市 +519002 四川省 绵阳市 江油市 +519001 四川省 德阳市 广汉市 +513825 四川省 眉山市 丹棱县 +513701 四川省 巴中市 巴中市 +513126 四川省 雅安市 天全县 +513124 四川省 雅安市 汉源县 +513123 四川省 雅安市 荥经县 +513122 四川省 雅安市 名山区 +513101 四川省 雅安市 雅安市 +513030 四川省 达州市 渠县 +513029 四川省 达州市 大竹县 +513027 四川省 巴中市 巴中市 +513024 四川省 达州市 万源市 +513023 四川省 达州市 开江县 +513022 四川省 达州市 宣汉县 +513002 四川省 达州市 万源市 +513001 四川省 达州市 达川区 +512930 四川省 南充市 阆中市 +512929 四川省 南充市 西充县 +512927 四川省 南充市 仪陇县 +512926 四川省 南充市 蓬安县 +512924 四川省 南充市 营山县 +512922 四川省 南充市 南部县 +512921 四川省 南充市 南充市 +512903 四川省 南充市 阆中市 +512535 四川省 宜宾市 屏山县 +512534 四川省 宜宾市 兴文县 +512533 四川省 宜宾市 珙县 +512532 四川省 宜宾市 筠连县 +512531 四川省 宜宾市 高县 +512529 四川省 宜宾市 江安县 +512527 四川省 宜宾市 宜宾市 +512501 四川省 宜宾市 宜宾市 +511130 四川省 眉山市 青神县 +511027 四川省 成都市 简阳市 +511021 四川省 内江市 内江市 +510721 四川省 绵阳市 江油市 +510625 四川省 德阳市 什邡市 +510624 四川省 德阳市 广汉市 +510622 四川省 德阳市 绵竹市 +510523 四川省 泸州市 纳溪区 +510125 四川省 成都市 新都区 +510123 四川省 成都市 温江区 +500384 重庆市 重庆城区 南川区 +460104 海南省 海口市 秀英区 +460036 海南省 儋州市 琼中黎族苗族自治县 +460035 海南省 儋州市 保亭黎族苗族自治县 +460034 海南省 儋州市 陵水黎族自治县 +460033 海南省 儋州市 乐东黎族自治县 +460031 海南省 儋州市 昌江黎族自治县 +460030 海南省 儋州市 白沙黎族自治县 +460028 海南省 儋州市 临高县 +460027 海南省 儋州市 澄迈县 +460022 海南省 儋州市 文昌市 +460021 海南省 海口市 琼山区 +460007 海南省 儋州市 东方市 +460006 海南省 儋州市 万宁市 +460004 海南省 海口市 琼山区 +460003 海南省 儋州市 儋州市 +460002 海南省 儋州市 琼海市 +452826 广西壮族自治区 钦州市 浦北县 +452824 广西壮族自治区 钦州市 灵山县 +452821 广西壮族自治区 防城港市 上思县 +452802 广西壮族自治区 钦州市 钦州市 +452730 广西壮族自治区 河池市 都安瑶族自治县 +452729 广西壮族自治区 河池市 巴马瑶族自治县 +452728 广西壮族自治区 河池市 东兰县 +452727 广西壮族自治区 河池市 凤山县 +452726 广西壮族自治区 河池市 天峨县 +452725 广西壮族自治区 河池市 南丹县 +452724 广西壮族自治区 河池市 环江毛南族自治县 +452723 广西壮族自治区 河池市 罗城仫佬族自治县 +452701 广西壮族自治区 河池市 河池市 +452631 广西壮族自治区 百色市 隆林各族自治县 +452629 广西壮族自治区 百色市 乐业县 +452626 广西壮族自治区 百色市 靖西市 +452625 广西壮族自治区 百色市 德保县 +452624 广西壮族自治区 百色市 平果市 +452623 广西壮族自治区 百色市 田东县 +452601 广西壮族自治区 百色市 百色市 +452528 广西壮族自治区 玉林市(鬱林市/郁林市) 博白县 +452526 广西壮族自治区 玉林市(鬱林市/郁林市) 北流市 +452525 广西壮族自治区 玉林市(鬱林市/郁林市) 容县 +452524 广西壮族自治区 贵港市 平南县 +452523 广西壮族自治区 贵港市 桂平市 +452503 广西壮族自治区 玉林市(鬱林市/郁林市) 北流市 +452502 广西壮族自治区 贵港市 贵港市 +452428 广西壮族自治区 贺州市 富川瑶族自治县 +452425 广西壮族自治区 梧州市 蒙山县 +452424 广西壮族自治区 贺州市 昭平县 +452423 广西壮族自治区 梧州市 藤县 +452421 广西壮族自治区 梧州市 岑溪市 +452402 广西壮族自治区 贺州市 贺州市 +452330 广西壮族自治区 桂林市 平乐县 +452329 广西壮族自治区 桂林市 资源县 +452327 广西壮族自治区 桂林市 灌阳县 +452323 广西壮族自治区 桂林市 全州县 +452322 广西壮族自治区 桂林市 灵川县 +452231 广西壮族自治区 来宾市 忻城县 +452230 广西壮族自治区 来宾市 金秀瑶族自治县 +452229 广西壮族自治区 柳州市 融水苗族自治县 +452228 广西壮族自治区 柳州市 三江侗族自治县 +452227 广西壮族自治区 柳州市 融安县 +452226 广西壮族自治区 来宾市 来宾市 +452225 广西壮族自治区 来宾市 武宣县 +452224 广西壮族自治区 来宾市 象州县 +452223 广西壮族自治区 柳州市 鹿寨县 +452201 广西壮族自治区 来宾市 合山市 +452131 广西壮族自治区 崇左市 天等县 +452130 广西壮族自治区 崇左市 大新县 +452128 广西壮族自治区 崇左市 扶绥县 +452127 广西壮族自治区 南宁市 马山县 +452126 广西壮族自治区 南宁市 隆安县 +452124 广西壮族自治区 南宁市 上林县 +452123 广西壮族自治区 南宁市 宾阳县 +452122 广西壮族自治区 南宁市 横县 +452101 广西壮族自治区 崇左市 凭祥市 +450322 广西壮族自治区 桂林市 临桂区 +450121 广西壮族自治区 南宁市 邕宁区 +445323 广东省 云浮市 云安区 +445121 广东省 东莞市 潮安区 +442827 广东省 云浮市 云浮市 +442823 广东省 肇庆市 广宁县 +442531 广东省 汕尾市 海丰县 +442527 广东省 东莞市 东莞市 +442526 广东省 惠州市 博罗县 +442501 广东省 惠州市 惠州市 +441822 广东省 清远市 英德市 +441703 广东省 阳江市 阳东区 +441522 广东省 汕尾市 陆丰市 +441381 广东省 惠州市 惠阳区 +441282 广东省 云浮市 罗定市 +441281 广东省 云浮市 云浮市 +441229 广东省 云浮市 郁南县 +440924 广东省 茂名市 化州市 +440922 广东省 茂名市 高州市 +440921 广东省 茂名市 信宜市 +440822 广东省 湛江市 廉江市 +440821 广东省 湛江市 吴川市 +440782 广东省 江门市 新会区 +440726 广东省 阳江市 阳江市 +440723 广东省 江门市 恩平市 +440722 广东省 江门市 台山市 +440721 广东省 江门市 新会区 +440702 广东省 江门市 江海区 +440683 广东省 佛山市 三水区 +440682 广东省 佛山市 南海区 +440681 广东省 佛山市 顺德区 +440623 广东省 佛山市 顺德区 +440622 广东省 佛山市 南海区 +440621 广东省 佛山市 三水区 +440583 广东省 汕头市 澄海区 +440582 广东省 汕头市 潮阳区 +440528 广东省 揭阳市 惠来县 +440526 广东省 揭阳市 揭西县 +440525 广东省 揭阳市 揭阳市 +440524 广东省 汕头市 潮阳区 +440522 广东省 东莞市 饶平县 +440521 广东省 汕头市 澄海区 +440520 广东省 东莞市 潮州市 +440421 广东省 珠海市 斗门区 +440225 广东省 韶关市 乐昌市 +440223 广东省 韶关市 南雄市 +440221 广东省 韶关市 曲江区 +440182 广东省 广州市 花都区 +440181 广东省 广州市 番禺区 +440126 广东省 广州市 番禺区 +440122 广东省 广州市 从化区 +439004 湖南省 岳阳市 汨罗市 +433031 湖南省 怀化市 通道侗族自治县 +433030 湖南省 怀化市 靖州苗族侗族自治县 +433029 湖南省 怀化市 会同县 +433027 湖南省 怀化市 芷江侗族自治县 +433026 湖南省 怀化市 新晃侗族自治县 +433025 湖南省 怀化市 麻阳苗族自治县 +433024 湖南省 怀化市 溆浦县 +433023 湖南省 怀化市 辰溪县 +433022 湖南省 怀化市 沅陵县 +433001 湖南省 怀化市 怀化市 +432930 湖南省 永州市 祁阳县 +432929 湖南省 永州市 双牌县 +432928 湖南省 永州市 新田县 +432927 湖南省 永州市 蓝山县 +432926 湖南省 永州市 江华瑶族自治县 +432925 湖南省 永州市 江永县 +432924 湖南省 永州市 宁远县 +432923 湖南省 永州市 道县 +432902 湖南省 永州市 冷水滩区 +432901 湖南省 永州市 永州市 +432831 湖南省 郴州市 安仁县 +432828 湖南省 郴州市 汝城县 +432826 湖南省 郴州市 嘉禾县 +432824 湖南省 郴州市 宜章县 +432823 湖南省 郴州市 永兴县 +432822 湖南省 郴州市 桂阳县 +432802 湖南省 郴州市 资兴市 +432801 湖南省 郴州市 郴州市 +432625 湖南省 邵阳市 新宁县 +432624 湖南省 邵阳市 洞口县 +432622 湖南省 邵阳市 隆回县 +432524 湖南省 娄底市 新化县 +432522 湖南省 娄底市 双峰县 +432503 湖南省 娄底市 涟源市 +432502 湖南省 娄底市 冷水江市 +432501 湖南省 娄底市 娄底市 +432427 湖南省 常德市 石门县 +432426 湖南省 常德市 桃源县 +432425 湖南省 常德市 临澧县 +432424 湖南省 常德市 澧县 +432423 湖南省 常德市 汉寿县 +432422 湖南省 常德市 安乡县 +432421 湖南省 常德市 常德市 +432402 湖南省 常德市 津市市 +432401 湖南省 常德市 常德市 +432326 湖南省 益阳市 安化县 +432325 湖南省 益阳市 桃江县 +432322 湖南省 益阳市 南县 +432321 湖南省 益阳市 益阳市 +432302 湖南省 益阳市 沅江市 +432301 湖南省 益阳市 益阳市 +430625 湖南省 岳阳市 汨罗市 +430622 湖南省 岳阳市 临湘市 +430425 湖南省 衡阳市 常宁市 +430419 湖南省 衡阳市 耒阳市 +430322 湖南省 湘潭市 湘乡市 +430219 湖南省 株洲市 醴陵市 +430123 湖南省 长沙市 浏阳市 +430122 湖南省 长沙市 望城区 +422824 湖北省 恩施土家族苗族自治州 利川市 +422727 湖北省 宜昌市 秭归县 +422722 湖北省 宜昌市 宜都市 +422626 湖北省 十堰市 房县 +422625 湖北省 十堰市 竹溪县 +422624 湖北省 十堰市 竹山县 +422601 湖北省 十堰市 丹江口市 +422432 湖北省 荆门市 京山市 +422429 湖北省 省直辖县级行政区划_恩施土家族苗族自治州 潜江市 +422428 湖北省 省直辖县级行政区划_恩施土家族苗族自治州 天门市 +422426 湖北省 荆州市 洪湖市 +422425 湖北省 荆州市 监利市 +422424 湖北省 荆州市 石首市 +422423 湖北省 荆州市 公安县 +422422 湖北省 荆州市 松滋市 +422403 湖北省 荆州市 洪湖市 +422401 湖北省 省直辖县级行政区划_恩施土家族苗族自治州 仙桃市 +422327 湖北省 黄石市 阳新县 +422326 湖北省 咸宁市 通山县 +422325 湖北省 咸宁市 崇阳县 +422324 湖北省 咸宁市 通城县 +422322 湖北省 咸宁市 嘉鱼县 +422321 湖北省 咸宁市 咸宁市 +422301 湖北省 咸宁市 咸宁市 +422228 湖北省 孝感市 汉川市 +422225 湖北省 孝感市 安陆市 +422223 湖北省 孝感市 大悟县 +422203 湖北省 孝感市 安陆市 +422202 湖北省 孝感市 应城市 +422201 湖北省 孝感市 孝感市 +422130 湖北省 黄冈市 黄梅县 +422128 湖北省 黄冈市 蕲春县 +422127 湖北省 黄冈市 浠水县 +422126 湖北省 黄冈市 英山县 +422124 湖北省 黄冈市 麻城市 +422123 湖北省 黄冈市 红安县 +422121 湖北省 黄冈市 黄冈市 +422103 湖北省 黄冈市 黄州区 +422101 湖北省 黄冈市 麻城市 +420803 湖北省 荆门市 沙洋县 +420623 湖北省 襄阳市 宜城市 +420622 湖北省 襄阳市 枣阳市 +420621 湖北省 襄阳市 襄阳市 +420620 湖北省 襄阳市 老河口市 +420400 湖北省 荆州市 沙市区 +420221 湖北省 黄石市 大冶市 +420124 湖北省 武汉市 新洲区 +420123 湖北省 武汉市 黄陂区 +420122 湖北省 武汉市 武昌区 +420121 湖北省 武汉市 汉阳区 +413029 河南省 信阳市 新县 +413028 河南省 信阳市 罗山县 +413027 河南省 信阳市 商城县 +413026 河南省 信阳市 固始县 +413025 河南省 信阳市 光山县 +413024 河南省 信阳市 潢川县 +413023 河南省 信阳市 信阳市 +413022 河南省 信阳市 淮滨县 +413021 河南省 信阳市 息县 +413001 河南省 信阳市 信阳市 +412932 河南省 南阳市 桐柏县 +412931 河南省 南阳市 新野县 +412929 河南省 南阳市 唐河县 +412928 河南省 南阳市 社旗县 +412927 河南省 南阳市 淅川县 +412926 河南省 南阳市 内乡县 +412925 河南省 南阳市 镇平县 +412924 河南省 南阳市 南阳市 +412923 河南省 南阳市 西峡县 +412922 河南省 南阳市 方城县 +412921 河南省 南阳市 南召县 +412902 河南省 南阳市 邓州市 +412901 河南省 南阳市 南阳市 +412829 河南省 驻马店市 正阳县 +412828 河南省 驻马店市 新蔡县 +412827 河南省 驻马店市 平舆县 +412826 河南省 驻马店市 汝南县 +412825 河南省 驻马店市 上蔡县 +412824 河南省 驻马店市 西平县 +412823 河南省 驻马店市 遂平县 +412822 河南省 驻马店市 泌阳县 +412821 河南省 驻马店市 确山县 +412801 河南省 驻马店市 驻马店市 +412727 河南省 周口市 淮阳区 +412726 河南省 周口市 郸城县 +412725 河南省 周口市 鹿邑县 +412724 河南省 周口市 太康县 +412723 河南省 周口市 商水县 +412722 河南省 周口市 西华县 +412721 河南省 周口市 扶沟县 +412702 河南省 周口市 项城市 +412701 河南省 周口市 周口市 +412328 河南省 商丘市(商邱市) 永城市 +412327 河南省 商丘市(商邱市) 柘城县 +412326 河南省 商丘市(商邱市) 夏邑县 +412325 河南省 商丘市(商邱市) 睢县 +412324 河南省 商丘市(商邱市) 宁陵县 +412323 河南省 商丘市(商邱市) 民权县 +412321 河南省 商丘市(商邱市) 虞城县 +411223 河南省 三门峡市 灵宝市 +411123 河南省 漯河市 郾城区 +410824 河南省 焦作市 沁阳市 +410321 河南省 洛阳市 偃师市 +410224 河南省 开封市 开封市 +410125 河南省 郑州市 登封市 +410123 河南省 郑州市 新郑市 +410121 河南省 郑州市 荥阳市 +410107 河南省 郑州市 新密市 +379014 山东省 青岛市 平度市 +379006 山东省 青岛市 胶州市 +372930 山东省 菏泽市 东明县 +372929 山东省 菏泽市 鄄城县 +372928 山东省 菏泽市 郓城县 +372927 山东省 济宁市 梁山县 +372926 山东省 菏泽市 巨野县 +372925 山东省 菏泽市 单县 +372924 山东省 菏泽市 成武县 +372923 山东省 菏泽市 定陶区 +372922 山东省 菏泽市 曹县 +372901 山东省 菏泽市 菏泽市 +372833 山东省 临沂市 临沭县 +372832 山东省 临沂市 沂南县 +372831 山东省 临沂市 费县 +372830 山东省 临沂市 平邑县 +372829 山东省 临沂市 蒙阴县 +372828 山东省 淄博市 沂源县 +372827 山东省 临沂市 沂水县 +372826 山东省 日照市 莒县 +372824 山东省 临沂市 莒南县 +372822 山东省 临沂市 郯城县 +372801 山东省 临沂市 临沂市 +372527 山东省 聊城市 高唐县 +372526 山东省 聊城市 冠县 +372525 山东省 聊城市 东阿县 +372524 山东省 聊城市 茌平区 +372523 山东省 聊城市 莘县 +372522 山东省 聊城市 阳谷县 +372502 山东省 聊城市 临清市 +372501 山东省 聊城市 聊城市 +372431 山东省 德州市 宁津县 +372430 山东省 济南市 济阳区 +372428 山东省 德州市 临邑县 +372427 山东省 德州市 乐陵市 +372426 山东省 德州市 禹城市 +372425 山东省 德州市 齐河县 +372423 山东省 德州市 夏津县 +372422 山东省 德州市 平原县 +372402 山东省 德州市 乐陵市 +372401 山东省 德州市 德州市 +372330 山东省 滨州市 邹平市 +372328 山东省 滨州市 博兴县 +372325 山东省 滨州市 沾化区 +372324 山东省 滨州市 无棣县 +372323 山东省 滨州市 阳信县 +372321 山东省 滨州市 惠民县 +372301 山东省 滨州市 滨州市 +370922 山东省 泰安市 肥城市 +370920 山东省 泰安市 新泰市 +370919 山东省 济南市 莱芜区 +370882 山东省 济宁市 兖州区 +370823 山东省 济宁市 曲阜市 +370822 山东省 济宁市 兖州区 +370729 山东省 日照市 五莲县 +370728 山东省 潍坊市 诸城市 +370727 山东省 潍坊市 高密市 +370723 山东省 潍坊市 寿光市 +370633 山东省 威海市 荣成市 +370632 山东省 威海市 文登区 +370631 山东省 烟台市 牟平区 +370629 山东省 烟台市 海阳市 +370627 山东省 烟台市 莱阳市 +370624 山东省 烟台市 招远市 +370622 山东省 烟台市 蓬莱区 +370226 山东省 青岛市 平度市 +370225 山东省 青岛市 莱西市 +370222 山东省 青岛市 即墨区 +370221 山东省 青岛市 崂山区 +370123 山东省 济南市 长清区 +370121 山东省 济南市 历城区 +362624 江西省 九江市 修水县 +362532 江西省 抚州市 广昌县 +362531 江西省 抚州市 东乡区 +362529 江西省 抚州市 资溪县 +362528 江西省 抚州市 金溪县 +362527 江西省 抚州市 宜黄县 +362526 江西省 抚州市 乐安县 +362525 江西省 抚州市 崇仁县 +362524 江西省 抚州市 南丰县 +362523 江西省 抚州市 黎川县 +362522 江西省 抚州市 南城县 +362502 江西省 抚州市 临川区 +362501 江西省 抚州市 抚州市 +362431 江西省 萍乡市 莲花县 +362430 江西省 吉安市 永新县 +362429 江西省 吉安市 安福县 +362428 江西省 吉安市 万安县 +362427 江西省 吉安市 遂川县 +362426 江西省 吉安市 泰和县 +362425 江西省 吉安市 永丰县 +362423 江西省 吉安市 峡江县 +362422 江西省 吉安市 吉水县 +362402 江西省 吉安市 井冈山市 +362334 江西省 上饶市 婺源县 +362333 江西省 上饶市 德兴市 +362331 江西省 上饶市 万年县 +362329 江西省 上饶市 余干县 +362326 江西省 上饶市 弋阳县 +362325 江西省 上饶市 横峰县 +362324 江西省 上饶市 铅山县 +362323 江西省 上饶市 玉山县 +362322 江西省 上饶市 广丰区 +362321 江西省 上饶市 上饶市 +362302 江西省 上饶市 德兴市 +362301 江西省 上饶市 上饶市 +362233 江西省 宜春市 铜鼓县 +362232 江西省 宜春市 靖安县 +362229 江西省 宜春市 宜丰县 +362228 江西省 宜春市 上高县 +362227 江西省 宜春市 万载县 +362226 江西省 宜春市 奉新县 +362222 江西省 宜春市 高安市 +362221 江西省 宜春市 丰城市 +362204 江西省 宜春市 高安市 +362203 江西省 宜春市 樟树市 +362202 江西省 宜春市 丰城市 +362201 江西省 宜春市 宜春市 +362137 江西省 赣州市 石城县 +362135 江西省 赣州市 会昌县 +362133 江西省 赣州市 兴国县 +362131 江西省 赣州市 宁都县 +362129 江西省 赣州市 定南县 +362128 江西省 赣州市 龙南市 +362127 江西省 赣州市 安远县 +362126 江西省 赣州市 崇义县 +362125 江西省 赣州市 上犹县 +362123 江西省 赣州市 信丰县 +362122 江西省 赣州市 南康区 +362102 江西省 赣州市 瑞金市 +362101 江西省 赣州市 赣州市 +360422 江西省 九江市 瑞昌市 +360312 江西省 萍乡市 芦溪县 +360311 江西省 萍乡市 上栗县 +360221 江西省 景德镇市 乐平市 +359002 福建省 泉州市 石狮市 +352627 福建省 龙岩市 连城县 +352626 福建省 龙岩市 漳平市 +352625 福建省 龙岩市 武平县 +352624 福建省 龙岩市 上杭县 +352622 福建省 龙岩市 长汀县 +352602 福建省 龙岩市 漳平市 +352601 福建省 龙岩市 龙岩市 +352231 福建省 宁德市 柘荣县 +352230 福建省 宁德市 周宁县 +352229 福建省 宁德市 寿宁县 +352228 福建省 宁德市 屏南县 +352227 福建省 宁德市 古田县 +352226 福建省 宁德市 福安市 +352225 福建省 宁德市 霞浦县 +352224 福建省 宁德市 福鼎市 +352221 福建省 宁德市 宁德市 +352203 福建省 宁德市 福鼎市 +352202 福建省 宁德市 福安市 +352201 福建省 宁德市 宁德市 +352129 福建省 南平市 政和县 +352128 福建省 南平市 松溪县 +352127 福建省 南平市 光泽县 +352124 福建省 南平市 浦城县 +352123 福建省 南平市 建瓯市 +352122 福建省 南平市 建阳区 +352121 福建省 南平市 顺昌县 +352104 福建省 南平市 建瓯市 +352103 福建省 南平市 武夷山市 +352102 福建省 南平市 邵武市 +352101 福建省 南平市 南平市 +350784 福建省 南平市 建阳区 +350621 福建省 漳州市 龙海市 +350523 福建省 泉州市 南安市 +350522 福建省 泉州市 晋江市 +350321 福建省 莆田市 莆田市 +350221 福建省 厦门市 同安区 +350127 福建省 福州市 福清市 +350126 福建省 福州市 长乐区 +342901 安徽省 池州市 贵池区 +342830 安徽省 池州市 贵池区 +342827 安徽省 安庆市 望江县 +342826 安徽省 安庆市 宿松县 +342825 安徽省 安庆市 太湖县 +342824 安徽省 安庆市 潜山市 +342726 安徽省 黄山市 祁门县 +342725 安徽省 黄山市 黟县 +342724 安徽省 黄山市 休宁县 +342723 安徽省 黄山市 歙县 +342701 安徽省 黄山市 屯溪区 +342626 安徽省 马鞍山市 和县 +342625 安徽省 马鞍山市 含山县 +342623 安徽省 芜湖市 无为市 +342622 安徽省 合肥市 庐江县 +342621 安徽省 合肥市 肥东县 +342601 安徽省 合肥市 巢湖市 +342530 安徽省 宣城市 旌德县 +342529 安徽省 宣城市 泾县 +342527 安徽省 芜湖市 南陵县 +342524 安徽省 宣城市 宁国市 +342523 安徽省 宣城市 广德市 +342522 安徽省 宣城市 郎溪县 +342502 安徽省 宣城市 宁国市 +342501 安徽省 宣城市 宣州区 +342427 安徽省 六安市 霍山县 +342426 安徽省 六安市 金寨县 +342425 安徽省 六安市 舒城县 +342423 安徽省 六安市 霍邱县 +342422 安徽省 淮南市 寿县 +342421 安徽省 六安市 六安市 +342401 安徽省 六安市 六安市 +342326 安徽省 滁州市 凤阳县 +342325 安徽省 滁州市 定远县 +342324 安徽省 滁州市 全椒县 +342321 安徽省 滁州市 天长市 +342301 安徽省 滁州市 滁州市 +342225 安徽省 宿州市 泗县 +342224 安徽省 宿州市 灵璧县 +342222 安徽省 宿州市 萧县 +342221 安徽省 宿州市 砀山县 +342201 安徽省 宿州市 宿州市 +342129 安徽省 阜阳市 界首市 +342128 安徽省 阜阳市 颍上县 +342127 安徽省 阜阳市 阜南县 +342122 安徽省 阜阳市 临泉县 +342121 安徽省 阜阳市 阜阳市 +342101 安徽省 阜阳市 阜阳市 +341281 安徽省 亳州市 亳州市 +339011 浙江省 绍兴市 诸暨市 +339007 浙江省 金华市 义乌市 +339005 浙江省 杭州市 萧山区 +332626 浙江省 台州市 三门县 +332625 浙江省 台州市 天台县 +332624 浙江省 台州市 仙居县 +332623 浙江省 台州市 温岭市 +332622 浙江省 台州市 黄岩区 +332621 浙江省 台州市 临海市 +332603 浙江省 台州市 黄岩区 +332602 浙江省 台州市 临海市 +332601 浙江省 台州市 椒江区 +332529 浙江省 丽水市 景宁畲族自治县 +332528 浙江省 丽水市 松阳县 +332527 浙江省 丽水市 遂昌县 +332526 浙江省 丽水市 缙云县 +332525 浙江省 丽水市 庆元县 +332524 浙江省 丽水市 龙泉市 +332523 浙江省 丽水市 云和县 +332522 浙江省 丽水市 青田县 +332521 浙江省 丽水市 丽水市 +332502 浙江省 丽水市 龙泉市 +332501 浙江省 丽水市 丽水市 +330823 浙江省 衢州市 江山市 +330724 浙江省 金华市 东阳市 +330722 浙江省 金华市 永康市 +330721 浙江省 金华市 金华市 +330719 浙江省 金华市 兰溪市 +330625 浙江省 绍兴市 诸暨市 +330622 浙江省 绍兴市 上虞区 +330425 浙江省 嘉兴市 桐乡市 +330423 浙江省 嘉兴市 海宁市 +330422 浙江省 嘉兴市 平湖市 +330419 浙江省 嘉兴市 海宁市 +330325 浙江省 温州市 瑞安市 +330323 浙江省 温州市 乐清市 +330321 浙江省 温州市 瓯海区 +330224 浙江省 宁波市 奉化区 +330222 浙江省 宁波市 慈溪市 +330221 浙江省 宁波市 镇海区 +330219 浙江省 宁波市 余姚市 +330184 浙江省 杭州市 余杭区 +330126 浙江省 杭州市 建德市 +330125 浙江省 杭州市 余杭区 +330124 浙江省 杭州市 临安区 +330123 浙江省 杭州市 富阳区 +321321 江苏省 宿迁市 宿豫区 +321124 江苏省 镇江市 扬中市 +321123 江苏省 镇江市 句容市 +321121 江苏省 镇江市 丹徒区 +321119 江苏省 镇江市 丹阳市 +321088 江苏省 扬州市 江都区 +321086 江苏省 泰州市 靖江市 +321085 江苏省 泰州市 泰兴市 +321083 江苏省 泰州市 兴化市 +321027 江苏省 扬州市 邗江区 +321026 江苏省 扬州市 江都区 +321025 江苏省 泰州市 泰兴市 +321024 江苏省 泰州市 靖江市 +321022 江苏省 扬州市 高邮市 +321021 江苏省 泰州市 兴化市 +321019 江苏省 扬州市 仪征市 +320928 江苏省 盐城市 盐都区 +320926 江苏省 盐城市 大丰区 +320919 江苏省 盐城市 东台市 +320827 江苏省 宿迁市 泗洪县 +320825 江苏省 宿迁市 泗阳县 +320823 江苏省 宿迁市 沭阳县 +320822 江苏省 连云港市 灌南县 +320821 江苏省 淮安市 淮阴区 +320626 江苏省 南通市 启东市 +320625 江苏省 南通市 海门区 +320624 江苏省 南通市 南通市 +320622 江苏省 南通市 如皋市 +320584 江苏省 苏州市 吴江区 +320525 江苏省 苏州市 吴江区 +320522 江苏省 苏州市 太仓市 +320520 江苏省 苏州市 常熟市 +320483 江苏省 常州市 武进区 +320423 江苏省 常州市 溧阳市 +320422 江苏省 常州市 金坛区 +320421 江苏省 常州市 武进区 +320326 江苏省 徐州市 新沂市 +320323 江苏省 徐州市 铜山区 +320283 江苏省 无锡市 锡山区 +320223 江苏省 无锡市 宜兴市 +320222 江苏省 无锡市 无锡市 +320219 江苏省 无锡市 江阴市 +320123 江苏省 南京市 六合区 +320121 江苏省 南京市 江宁区 +310229 上海市 上海城区 青浦区 +310228 上海市 上海城区 金山区 +310227 上海市 上海城区 松江区 +310226 上海市 上海城区 奉贤区 +310222 上海市 上海城区 嘉定区 +239004 黑龙江省 佳木斯市 富锦市 +232625 黑龙江省 黑河市 逊克县 +232622 黑龙江省 黑河市 嫩江市 +232602 黑龙江省 黑河市 北安市 +232601 黑龙江省 黑河市 黑河市 +232332 黑龙江省 绥化市 绥棱县 +232331 黑龙江省 绥化市 明水县 +232330 黑龙江省 绥化市 庆安县 +232326 黑龙江省 绥化市 青冈县 +232325 黑龙江省 绥化市 兰西县 +232324 黑龙江省 绥化市 望奎县 +232321 黑龙江省 绥化市 海伦市 +232303 黑龙江省 绥化市 肇东市 +232302 黑龙江省 绥化市 安达市 +232301 黑龙江省 绥化市 绥化市 +232131 黑龙江省 哈尔滨市 延寿县 +232130 黑龙江省 哈尔滨市 方正县 +232128 黑龙江省 哈尔滨市 通河县 +232127 黑龙江省 哈尔滨市 木兰县 +232126 黑龙江省 哈尔滨市 巴彦县 +232125 黑龙江省 哈尔滨市 五常市 +232122 黑龙江省 哈尔滨市 宾县 +232103 黑龙江省 哈尔滨市 五常市 +232102 黑龙江省 哈尔滨市 尚志市 +231027 黑龙江省 鸡西市 虎林市 +231026 黑龙江省 鸡西市 密山市 +231023 黑龙江省 牡丹江市 穆棱市 +231021 黑龙江省 牡丹江市 宁安市 +230834 黑龙江省 双鸭山市 友谊县 +230832 黑龙江省 双鸭山市 饶河县 +230827 黑龙江省 双鸭山市 宝清县 +230823 黑龙江省 哈尔滨市 依兰县 +230228 黑龙江省 大庆市 林甸县 +230222 黑龙江省 齐齐哈尔市 讷河市 +230122 黑龙江省 哈尔滨市 阿城区 +230121 黑龙江省 哈尔滨市 呼兰区 +230106 黑龙江省 哈尔滨市 香坊区 +222425 吉林省 延边朝鲜族自治州 珲春市 +222423 吉林省 延边朝鲜族自治州 和龙市 +222421 吉林省 延边朝鲜族自治州 龙井市 +222303 吉林省 松原市 扶余市 +222301 吉林省 白城市 白城市 +220625 吉林省 白山市 江源区 +220522 吉林省 通化市 集安市 +220324 吉林省 四平市 双辽市 +220225 吉林省 吉林市 桦甸市 +220223 吉林省 吉林市 磐石市 +220222 吉林省 吉林市 舒兰市 +220125 吉林省 长春市 双阳区 +220124 吉林省 长春市 德惠市 +220123 吉林省 长春市 九台区 +220121 吉林省 长春市 榆树市 +211325 辽宁省 葫芦岛市 建昌县 +211323 辽宁省 朝阳市 凌源市 +211225 辽宁省 沈阳市 康平县 +211222 辽宁省 铁岭市 开原市 +211022 辽宁省 辽阳市 灯塔市 +210821 辽宁省 营口市 营口市 +210722 辽宁省 葫芦岛市 兴城市 +210704 辽宁省 葫芦岛市 南票区 +210225 辽宁省 大连市 庄河市 +210121 辽宁省 沈阳市 新民市 +152827 内蒙古自治区 巴彦淖尔市 杭锦后旗 +152824 内蒙古自治区 巴彦淖尔市 乌拉特前旗 +152822 内蒙古自治区 巴彦淖尔市 五原县 +152801 内蒙古自治区 巴彦淖尔市 临河区 +152728 内蒙古自治区 鄂尔多斯市 伊金霍洛旗 +152727 内蒙古自治区 鄂尔多斯市 乌审旗 +152725 内蒙古自治区 鄂尔多斯市 鄂托克旗 +152723 内蒙古自治区 鄂尔多斯市 准格尔旗 +152722 内蒙古自治区 鄂尔多斯市 达拉特旗 +152701 内蒙古自治区 鄂尔多斯市 东胜区 +152634 内蒙古自治区 乌兰察布市 四子王旗 +152632 内蒙古自治区 乌兰察布市 察哈尔右翼后旗 +152630 内蒙古自治区 乌兰察布市 察哈尔右翼前旗 +152628 内蒙古自治区 乌兰察布市 丰镇市 +152627 内蒙古自治区 乌兰察布市 兴和县 +152626 内蒙古自治区 乌兰察布市 商都县 +152625 内蒙古自治区 乌兰察布市 化德县 +152624 内蒙古自治区 乌兰察布市 卓资县 +152601 内蒙古自治区 乌兰察布市 集宁区 +152327 内蒙古自治区 通辽市 扎鲁特旗 +152326 内蒙古自治区 通辽市 奈曼旗 +152325 内蒙古自治区 通辽市 库伦旗 +152324 内蒙古自治区 通辽市 开鲁县 +152323 内蒙古自治区 通辽市 科尔沁左翼后旗 +152322 内蒙古自治区 通辽市 科尔沁左翼中旗 +152321 内蒙古自治区 通辽市 通辽市 +152302 内蒙古自治区 通辽市 霍林郭勒市 +152301 内蒙古自治区 通辽市 通辽市 +152128 内蒙古自治区 呼伦贝尔市 鄂温克族自治旗 +152127 内蒙古自治区 呼伦贝尔市 鄂伦春自治旗 +152123 内蒙古自治区 呼伦贝尔市 莫力达瓦达斡尔族自治旗 +152122 内蒙古自治区 呼伦贝尔市 阿荣旗 +152106 内蒙古自治区 呼伦贝尔市 额尔古纳市 +152105 内蒙古自治区 呼伦贝尔市 根河市 +152104 内蒙古自治区 呼伦贝尔市 牙克石市 +152103 内蒙古自治区 呼伦贝尔市 扎兰屯市 +152102 内蒙古自治区 呼伦贝尔市 满洲里市 +152101 内蒙古自治区 呼伦贝尔市 海拉尔区 +149001 山西省 太原市 古交市 +142733 山西省 运城市 垣曲县 +142732 山西省 运城市 平陆县 +142731 山西省 运城市 绛县 +142730 山西省 运城市 夏县 +142729 山西省 运城市 闻喜县 +142728 山西省 运城市 河津市 +142727 山西省 运城市 稷山县 +142726 山西省 运城市 新绛县 +142725 山西省 运城市 万荣县 +142724 山西省 运城市 临猗县 +142723 山西省 运城市 芮城县 +142703 山西省 运城市 河津市 +142702 山西省 运城市 永济市 +142701 山西省 运城市 运城市 +142635 山西省 临汾市 隰县 +142632 山西省 临汾市 蒲县 +142631 山西省 临汾市 乡宁县 +142630 山西省 临汾市 吉县 +142629 山西省 临汾市 浮山县 +142628 山西省 临汾市 安泽县 +142627 山西省 临汾市 古县 +142625 山西省 临汾市 洪洞县 +142623 山西省 临汾市 襄汾县 +142622 山西省 临汾市 翼城县 +142621 山西省 临汾市 曲沃县 +142603 山西省 临汾市 霍州市 +142602 山西省 临汾市 侯马市 +142601 山西省 临汾市 临汾市 +142433 山西省 晋中市 灵石县 +142431 山西省 晋中市 平遥县 +142430 山西省 晋中市 祁县 +142429 山西省 晋中市 太谷区 +142427 山西省 晋中市 寿阳县 +142424 山西省 晋中市 昔阳县 +142422 山西省 晋中市 左权县 +142421 山西省 晋中市 榆社县 +142402 山西省 晋中市 介休市 +142401 山西省 晋中市 榆次区 +142333 山西省 吕梁市 交口县 +142329 山西省 吕梁市 岚县 +142328 山西省 吕梁市 石楼县 +142327 山西省 吕梁市 柳林县 +142326 山西省 吕梁市 临县 +142325 山西省 吕梁市 兴县 +142324 山西省 吕梁市 孝义市 +142323 山西省 吕梁市 交城县 +142322 山西省 吕梁市 文水县 +142321 山西省 吕梁市 汾阳市 +142303 山西省 吕梁市 汾阳市 +142301 山西省 吕梁市 孝义市 +142234 山西省 忻州市 偏关县 +142233 山西省 忻州市 保德县 +142232 山西省 忻州市 河曲县 +142230 山西省 忻州市 五寨县 +142229 山西省 忻州市 神池县 +142228 山西省 忻州市 静乐县 +142227 山西省 忻州市 宁武县 +142226 山西省 忻州市 繁峙县 +142225 山西省 忻州市 代县 +142223 山西省 忻州市 五台县 +142202 山西省 忻州市 原平市 +142201 山西省 忻州市 忻州市 +142126 山西省 朔州市 应县 +142122 山西省 大同市 天镇县 +133031 河北省 衡水市 阜城县 +133030 河北省 衡水市 景县 +133029 河北省 衡水市 故城县 +133028 河北省 衡水市 安平县 +133026 河北省 衡水市 武强县 +133024 河北省 衡水市 武邑县 +133023 河北省 衡水市 枣强县 +133001 河北省 衡水市 衡水市 +132931 河北省 沧州市 孟村回族自治县 +132930 河北省 沧州市 黄骅市 +132928 河北省 沧州市 南皮县 +132927 河北省 沧州市 东光县 +132926 河北省 沧州市 吴桥县 +132924 河北省 沧州市 献县 +132923 河北省 沧州市 肃宁县 +132922 河北省 沧州市 河间市 +132902 河北省 沧州市 泊头市 +132829 河北省 廊坊市 大城县 +132828 河北省 廊坊市 文安县 +132826 河北省 廊坊市 固安县 +132825 河北省 廊坊市 永清县 +132822 河北省 廊坊市 大厂回族自治县 +132801 河北省 廊坊市 廊坊市 +132629 河北省 承德市 围场满族蒙古族自治县 +132628 河北省 承德市 隆化县 +132627 河北省 承德市 丰宁满族自治县 +132530 河北省 张家口市 涿鹿县 +132529 河北省 张家口市 怀来县 +132525 河北省 张家口市 蔚县 +132522 河北省 张家口市 康保县 +132521 河北省 张家口市 张北县 +132442 河北省 保定市 蠡县 +132435 河北省 保定市 容城县 +132434 河北省 保定市 雄县 +132433 河北省 保定市 安新县 +132432 河北省 保定市 高阳县 +132428 河北省 保定市 望都县 +132427 河北省 保定市 唐县 +132425 河北省 保定市 定兴县 +132421 河北省 保定市 易县 +132404 河北省 保定市 高碑店市 +132402 河北省 保定市 涿州市 +132401 河北省 保定市 定州市 +132337 河北省 石家庄市 行唐县 +132336 河北省 石家庄市 灵寿县 +132332 河北省 石家庄市 赞皇县 +132331 河北省 石家庄市 元氏县 +132330 河北省 石家庄市 高邑县 +132329 河北省 石家庄市 新乐市 +132326 河北省 石家庄市 赵县 +132325 河北省 石家庄市 藁城区 +132324 河北省 石家庄市 无极县 +132323 河北省 石家庄市 深泽县 +132235 河北省 邢台市 威县 +132234 河北省 邢台市 平乡县 +132233 河北省 邢台市 广宗县 +132232 河北省 邢台市 新河县 +132231 河北省 邢台市 巨鹿县 +132229 河北省 邢台市 宁晋县 +132228 河北省 邢台市 南和区 +132226 河北省 邢台市 隆尧县 +132201 河北省 邢台市 南宫市 +132135 河北省 邯郸市 馆陶县 +132132 河北省 邯郸市 涉县 +132130 河北省 邯郸市 磁县 +132129 河北省 邯郸市 临漳县 +132128 河北省 邯郸市 成安县 +132127 河北省 邯郸市 广平县 +132123 河北省 邯郸市 曲周县 +132122 河北省 邯郸市 魏县 +130282 河北省 唐山市 丰南区 +130228 河北省 唐山市 遵化市 +130226 河北省 唐山市 迁安市 +130222 河北省 唐山市 丰南区 +130221 河北省 唐山市 丰润区 +130185 河北省 石家庄市 鹿泉区 +130124 河北省 石家庄市 栾城区 +120224 天津市 天津城区 宝坻区 +120222 天津市 天津城区 武清区 +110227 北京市 北京城区 怀柔区 +110226 北京市 北京城区 平谷区 +110224 北京市 北京城区 大兴区 +110222 北京市 北京城区 顺义区 +110221 北京市 北京城区 昌平区 \ No newline at end of file diff --git a/src/main/resources/hdfs-site.xml b/src/main/resources/hdfs-site.xml new file mode 100644 index 0000000..f205a13 --- /dev/null +++ b/src/main/resources/hdfs-site.xml @@ -0,0 +1,69 @@ + + + + + + dfs.namenode.name.dir + file:///hdfs01/dfs/nn,file:///hdfs02/dfs/nn,file:///hdfs03/dfs/nn + + + dfs.namenode.servicerpc-address + bigdata-master-01.chinagoods.te:8022 + + + dfs.https.address + bigdata-master-01.chinagoods.te:9871 + + + dfs.https.port + 9871 + + + dfs.namenode.http-address + bigdata-master-01.chinagoods.te:9870 + + + dfs.replication + 3 + + + dfs.blocksize + 134217728 + + + dfs.client.use.datanode.hostname + false + + + fs.permissions.umask-mode + 022 + + + dfs.client.block.write.locateFollowingBlock.retries + 7 + + + dfs.namenode.acls.enabled + true + + + dfs.client.read.shortcircuit + false + + + dfs.domain.socket.path + /var/run/hdfs-sockets/dn + + + dfs.client.read.shortcircuit.skip.checksum + false + + + dfs.client.domain.socket.data.traffic + false + + + dfs.datanode.hdfs-blocks-metadata.enabled + true + + diff --git a/src/main/resources/ip2region.db b/src/main/resources/ip2region.db new file mode 100644 index 0000000..b688511 Binary files /dev/null and b/src/main/resources/ip2region.db differ diff --git a/src/test/java/com/chinagoods/bigdata/functions/array/UDAFSortKeyByValueTest.java b/src/test/java/com/chinagoods/bigdata/functions/array/UDAFSortKeyByValueTest.java new file mode 100644 index 0000000..41a5a1e --- /dev/null +++ b/src/test/java/com/chinagoods/bigdata/functions/array/UDAFSortKeyByValueTest.java @@ -0,0 +1,321 @@ +package com.chinagoods.bigdata.functions.array; + +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.parse.SemanticException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory; +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.*; + +public class UDAFSortKeyByValueTest { + + @Test + public void testSortKeyByValueBasic() throws Exception { + UDAFSortKeyByValue udaf = new UDAFSortKeyByValue(); + + // Get evaluator + GenericUDAFEvaluator evaluator = udaf.getEvaluator(new org.apache.hadoop.hive.serde2.typeinfo.TypeInfo[]{ + TypeInfoFactory.stringTypeInfo, + TypeInfoFactory.doubleTypeInfo + }); + + // Initialize + ObjectInspector[] parameters = { + PrimitiveObjectInspectorFactory.javaStringObjectInspector, + PrimitiveObjectInspectorFactory.javaDoubleObjectInspector + }; + ObjectInspector result = evaluator.init(GenericUDAFEvaluator.Mode.COMPLETE, parameters); + + // Create aggregation buffer + GenericUDAFEvaluator.AggregationBuffer agg = evaluator.getNewAggregationBuffer(); + + // Add test data: keys with values for sorting + evaluator.iterate(agg, new Object[]{"apple", 3.5}); + evaluator.iterate(agg, new Object[]{"banana", 1.2}); + evaluator.iterate(agg, new Object[]{"cherry", 2.8}); + evaluator.iterate(agg, new Object[]{"date", 0.5}); + + // Get final result + @SuppressWarnings("unchecked") + List sortedKeys = (List) evaluator.terminate(agg); + + // Verify sorting (descending by value: 3.5, 2.8, 1.2, 0.5) + assertNotNull("Result should not be null", sortedKeys); + assertEquals("Should have 4 elements", 4, sortedKeys.size()); + assertEquals("First key should be 'apple'", "apple", sortedKeys.get(0)); + assertEquals("Second key should be 'cherry'", "cherry", sortedKeys.get(1)); + assertEquals("Third key should be 'banana'", "banana", sortedKeys.get(2)); + assertEquals("Fourth key should be 'date'", "date", sortedKeys.get(3)); + } + + @Test + public void testSortKeyByValueWithDuplicateValues() throws Exception { + UDAFSortKeyByValue udaf = new UDAFSortKeyByValue(); + + GenericUDAFEvaluator evaluator = udaf.getEvaluator(new org.apache.hadoop.hive.serde2.typeinfo.TypeInfo[]{ + TypeInfoFactory.stringTypeInfo, + TypeInfoFactory.doubleTypeInfo + }); + + ObjectInspector[] parameters = { + PrimitiveObjectInspectorFactory.javaStringObjectInspector, + PrimitiveObjectInspectorFactory.javaDoubleObjectInspector + }; + evaluator.init(GenericUDAFEvaluator.Mode.COMPLETE, parameters); + + GenericUDAFEvaluator.AggregationBuffer agg = evaluator.getNewAggregationBuffer(); + + // Add test data with duplicate values + evaluator.iterate(agg, new Object[]{"zebra", 2.0}); + evaluator.iterate(agg, new Object[]{"apple", 2.0}); + evaluator.iterate(agg, new Object[]{"banana", 1.0}); + + @SuppressWarnings("unchecked") + List sortedKeys = (List) evaluator.terminate(agg); + + // Should sort by value first (descending), then by key for ties (ascending) + assertEquals("Should have 3 elements", 3, sortedKeys.size()); + assertEquals("First key should be 'apple' (2.0, alphabetically before zebra)", "apple", sortedKeys.get(0)); + assertEquals("Second key should be 'zebra' (2.0, alphabetically after apple)", "zebra", sortedKeys.get(1)); + assertEquals("Third key should be 'banana' (1.0)", "banana", sortedKeys.get(2)); + } + + @Test + public void testSortKeyByValueWithIntegerValues() throws Exception { + UDAFSortKeyByValue udaf = new UDAFSortKeyByValue(); + + GenericUDAFEvaluator evaluator = udaf.getEvaluator(new org.apache.hadoop.hive.serde2.typeinfo.TypeInfo[]{ + TypeInfoFactory.stringTypeInfo, + TypeInfoFactory.intTypeInfo + }); + + ObjectInspector[] parameters = { + PrimitiveObjectInspectorFactory.javaStringObjectInspector, + PrimitiveObjectInspectorFactory.javaIntObjectInspector + }; + evaluator.init(GenericUDAFEvaluator.Mode.COMPLETE, parameters); + + GenericUDAFEvaluator.AggregationBuffer agg = evaluator.getNewAggregationBuffer(); + + // Add test data with integer values + evaluator.iterate(agg, new Object[]{"high", 100}); + evaluator.iterate(agg, new Object[]{"low", 10}); + evaluator.iterate(agg, new Object[]{"medium", 50}); + + @SuppressWarnings("unchecked") + List sortedKeys = (List) evaluator.terminate(agg); + + assertEquals("Should have 3 elements", 3, sortedKeys.size()); + assertEquals("First key should be 'high'", "high", sortedKeys.get(0)); + assertEquals("Second key should be 'medium'", "medium", sortedKeys.get(1)); + assertEquals("Third key should be 'low'", "low", sortedKeys.get(2)); + } + + @Test + public void testSortKeyByValueWithNullValues() throws Exception { + UDAFSortKeyByValue udaf = new UDAFSortKeyByValue(); + + GenericUDAFEvaluator evaluator = udaf.getEvaluator(new org.apache.hadoop.hive.serde2.typeinfo.TypeInfo[]{ + TypeInfoFactory.stringTypeInfo, + TypeInfoFactory.doubleTypeInfo + }); + + ObjectInspector[] parameters = { + PrimitiveObjectInspectorFactory.javaStringObjectInspector, + PrimitiveObjectInspectorFactory.javaDoubleObjectInspector + }; + evaluator.init(GenericUDAFEvaluator.Mode.COMPLETE, parameters); + + GenericUDAFEvaluator.AggregationBuffer agg = evaluator.getNewAggregationBuffer(); + + // Add some valid data + evaluator.iterate(agg, new Object[]{"valid", 5.0}); + + // Try to add null values (should be ignored) + evaluator.iterate(agg, new Object[]{null, 3.0}); + evaluator.iterate(agg, new Object[]{"key", null}); + evaluator.iterate(agg, new Object[]{null, null}); + + @SuppressWarnings("unchecked") + List sortedKeys = (List) evaluator.terminate(agg); + + // Should only have the valid entry + assertEquals("Should have 1 element", 1, sortedKeys.size()); + assertEquals("Should contain only the valid key", "valid", sortedKeys.get(0)); + } + + @Test + public void testSortKeyByValueWithStringNumbers() throws Exception { + UDAFSortKeyByValue udaf = new UDAFSortKeyByValue(); + + GenericUDAFEvaluator evaluator = udaf.getEvaluator(new org.apache.hadoop.hive.serde2.typeinfo.TypeInfo[]{ + TypeInfoFactory.stringTypeInfo, + TypeInfoFactory.stringTypeInfo + }); + + ObjectInspector[] parameters = { + PrimitiveObjectInspectorFactory.javaStringObjectInspector, + PrimitiveObjectInspectorFactory.javaStringObjectInspector + }; + evaluator.init(GenericUDAFEvaluator.Mode.COMPLETE, parameters); + + GenericUDAFEvaluator.AggregationBuffer agg = evaluator.getNewAggregationBuffer(); + + // Add test data with string numbers (should be compared as numbers, descending) + evaluator.iterate(agg, new Object[]{"first", "30"}); + evaluator.iterate(agg, new Object[]{"second", "10"}); + evaluator.iterate(agg, new Object[]{"third", "20"}); + evaluator.iterate(agg, new Object[]{"fourth", "5"}); + + @SuppressWarnings("unchecked") + List sortedKeys = (List) evaluator.terminate(agg); + + assertEquals("Should have 4 elements", 4, sortedKeys.size()); + assertEquals("First should be '30'", "first", sortedKeys.get(0)); + assertEquals("Second should be '20'", "third", sortedKeys.get(1)); + assertEquals("Third should be '10'", "second", sortedKeys.get(2)); + assertEquals("Fourth should be '5'", "fourth", sortedKeys.get(3)); + } + + @Test + public void testSortKeyByValueWithPureStringValues() throws Exception { + UDAFSortKeyByValue udaf = new UDAFSortKeyByValue(); + + GenericUDAFEvaluator evaluator = udaf.getEvaluator(new org.apache.hadoop.hive.serde2.typeinfo.TypeInfo[]{ + TypeInfoFactory.stringTypeInfo, + TypeInfoFactory.stringTypeInfo + }); + + ObjectInspector[] parameters = { + PrimitiveObjectInspectorFactory.javaStringObjectInspector, + PrimitiveObjectInspectorFactory.javaStringObjectInspector + }; + evaluator.init(GenericUDAFEvaluator.Mode.COMPLETE, parameters); + + GenericUDAFEvaluator.AggregationBuffer agg = evaluator.getNewAggregationBuffer(); + + // Add test data with pure string values (should be compared as strings, descending) + evaluator.iterate(agg, new Object[]{"key1", "zebra"}); + evaluator.iterate(agg, new Object[]{"key2", "apple"}); + evaluator.iterate(agg, new Object[]{"key3", "banana"}); + evaluator.iterate(agg, new Object[]{"key4", "cherry"}); + + @SuppressWarnings("unchecked") + List sortedKeys = (List) evaluator.terminate(agg); + + assertEquals("Should have 4 elements", 4, sortedKeys.size()); + assertEquals("First should be 'zebra'", "key1", sortedKeys.get(0)); + assertEquals("Second should be 'cherry'", "key4", sortedKeys.get(1)); + assertEquals("Third should be 'banana'", "key3", sortedKeys.get(2)); + assertEquals("Fourth should be 'apple'", "key2", sortedKeys.get(3)); + } + + @Test + public void testSortKeyByValueWithMixedValues() throws Exception { + UDAFSortKeyByValue udaf = new UDAFSortKeyByValue(); + + GenericUDAFEvaluator evaluator = udaf.getEvaluator(new org.apache.hadoop.hive.serde2.typeinfo.TypeInfo[]{ + TypeInfoFactory.stringTypeInfo, + TypeInfoFactory.stringTypeInfo + }); + + ObjectInspector[] parameters = { + PrimitiveObjectInspectorFactory.javaStringObjectInspector, + PrimitiveObjectInspectorFactory.javaStringObjectInspector + }; + evaluator.init(GenericUDAFEvaluator.Mode.COMPLETE, parameters); + + GenericUDAFEvaluator.AggregationBuffer agg = evaluator.getNewAggregationBuffer(); + + // Add test data with mixed numeric and non-numeric strings + evaluator.iterate(agg, new Object[]{"number", "10"}); + evaluator.iterate(agg, new Object[]{"text", "banana"}); + evaluator.iterate(agg, new Object[]{"number2", "5"}); + evaluator.iterate(agg, new Object[]{"text2", "apple"}); + + @SuppressWarnings("unchecked") + List sortedKeys = (List) evaluator.terminate(agg); + + // When mixed, numeric strings and non-numeric strings will be compared as strings (descending) + // So "banana" > "apple" > "5" > "10" (lexicographically descending) + assertEquals("Should have 4 elements", 4, sortedKeys.size()); + assertEquals("First should be 'banana'", "text", sortedKeys.get(0)); + assertEquals("Second should be 'apple'", "text2", sortedKeys.get(1)); + assertEquals("Third should be '5'", "number2", sortedKeys.get(2)); + assertEquals("Fourth should be '10'", "number", sortedKeys.get(3)); + } + + @Test + public void testSortKeyByValueEmptyData() throws Exception { + UDAFSortKeyByValue udaf = new UDAFSortKeyByValue(); + + GenericUDAFEvaluator evaluator = udaf.getEvaluator(new org.apache.hadoop.hive.serde2.typeinfo.TypeInfo[]{ + TypeInfoFactory.stringTypeInfo, + TypeInfoFactory.doubleTypeInfo + }); + + ObjectInspector[] parameters = { + PrimitiveObjectInspectorFactory.javaStringObjectInspector, + PrimitiveObjectInspectorFactory.javaDoubleObjectInspector + }; + evaluator.init(GenericUDAFEvaluator.Mode.COMPLETE, parameters); + + GenericUDAFEvaluator.AggregationBuffer agg = evaluator.getNewAggregationBuffer(); + + // Don't add any data + @SuppressWarnings("unchecked") + List sortedKeys = (List) evaluator.terminate(agg); + + assertNotNull("Result should not be null", sortedKeys); + assertEquals("Should be empty", 0, sortedKeys.size()); + } + + @Test(expected = org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException.class) + public void testInvalidArgumentCount() throws Exception { + UDAFSortKeyByValue udaf = new UDAFSortKeyByValue(); + + // Should throw exception for wrong number of arguments + udaf.getEvaluator(new org.apache.hadoop.hive.serde2.typeinfo.TypeInfo[]{ + TypeInfoFactory.stringTypeInfo + }); + } + + @Test + public void testReset() throws Exception { + UDAFSortKeyByValue udaf = new UDAFSortKeyByValue(); + + GenericUDAFEvaluator evaluator = udaf.getEvaluator(new org.apache.hadoop.hive.serde2.typeinfo.TypeInfo[]{ + TypeInfoFactory.stringTypeInfo, + TypeInfoFactory.doubleTypeInfo + }); + + ObjectInspector[] parameters = { + PrimitiveObjectInspectorFactory.javaStringObjectInspector, + PrimitiveObjectInspectorFactory.javaDoubleObjectInspector + }; + evaluator.init(GenericUDAFEvaluator.Mode.COMPLETE, parameters); + + GenericUDAFEvaluator.AggregationBuffer agg = evaluator.getNewAggregationBuffer(); + + // Add some data + evaluator.iterate(agg, new Object[]{"test", 1.0}); + + // Reset buffer + evaluator.reset(agg); + + // Add different data + evaluator.iterate(agg, new Object[]{"new", 2.0}); + + @SuppressWarnings("unchecked") + List sortedKeys = (List) evaluator.terminate(agg); + + // Should only contain the new data + assertEquals("Should have 1 element", 1, sortedKeys.size()); + assertEquals("Should contain only the new key", "new", sortedKeys.get(0)); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/aaronshan/functions/array/UDFArrayContainsTest.java b/src/test/java/com/chinagoods/bigdata/functions/array/UDFArrayContainsTest.java similarity index 97% rename from src/test/java/com/github/aaronshan/functions/array/UDFArrayContainsTest.java rename to src/test/java/com/chinagoods/bigdata/functions/array/UDFArrayContainsTest.java index a5efc4b..6df77aa 100644 --- a/src/test/java/com/github/aaronshan/functions/array/UDFArrayContainsTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/array/UDFArrayContainsTest.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; import com.google.common.collect.ImmutableList; import java.util.List; diff --git a/src/test/java/com/github/aaronshan/functions/array/UDFArrayIntersectTest.java b/src/test/java/com/chinagoods/bigdata/functions/array/UDFArrayIntersectTest.java similarity index 97% rename from src/test/java/com/github/aaronshan/functions/array/UDFArrayIntersectTest.java rename to src/test/java/com/chinagoods/bigdata/functions/array/UDFArrayIntersectTest.java index 37c1143..4c13828 100644 --- a/src/test/java/com/github/aaronshan/functions/array/UDFArrayIntersectTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/array/UDFArrayIntersectTest.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; diff --git a/src/test/java/com/github/aaronshan/functions/array/UDFArrayShuffleTest.java b/src/test/java/com/chinagoods/bigdata/functions/array/UDFArrayShuffleTest.java similarity index 91% rename from src/test/java/com/github/aaronshan/functions/array/UDFArrayShuffleTest.java rename to src/test/java/com/chinagoods/bigdata/functions/array/UDFArrayShuffleTest.java index 0f8a654..bef3085 100644 --- a/src/test/java/com/github/aaronshan/functions/array/UDFArrayShuffleTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/array/UDFArrayShuffleTest.java @@ -1,6 +1,5 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; -import com.github.aaronshan.functions.array.UDFArrayShuffle; import com.google.common.collect.ImmutableList; import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; diff --git a/src/test/java/com/github/aaronshan/functions/array/UDFArrayValueCountTest.java b/src/test/java/com/chinagoods/bigdata/functions/array/UDFArrayValueCountTest.java similarity index 95% rename from src/test/java/com/github/aaronshan/functions/array/UDFArrayValueCountTest.java rename to src/test/java/com/chinagoods/bigdata/functions/array/UDFArrayValueCountTest.java index 41c1acb..04c11bd 100644 --- a/src/test/java/com/github/aaronshan/functions/array/UDFArrayValueCountTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/array/UDFArrayValueCountTest.java @@ -1,11 +1,10 @@ -package com.github.aaronshan.functions.array; +package com.chinagoods.bigdata.functions.array; import com.google.common.collect.ImmutableList; import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory; import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; -import org.apache.hadoop.io.BooleanWritable; import org.apache.hadoop.io.LongWritable; import org.junit.Test; diff --git a/src/test/java/com/github/aaronshan/functions/bitwise/UDFBitCountTest.java b/src/test/java/com/chinagoods/bigdata/functions/bitwise/UDFBitCountTest.java similarity index 94% rename from src/test/java/com/github/aaronshan/functions/bitwise/UDFBitCountTest.java rename to src/test/java/com/chinagoods/bigdata/functions/bitwise/UDFBitCountTest.java index c344a33..f8ad839 100644 --- a/src/test/java/com/github/aaronshan/functions/bitwise/UDFBitCountTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/bitwise/UDFBitCountTest.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.bitwise; +package com.chinagoods.bigdata.functions.bitwise; import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.io.LongWritable; diff --git a/src/test/java/com/github/aaronshan/functions/date/UDFDayOfYearTest.java b/src/test/java/com/chinagoods/bigdata/functions/date/UDFDayOfYearTest.java similarity index 94% rename from src/test/java/com/github/aaronshan/functions/date/UDFDayOfYearTest.java rename to src/test/java/com/chinagoods/bigdata/functions/date/UDFDayOfYearTest.java index d70cdd6..88c35b9 100644 --- a/src/test/java/com/github/aaronshan/functions/date/UDFDayOfYearTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/date/UDFDayOfYearTest.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.date; +package com.chinagoods.bigdata.functions.date; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; diff --git a/src/test/java/com/github/aaronshan/functions/geo/UDFGeoBdToGcjTest.java b/src/test/java/com/chinagoods/bigdata/functions/geo/UDFGeoBdToGcjTest.java similarity index 93% rename from src/test/java/com/github/aaronshan/functions/geo/UDFGeoBdToGcjTest.java rename to src/test/java/com/chinagoods/bigdata/functions/geo/UDFGeoBdToGcjTest.java index a720e53..4cff787 100644 --- a/src/test/java/com/github/aaronshan/functions/geo/UDFGeoBdToGcjTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/geo/UDFGeoBdToGcjTest.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.geo; +package com.chinagoods.bigdata.functions.geo; import org.apache.hadoop.io.Text; import org.junit.Assert; diff --git a/src/test/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayGroupTest.java b/src/test/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayGroupTest.java new file mode 100644 index 0000000..832f61e --- /dev/null +++ b/src/test/java/com/chinagoods/bigdata/functions/json/UDFJsonArrayGroupTest.java @@ -0,0 +1,112 @@ +package com.chinagoods.bigdata.functions.json; + +import org.junit.Test; +import static org.junit.Assert.*; + +import java.util.ArrayList; + +/** + * UDFJsonArrayGroup 测试类 + */ +public class UDFJsonArrayGroupTest { + + private UDFJsonArrayGroup udf = new UDFJsonArrayGroup(); + + @Test + public void testDefaultParameters() { + // 测试默认参数(分组大小为2,分隔符为#) + String jsonString = "[\"a\",\"b\",\"c\",\"d\"]"; + ArrayList result = udf.evaluate(jsonString); + + assertNotNull(result); + assertEquals(2, result.size()); + assertEquals("a#b", result.get(0)); + assertEquals("c#d", result.get(1)); + } + + @Test + public void testCustomGroupSize() { + // 测试自定义分组大小 + String jsonString = "[\"a\",\"b\",\"c\",\"d\",\"e\"]"; + ArrayList result = udf.evaluate(jsonString, 3); + + assertNotNull(result); + assertEquals(2, result.size()); + assertEquals("a#b#c", result.get(0)); + assertEquals("d#e", result.get(1)); + } + + @Test + public void testCustomSeparator() { + // 测试自定义分隔符 + String jsonString = "[\"a\",\"b\",\"c\",\"d\"]"; + ArrayList result = udf.evaluate(jsonString, 2, "|"); + + assertNotNull(result); + assertEquals(2, result.size()); + assertEquals("a|b", result.get(0)); + assertEquals("c|d", result.get(1)); + } + + @Test + public void testSingleElement() { + // 测试单个元素 + String jsonString = "[\"a\"]"; + ArrayList result = udf.evaluate(jsonString); + + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals("a", result.get(0)); + } + + @Test + public void testEmptyArray() { + // 测试空数组 + String jsonString = "[]"; + ArrayList result = udf.evaluate(jsonString); + + assertNotNull(result); + assertEquals(0, result.size()); + } + + @Test + public void testNullInput() { + // 测试空输入 + ArrayList result = udf.evaluate(null); + assertNull(result); + } + + @Test + public void testInvalidGroupSize() { + // 测试无效的分组大小 + String jsonString = "[\"a\",\"b\",\"c\"]"; + ArrayList result = udf.evaluate(jsonString, 0); + assertNull(result); + + result = udf.evaluate(jsonString, -1); + assertNull(result); + } + + @Test + public void testLargeGroupSize() { + // 测试分组大小大于数组长度 + String jsonString = "[\"a\",\"b\"]"; + ArrayList result = udf.evaluate(jsonString, 5); + + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals("a#b", result.get(0)); + } + + @Test + public void testNumbersAndStrings() { + // 测试数字和字符串混合 + String jsonString = "[\"a\",1,\"c\",2.5]"; + ArrayList result = udf.evaluate(jsonString, 2); + + assertNotNull(result); + assertEquals(2, result.size()); + assertEquals("a#1", result.get(0)); + assertEquals("c#2.5", result.get(1)); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/aaronshan/functions/map/UDFMapBuildTest.java b/src/test/java/com/chinagoods/bigdata/functions/map/UDFMapBuildTest.java similarity index 91% rename from src/test/java/com/github/aaronshan/functions/map/UDFMapBuildTest.java rename to src/test/java/com/chinagoods/bigdata/functions/map/UDFMapBuildTest.java index 0fc2ed6..a314cd2 100644 --- a/src/test/java/com/github/aaronshan/functions/map/UDFMapBuildTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/map/UDFMapBuildTest.java @@ -1,7 +1,6 @@ -package com.github.aaronshan.functions.map; +package com.chinagoods.bigdata.functions.map; -import com.github.aaronshan.functions.utils.MapUtils; -import com.github.aaronshan.functions.utils.MapUtils; +import com.chinagoods.bigdata.functions.utils.MapUtils; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; @@ -15,8 +14,6 @@ import org.junit.Assert; import org.junit.Test; -import static org.junit.Assert.*; - /** * @author ruifeng.shan * @date 2016-07-27 diff --git a/src/test/java/com/github/aaronshan/functions/map/UDFMapConcatTest.java b/src/test/java/com/chinagoods/bigdata/functions/map/UDFMapConcatTest.java similarity index 92% rename from src/test/java/com/github/aaronshan/functions/map/UDFMapConcatTest.java rename to src/test/java/com/chinagoods/bigdata/functions/map/UDFMapConcatTest.java index 0094f43..2088347 100644 --- a/src/test/java/com/github/aaronshan/functions/map/UDFMapConcatTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/map/UDFMapConcatTest.java @@ -1,7 +1,6 @@ -package com.github.aaronshan.functions.map; +package com.chinagoods.bigdata.functions.map; -import com.github.aaronshan.functions.utils.MapUtils; -import com.github.aaronshan.functions.utils.MapUtils; +import com.chinagoods.bigdata.functions.utils.MapUtils; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import java.util.LinkedHashMap; @@ -13,8 +12,6 @@ import org.junit.Assert; import org.junit.Test; -import static org.junit.Assert.*; - /** * @author ruifeng.shan * @date 2016-07-27 diff --git a/src/test/java/com/github/aaronshan/functions/map/UDFMapElementAtTest.java b/src/test/java/com/chinagoods/bigdata/functions/map/UDFMapElementAtTest.java similarity index 91% rename from src/test/java/com/github/aaronshan/functions/map/UDFMapElementAtTest.java rename to src/test/java/com/chinagoods/bigdata/functions/map/UDFMapElementAtTest.java index b98259d..3e846a8 100644 --- a/src/test/java/com/github/aaronshan/functions/map/UDFMapElementAtTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/map/UDFMapElementAtTest.java @@ -1,11 +1,9 @@ -package com.github.aaronshan.functions.map; +package com.chinagoods.bigdata.functions.map; -import com.github.aaronshan.functions.utils.MapUtils; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import java.util.LinkedHashMap; -import java.util.List; + import org.apache.hadoop.hive.ql.udf.generic.GenericUDF.DeferredJavaObject; import org.apache.hadoop.hive.ql.udf.generic.GenericUDF.DeferredObject; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; diff --git a/src/test/java/com/github/aaronshan/functions/map/UDFMapEqualsTest.java b/src/test/java/com/chinagoods/bigdata/functions/map/UDFMapEqualsTest.java similarity index 96% rename from src/test/java/com/github/aaronshan/functions/map/UDFMapEqualsTest.java rename to src/test/java/com/chinagoods/bigdata/functions/map/UDFMapEqualsTest.java index af8917f..3f1b3df 100644 --- a/src/test/java/com/github/aaronshan/functions/map/UDFMapEqualsTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/map/UDFMapEqualsTest.java @@ -1,6 +1,5 @@ -package com.github.aaronshan.functions.map; +package com.chinagoods.bigdata.functions.map; -import com.github.aaronshan.functions.utils.MapUtils; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import java.util.LinkedHashMap; diff --git a/src/test/java/com/github/aaronshan/functions/math/UDFMathCosineSimilarityTest.java b/src/test/java/com/chinagoods/bigdata/functions/math/UDFMathCosineSimilarityTest.java similarity index 98% rename from src/test/java/com/github/aaronshan/functions/math/UDFMathCosineSimilarityTest.java rename to src/test/java/com/chinagoods/bigdata/functions/math/UDFMathCosineSimilarityTest.java index ecff4ea..bd4d62f 100644 --- a/src/test/java/com/github/aaronshan/functions/math/UDFMathCosineSimilarityTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/math/UDFMathCosineSimilarityTest.java @@ -1,4 +1,4 @@ -package com.github.aaronshan.functions.math; +package com.chinagoods.bigdata.functions.math; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; diff --git a/src/test/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpExtractAllTest.java b/src/test/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpExtractAllTest.java similarity index 92% rename from src/test/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpExtractAllTest.java rename to src/test/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpExtractAllTest.java index f8b59eb..1a38afb 100644 --- a/src/test/java/com/github/aaronshan/functions/regexp/UDFRe2JRegexpExtractAllTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/regexp/UDFRe2JRegexpExtractAllTest.java @@ -1,8 +1,7 @@ -package com.github.aaronshan.functions.regexp; +package com.chinagoods.bigdata.functions.regexp; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; -import org.apache.hadoop.hive.ql.exec.UDFArgumentException; import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; diff --git a/src/test/java/com/github/aaronshan/functions/string/UDFStringSplitToMapTest.java b/src/test/java/com/chinagoods/bigdata/functions/string/UDFStringSplitToMapTest.java similarity index 91% rename from src/test/java/com/github/aaronshan/functions/string/UDFStringSplitToMapTest.java rename to src/test/java/com/chinagoods/bigdata/functions/string/UDFStringSplitToMapTest.java index a1e82e6..9b30507 100644 --- a/src/test/java/com/github/aaronshan/functions/string/UDFStringSplitToMapTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/string/UDFStringSplitToMapTest.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.string; +package com.chinagoods.bigdata.functions.string; -import com.github.aaronshan.functions.utils.MapUtils; +import com.chinagoods.bigdata.functions.utils.MapUtils; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; diff --git a/src/test/java/com/github/aaronshan/functions/string/UDFStringSplitToMultimapTest.java b/src/test/java/com/chinagoods/bigdata/functions/string/UDFStringSplitToMultimapTest.java similarity index 92% rename from src/test/java/com/github/aaronshan/functions/string/UDFStringSplitToMultimapTest.java rename to src/test/java/com/chinagoods/bigdata/functions/string/UDFStringSplitToMultimapTest.java index d7fe5fd..be41dbd 100644 --- a/src/test/java/com/github/aaronshan/functions/string/UDFStringSplitToMultimapTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/string/UDFStringSplitToMultimapTest.java @@ -1,6 +1,6 @@ -package com.github.aaronshan.functions.string; +package com.chinagoods.bigdata.functions.string; -import com.github.aaronshan.functions.utils.MapUtils; +import com.chinagoods.bigdata.functions.utils.MapUtils; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; diff --git a/src/test/java/com/chinagoods/bigdata/functions/url/UDFStandardUrlFormatTest.java b/src/test/java/com/chinagoods/bigdata/functions/url/UDFStandardUrlFormatTest.java new file mode 100644 index 0000000..59d0b14 --- /dev/null +++ b/src/test/java/com/chinagoods/bigdata/functions/url/UDFStandardUrlFormatTest.java @@ -0,0 +1,71 @@ +package com.chinagoods.bigdata.functions.url; + +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.apache.hadoop.io.Text; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +public class UDFStandardUrlFormatTest { + private static final Logger logger = LoggerFactory.getLogger(UDFStandardUrlFormat.class); + private static final String DB_URL = "jdbc:mysql://172.18.5.10:23307/source?characterEncoding=UTF-8&useSSL=false"; + private static final String DB_USER = "source"; + private static final String DB_PASSWORD = "jP8*dKw,bRjBVos="; + + @Test + public void testMiniProgramsUrl() throws Exception { +// String aa="https://m.chinagoods.com/searchsort/?typeKeywords=????&product_type_id=587&parent_product_type_id=35&from=indushttps://www.chinagoods.com/search/categoryProduct/T--51---S--1---P--1"; +// System.out.println(aa.lastIndexOf("/")); +// String ss=aa.substring(161,180); +// System.out.print(ss); + ArrayList resList; + try (UDFStandardUrlFormat udf = new UDFStandardUrlFormat()) { + ObjectInspector platform_type = PrimitiveObjectInspectorFactory.javaStringObjectInspector; + ObjectInspector sc_url = PrimitiveObjectInspectorFactory.javaStringObjectInspector; + ObjectInspector[] arguments = {platform_type, sc_url}; + udf.initialize(arguments); + + resList = null; + GenericUDF.DeferredObject sourceObj = new GenericUDF.DeferredJavaObject("wap"); + GenericUDF.DeferredObject patternObj = new GenericUDF.DeferredJavaObject("https://m.chinagoods.com/searchsort/?typeKeywords=????&product_type_id=587&parent_product_type_id=35&from=indushttps://www.chinagoods.com/search/categoryProduct/T--51---S--1---P--1"); + GenericUDF.DeferredObject[] args = {sourceObj, patternObj}; + resList = udf.evaluate(args); + + } + +// String RULE_SQL = "select platform_type,sc_url from test2 where" + +// " sc_url not like 'http://localhost%' " + +// "and sc_url not like 'https://localhost%' " + +// "and sc_url not like 'http://%.%.%.%' " + +// "and sc_url not like 'https://%.%.%.%' " + +// "and sc_url not like '%cgb.chinagoods.com%'"; + +// String RULE_SQL = "select platform_type,sc_url from standard_rule_url where regex is not null"; +// MysqlUtil mysqlUtil = new MysqlUtil(DB_URL, DB_USER, DB_PASSWORD); +// List> list = mysqlUtil.getLists(RULE_SQL); +// int a = 0; +// for (List r:list) { +// ArrayList reslist1 = new ArrayList<>(); +// List array = null; +// try { +// GenericUDF.DeferredObject sourceObj1 = new GenericUDF.DeferredJavaObject(r.get(0)); +// GenericUDF.DeferredObject patternObj1 = new GenericUDF.DeferredJavaObject(r.get(1)); +// GenericUDF.DeferredObject[] args1 = {sourceObj1, patternObj1}; +// reslist1 = udf.evaluate(args1); +// } catch (Exception e) { +// e.printStackTrace(); +// System.out.println(array); +// } +// if (reslist1.size() != 4 || reslist1.get(0).toString().equals("0000")) { +// a++; +// System.out.println(a+"************************"); +// System.out.println(r.get(0) + "-----" + r.get(1) + "-----" + reslist1); +// } +// } + + } +} diff --git a/src/test/java/com/github/aaronshan/functions/url/UDFUrlDecodeTest.java b/src/test/java/com/chinagoods/bigdata/functions/url/UDFUrlDecodeTest.java similarity index 89% rename from src/test/java/com/github/aaronshan/functions/url/UDFUrlDecodeTest.java rename to src/test/java/com/chinagoods/bigdata/functions/url/UDFUrlDecodeTest.java index a771cd1..0dadaf7 100644 --- a/src/test/java/com/github/aaronshan/functions/url/UDFUrlDecodeTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/url/UDFUrlDecodeTest.java @@ -1,11 +1,9 @@ -package com.github.aaronshan.functions.url; +package com.chinagoods.bigdata.functions.url; import org.apache.hadoop.io.Text; import org.junit.Assert; import org.junit.Test; -import static org.junit.Assert.*; - /** * @author ruifeng.shan * @date 2016-07-28 diff --git a/src/test/java/com/github/aaronshan/functions/url/UDFUrlEncodeTest.java b/src/test/java/com/chinagoods/bigdata/functions/url/UDFUrlEncodeTest.java similarity index 83% rename from src/test/java/com/github/aaronshan/functions/url/UDFUrlEncodeTest.java rename to src/test/java/com/chinagoods/bigdata/functions/url/UDFUrlEncodeTest.java index 3cec438..a264b82 100644 --- a/src/test/java/com/github/aaronshan/functions/url/UDFUrlEncodeTest.java +++ b/src/test/java/com/chinagoods/bigdata/functions/url/UDFUrlEncodeTest.java @@ -1,12 +1,9 @@ -package com.github.aaronshan.functions.url; +package com.chinagoods.bigdata.functions.url; -import com.github.aaronshan.functions.date.UDFDayOfYear; import org.apache.hadoop.io.Text; import org.junit.Assert; import org.junit.Test; -import static org.junit.Assert.*; - /** * @author ruifeng.shan * @date 2016-07-28