>From Ali Alsuliman <[email protected]>:

Ali Alsuliman has uploaded this change for review. ( 
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19829 )


Change subject: hash func
......................................................................

hash func

Change-Id: I426bea33d8eec5adfe94dfe1566ee58dccf1e169
---
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
A 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/FromBaseDescriptor.java
M 
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
A 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/HashBytesStrDescriptor.java
4 files changed, 386 insertions(+), 0 deletions(-)



  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/29/19829/1

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 1250eb9..bffe062 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
@@ -1307,6 +1307,10 @@

     public static final FunctionIdentifier IF_ERROR = 
FunctionConstants.newAsterix("if-error", 2);

+    public static final FunctionIdentifier HASHBYTES_STR = 
FunctionConstants.newAsterix("hashbytes-str", 2);
+
+    public static final FunctionIdentifier FROM_BASE = 
FunctionConstants.newAsterix("from-base", 2);
+
     static {
         // first, take care of Algebricks builtin functions
         addFunction(IS_MISSING, BooleanOnlyTypeComputer.INSTANCE, true);
@@ -2180,6 +2184,8 @@
         addPrivateFunction(ACCESS_FIELD, FieldAccessByNameResultType.INSTANCE, 
false);
         addPrivateFunction(ACCESS_NESTED_FIELD, 
FieldAccessNestedResultType.INSTANCE, false);

+        addFunction(HASHBYTES_STR, AStringTypeComputer.INSTANCE_NULLABLE, 
true);
+        addFunction(FROM_BASE, AInt64TypeComputer.INSTANCE_NULLABLE, true);
     }

     static {
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/FromBaseDescriptor.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/FromBaseDescriptor.java
new file mode 100644
index 0000000..5385400
--- /dev/null
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/FromBaseDescriptor.java
@@ -0,0 +1,125 @@
+/*
+ * 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.formats.nontagged.SerializerDeserializerProvider;
+import org.apache.asterix.om.base.AInt64;
+import org.apache.asterix.om.base.AMutableInt32;
+import org.apache.asterix.om.base.AMutableInt64;
+import org.apache.asterix.om.exceptions.ExceptionUtil;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.BuiltinType;
+import 
org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+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.dataflow.value.ISerializerDeserializer;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.VoidPointable;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+import org.apache.hyracks.util.string.UTF8StringUtil;
+
+@MissingNullInOutFunction
+public class FromBaseDescriptor extends 
AbstractScalarFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final IFunctionDescriptorFactory FACTORY = 
FromBaseDescriptor::new;
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final 
IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final 
IEvaluatorContext ctx) throws HyracksDataException {
+                return new IScalarEvaluator() {
+
+                    private final ArrayBackedValueStorage storage = new 
ArrayBackedValueStorage();
+                    private final StringBuilder strBuilder = new 
StringBuilder();
+                    private final IScalarEvaluator evalString = 
args[0].createScalarEvaluator(ctx);
+                    private final IScalarEvaluator evalBase = 
args[1].createScalarEvaluator(ctx);
+                    private final IPointable argString = new VoidPointable();
+                    private final IPointable argNumber = new VoidPointable();
+                    private final AMutableInt32 aInt32 = new AMutableInt32(0);
+                    private final AMutableInt64 aInt64 = new AMutableInt64(0);
+                    @SuppressWarnings("unchecked")
+                    private final ISerializerDeserializer<AInt64> int64Serde =
+                            
SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT64);
+
+                    @Override
+                    public void evaluate(IFrameTupleReference tuple, 
IPointable result) throws HyracksDataException {
+                        evalString.evaluate(tuple, argString);
+                        evalBase.evaluate(tuple, argNumber);
+
+                        if (PointableHelper.checkAndSetMissingOrNull(result, 
argString, argNumber)) {
+                            return;
+                        }
+                        byte[] bytes = argNumber.getByteArray();
+                        int offset = argNumber.getStartOffset();
+                        if (!ArgumentUtils.setInteger(ctx, sourceLoc, 
getIdentifier(), 1, bytes, offset, aInt32)) {
+                            PointableHelper.setNull(result);
+                            return;
+                        }
+                        int base = aInt32.getIntegerValue();
+                        if (base < 2 || base > 36) {
+                            PointableHelper.setNull(result);
+                            return;
+                        }
+
+                        bytes = argString.getByteArray();
+                        offset = argString.getStartOffset();
+                        if (bytes[offset] != 
ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
+                            PointableHelper.setNull(result);
+                            ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, 
getIdentifier(), bytes[offset], 0,
+                                    ATypeTag.STRING);
+                            return;
+                        }
+                        strBuilder.setLength(0);
+                        UTF8StringUtil.toString(strBuilder, bytes, offset + 1);
+
+                        try {
+                            aInt64.setValue(Long.parseLong(strBuilder, 0, 
strBuilder.length(), base));
+                        } catch (NumberFormatException e) {
+                            PointableHelper.setNull(result);
+                            return;
+                        }
+                        storage.reset();
+                        int64Serde.serialize(aInt64, storage.getDataOutput());
+                        result.set(storage);
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.FROM_BASE;
+    }
+
+}
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/HashBytesStrDescriptor.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/HashBytesStrDescriptor.java
new file mode 100644
index 0000000..bf992cf
--- /dev/null
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/HashBytesStrDescriptor.java
@@ -0,0 +1,242 @@
+/*
+ * 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.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.apache.asterix.common.annotations.MissingNullInOutFunction;
+import org.apache.asterix.dataflow.data.nontagged.printers.PrintTools;
+import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
+import org.apache.asterix.om.base.ARecord;
+import org.apache.asterix.om.base.AString;
+import org.apache.asterix.om.base.IAObject;
+import org.apache.asterix.om.exceptions.ExceptionUtil;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.ATypeTag;
+import 
org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.asterix.runtime.functions.FunctionTypeInferers;
+import org.apache.asterix.runtime.utils.DescriptorFactoryUtil;
+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.algebricks.runtime.evaluators.ConstantEvalFactory;
+import org.apache.hyracks.api.context.IEvaluatorContext;
+import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.VoidPointable;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+import org.apache.hyracks.data.std.util.ByteArrayAccessibleDataInputStream;
+import org.apache.hyracks.data.std.util.ByteArrayAccessibleInputStream;
+import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+import org.apache.hyracks.util.bytes.Base64Printer;
+import org.apache.hyracks.util.bytes.HexPrinter;
+import org.apache.hyracks.util.string.UTF8StringWriter;
+
+@MissingNullInOutFunction
+public class HashBytesStrDescriptor extends 
AbstractScalarFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final IFunctionDescriptorFactory FACTORY = 
DescriptorFactoryUtil.createFactory(HashBytesStrDescriptor::new, 
FunctionTypeInferers.SET_ARGUMENTS_TYPE);
+
+    private ARecordType recType;
+
+    @Override
+    public void setImmutableStates(Object... states) {
+        if (states.length > 1 && states[1] instanceof ARecordType) {
+            this.recType = (ARecordType) states[1];
+        }
+    }
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final 
IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final 
IEvaluatorContext ctx) throws HyracksDataException {
+                return new IScalarEvaluator() {
+
+                    private final IScalarEvaluator eval = 
args[0].createScalarEvaluator(ctx);
+                    private final IScalarEvaluator optionsEval = 
args[1].createScalarEvaluator(ctx);
+                    private final ArrayBackedValueStorage storage = new 
ArrayBackedValueStorage(43);
+                    private final IPointable argPtr = new VoidPointable();
+                    private final IPointable optionsPtr = new VoidPointable();
+                    private final UTF8StringWriter writer = new 
UTF8StringWriter();
+                    private final StringBuilder strBuilder = new 
StringBuilder(40);
+                    private Encoding encoding;
+                    private MessageDigest md;
+                    {
+                        trySetOptions(args[1]);
+                    }
+
+                    @Override
+                    public void evaluate(IFrameTupleReference tuple, 
IPointable result) throws HyracksDataException {
+                        eval.evaluate(tuple, argPtr);
+                        optionsEval.evaluate(tuple, optionsPtr);
+                        if (PointableHelper.checkAndSetMissingOrNull(result, 
argPtr, optionsPtr)) {
+                            return;
+                        }
+                        byte[] bytes = argPtr.getByteArray();
+                        int offset = argPtr.getStartOffset();
+                        if (bytes[offset] != 
ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
+                            PointableHelper.setNull(result);
+                            ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, 
getIdentifier(), bytes[offset], 0,
+                                    ATypeTag.STRING);
+                            return;
+                        }
+
+                        if (md == null || encoding == null) {
+                            if (!processOptions(optionsPtr)) {
+                                PointableHelper.setNull(result);
+                                return;
+                            }
+                        }
+
+                        storage.reset();
+                        try {
+                            PrintTools.writeUTF8StringRaw(bytes, offset + 1, 
argPtr.getLength() - 1,
+                                    storage.getDataOutput());
+                            md.update(storage.getByteArray(), 
storage.getStartOffset(), storage.getLength());
+                            byte[] digestBytes = md.digest();
+                            strBuilder.setLength(0);
+                            if (encoding == Encoding.BASE64) {
+                                Base64Printer.printBase64Binary(digestBytes, 
0, digestBytes.length, strBuilder);
+                            } else if (encoding == Encoding.HEX) {
+                                HexPrinter.printHexString(digestBytes, 0, 
digestBytes.length, strBuilder);
+                            } else {
+                                PointableHelper.setNull(result);
+                                return;
+                            }
+                            storage.reset();
+                            
storage.getDataOutput().writeByte(ATypeTag.SERIALIZED_STRING_TYPE_TAG);
+                            writer.writeUTF8(strBuilder, 
storage.getDataOutput());
+                        } catch (IOException e) {
+                            throw HyracksDataException.create(e);
+                        }
+                        result.set(storage);
+                    }
+
+                    private boolean processOptions(IPointable optionsEval) 
throws HyracksDataException {
+                        if (recType == null) {
+                            return false;
+                        }
+                        @SuppressWarnings("unchecked")
+                        ISerializerDeserializer<ARecord> serde =
+                                
SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(recType);
+                        ARecord rec = serde.deserialize(new 
ByteArrayAccessibleDataInputStream(new 
ByteArrayAccessibleInputStream(optionsEval.getByteArray(), 
optionsEval.getStartOffset(), optionsEval.getLength())));
+                        return setOptions(rec);
+                    }
+
+                    private void trySetOptions(IScalarEvaluatorFactory 
factory) throws HyracksDataException {
+                        if (!(factory instanceof ConstantEvalFactory) || 
recType == null) {
+                            return;
+                        }
+                        byte[] value = ((ConstantEvalFactory) 
factory).getValue();
+                        if (value[0] != ATypeTag.SERIALIZED_RECORD_TYPE_TAG) {
+                            return;
+                        }
+                        @SuppressWarnings("unchecked")
+                        ISerializerDeserializer<ARecord> serde =
+                                
SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(recType);
+                        ARecord rec = serde.deserialize(new 
ByteArrayAccessibleDataInputStream(new ByteArrayAccessibleInputStream(value, 0, 
value.length)));
+                        setOptions(rec);
+                    }
+
+                    private boolean setOptions(ARecord rec) throws 
HyracksDataException {
+                        ARecordType type = rec.getType();
+                        if (this.encoding == null) {
+                            int encodingIdx = type.getFieldIndex("encoding");
+                            if (encodingIdx < 0) {
+                                return false;
+                            }
+                            IAObject encodingVal = 
rec.getValueByPos(encodingIdx);
+                            if (encodingVal.getType().getTypeTag() != 
ATypeTag.STRING) {
+                                return true;
+                            }
+                            String encodingStr = ((AString) 
encodingVal).getStringValue();
+                            this.encoding = Encoding.from(encodingStr);
+                            if (this.encoding == null) {
+                                return false;
+                            }
+                        }
+                        if (md == null) {
+                            int algorithmIdx = type.getFieldIndex("algorithm");
+                            if (algorithmIdx < 0) {
+                                return false;
+                            }
+                            IAObject algorithmVal = 
rec.getValueByPos(algorithmIdx);
+                            if (algorithmVal.getType().getTypeTag() != 
ATypeTag.STRING) {
+                                return false;
+                            }
+                            String algorithmStr = ((AString) 
algorithmVal).getStringValue();
+                            if 
(HashAlgorithm.SHA1.toString().equalsIgnoreCase(algorithmStr)) {
+                                try {
+                                    md = 
MessageDigest.getInstance(HashAlgorithm.SHA1.algorithmName());
+                                } catch (NoSuchAlgorithmException e) {
+                                    throw HyracksDataException.create(e);
+                                }
+                            } else {
+                                return false;
+                            }
+                        }
+                        return true;
+                    }
+                };
+            }
+        };
+    }
+
+    enum HashAlgorithm {
+        SHA1, SHA256, SHA512;
+
+        String algorithmName() {
+            return switch (this) {
+                case SHA1 -> "SHA-1";
+                case SHA256 -> "SHA-256";
+                case SHA512 -> "SHA-512";
+            };
+        }
+    }
+
+    enum Encoding {
+        HEX, BASE64;
+
+        static Encoding from(String encodingStr) {
+            if (HEX.toString().equalsIgnoreCase(encodingStr)) {
+                return HEX;
+            } else if (BASE64.toString().equalsIgnoreCase(encodingStr)) {
+                return BASE64;
+            }
+            return null;
+        }
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.HASHBYTES_STR;
+    }
+
+}
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 f6ef58f..eb8b01f 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
@@ -382,6 +382,7 @@
 import org.apache.asterix.runtime.evaluators.functions.CreateUUIDDescriptor;
 import 
org.apache.asterix.runtime.evaluators.functions.DecodeDataverseNameDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.DeepEqualityDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.FromBaseDescriptor;
 import 
org.apache.asterix.runtime.evaluators.functions.FullTextContainsFunctionDescriptor;
 import 
org.apache.asterix.runtime.evaluators.functions.FullTextContainsWithoutOptionFunctionDescriptor;
 import 
org.apache.asterix.runtime.evaluators.functions.GetIntersectionDescriptor;
@@ -464,6 +465,7 @@
 import 
org.apache.asterix.runtime.evaluators.functions.RandomWithSeedDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ReferenceTileDescriptor;
 import 
org.apache.asterix.runtime.evaluators.functions.SerializedSizeDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.HashBytesStrDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.SleepDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.SpatialAreaDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.SpatialCellDescriptor;
@@ -1363,6 +1365,8 @@
         fc.add(SerializedSizeDescriptor.FACTORY);
         fc.add(PutAutogeneratedKeyDescriptor.FACTORY);
         fc.add(IfErrorDescriptor.FACTORY);
+        fc.add(HashBytesStrDescriptor.FACTORY);
+        fc.add(FromBaseDescriptor.FACTORY);

         
ServiceLoader.load(IFunctionRegistrant.class).iterator().forEachRemaining(c -> 
c.register(fc));
         return fc;

--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19829
To unsubscribe, or for help writing mail filters, visit 
https://asterix-gerrit.ics.uci.edu/settings

Gerrit-Project: asterixdb
Gerrit-Branch: ionic
Gerrit-Change-Id: I426bea33d8eec5adfe94dfe1566ee58dccf1e169
Gerrit-Change-Number: 19829
Gerrit-PatchSet: 1
Gerrit-Owner: Ali Alsuliman <[email protected]>
Gerrit-MessageType: newchange

Reply via email to