@@ -5,9 +5,11 @@ use itertools::Itertools;
5
5
use partiql_logical:: Type ;
6
6
use partiql_value:: Value :: { Boolean , Missing , Null } ;
7
7
use partiql_value:: {
8
- Bag , BinaryAnd , BinaryOr , BindingsName , List , NullableEq , NullableOrd , Tuple , UnaryPlus , Value ,
8
+ Bag , BinaryAnd , BinaryOr , BindingsName , DateTime , List , NullableEq , NullableOrd , Tuple ,
9
+ UnaryPlus , Value ,
9
10
} ;
10
11
use regex:: { Regex , RegexBuilder } ;
12
+ use rust_decimal:: prelude:: FromPrimitive ;
11
13
use std:: borrow:: { Borrow , Cow } ;
12
14
use std:: fmt:: Debug ;
13
15
@@ -935,3 +937,213 @@ impl EvalExpr for EvalFnCardinality {
935
937
Cow :: Owned ( result)
936
938
}
937
939
}
940
+
941
+ /// Represents a year `EXTRACT` function, e.g. `extract(YEAR FROM t)`.
942
+ #[ derive( Debug ) ]
943
+ pub struct EvalFnExtractYear {
944
+ pub value : Box < dyn EvalExpr > ,
945
+ }
946
+
947
+ impl EvalExpr for EvalFnExtractYear {
948
+ #[ inline]
949
+ fn evaluate < ' a > ( & ' a self , bindings : & ' a Tuple , ctx : & ' a dyn EvalContext ) -> Cow < ' a , Value > {
950
+ let value = self . value . evaluate ( bindings, ctx) ;
951
+ let result = match value. borrow ( ) {
952
+ Null => Null ,
953
+ Value :: DateTime ( dt) => match dt. as_ref ( ) {
954
+ DateTime :: Date ( d) => Value :: from ( d. year ( ) ) ,
955
+ DateTime :: Timestamp ( tstamp) => Value :: from ( tstamp. year ( ) ) ,
956
+ DateTime :: TimestampWithTz ( tstamp) => Value :: from ( tstamp. year ( ) ) ,
957
+ DateTime :: Time ( _) => Missing ,
958
+ DateTime :: TimeWithTz ( _, _) => Missing ,
959
+ } ,
960
+ _ => Missing ,
961
+ } ;
962
+ Cow :: Owned ( result)
963
+ }
964
+ }
965
+
966
+ /// Represents a month `EXTRACT` function, e.g. `extract(MONTH FROM t)`.
967
+ #[ derive( Debug ) ]
968
+ pub struct EvalFnExtractMonth {
969
+ pub value : Box < dyn EvalExpr > ,
970
+ }
971
+
972
+ impl EvalExpr for EvalFnExtractMonth {
973
+ #[ inline]
974
+ fn evaluate < ' a > ( & ' a self , bindings : & ' a Tuple , ctx : & ' a dyn EvalContext ) -> Cow < ' a , Value > {
975
+ let value = self . value . evaluate ( bindings, ctx) ;
976
+ let result = match value. borrow ( ) {
977
+ Null => Null ,
978
+ Value :: DateTime ( dt) => match dt. as_ref ( ) {
979
+ DateTime :: Date ( d) => Value :: from ( d. month ( ) as u8 ) ,
980
+ DateTime :: Timestamp ( tstamp) => Value :: from ( tstamp. month ( ) as u8 ) ,
981
+ DateTime :: TimestampWithTz ( tstamp) => Value :: from ( tstamp. month ( ) as u8 ) ,
982
+ DateTime :: Time ( _) => Missing ,
983
+ DateTime :: TimeWithTz ( _, _) => Missing ,
984
+ } ,
985
+ _ => Missing ,
986
+ } ;
987
+ Cow :: Owned ( result)
988
+ }
989
+ }
990
+
991
+ /// Represents a day `EXTRACT` function, e.g. `extract(DAY FROM t)`.
992
+ #[ derive( Debug ) ]
993
+ pub struct EvalFnExtractDay {
994
+ pub value : Box < dyn EvalExpr > ,
995
+ }
996
+
997
+ impl EvalExpr for EvalFnExtractDay {
998
+ #[ inline]
999
+ fn evaluate < ' a > ( & ' a self , bindings : & ' a Tuple , ctx : & ' a dyn EvalContext ) -> Cow < ' a , Value > {
1000
+ let value = self . value . evaluate ( bindings, ctx) ;
1001
+ let result = match value. borrow ( ) {
1002
+ Null => Null ,
1003
+ Value :: DateTime ( dt) => match dt. as_ref ( ) {
1004
+ DateTime :: Date ( d) => Value :: from ( d. day ( ) ) ,
1005
+ DateTime :: Timestamp ( tstamp) => Value :: from ( tstamp. day ( ) ) ,
1006
+ DateTime :: TimestampWithTz ( tstamp) => Value :: from ( tstamp. day ( ) ) ,
1007
+ DateTime :: Time ( _) => Missing ,
1008
+ DateTime :: TimeWithTz ( _, _) => Missing ,
1009
+ } ,
1010
+ _ => Missing ,
1011
+ } ;
1012
+ Cow :: Owned ( result)
1013
+ }
1014
+ }
1015
+
1016
+ /// Represents an hour `EXTRACT` function, e.g. `extract(HOUR FROM t)`.
1017
+ #[ derive( Debug ) ]
1018
+ pub struct EvalFnExtractHour {
1019
+ pub value : Box < dyn EvalExpr > ,
1020
+ }
1021
+
1022
+ impl EvalExpr for EvalFnExtractHour {
1023
+ #[ inline]
1024
+ fn evaluate < ' a > ( & ' a self , bindings : & ' a Tuple , ctx : & ' a dyn EvalContext ) -> Cow < ' a , Value > {
1025
+ let value = self . value . evaluate ( bindings, ctx) ;
1026
+ let result = match value. borrow ( ) {
1027
+ Null => Null ,
1028
+ Value :: DateTime ( dt) => match dt. as_ref ( ) {
1029
+ DateTime :: Time ( t) => Value :: from ( t. hour ( ) ) ,
1030
+ DateTime :: TimeWithTz ( t, _) => Value :: from ( t. hour ( ) ) ,
1031
+ DateTime :: Timestamp ( tstamp) => Value :: from ( tstamp. hour ( ) ) ,
1032
+ DateTime :: TimestampWithTz ( tstamp) => Value :: from ( tstamp. hour ( ) ) ,
1033
+ DateTime :: Date ( _) => Missing ,
1034
+ } ,
1035
+ _ => Missing ,
1036
+ } ;
1037
+ Cow :: Owned ( result)
1038
+ }
1039
+ }
1040
+
1041
+ /// Represents a minute `EXTRACT` function, e.g. `extract(MINUTE FROM t)`.
1042
+ #[ derive( Debug ) ]
1043
+ pub struct EvalFnExtractMinute {
1044
+ pub value : Box < dyn EvalExpr > ,
1045
+ }
1046
+
1047
+ impl EvalExpr for EvalFnExtractMinute {
1048
+ #[ inline]
1049
+ fn evaluate < ' a > ( & ' a self , bindings : & ' a Tuple , ctx : & ' a dyn EvalContext ) -> Cow < ' a , Value > {
1050
+ let value = self . value . evaluate ( bindings, ctx) ;
1051
+ let result = match value. borrow ( ) {
1052
+ Null => Null ,
1053
+ Value :: DateTime ( dt) => match dt. as_ref ( ) {
1054
+ DateTime :: Time ( t) => Value :: from ( t. minute ( ) ) ,
1055
+ DateTime :: TimeWithTz ( t, _) => Value :: from ( t. minute ( ) ) ,
1056
+ DateTime :: Timestamp ( tstamp) => Value :: from ( tstamp. minute ( ) ) ,
1057
+ DateTime :: TimestampWithTz ( tstamp) => Value :: from ( tstamp. minute ( ) ) ,
1058
+ DateTime :: Date ( _) => Missing ,
1059
+ } ,
1060
+ _ => Missing ,
1061
+ } ;
1062
+ Cow :: Owned ( result)
1063
+ }
1064
+ }
1065
+
1066
+ /// Represents a second `EXTRACT` function, e.g. `extract(SECOND FROM t)`.
1067
+ #[ derive( Debug ) ]
1068
+ pub struct EvalFnExtractSecond {
1069
+ pub value : Box < dyn EvalExpr > ,
1070
+ }
1071
+
1072
+ fn total_seconds ( second : u8 , nanosecond : u32 ) -> Value {
1073
+ let result = rust_decimal:: Decimal :: from_f64 ( ( ( second as f64 * 1e9 ) + nanosecond as f64 ) / 1e9 )
1074
+ . expect ( "time as decimal" ) ;
1075
+ Value :: from ( result)
1076
+ }
1077
+
1078
+ impl EvalExpr for EvalFnExtractSecond {
1079
+ #[ inline]
1080
+ fn evaluate < ' a > ( & ' a self , bindings : & ' a Tuple , ctx : & ' a dyn EvalContext ) -> Cow < ' a , Value > {
1081
+ let value = self . value . evaluate ( bindings, ctx) ;
1082
+ let result = match value. borrow ( ) {
1083
+ Null => Null ,
1084
+ Value :: DateTime ( dt) => match dt. as_ref ( ) {
1085
+ DateTime :: Time ( t) => total_seconds ( t. second ( ) , t. nanosecond ( ) ) ,
1086
+ DateTime :: TimeWithTz ( t, _) => total_seconds ( t. second ( ) , t. nanosecond ( ) ) ,
1087
+ DateTime :: Timestamp ( tstamp) => total_seconds ( tstamp. second ( ) , tstamp. nanosecond ( ) ) ,
1088
+ DateTime :: TimestampWithTz ( tstamp) => {
1089
+ total_seconds ( tstamp. second ( ) , tstamp. nanosecond ( ) )
1090
+ }
1091
+ DateTime :: Date ( _) => Missing ,
1092
+ } ,
1093
+ _ => Missing ,
1094
+ } ;
1095
+ Cow :: Owned ( result)
1096
+ }
1097
+ }
1098
+
1099
+ /// Represents a timezone hour `EXTRACT` function, e.g. `extract(TIMEZONE_HOUR FROM t)`.
1100
+ #[ derive( Debug ) ]
1101
+ pub struct EvalFnExtractTimezoneHour {
1102
+ pub value : Box < dyn EvalExpr > ,
1103
+ }
1104
+
1105
+ impl EvalExpr for EvalFnExtractTimezoneHour {
1106
+ #[ inline]
1107
+ fn evaluate < ' a > ( & ' a self , bindings : & ' a Tuple , ctx : & ' a dyn EvalContext ) -> Cow < ' a , Value > {
1108
+ let value = self . value . evaluate ( bindings, ctx) ;
1109
+ let result = match value. borrow ( ) {
1110
+ Null => Null ,
1111
+ Value :: DateTime ( dt) => match dt. as_ref ( ) {
1112
+ DateTime :: TimeWithTz ( _, tz) => Value :: from ( tz. whole_hours ( ) ) ,
1113
+ DateTime :: TimestampWithTz ( tstamp) => Value :: from ( tstamp. offset ( ) . whole_hours ( ) ) ,
1114
+ DateTime :: Date ( _) => Missing ,
1115
+ DateTime :: Time ( _) => Missing ,
1116
+ DateTime :: Timestamp ( _) => Missing ,
1117
+ } ,
1118
+ _ => Missing ,
1119
+ } ;
1120
+ Cow :: Owned ( result)
1121
+ }
1122
+ }
1123
+
1124
+ /// Represents a timezone minute `EXTRACT` function, e.g. `extract(TIMEZONE_MINUTE FROM t)`.
1125
+ #[ derive( Debug ) ]
1126
+ pub struct EvalFnExtractTimezoneMinute {
1127
+ pub value : Box < dyn EvalExpr > ,
1128
+ }
1129
+
1130
+ impl EvalExpr for EvalFnExtractTimezoneMinute {
1131
+ #[ inline]
1132
+ fn evaluate < ' a > ( & ' a self , bindings : & ' a Tuple , ctx : & ' a dyn EvalContext ) -> Cow < ' a , Value > {
1133
+ let value = self . value . evaluate ( bindings, ctx) ;
1134
+ let result = match value. borrow ( ) {
1135
+ Null => Null ,
1136
+ Value :: DateTime ( dt) => match dt. as_ref ( ) {
1137
+ DateTime :: TimeWithTz ( _, tz) => Value :: from ( tz. minutes_past_hour ( ) ) ,
1138
+ DateTime :: TimestampWithTz ( tstamp) => {
1139
+ Value :: from ( tstamp. offset ( ) . minutes_past_hour ( ) )
1140
+ }
1141
+ DateTime :: Date ( _) => Missing ,
1142
+ DateTime :: Time ( _) => Missing ,
1143
+ DateTime :: Timestamp ( _) => Missing ,
1144
+ } ,
1145
+ _ => Missing ,
1146
+ } ;
1147
+ Cow :: Owned ( result)
1148
+ }
1149
+ }
0 commit comments