[ASTERIXDB-3615][FUN]: lpad and rpad func
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
- Implements the LPAD(input_str, length, pad_char) function
for left-padding strings to a target length using the specified pad_str.
- Truncates input if longer than the target length
- Supports Unicode input_str and pad_str.
- Implements the RPAD(input_str, length, pad_char) function
for right-padding strings to a target codepoint length using the pad_str.
Ext-ref: MB-67008
Change-Id: Ia74279fbbe9d23538c057cbbae9538cb219da1f2
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19828
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.00.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.00.ddl.sqlpp
new file mode 100644
index 0000000..897aac5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.00.ddl.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+drop dataset padding_example if exists;
+create dataset padding_example primary key (id:int);
+upsert into padding_example ([
+{"id":1, "f":"Hi", "f1": "👩"},
+{"id":2, "f": "-7262.98", "f1": "👨"},
+{"id":3, "f": "a𩸽b", "f1": "🎉"},
+{"id":4, "f": "👩👩👧👦", "f1": "✓✓✓"},
+{"id":5, "f": null, "f1" : null}
+]);
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.01.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.01.query.sqlpp
new file mode 100644
index 0000000..9b3f0bf
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.01.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+SELECT id, f, f1,
+ lpad(f, 10, '$') AS f_padded_with_dollar_to_10_codepoints,
+ lpad(f, 2, '$') AS f_truncated_or_padded_to_2_codepoints,
+ lpad(f, 10, '👩👩👧👦') AS f_padded_with_emoji_to_10_codepoints,
+ lpad(f1, 4, '%%') AS f1_padded_to_4_codepoints
+FROM padding_example
+ORDER BY id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.02.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.02.query.sqlpp
new file mode 100644
index 0000000..a1383e6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.02.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+SELECT
+ lpad('asterix', 11, '$&^') AS padded_to_11_codepoints,
+ lpad('👩👩👧', 2, '$') AS truncated_to_2_codepoints,
+ lpad('👩👩👧', 10, '👩👩👧👦') AS padded_to_10_codepoints,
+ lpad(null, 4, '%%') AS padded_to_null_is_null,
+ lpad(22, 11, 'y') AS padded_non_str,
+ lpad('abcd', -2, 'y') AS negative_length;
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.03.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.03.query.sqlpp
new file mode 100644
index 0000000..5adab87
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/lpad/lpad.03.query.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+SELECT lpad(repeat('a', 228), 240, '$') AS padded_long_input,
+ lpad(repeat('u', 310) || '你8世界🌍', 1000, repeat('彩2', 150) || 'END') AS very_long_unicode_test,
+ lpad(repeat('s', 95) || '©®™§¶你好世界🌍', 100, '$') AS very_long_truncation_with_unicode_result;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.00.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.00.ddl.sqlpp
new file mode 100644
index 0000000..897aac5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.00.ddl.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+drop dataset padding_example if exists;
+create dataset padding_example primary key (id:int);
+upsert into padding_example ([
+{"id":1, "f":"Hi", "f1": "👩"},
+{"id":2, "f": "-7262.98", "f1": "👨"},
+{"id":3, "f": "a𩸽b", "f1": "🎉"},
+{"id":4, "f": "👩👩👧👦", "f1": "✓✓✓"},
+{"id":5, "f": null, "f1" : null}
+]);
+
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.01.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.01.query.sqlpp
new file mode 100644
index 0000000..a95ec0b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.01.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+SELECT id, f, f1,
+ rpad(f, 10, '$') AS f_padded_with_dollar_to_10_codepoints,
+ rpad(f, 2, '$') AS f_truncated_or_padded_to_2_codepoints,
+ rpad(f, 10, '👩👩👧👦') AS f_padded_with_emoji_to_10_codepoints,
+ rpad(f1, 4, '%%') AS f1_padded_to_4_codepoints
+FROM padding_example
+ORDER BY id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.02.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.02.query.sqlpp
new file mode 100644
index 0000000..c0d1316
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.02.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+SELECT
+ rpad('asterix', 11, '$&^') AS padded_to_11_codepoints,
+ rpad('👩👩👧', 2, '$') AS truncated_to_2_codepoints,
+ rpad('👩👩👧', 10, '👩👩👧👦') AS padded_to_10_codepoints,
+ rpad(null, 4, '%%') AS padded_to_null_is_null,
+ rpad(22, 11, 'y') AS padded_non_str;
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.03.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.03.query.sqlpp
new file mode 100644
index 0000000..701d36b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/pad/rpad/rpad.03.query.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+SELECT rpad(repeat('a', 228), 240, '$') AS padded_long_input,
+ rpad(repeat('u', 310) || '你8世界🌍', 1000, repeat('彩2', 150) || 'END') AS very_long_unicode_test,
+ rpad(repeat('s', 95) || '©®™§¶你好世界🌍', 100, '$') AS very_long_truncation_with_unicode_result;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.01.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.01.adm
new file mode 100644
index 0000000..006e70c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.01.adm
@@ -0,0 +1,5 @@
+{ "id": 1, "f_padded_with_dollar_to_10_codepoints": "$$$$$$$$Hi", "f_truncated_or_padded_to_2_codepoints": "Hi", "f_padded_with_emoji_to_10_codepoints": "👩👩👧👦👩Hi", "f1_padded_to_4_codepoints": "%%%👩", "f": "Hi", "f1": "👩" }
+{ "id": 2, "f_padded_with_dollar_to_10_codepoints": "$$-7262.98", "f_truncated_or_padded_to_2_codepoints": "-7", "f_padded_with_emoji_to_10_codepoints": "👩-7262.98", "f1_padded_to_4_codepoints": "%%👨", "f": "-7262.98", "f1": "👨" }
+{ "id": 3, "f_padded_with_dollar_to_10_codepoints": "$$$$$$$a𩸽b", "f_truncated_or_padded_to_2_codepoints": "a𩸽", "f_padded_with_emoji_to_10_codepoints": "👩👩👧👦a𩸽b", "f1_padded_to_4_codepoints": "%%%🎉", "f": "a𩸽b", "f1": "🎉" }
+{ "id": 4, "f_padded_with_dollar_to_10_codepoints": "$$$👩👩👧👦", "f_truncated_or_padded_to_2_codepoints": "👩", "f_padded_with_emoji_to_10_codepoints": "👩👩👩👩👧👦", "f1_padded_to_4_codepoints": "%✓✓✓", "f": "👩👩👧👦", "f1": "✓✓✓" }
+{ "id": 5, "f_padded_with_dollar_to_10_codepoints": null, "f_truncated_or_padded_to_2_codepoints": null, "f_padded_with_emoji_to_10_codepoints": null, "f1_padded_to_4_codepoints": null, "f": null, "f1": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.02.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.02.adm
new file mode 100644
index 0000000..3f6d3e4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.02.adm
@@ -0,0 +1 @@
+{ "padded_to_11_codepoints": "$&^$asterix", "truncated_to_2_codepoints": "👩", "padded_to_10_codepoints": "👩👩👩👩👧", "padded_to_null_is_null": null, "padded_non_str": null, "negative_length": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.03.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.03.adm
new file mode 100644
index 0000000..6ef482b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/lpad/lpad.03.adm
@@ -0,0 +1 @@
+{ "padded_long_input": "$$$$$$$$$$$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "very_long_unicode_test": "彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2END彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2END彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu你8世界🌍", "very_long_truncation_with_unicode_result": "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss©®™§¶" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.01.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.01.adm
new file mode 100644
index 0000000..d534124
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.01.adm
@@ -0,0 +1,5 @@
+{ "id": 1, "f_padded_with_dollar_to_10_codepoints": "Hi$$$$$$$$", "f_truncated_or_padded_to_2_codepoints": "Hi", "f_padded_with_emoji_to_10_codepoints": "Hi👩👩👧👦👩", "f1_padded_to_4_codepoints": "👩%%%", "f": "Hi", "f1": "👩" }
+{ "id": 2, "f_padded_with_dollar_to_10_codepoints": "-7262.98$$", "f_truncated_or_padded_to_2_codepoints": "-7", "f_padded_with_emoji_to_10_codepoints": "-7262.98👩", "f1_padded_to_4_codepoints": "👨%%", "f": "-7262.98", "f1": "👨" }
+{ "id": 3, "f_padded_with_dollar_to_10_codepoints": "a𩸽b$$$$$$$", "f_truncated_or_padded_to_2_codepoints": "a𩸽", "f_padded_with_emoji_to_10_codepoints": "a𩸽b👩👩👧👦", "f1_padded_to_4_codepoints": "🎉%%%", "f": "a𩸽b", "f1": "🎉" }
+{ "id": 4, "f_padded_with_dollar_to_10_codepoints": "👩👩👧👦$$$", "f_truncated_or_padded_to_2_codepoints": "👩", "f_padded_with_emoji_to_10_codepoints": "👩👩👧👦👩👩", "f1_padded_to_4_codepoints": "✓✓✓%", "f": "👩👩👧👦", "f1": "✓✓✓" }
+{ "id": 5, "f_padded_with_dollar_to_10_codepoints": null, "f_truncated_or_padded_to_2_codepoints": null, "f_padded_with_emoji_to_10_codepoints": null, "f1_padded_to_4_codepoints": null, "f": null, "f1": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.02.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.02.adm
new file mode 100644
index 0000000..ba875f6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.02.adm
@@ -0,0 +1 @@
+{ "padded_to_11_codepoints": "asterix$&^$", "truncated_to_2_codepoints": "👩", "padded_to_10_codepoints": "👩👩👧👩👩", "padded_to_null_is_null": null, "padded_non_str": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.03.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.03.adm
new file mode 100644
index 0000000..8f86a8a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/pad/rpad/rpad.03.adm
@@ -0,0 +1 @@
+{ "padded_long_input": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$$$$$$$$$$$$", "very_long_unicode_test": "uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu你8世界🌍彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2END彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2END彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩2彩", "very_long_truncation_with_unicode_result": "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss©®™§¶" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
index de55877..600823a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
@@ -11711,6 +11711,16 @@
<expected-warn>Function 'position1' failed to evaluate because: Decoding error - got a low surrogate without a leading high surrogate</expected-warn>
</compilation-unit>
</test-case>
+ <test-case FilePath="string">
+ <compilation-unit name="pad/lpad">
+ <output-dir compare="Text">pad/lpad</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="string">
+ <compilation-unit name="pad/rpad">
+ <output-dir compare="Text">pad/rpad</output-dir>
+ </compilation-unit>
+ </test-case>
</test-group>
<test-group name="subquery">
<test-case FilePath="subquery">
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
index 790f040..f631b32 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
@@ -398,6 +398,8 @@
public static final FunctionIdentifier STRING_REPEAT = FunctionConstants.newAsterix("repeat", 2);
public static final FunctionIdentifier STRING_SPLIT = FunctionConstants.newAsterix("split", 2);
public static final FunctionIdentifier STRING_PARSE_JSON = FunctionConstants.newAsterix("parse-json", 1);
+ public static final FunctionIdentifier STRING_LPAD = FunctionConstants.newAsterix("lpad", 3);
+ public static final FunctionIdentifier STRING_RPAD = FunctionConstants.newAsterix("rpad", 3);
public static final FunctionIdentifier DATASET =
FunctionConstants.newAsterix("dataset", FunctionIdentifier.VARARGS); // 1, 2 or 3
@@ -1343,7 +1345,6 @@
addFunction(NOT, ABooleanTypeComputer.INSTANCE, true);
addFunction(GET_TYPE, AStringTypeComputer.INSTANCE, true);
-
addPrivateFunction(EQ, BooleanFunctionTypeComputer.INSTANCE, true);
addPrivateFunction(LE, BooleanFunctionTypeComputer.INSTANCE, true);
addPrivateFunction(GE, BooleanFunctionTypeComputer.INSTANCE, true);
@@ -1540,6 +1541,8 @@
addFunction(STRING_REPEAT, AStringTypeComputer.INSTANCE_NULLABLE, true);
addFunction(STRING_SPLIT, UniformInputTypeComputer.STRING_STRING_LIST_INSTANCE, true);
addFunction(STRING_PARSE_JSON, AnyTypeComputer.INSTANCE, true);
+ addFunction(STRING_LPAD, AStringTypeComputer.INSTANCE_NULLABLE, true);
+ addFunction(STRING_RPAD, AStringTypeComputer.INSTANCE_NULLABLE, true);
addPrivateFunction(ORDERED_LIST_CONSTRUCTOR, OrderedListConstructorTypeComputer.INSTANCE, true);
addFunction(POINT_CONSTRUCTOR, APointTypeComputer.INSTANCE, true);
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringLpadDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringLpadDescriptor.java
new file mode 100644
index 0000000..a801d9a
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringLpadDescriptor.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.asterix.runtime.evaluators.functions;
+
+import org.apache.asterix.common.annotations.MissingNullInOutFunction;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IEvaluatorContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+@MissingNullInOutFunction
+public class StringLpadDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+ private static final long serialVersionUID = 1L;
+
+ public static final IFunctionDescriptorFactory FACTORY = StringLpadDescriptor::new;
+
+ @Override
+ public FunctionIdentifier getIdentifier() {
+ return BuiltinFunctions.STRING_LPAD;
+ }
+
+ @Override
+ public IScalarEvaluatorFactory createEvaluatorFactory(IScalarEvaluatorFactory[] args) {
+ return new IScalarEvaluatorFactory() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public IScalarEvaluator createScalarEvaluator(IEvaluatorContext ctx) throws HyracksDataException {
+ return new StringPadEvaluator(ctx, args[0], args[1], args[2], StringLpadDescriptor.this.getIdentifier(),
+ sourceLoc, true) {
+ };
+ }
+ };
+ }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringPadEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringPadEvaluator.java
new file mode 100644
index 0000000..d4b01e2
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringPadEvaluator.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.asterix.runtime.evaluators.functions;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.asterix.om.base.AMutableInt32;
+import org.apache.asterix.om.exceptions.ExceptionUtil;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.runtime.evaluators.common.ArgumentUtils;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IEvaluatorContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.UTF8StringPointable;
+import org.apache.hyracks.data.std.primitive.VoidPointable;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+import org.apache.hyracks.data.std.util.GrowableArray;
+import org.apache.hyracks.data.std.util.UTF8StringBuilder;
+import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+import org.apache.hyracks.util.string.UTF8StringUtil;
+
+public abstract class StringPadEvaluator extends AbstractScalarEval {
+
+ private final IEvaluatorContext ctx;
+ private final IScalarEvaluator inStrEval;
+ private final IScalarEvaluator lenEval;
+ private final IScalarEvaluator padStrEval;
+
+ private final UTF8StringPointable inStrUtf8Ptr = new UTF8StringPointable();
+ private final UTF8StringPointable padStrUtf8Ptr = new UTF8StringPointable();
+ private final IPointable inStrArg = new VoidPointable();
+ private final IPointable lenArg = new VoidPointable();
+ private final IPointable padStrArg = new VoidPointable();
+ private final AMutableInt32 mutableInt = new AMutableInt32(0);
+
+ private final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
+ private final DataOutput out = resultStorage.getDataOutput();
+ private final GrowableArray builderInternalArray = new GrowableArray();
+ private final UTF8StringBuilder builder = new UTF8StringBuilder();
+ private final boolean lpad;
+
+ public StringPadEvaluator(IEvaluatorContext ctx, IScalarEvaluatorFactory inStrEvalFact,
+ IScalarEvaluatorFactory lenEvalFact, IScalarEvaluatorFactory padStrEvalFact, FunctionIdentifier funcID,
+ SourceLocation srcLoc, boolean lpad) throws HyracksDataException {
+ super(srcLoc, funcID);
+ this.lpad = lpad;
+ this.inStrEval = inStrEvalFact.createScalarEvaluator(ctx);
+ this.lenEval = lenEvalFact.createScalarEvaluator(ctx);
+ this.padStrEval = padStrEvalFact.createScalarEvaluator(ctx);
+ this.ctx = ctx;
+ }
+
+ @Override
+ public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
+ inStrEval.evaluate(tuple, inStrArg);
+ lenEval.evaluate(tuple, lenArg);
+ padStrEval.evaluate(tuple, padStrArg);
+
+ if (PointableHelper.checkAndSetMissingOrNull(result, inStrArg, lenArg, padStrArg)) {
+ return;
+ }
+
+ byte[] inStrBytes = inStrArg.getByteArray();
+ int inStrStart = inStrArg.getStartOffset();
+ if (inStrBytes[inStrStart] != ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
+ PointableHelper.setNull(result);
+ ExceptionUtil.warnTypeMismatch(ctx, srcLoc, funID, inStrBytes[inStrStart], 0, ATypeTag.STRING);
+ return;
+ }
+
+ byte[] lenBytes = lenArg.getByteArray();
+ int lenStart = lenArg.getStartOffset();
+ if (!ArgumentUtils.setInteger(ctx, srcLoc, funID, 1, lenBytes, lenStart, mutableInt)) {
+ PointableHelper.setNull(result);
+ return;
+ }
+ // Desired length of the string in Unicode code points
+ int targetNumCodePoints = mutableInt.getIntegerValue();
+ if (targetNumCodePoints < 0) {
+ PointableHelper.setNull(result);
+ ExceptionUtil.warnNegativeValue(ctx, srcLoc, funID, 1, targetNumCodePoints);
+ return;
+ }
+
+ // TODO: usually this will be a constant. if constant, the code could be optimized
+ byte[] padStrBytes = padStrArg.getByteArray();
+ int padStrStart = padStrArg.getStartOffset();
+ if (padStrBytes[padStrStart] != ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
+ PointableHelper.setNull(result);
+ ExceptionUtil.warnTypeMismatch(ctx, srcLoc, funID, padStrBytes[padStrStart], 2, ATypeTag.STRING);
+ return;
+ }
+
+ int inStrCodePointsNum = UTF8StringUtil.getNumCodePoint(inStrBytes, inStrStart + 1);
+ if (inStrCodePointsNum == targetNumCodePoints) {
+ result.set(inStrArg);
+ return;
+ }
+ try {
+ builderInternalArray.reset();
+ builder.reset(builderInternalArray, targetNumCodePoints);
+ // skip the type tag byte
+ inStrUtf8Ptr.set(inStrBytes, inStrStart + 1, inStrArg.getLength() - 1);
+ padStrUtf8Ptr.set(padStrBytes, padStrStart + 1, padStrArg.getLength() - 1);
+
+ process(targetNumCodePoints, inStrCodePointsNum);
+ builder.finish();
+
+ resultStorage.reset();
+ out.writeByte(ATypeTag.SERIALIZED_STRING_TYPE_TAG);
+ out.write(builderInternalArray.getByteArray(), 0, builderInternalArray.getLength());
+ //result -> type tag, len, actual data
+ result.set(resultStorage);
+ } catch (IOException e) {
+ throw HyracksDataException.create(e);
+ }
+ }
+
+ public void process(int targetNumCodePoints, int inStrCodePointsNum) throws IOException {
+ if (targetNumCodePoints < inStrCodePointsNum) {
+ truncate(targetNumCodePoints);
+ } else {
+ int numCodePointsToPad = targetNumCodePoints - inStrCodePointsNum;
+ if (lpad) {
+ // For LPAD: first, append the required padding characters.
+ appendPaddingCodepoints(numCodePointsToPad);
+ // Then, append the codepoints of the original string.
+ appendCodePoints();
+ } else {
+ appendCodePoints();
+ appendPaddingCodepoints(numCodePointsToPad);
+ }
+ }
+ }
+
+ private void truncate(int targetNumCodePoints) throws IOException {
+ UTF8StringPointable.append(inStrUtf8Ptr, targetNumCodePoints, builder, builderInternalArray);
+ }
+
+ private void appendCodePoints() throws IOException {
+ builder.appendUtf8StringPointable(inStrUtf8Ptr);
+ }
+
+ private void appendPaddingCodepoints(int numCodePointsToPad) throws IOException {
+ UTF8StringPointable.append(padStrUtf8Ptr, numCodePointsToPad, builder, builderInternalArray);
+ }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRpadDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRpadDescriptor.java
new file mode 100644
index 0000000..2ff28e4
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRpadDescriptor.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.asterix.runtime.evaluators.functions;
+
+import org.apache.asterix.common.annotations.MissingNullInOutFunction;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IEvaluatorContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+@MissingNullInOutFunction
+public class StringRpadDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+ private static final long serialVersionUID = 1L;
+
+ public static final IFunctionDescriptorFactory FACTORY = StringRpadDescriptor::new;
+
+ @Override
+ public FunctionIdentifier getIdentifier() {
+ return BuiltinFunctions.STRING_RPAD;
+ }
+
+ @Override
+ public IScalarEvaluatorFactory createEvaluatorFactory(IScalarEvaluatorFactory[] args) {
+ return new IScalarEvaluatorFactory() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public IScalarEvaluator createScalarEvaluator(IEvaluatorContext ctx) throws HyracksDataException {
+ return new StringPadEvaluator(ctx, args[0], args[1], args[2], StringRpadDescriptor.this.getIdentifier(),
+ sourceLoc, false) {
+ };
+ }
+ };
+ }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
index b4710de..166352c 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
@@ -483,6 +483,7 @@
import org.apache.asterix.runtime.evaluators.functions.StringLengthDescriptor;
import org.apache.asterix.runtime.evaluators.functions.StringLikeDescriptor;
import org.apache.asterix.runtime.evaluators.functions.StringLowerCaseDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.StringLpadDescriptor;
import org.apache.asterix.runtime.evaluators.functions.StringPositionDescriptor;
import org.apache.asterix.runtime.evaluators.functions.StringPositionOffset1Descriptor;
import org.apache.asterix.runtime.evaluators.functions.StringRTrim2Descriptor;
@@ -503,6 +504,7 @@
import org.apache.asterix.runtime.evaluators.functions.StringReplaceDescriptor;
import org.apache.asterix.runtime.evaluators.functions.StringReplaceWithLimitDescriptor;
import org.apache.asterix.runtime.evaluators.functions.StringReverseDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.StringRpadDescriptor;
import org.apache.asterix.runtime.evaluators.functions.StringSplitDescriptor;
import org.apache.asterix.runtime.evaluators.functions.StringStartsWithDescriptor;
import org.apache.asterix.runtime.evaluators.functions.StringToCodePointDescriptor;
@@ -1146,6 +1148,8 @@
fc.add(StringReplaceWithLimitDescriptor.FACTORY);
fc.add(StringReverseDescriptor.FACTORY);
fc.add(StringSplitDescriptor.FACTORY);
+ fc.add(StringLpadDescriptor.FACTORY);
+ fc.add(StringRpadDescriptor.FACTORY);
// Constructors
fc.add(ABooleanConstructorDescriptor.FACTORY);
diff --git a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/UTF8StringPointable.java b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/UTF8StringPointable.java
index 530dab4..81afdf6 100644
--- a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/UTF8StringPointable.java
+++ b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/UTF8StringPointable.java
@@ -474,6 +474,25 @@
return true;
}
+ /*
+ * Appends {@code numCodePoints} code points from the given source string {@code src} to the {@code builder}.
+ * {@code src} is shorter than {@code numCodePoints}, it repeats from the beginning of {@code src} as needed
+ * until the required number of code points have been appended.
+ */
+ public static void append(UTF8StringPointable src, int numCodePoints, UTF8StringBuilder builder, GrowableArray out)
+ throws IOException {
+ int utfLen = src.getUTF8Length();
+ int byteIdx = 0;
+ while (numCodePoints > 0) {
+ if (byteIdx == utfLen) {
+ byteIdx = 0;
+ }
+ builder.appendCodePoint(src.codePointAt(src.getMetaDataLength() + byteIdx));
+ numCodePoints--;
+ byteIdx += src.codePointSize(src.getMetaDataLength() + byteIdx);
+ }
+ }
+
public void substrBefore(UTF8StringPointable match, UTF8StringBuilder builder, GrowableArray out)
throws IOException {
substrBefore(this, match, builder, out);