[SPARK-21485][FOLLOWUP][SQL][DOCS] Describes examples and arguments separately, and...
[spark.git] / sql / catalyst / src / main / scala / org / apache / spark / sql / catalyst / expressions / bitwiseExpressions.scala
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *    http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package org.apache.spark.sql.catalyst.expressions
19
20 import org.apache.spark.sql.catalyst.expressions.codegen._
21 import org.apache.spark.sql.types._
22
23
24 /**
25  * A function that calculates bitwise and(&) of two numbers.
26  *
27  * Code generation inherited from BinaryArithmetic.
28  */
29 @ExpressionDescription(
30   usage = "expr1 _FUNC_ expr2 - Returns the result of bitwise AND of `expr1` and `expr2`.",
31   examples = """
32     Examples:
33       > SELECT 3 _FUNC_ 5;
34        1
35   """)
36 case class BitwiseAnd(left: Expression, right: Expression) extends BinaryArithmetic {
37
38   override def inputType: AbstractDataType = IntegralType
39
40   override def symbol: String = "&"
41
42   private lazy val and: (Any, Any) => Any = dataType match {
43     case ByteType =>
44       ((evalE1: Byte, evalE2: Byte) => (evalE1 & evalE2).toByte).asInstanceOf[(Any, Any) => Any]
45     case ShortType =>
46       ((evalE1: Short, evalE2: Short) => (evalE1 & evalE2).toShort).asInstanceOf[(Any, Any) => Any]
47     case IntegerType =>
48       ((evalE1: Int, evalE2: Int) => evalE1 & evalE2).asInstanceOf[(Any, Any) => Any]
49     case LongType =>
50       ((evalE1: Long, evalE2: Long) => evalE1 & evalE2).asInstanceOf[(Any, Any) => Any]
51   }
52
53   protected override def nullSafeEval(input1: Any, input2: Any): Any = and(input1, input2)
54 }
55
56 /**
57  * A function that calculates bitwise or(|) of two numbers.
58  *
59  * Code generation inherited from BinaryArithmetic.
60  */
61 @ExpressionDescription(
62   usage = "expr1 _FUNC_ expr2 - Returns the result of bitwise OR of `expr1` and `expr2`.",
63   examples = """
64     Examples:
65       > SELECT 3 _FUNC_ 5;
66        7
67   """)
68 case class BitwiseOr(left: Expression, right: Expression) extends BinaryArithmetic {
69
70   override def inputType: AbstractDataType = IntegralType
71
72   override def symbol: String = "|"
73
74   private lazy val or: (Any, Any) => Any = dataType match {
75     case ByteType =>
76       ((evalE1: Byte, evalE2: Byte) => (evalE1 | evalE2).toByte).asInstanceOf[(Any, Any) => Any]
77     case ShortType =>
78       ((evalE1: Short, evalE2: Short) => (evalE1 | evalE2).toShort).asInstanceOf[(Any, Any) => Any]
79     case IntegerType =>
80       ((evalE1: Int, evalE2: Int) => evalE1 | evalE2).asInstanceOf[(Any, Any) => Any]
81     case LongType =>
82       ((evalE1: Long, evalE2: Long) => evalE1 | evalE2).asInstanceOf[(Any, Any) => Any]
83   }
84
85   protected override def nullSafeEval(input1: Any, input2: Any): Any = or(input1, input2)
86 }
87
88 /**
89  * A function that calculates bitwise xor({@literal ^}) of two numbers.
90  *
91  * Code generation inherited from BinaryArithmetic.
92  */
93 @ExpressionDescription(
94   usage = "expr1 _FUNC_ expr2 - Returns the result of bitwise exclusive OR of `expr1` and `expr2`.",
95   examples = """
96     Examples:
97       > SELECT 3 _FUNC_ 5;
98        2
99   """)
100 case class BitwiseXor(left: Expression, right: Expression) extends BinaryArithmetic {
101
102   override def inputType: AbstractDataType = IntegralType
103
104   override def symbol: String = "^"
105
106   private lazy val xor: (Any, Any) => Any = dataType match {
107     case ByteType =>
108       ((evalE1: Byte, evalE2: Byte) => (evalE1 ^ evalE2).toByte).asInstanceOf[(Any, Any) => Any]
109     case ShortType =>
110       ((evalE1: Short, evalE2: Short) => (evalE1 ^ evalE2).toShort).asInstanceOf[(Any, Any) => Any]
111     case IntegerType =>
112       ((evalE1: Int, evalE2: Int) => evalE1 ^ evalE2).asInstanceOf[(Any, Any) => Any]
113     case LongType =>
114       ((evalE1: Long, evalE2: Long) => evalE1 ^ evalE2).asInstanceOf[(Any, Any) => Any]
115   }
116
117   protected override def nullSafeEval(input1: Any, input2: Any): Any = xor(input1, input2)
118 }
119
120 /**
121  * A function that calculates bitwise not(~) of a number.
122  */
123 @ExpressionDescription(
124   usage = "_FUNC_ expr - Returns the result of bitwise NOT of `expr`.",
125   examples = """
126     Examples:
127       > SELECT _FUNC_ 0;
128        -1
129   """)
130 case class BitwiseNot(child: Expression) extends UnaryExpression with ExpectsInputTypes {
131
132   override def inputTypes: Seq[AbstractDataType] = Seq(IntegralType)
133
134   override def dataType: DataType = child.dataType
135
136   override def toString: String = s"~$child"
137
138   private lazy val not: (Any) => Any = dataType match {
139     case ByteType =>
140       ((evalE: Byte) => (~evalE).toByte).asInstanceOf[(Any) => Any]
141     case ShortType =>
142       ((evalE: Short) => (~evalE).toShort).asInstanceOf[(Any) => Any]
143     case IntegerType =>
144       ((evalE: Int) => ~evalE).asInstanceOf[(Any) => Any]
145     case LongType =>
146       ((evalE: Long) => ~evalE).asInstanceOf[(Any) => Any]
147   }
148
149   override def doGenCode(ctx: CodegenContext, ev: ExprCode): ExprCode = {
150     defineCodeGen(ctx, ev, c => s"(${ctx.javaType(dataType)}) ~($c)")
151   }
152
153   protected override def nullSafeEval(input: Any): Any = not(input)
154
155   override def sql: String = s"~${child.sql}"
156 }