@@ -5,9 +5,11 @@ use itertools::Itertools;
55use partiql_logical:: Type ;
66use partiql_value:: Value :: { Boolean , Missing , Null } ;
77use 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 ,
910} ;
1011use regex:: { Regex , RegexBuilder } ;
12+ use rust_decimal:: prelude:: FromPrimitive ;
1113use std:: borrow:: { Borrow , Cow } ;
1214use std:: fmt:: Debug ;
1315
@@ -935,3 +937,213 @@ impl EvalExpr for EvalFnCardinality {
935937 Cow :: Owned ( result)
936938 }
937939}
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