mirror of
https://github.com/enso-org/enso.git
synced 2024-12-22 10:11:37 +03:00
Adding support for creating Atoms in expressions (#10820)
- Enables the `..` autoscoping style for creating Atoms in expressions. - Add type checking to methods in columns. - Auto wrap returns from method in expressions into a column as needed. - Remove `Time_Period.Day` to remove confusion..
This commit is contained in:
parent
a168baddb3
commit
422fa8c16b
@ -16,12 +16,14 @@
|
||||
- [Support for reading from Tableau Hyper files.][10733]
|
||||
- [Mixed Decimal/Float arithmetic now throws an error; mixed comparisons now
|
||||
attach warnings.][10725]
|
||||
- [Support for creating Atoms in expressions.][10820]
|
||||
|
||||
[10614]: https://github.com/enso-org/enso/pull/10614
|
||||
[10660]: https://github.com/enso-org/enso/pull/10660
|
||||
[10761]: https://github.com/enso-org/enso/pull/10761
|
||||
[10733]: https://github.com/enso-org/enso/pull/10733
|
||||
[10725]: https://github.com/enso-org/enso/pull/10725
|
||||
[10820]: https://github.com/enso-org/enso/pull/10820
|
||||
|
||||
# Enso 2023.3
|
||||
|
||||
|
@ -25,8 +25,8 @@ import Standard.Database.Internal.Statement_Setter.Statement_Setter
|
||||
import Standard.Database.SQL.SQL_Builder
|
||||
import Standard.Database.SQL_Statement.SQL_Statement
|
||||
import Standard.Database.SQL_Type.SQL_Type
|
||||
from Standard.Database.Errors import SQL_Error, Unsupported_Database_Operation
|
||||
from Standard.Database.Dialect import Temp_Table_Style
|
||||
from Standard.Database.Errors import SQL_Error, Unsupported_Database_Operation
|
||||
|
||||
import project.Database.Redshift.Internal.Redshift_Error_Mapper.Redshift_Error_Mapper
|
||||
|
||||
|
@ -470,7 +470,7 @@ type Decimal
|
||||
b = Decimal.new "20.33"
|
||||
a.add b (Math_Context.new 3)
|
||||
# => Decimal.new 30.5
|
||||
# TODO: restore checked return type (here and elsewhere) after https://github.com/enso-org/enso/issues/10736
|
||||
TODO: restore checked return type (here and elsewhere) after https://github.com/enso-org/enso/issues/10736
|
||||
add : Decimal -> Math_Context | Nothing -> Decimal ! Arithmetic_Error
|
||||
add self (that : Decimal) (math_context : Math_Context | Nothing = Nothing) -> Decimal ! Arithmetic_Error =
|
||||
error_if_from_float self that <| handle_java_exception <|
|
||||
|
@ -3,9 +3,9 @@ private
|
||||
import project.Data.Decimal.Decimal
|
||||
import project.Data.Numbers.Number
|
||||
import project.Data.Text.Text
|
||||
from project.Errors.Common import Loss_Of_Numeric_Precision
|
||||
import project.Warning.Warning
|
||||
from project.Data.Ordering import Comparable, Ordering
|
||||
from project.Errors.Common import Loss_Of_Numeric_Precision
|
||||
|
||||
polyglot java import org.enso.base.numeric.Decimal_Utils
|
||||
|
||||
|
@ -46,12 +46,6 @@ type Date_Period
|
||||
Week (first_day:Day_Of_Week = Day_Of_Week.Monday)
|
||||
|
||||
## Represents a time period of a single calendar day.
|
||||
|
||||
? Daylight Saving Time
|
||||
|
||||
Note that due to DST changes, some days may be slightly longer or
|
||||
shorter. This date period will reflect that and still count such days
|
||||
as one day. For a measure of exactly 24 hours, use `Time_Period.Day`.
|
||||
Day
|
||||
|
||||
## PRIVATE
|
||||
@ -67,7 +61,7 @@ type Date_Period
|
||||
|
||||
## PRIVATE
|
||||
adjust_end : (Date | Date_Time) -> (Date | Date_Time)
|
||||
adjust_end self date = if self == Date_Period.Day then date else
|
||||
adjust_end self date =
|
||||
adjuster = case self of
|
||||
Date_Period.Year -> TemporalAdjusters.lastDayOfYear
|
||||
Date_Period.Quarter -> Date_Period_Utils.quarter_end
|
||||
|
@ -605,7 +605,7 @@ type Date_Time
|
||||
start_of self period=Date_Period.Month =
|
||||
adjusted = period.adjust_start self
|
||||
case period of
|
||||
_ : Date_Period -> Time_Period.Day.adjust_start adjusted
|
||||
_ : Date_Period -> Date_Period.Day.adjust_start adjusted
|
||||
_ : Time_Period -> adjusted
|
||||
|
||||
## GROUP DateTime
|
||||
@ -616,7 +616,7 @@ type Date_Time
|
||||
end_of self period=Date_Period.Month =
|
||||
adjusted = period.adjust_end self
|
||||
case period of
|
||||
_ : Date_Period -> Time_Period.Day.adjust_end adjusted
|
||||
_ : Date_Period -> Date_Period.Day.adjust_end adjusted
|
||||
_ : Time_Period -> adjusted
|
||||
|
||||
## ALIAS time to date
|
||||
@ -668,7 +668,6 @@ type Date_Time
|
||||
Date_Period.Month -> self.month
|
||||
Date_Period.Week _ -> self.week_of_year locale=Nothing
|
||||
Date_Period.Day -> self.day
|
||||
Time_Period.Day -> self.day
|
||||
Time_Period.Hour -> self.hour
|
||||
Time_Period.Minute -> self.minute
|
||||
Time_Period.Second -> self.second
|
||||
|
@ -272,13 +272,13 @@ type Time_Of_Day
|
||||
ICON time
|
||||
Returns the first time within the `Time_Period` containing self.
|
||||
start_of : Time_Period -> Time_Of_Day
|
||||
start_of self period=Time_Period.Day = period.adjust_start self
|
||||
start_of self period=Time_Period.Hour = period.adjust_start self
|
||||
|
||||
## GROUP DateTime
|
||||
ICON time
|
||||
Returns the last time within the `Time_Period` containing self.
|
||||
end_of : Time_Period -> Time_Of_Day
|
||||
end_of self period=Time_Period.Day = period.adjust_end self
|
||||
end_of self period=Time_Period.Hour = period.adjust_end self
|
||||
|
||||
## GROUP Conversions
|
||||
ICON convert
|
||||
@ -318,7 +318,6 @@ type Time_Of_Day
|
||||
date_part : Time_Period -> Integer
|
||||
date_part self (period : Time_Period) =
|
||||
case period of
|
||||
Time_Period.Day -> Error.throw (Illegal_Argument.Error "The Time_Of_Day does not have a day part.")
|
||||
Time_Period.Hour -> self.hour
|
||||
Time_Period.Minute -> self.minute
|
||||
Time_Period.Second -> self.second
|
||||
@ -339,11 +338,8 @@ type Time_Of_Day
|
||||
- end: A time of day to compute the difference from.
|
||||
- period: The period to compute the difference in.
|
||||
date_diff : Time_Of_Day -> Time_Period -> Integer
|
||||
date_diff self (end : Time_Of_Day) (period : Time_Period) = case period of
|
||||
Time_Period.Day ->
|
||||
Error.throw (Illegal_Argument.Error "The Time_Of_Day does not have a day part to compute a difference in days.")
|
||||
_ ->
|
||||
Time_Utils.unit_time_difference period.to_java_unit self end
|
||||
date_diff self (end : Time_Of_Day) (period : Time_Period) =
|
||||
Time_Utils.unit_time_difference period.to_java_unit self end
|
||||
|
||||
## GROUP DateTime
|
||||
ICON time
|
||||
@ -353,11 +349,8 @@ type Time_Of_Day
|
||||
- amount: An integer specifying by how many periods to shift the time.
|
||||
- period: The period by which to shift.
|
||||
date_add : Integer -> Time_Period -> Time_Of_Day
|
||||
date_add self (amount : Integer) (period : Time_Period) = case period of
|
||||
Time_Period.Day ->
|
||||
Error.throw (Illegal_Argument.Error "The Time_Of_Day does not have a day part to add days to.")
|
||||
_ ->
|
||||
Time_Utils.unit_time_add period.to_java_unit self amount
|
||||
date_add self (amount : Integer) (period : Time_Period) =
|
||||
Time_Utils.unit_time_add period.to_java_unit self amount
|
||||
|
||||
## ALIAS add duration
|
||||
GROUP Operators
|
||||
|
@ -10,15 +10,6 @@ polyglot java import org.enso.base.Time_Utils
|
||||
|
||||
## Represents a unit of time of a day or shorter.
|
||||
type Time_Period
|
||||
## Represents a time period of a single day, measured as 24 hours.
|
||||
|
||||
? Daylight Saving Time
|
||||
|
||||
Note that due to DST changes, some days may be slightly longer or
|
||||
shorter. This is not reflected in the duration of this time period. For
|
||||
a calendar-oriented day period, use `Date_Period.Day` instead.
|
||||
Day
|
||||
|
||||
## Represents a time period of an hour.
|
||||
Hour
|
||||
|
||||
@ -38,10 +29,8 @@ type Time_Period
|
||||
Nanosecond
|
||||
|
||||
## PRIVATE
|
||||
We treat the `Time_Period.Day` as a period of 24 hours, not a calendar day.
|
||||
to_java_unit : TemporalUnit
|
||||
to_java_unit self = case self of
|
||||
Time_Period.Day -> CustomTemporalUnits.DAY_AS_24_HOURS
|
||||
Time_Period.Hour -> ChronoUnit.HOURS
|
||||
Time_Period.Minute -> ChronoUnit.MINUTES
|
||||
Time_Period.Second -> ChronoUnit.SECONDS
|
||||
@ -49,30 +38,19 @@ type Time_Period
|
||||
Time_Period.Microsecond -> ChronoUnit.MICROS
|
||||
Time_Period.Nanosecond -> ChronoUnit.NANOS
|
||||
|
||||
## PRIVATE
|
||||
A special case for `adjust_start` and `adjust_end` methods.
|
||||
In this particular case, it seems better to treat `Time_Period.Day` as a
|
||||
calendar day. Otherwise, the behaviour of `start_of` and `end_of` methods
|
||||
near DST would become unintuitive.
|
||||
to_java_unit_for_adjust : TemporalUnit
|
||||
to_java_unit_for_adjust self = case self of
|
||||
Time_Period.Day -> ChronoUnit.DAYS
|
||||
_ -> self.to_java_unit
|
||||
|
||||
## PRIVATE
|
||||
adjust_start : (Time_Of_Day | Date_Time) -> (Time_Of_Day | Date_Time)
|
||||
adjust_start self date =
|
||||
(Time_Utils.utils_for date).start_of_time_period date self.to_java_unit_for_adjust
|
||||
(Time_Utils.utils_for date).start_of_time_period date self.to_java_unit
|
||||
|
||||
## PRIVATE
|
||||
adjust_end : (Time_Of_Day | Date_Time) -> (Time_Of_Day | Date_Time)
|
||||
adjust_end self date =
|
||||
(Time_Utils.utils_for date).end_of_time_period date self.to_java_unit_for_adjust
|
||||
(Time_Utils.utils_for date).end_of_time_period date self.to_java_unit
|
||||
|
||||
## PRIVATE
|
||||
to_duration : Duration
|
||||
to_duration self = case self of
|
||||
Time_Period.Day -> Duration.new hours=24
|
||||
Time_Period.Hour -> Duration.new hours=1
|
||||
Time_Period.Minute -> Duration.new minutes=1
|
||||
Time_Period.Second -> Duration.new seconds=1
|
||||
|
@ -159,6 +159,22 @@ type DB_Column
|
||||
if index < 0 then Error.throw (Unsupported_Database_Operation.Error "Reading backwards from end is not supported in-database. Use `read` to materialize the column.") else
|
||||
self.read (..First index+1) . get index default
|
||||
|
||||
## GROUP Standard.Base.Selections
|
||||
ICON parse3
|
||||
Returns the first element in the column, if it exists.
|
||||
|
||||
If the column is empty, this method will return a dataflow error
|
||||
containing an `Index_Out_Of_Bounds`.
|
||||
|
||||
> Example
|
||||
Get the first element of a column.
|
||||
|
||||
import Standard.Examples
|
||||
|
||||
example_first = Examples.integer_column.first
|
||||
first : Any ! Index_Out_Of_Bounds
|
||||
first self = self.at 0
|
||||
|
||||
## GROUP Standard.Base.Metadata
|
||||
ICON metadata
|
||||
Returns the `Value_Type` associated with that column.
|
||||
@ -323,7 +339,7 @@ type DB_Column
|
||||
`other`.
|
||||
@locale Locale.default_widget
|
||||
equals_ignore_case : DB_Column | Any -> Locale -> DB_Column
|
||||
equals_ignore_case self other locale=Locale.default =
|
||||
equals_ignore_case self other locale:Locale=Locale.default =
|
||||
Value_Type.expect_text self <|
|
||||
Value_Type.expect_text other <|
|
||||
Helpers.assume_default_locale locale <|
|
||||
@ -1208,7 +1224,7 @@ type DB_Column
|
||||
Sorting `column` in descending order.
|
||||
column.sort Sort_Direction.Descending
|
||||
sort : Sort_Direction -> DB_Column
|
||||
sort self order=Sort_Direction.Ascending =
|
||||
sort self order:Sort_Direction=..Ascending =
|
||||
self.to_table.sort [..Index 0 order] . at 0
|
||||
|
||||
## ALIAS first, head, keep, last, limit, sample, slice, tail, top
|
||||
@ -1249,7 +1265,7 @@ type DB_Column
|
||||
missing value (a Nothing or a column with missing values), the behaviour
|
||||
on these missing values is vendor specific.
|
||||
starts_with : DB_Column | Text -> Case_Sensitivity -> DB_Column
|
||||
starts_with self other case_sensitivity=Case_Sensitivity.Default =
|
||||
starts_with self other case_sensitivity:Case_Sensitivity=..Default =
|
||||
new_name = self.naming_helper.function_name "starts_with" [self, other]
|
||||
make_text_case_op self "STARTS_WITH" other case_sensitivity new_name
|
||||
|
||||
@ -1267,7 +1283,7 @@ type DB_Column
|
||||
missing value (a Nothing or a column with missing values), the behaviour
|
||||
on these missing values is vendor specific.
|
||||
ends_with : DB_Column | Text -> Case_Sensitivity -> DB_Column
|
||||
ends_with self other case_sensitivity=Case_Sensitivity.Default =
|
||||
ends_with self other case_sensitivity:Case_Sensitivity=..Default =
|
||||
new_name = self.naming_helper.function_name "ends_with" [self, other]
|
||||
make_text_case_op self "ENDS_WITH" other case_sensitivity new_name
|
||||
|
||||
@ -1347,7 +1363,7 @@ type DB_Column
|
||||
missing value (a Nothing or a column with missing values), the behaviour
|
||||
on these missing values is vendor specific.
|
||||
contains : DB_Column | Text -> Case_Sensitivity -> DB_Column
|
||||
contains self other case_sensitivity=Case_Sensitivity.Default =
|
||||
contains self other case_sensitivity:Case_Sensitivity=..Default =
|
||||
new_name = self.naming_helper.function_name "contains" [self, other]
|
||||
make_text_case_op self "CONTAINS" other case_sensitivity new_name
|
||||
|
||||
@ -1461,7 +1477,7 @@ type DB_Column
|
||||
column.text_replace '"(.*?)"'.to_regex '($1)'
|
||||
@term make_regex_text_widget
|
||||
text_replace : Text | Regex | DB_Column -> Text | DB_Column -> Case_Sensitivity -> Boolean -> DB_Column ! Unsupported_Database_Operation
|
||||
text_replace self (term : Text | Regex | DB_Column = "") new_text="" case_sensitivity=Case_Sensitivity.Default only_first=False =
|
||||
text_replace self (term : Text | Regex | DB_Column = "") new_text="" case_sensitivity:Case_Sensitivity=..Default only_first=False =
|
||||
Value_Type.expect_text self <| case_sensitivity.disallow_non_default_locale <|
|
||||
input_type = Meta.type_of term
|
||||
params = Replace_Params.Value input_type case_sensitivity only_first
|
||||
@ -1594,7 +1610,7 @@ type DB_Column
|
||||
Returns a column of `Integer` type.
|
||||
@period Date_Time_Helpers.make_period_selector_for_column
|
||||
date_part : Date_Period | Time_Period -> DB_Column ! Invalid_Value_Type | Illegal_Argument
|
||||
date_part self period =
|
||||
date_part self period:(Date_Period | Time_Period) =
|
||||
Date_Time_Helpers.make_date_part_function self period (column->op_name-> column.make_unary_op op_name) self.naming_helper
|
||||
|
||||
## GROUP Standard.Base.DateTime
|
||||
@ -1763,7 +1779,7 @@ type DB_Column
|
||||
@locale Locale.default_widget
|
||||
@format (self-> Widget_Helpers.make_format_chooser_for_type self.value_type)
|
||||
format : Text | Date_Time_Formatter | DB_Column -> Locale -> DB_Column ! Illegal_Argument
|
||||
format self format:(Text | Date_Time_Formatter | DB_Column)="" locale=Locale.default =
|
||||
format self format:(Text | Date_Time_Formatter | DB_Column)="" locale:Locale=Locale.default =
|
||||
_ = [format, locale]
|
||||
Error.throw <| Unsupported_Database_Operation.Error "`DB_Column.format` is not implemented yet for the Database backends."
|
||||
|
||||
@ -1816,7 +1832,7 @@ type DB_Column
|
||||
types. Due to this, a Mixed column containing values `[2, "3"]` will
|
||||
actually be converted into `[2, Nothing]` when casting to Integer type.
|
||||
cast : Value_Type -> Problem_Behavior -> DB_Column ! Illegal_Argument | Inexact_Type_Coercion | Conversion_Failure
|
||||
cast self value_type on_problems:Problem_Behavior=..Report_Warning =
|
||||
cast self value_type:Value_Type on_problems:Problem_Behavior=..Report_Warning =
|
||||
check_cast_compatibility self.value_type value_type <|
|
||||
self.internal_do_cast value_type on_problems
|
||||
|
||||
|
@ -1045,7 +1045,10 @@ type DB_Table
|
||||
evaluate_expression : Text | Expression -> Problem_Behavior -> DB_Column ! No_Such_Column | Invalid_Value_Type | Expression_Error
|
||||
evaluate_expression self expression:(Text | Expression) on_problems:Problem_Behavior=..Report_Warning = if expression.is_a Text then self.evaluate_expression (Expression.Value expression) on_problems else
|
||||
get_column name = self.at name
|
||||
new_column = Expression.evaluate expression get_column self.make_constant_column "Standard.Database.DB_Column" "DB_Column" DB_Column.var_args_functions
|
||||
make_constant_column value = case value of
|
||||
_ : DB_Column -> value
|
||||
_ -> self.make_constant_column value
|
||||
new_column = Expression.evaluate expression get_column make_constant_column "Standard.Database.DB_Column" "DB_Column" DB_Column.var_args_functions
|
||||
problems = Warning.get_all new_column . map .value
|
||||
result = new_column.rename (self.connection.base_connection.column_naming_helper.sanitize_name expression.expression)
|
||||
on_problems.attach_problems_before problems <|
|
||||
|
@ -288,10 +288,10 @@ default_fetch_primary_key connection table_name =
|
||||
|
||||
## PRIVATE
|
||||
type Temp_Table_Style
|
||||
## PRIVATE
|
||||
The temporary table is created using a create table statement.
|
||||
Temporary_Table
|
||||
|
||||
## PRIVATE
|
||||
The temporary table is created using a # table name.
|
||||
Hash_Prefix
|
||||
## PRIVATE
|
||||
The temporary table is created using a create table statement.
|
||||
Temporary_Table
|
||||
|
||||
## PRIVATE
|
||||
The temporary table is created using a # table name.
|
||||
Hash_Prefix
|
||||
|
@ -11,8 +11,8 @@ import project.Internal.IR.Query.Query
|
||||
import project.Internal.IR.SQL_Expression.SQL_Expression
|
||||
import project.Internal.IR.SQL_Join_Kind.SQL_Join_Kind
|
||||
import project.SQL.SQL_Builder
|
||||
from project.Errors import Unsupported_Database_Operation
|
||||
from project.Dialect import Temp_Table_Style
|
||||
from project.Errors import Unsupported_Database_Operation
|
||||
from project.Internal.IR.Operation_Metadata import Row_Number_Metadata
|
||||
|
||||
type Dialect_Operations
|
||||
|
@ -38,7 +38,9 @@ type Support_Level
|
||||
if metadata.dataDefinitionCausesTransactionCommit then Support_Level.Causes_Commit else
|
||||
Support_Level.Allowed
|
||||
|
||||
## PRIVATE
|
||||
type Transactional_Table_Description
|
||||
## PRIVATE
|
||||
Value name:Text temporary:Boolean (structure : Vector Column_Description) (primary_key : Vector Text | Nothing) (remove_after_transaction:Boolean) (on_problems:Problem_Behavior)
|
||||
|
||||
## PRIVATE
|
||||
@ -107,9 +109,11 @@ private create_tables_outside_transaction connection (tables : Vector Transactio
|
||||
cleanup_transaction_scoped_tables connection tables
|
||||
cleanup_errors.if_not_error result
|
||||
|
||||
## PRIVATE
|
||||
private cleanup_tables_silently connection table_names = Context.Output.with_enabled <|
|
||||
table_names.each (name-> connection.drop_table name if_exists=True . catch)
|
||||
|
||||
## PRIVATE
|
||||
private cleanup_transaction_scoped_tables connection tables = Context.Output.with_enabled <|
|
||||
tables.each (t-> if t.remove_after_transaction then connection.drop_table t.name if_exists=True)
|
||||
|
||||
|
@ -37,8 +37,8 @@ import project.SQL.SQL_Builder
|
||||
import project.SQL.SQL_Fragment
|
||||
import project.SQL_Statement.SQL_Statement
|
||||
import project.SQL_Type.SQL_Type
|
||||
from project.Errors import SQL_Error, Unsupported_Database_Operation
|
||||
from project.Dialect import Temp_Table_Style
|
||||
from project.Errors import SQL_Error, Unsupported_Database_Operation
|
||||
from project.Internal.IR.Operation_Metadata import Date_Period_Metadata
|
||||
|
||||
polyglot java import java.sql.Types
|
||||
@ -667,8 +667,6 @@ make_date_add arguments (metadata : Date_Period_Metadata) =
|
||||
"weeks=>1"
|
||||
Date_Period.Day ->
|
||||
"days=>1"
|
||||
Time_Period.Day ->
|
||||
"hours=>24"
|
||||
Time_Period.Hour ->
|
||||
"hours=>1"
|
||||
Time_Period.Minute ->
|
||||
@ -734,10 +732,6 @@ make_date_diff arguments (metadata : Date_Period_Metadata) =
|
||||
Time_Period.Hour -> (extract_seconds ++ " / 3600").paren
|
||||
Time_Period.Minute -> (extract_seconds ++ " / 60").paren
|
||||
Time_Period.Second -> extract_seconds
|
||||
Time_Period.Day -> case metadata.input_value_type of
|
||||
Value_Type.Date -> extract_days
|
||||
# Time_Period.Day is treated as 24 hours, so for types that support time we use the same algorithm like for hours, but divide by 24.
|
||||
_ -> (extract_seconds ++ " / (3600 * 24)").paren
|
||||
## The EPOCH gives back just the integer amount of seconds, without
|
||||
the fractional part. So we get the fractional part using
|
||||
MILLISECONDS - but that does not give the _total_ just the
|
||||
|
@ -31,8 +31,8 @@ import project.Internal.Statement_Setter.Statement_Setter
|
||||
import project.SQL.SQL_Builder
|
||||
import project.SQL_Statement.SQL_Statement
|
||||
import project.SQL_Type.SQL_Type
|
||||
from project.Errors import SQL_Error, Unsupported_Database_Operation
|
||||
from project.Dialect import Temp_Table_Style
|
||||
from project.Errors import SQL_Error, Unsupported_Database_Operation
|
||||
|
||||
## PRIVATE
|
||||
|
||||
|
@ -7,8 +7,8 @@ import Standard.Base.Errors.Illegal_State.Illegal_State
|
||||
import Standard.Table.Internal.Problem_Builder.Problem_Builder
|
||||
from Standard.Table import Table
|
||||
|
||||
import project.Connection.Connection.Connection
|
||||
import project.Column_Description.Column_Description
|
||||
import project.Connection.Connection.Connection
|
||||
import project.DB_Table.DB_Table
|
||||
|
||||
## PRIVATE
|
||||
|
@ -14,7 +14,7 @@ from project.Errors import SQL_Error
|
||||
from project.Internal.Upload.Helpers.Argument_Checks import check_delete_rows_arguments
|
||||
from project.Internal.Upload.Helpers.Check_Queries import check_duplicate_key_matches_for_delete, check_for_null_keys
|
||||
from project.Internal.Upload.Helpers.Constants import dry_run_row_limit
|
||||
from project.Internal.Upload.Operations.Internal_Core import Table_Upload_Operation, internal_upload_in_memory_table, internal_upload_table
|
||||
from project.Internal.Upload.Operations.Internal_Core import internal_upload_in_memory_table, internal_upload_table, Table_Upload_Operation
|
||||
|
||||
## PRIVATE
|
||||
common_delete_rows (target_table : DB_Table) (key_values_to_delete : Table | DB_Table) (key_columns : Vector Text) (allow_duplicate_matches : Boolean) -> Integer =
|
||||
|
@ -13,8 +13,8 @@ import project.Internal.DDL_Transaction.Transactional_Table_Description
|
||||
import project.Internal.In_Transaction.In_Transaction
|
||||
import project.Internal.IR.Query.Query
|
||||
import project.SQL_Query.SQL_Query
|
||||
from project.Errors import SQL_Error, Table_Already_Exists, Unsupported_Database_Operation
|
||||
from project.Dialect import Temp_Table_Style
|
||||
from project.Errors import SQL_Error, Table_Already_Exists, Unsupported_Database_Operation
|
||||
from project.Internal.Upload.Helpers.Argument_Checks import resolve_primary_key
|
||||
from project.Internal.Upload.Helpers.Constants import default_batch_size
|
||||
from project.Internal.Upload.Helpers.Error_Helpers import handle_upload_errors, internal_translate_known_upload_errors
|
||||
|
@ -13,9 +13,9 @@ import project.Internal.DDL_Transaction
|
||||
import project.Internal.In_Transaction.In_Transaction
|
||||
import project.Internal.IR.Query.Query
|
||||
import project.Update_Action.Update_Action
|
||||
from project.Errors import SQL_Error, Rows_Already_Present, Unmatched_Rows
|
||||
from project.Errors import Rows_Already_Present, SQL_Error, Unmatched_Rows
|
||||
from project.Internal.Upload.Helpers.Argument_Checks import all
|
||||
from project.Internal.Upload.Helpers.Check_Queries import check_multiple_rows_match, check_for_null_keys_if_any_keys_set
|
||||
from project.Internal.Upload.Helpers.Check_Queries import check_for_null_keys_if_any_keys_set, check_multiple_rows_match
|
||||
from project.Internal.Upload.Helpers.Constants import dry_run_row_limit
|
||||
from project.Internal.Upload.Helpers.Error_Helpers import handle_upload_errors
|
||||
from project.Internal.Upload.Operations.Internal_Core import internal_upload_table
|
||||
|
@ -1,5 +1,5 @@
|
||||
from Standard.Base import Text
|
||||
import Standard.Base.Errors.Common.Missing_Argument
|
||||
from Standard.Base import Text
|
||||
|
||||
type SQL_Query
|
||||
## Query a whole table or view.
|
||||
|
@ -38,8 +38,8 @@ import Standard.Database.SQL.SQL_Builder
|
||||
import Standard.Database.SQL.SQL_Fragment
|
||||
import Standard.Database.SQL_Statement.SQL_Statement
|
||||
import Standard.Database.SQL_Type.SQL_Type
|
||||
from Standard.Database.Errors import SQL_Error, Unsupported_Database_Operation
|
||||
from Standard.Database.Dialect import Temp_Table_Style
|
||||
from Standard.Database.Errors import SQL_Error, Unsupported_Database_Operation
|
||||
from Standard.Database.Internal.IR.Operation_Metadata import Date_Period_Metadata
|
||||
from Standard.Database.Internal.Statement_Setter import fill_hole_default
|
||||
|
||||
@ -193,7 +193,7 @@ type SQLSever_Dialect
|
||||
Specifies how the database creates temp tables.
|
||||
temp_table_style : Temp_Table_Style
|
||||
temp_table_style self = Temp_Table_Style.Hash_Prefix
|
||||
|
||||
|
||||
## PRIVATE
|
||||
adapt_unified_column : Internal_Column -> Value_Type -> (SQL_Expression -> SQL_Type_Reference) -> Internal_Column
|
||||
adapt_unified_column self column approximate_result_type infer_result_type_from_database_callback =
|
||||
@ -565,8 +565,6 @@ make_date_add arguments (metadata : Date_Period_Metadata) =
|
||||
"weeks=>1"
|
||||
Date_Period.Day ->
|
||||
"days=>1"
|
||||
Time_Period.Day ->
|
||||
"hours=>24"
|
||||
Time_Period.Hour ->
|
||||
"hours=>1"
|
||||
Time_Period.Minute ->
|
||||
@ -630,10 +628,6 @@ make_date_diff arguments (metadata : Date_Period_Metadata) =
|
||||
Time_Period.Hour -> (extract_seconds ++ " / 3600").paren
|
||||
Time_Period.Minute -> (extract_seconds ++ " / 60").paren
|
||||
Time_Period.Second -> extract_seconds
|
||||
Time_Period.Day -> case metadata.input_value_type of
|
||||
Value_Type.Date -> extract_days
|
||||
# Time_Period.Day is treated as 24 hours, so for types that support time we use the same algorithm like for hours, but divide by 24.
|
||||
_ -> (extract_seconds ++ " / (3600 * 24)").paren
|
||||
## The EPOCH gives back just the integer amount of seconds, without
|
||||
the fractional part. So we get the fractional part using
|
||||
MILLISECONDS - but that does not give the _total_ just the
|
||||
|
@ -39,8 +39,8 @@ import Standard.Database.SQL.SQL_Builder
|
||||
import Standard.Database.SQL.SQL_Fragment
|
||||
import Standard.Database.SQL_Statement.SQL_Statement
|
||||
import Standard.Database.SQL_Type.SQL_Type
|
||||
from Standard.Database.Errors import SQL_Error, Unsupported_Database_Operation
|
||||
from Standard.Database.Dialect import Temp_Table_Style
|
||||
from Standard.Database.Errors import SQL_Error, Unsupported_Database_Operation
|
||||
from Standard.Database.Internal.IR.Operation_Metadata import Date_Period_Metadata
|
||||
from Standard.Database.Internal.Statement_Setter import fill_hole_default
|
||||
|
||||
@ -616,7 +616,6 @@ date_period_to_part_with_multiplier period =
|
||||
Date_Period.Month -> ["month", 1]
|
||||
Date_Period.Week _ -> ["week", 1]
|
||||
Date_Period.Day -> ["day", 1]
|
||||
Time_Period.Day -> ["hour", 24]
|
||||
Time_Period.Hour -> ["hour", 1]
|
||||
Time_Period.Minute -> ["minute", 1]
|
||||
Time_Period.Second -> ["second", 1]
|
||||
|
@ -240,7 +240,7 @@ type Column
|
||||
`other`.
|
||||
@locale Locale.default_widget
|
||||
equals_ignore_case : Column | Any -> Locale -> Column
|
||||
equals_ignore_case self other locale=Locale.default =
|
||||
equals_ignore_case self other locale:Locale=Locale.default =
|
||||
## TODO currently this always runs the fallback which is slow due to the
|
||||
cost of Java-to-Enso calls. We want to have a vectorized
|
||||
implementation, but we need to extend the architecture to allow
|
||||
@ -1244,7 +1244,7 @@ type Column
|
||||
|
||||
example_starts_with = Examples.text_column_1.starts_with "hell" Case_Sensitivity.Insensitive
|
||||
starts_with : Column | Text -> Case_Sensitivity -> Column
|
||||
starts_with self other case_sensitivity=Case_Sensitivity.Default =
|
||||
starts_with self other case_sensitivity:Case_Sensitivity=..Default =
|
||||
new_name = naming_helper.function_name "starts_with" [self, other]
|
||||
run_vectorized_binary_case_text_op self Java_Storage.Maps.STARTS_WITH other case_sensitivity (a -> b -> a.starts_with b case_sensitivity) new_name
|
||||
|
||||
@ -1275,7 +1275,7 @@ type Column
|
||||
|
||||
example_ends_with = Examples.text_column_1.ends_with "hell"
|
||||
ends_with : Column | Text -> Case_Sensitivity -> Column
|
||||
ends_with self other case_sensitivity=Case_Sensitivity.Default =
|
||||
ends_with self other case_sensitivity:Case_Sensitivity=..Default =
|
||||
new_name = naming_helper.function_name "ends_with" [self, other]
|
||||
run_vectorized_binary_case_text_op self Java_Storage.Maps.ENDS_WITH other case_sensitivity (a -> b -> a.ends_with b case_sensitivity) new_name
|
||||
|
||||
@ -1367,7 +1367,7 @@ type Column
|
||||
|
||||
example_contains = Examples.text_column_1.contains "hell"
|
||||
contains : Column | Text -> Case_Sensitivity -> Column
|
||||
contains self other case_sensitivity=Case_Sensitivity.Default =
|
||||
contains self other case_sensitivity:Case_Sensitivity=..Default =
|
||||
new_name = naming_helper.function_name "contains" [self, other]
|
||||
run_vectorized_binary_case_text_op self Java_Storage.Maps.CONTAINS other case_sensitivity (a -> b -> a.contains b case_sensitivity) new_name
|
||||
|
||||
@ -1450,7 +1450,7 @@ type Column
|
||||
column.text_replace '"(.*?)"'.to_regex '($1)'
|
||||
@term make_regex_text_widget
|
||||
text_replace : Text | Regex | Column -> Text | Column -> Case_Sensitivity -> Boolean -> Column
|
||||
text_replace self (term : Text | Regex | Column = "") new_text="" case_sensitivity=Case_Sensitivity.Sensitive only_first=False =
|
||||
text_replace self (term : Text | Regex | Column = "") new_text="" case_sensitivity:Case_Sensitivity=..Sensitive only_first=False =
|
||||
Value_Type.expect_text self <|
|
||||
term_fn = wrap_text_or_regex_argument_as_value_provider term
|
||||
new_text_fn = wrap_text_argument_as_value_provider new_text
|
||||
@ -1596,7 +1596,7 @@ type Column
|
||||
Returns a column of `Integer` type.
|
||||
@period Date_Time_Helpers.make_period_selector_for_column
|
||||
date_part : Date_Period | Time_Period -> Column ! Invalid_Value_Type | Illegal_Argument
|
||||
date_part self period =
|
||||
date_part self period:(Date_Period | Time_Period)=..Day =
|
||||
date_part_operation col name =
|
||||
operation = case name of
|
||||
DatePartOperation.YEAR -> DatePartOperation.YEAR_INSTANCE
|
||||
@ -1639,7 +1639,7 @@ type Column
|
||||
unusual events like DST.
|
||||
@period Date_Time_Helpers.make_period_selector_for_column
|
||||
date_diff : (Column | Date | Date_Time | Time_Of_Day) -> Date_Period | Time_Period -> Column ! Invalid_Value_Type | Illegal_Argument
|
||||
date_diff self end (period : Date_Period | Time_Period = Date_Period.Day) =
|
||||
date_diff self end (period : Date_Period | Time_Period = ..Day) =
|
||||
Value_Type.expect_type self .is_date_or_time "date/time" <|
|
||||
my_type = self.inferred_precise_value_type
|
||||
Value_Type.expect_type end (== my_type) my_type.to_display_text <|
|
||||
@ -1900,7 +1900,7 @@ type Column
|
||||
@locale Locale.default_widget
|
||||
@format (self-> Widget_Helpers.make_format_chooser_for_type self.value_type)
|
||||
format : Text | Date_Time_Formatter | Column -> Locale -> Column ! Illegal_Argument
|
||||
format self format:(Text | Date_Time_Formatter | Column)="" locale=Locale.default = case format of
|
||||
format self format:(Text | Date_Time_Formatter | Column)="" locale:Locale=Locale.default = case format of
|
||||
format_column : Column -> Value_Type.expect_text format_column <|
|
||||
formatter = make_value_formatter_for_value_type self.value_type locale
|
||||
formatter.if_not_error <|
|
||||
@ -1959,7 +1959,7 @@ type Column
|
||||
types. Due to this, a Mixed column containing values `[2, "3"]` will
|
||||
actually be converted into `[2, Nothing]` when casting to Integer type.
|
||||
cast : Value_Type -> Problem_Behavior -> Column ! Illegal_Argument | Inexact_Type_Coercion | Conversion_Failure
|
||||
cast self value_type on_problems:Problem_Behavior=..Report_Warning =
|
||||
cast self value_type:Value_Type on_problems:Problem_Behavior=..Report_Warning =
|
||||
Cast_Helpers.check_cast_compatibility self.value_type value_type <|
|
||||
target_storage_type = Storage.from_value_type value_type on_problems
|
||||
Java_Problems.with_problem_aggregator on_problems java_problem_aggregator->
|
||||
@ -2377,7 +2377,7 @@ type Column
|
||||
my_compare a b = Ordering.compare a.abs b.abs
|
||||
Examples.decimal_column.sort by=my_compare
|
||||
sort : Sort_Direction -> Boolean -> (Any -> Any -> Ordering) | Nothing -> Column
|
||||
sort self order=Sort_Direction.Ascending missing_last=True by=Nothing = case by of
|
||||
sort self order:Sort_Direction=..Ascending missing_last:Boolean=True by=Nothing = case by of
|
||||
Nothing ->
|
||||
order_bool = case order of
|
||||
Sort_Direction.Ascending -> True
|
||||
|
@ -12,18 +12,10 @@ import project.Value_Type.Value_Type
|
||||
align_period_with_value_type value_type (period : Date_Period | Time_Period) = case value_type of
|
||||
Value_Type.Date ->
|
||||
if period.is_a Date_Period then period else
|
||||
## We don't 'officially' allow `Time_Period` for Date, but since
|
||||
`Time_Period.Day` and `Date_Period.Day` in this context can be interchangeable,
|
||||
we allow it as an exception - we just swap it to be the right type.
|
||||
if period == Time_Period.Day then Date_Period.Day else
|
||||
Error.throw (Illegal_Argument.Error "`Time_Period` is not allowed for Date columns. Use `Date_Period`.")
|
||||
Error.throw (Illegal_Argument.Error "`Time_Period` is not allowed for Date columns. Use `Date_Period`.")
|
||||
Value_Type.Time ->
|
||||
case period of
|
||||
_ : Date_Period ->
|
||||
Error.throw (Illegal_Argument.Error "`Date_Period` is not allowed for Time columns. Use `Time_Period`.")
|
||||
Time_Period.Day ->
|
||||
Error.throw (Illegal_Argument.Error "`Time_Period.Day` does not make sense for Time columns.")
|
||||
_ -> period
|
||||
if period.is_a Time_Period then period else
|
||||
Error.throw (Illegal_Argument.Error "`Date_Period` is not allowed for Time columns. Use `Time_Period`.")
|
||||
Value_Type.Date_Time _ ->
|
||||
## Both kinds are allowed for `Date_Time` columns, return them as-is.
|
||||
period
|
||||
@ -41,7 +33,6 @@ make_date_part_function column period make_unary_op naming_helper =
|
||||
Date_Period.Month -> make_unary_op column "month"
|
||||
Date_Period.Week _ -> make_unary_op column "week"
|
||||
Date_Period.Day -> make_unary_op column "day"
|
||||
Time_Period.Day -> make_unary_op column "day"
|
||||
Time_Period.Hour -> make_unary_op column "hour"
|
||||
Time_Period.Minute -> make_unary_op column "minute"
|
||||
Time_Period.Second -> make_unary_op column "second"
|
||||
|
@ -1894,7 +1894,10 @@ type Table
|
||||
evaluate_expression : Text | Expression -> Problem_Behavior -> Column ! No_Such_Column | Invalid_Value_Type | Expression_Error
|
||||
evaluate_expression self expression:(Text | Expression) on_problems:Problem_Behavior=..Report_Warning = if expression.is_a Text then self.evaluate_expression (Expression.Value expression) on_problems else
|
||||
get_column name = self.at name
|
||||
new_column = Expression.evaluate expression get_column self.make_constant_column "Standard.Table.Column" "Column" Column.var_args_functions
|
||||
make_constant_column value = case value of
|
||||
_ : Column -> value
|
||||
_ -> self.make_constant_column value
|
||||
new_column = Expression.evaluate expression get_column make_constant_column "Standard.Table.Column" "Column" Column.var_args_functions
|
||||
problems = Warning.get_all new_column . map .value
|
||||
result = new_column.rename (self.column_naming_helper.sanitize_name expression.expression)
|
||||
on_problems.attach_problems_before problems <|
|
||||
|
@ -4,6 +4,7 @@ from Standard.Table import Value_Type
|
||||
|
||||
## An Enso representation of a Column in a Tableau Hyper Table.
|
||||
type Hyper_Column
|
||||
## PRIVATE
|
||||
Value name:Text value_type:Value_Type nullable:Boolean
|
||||
|
||||
## PRIVATE
|
||||
|
@ -4,15 +4,17 @@ polyglot java import org.enso.tableau.HyperQueryError
|
||||
polyglot java import org.enso.tableau.HyperTableNotFound
|
||||
|
||||
## Error when a Table is not found in a Hyper File.
|
||||
type Table_Not_Found
|
||||
type Hyper_Table_Not_Found
|
||||
## PRIVATE
|
||||
Error schema:Text name:Text
|
||||
|
||||
## Error when a query fails.
|
||||
type Query_Failed
|
||||
## PRIVATE
|
||||
Error message:Text query:Text
|
||||
|
||||
## PRIVATE
|
||||
private handle_java_exceptions ~action =
|
||||
Panic.catch HyperTableNotFound handler=(c-> Error.throw (Table_Not_Found.Error c.payload.getSchema c.payload.getName)) <|
|
||||
Panic.catch HyperTableNotFound handler=(c-> Error.throw (Hyper_Table_Not_Found.Error c.payload.getSchema c.payload.getName)) <|
|
||||
Panic.catch HyperQueryError handler=(c-> Error.throw (Query_Failed.Error c.payload.getMessage c.payload.getQuery)) <|
|
||||
action
|
||||
|
@ -4,11 +4,11 @@ import Standard.Base.Errors.Illegal_Argument.Illegal_Argument
|
||||
from Standard.Base.Metadata.Choice import Option
|
||||
from Standard.Base.Metadata.Widget import Single_Choice
|
||||
|
||||
from Standard.Table import Table
|
||||
import Standard.Table.Rows_To_Read.Rows_To_Read
|
||||
from Standard.Table import Table
|
||||
|
||||
import project.Hyper_Errors.Hyper_Table_Not_Found
|
||||
import project.Hyper_Table.Hyper_Table
|
||||
import project.Hyper_Errors.Table_Not_Found
|
||||
|
||||
polyglot java import org.enso.tableau.HyperReader
|
||||
|
||||
@ -66,7 +66,7 @@ type Hyper_File
|
||||
_ -> HyperReader.listTables self.file.path schema
|
||||
array.map t-> Hyper_Table.Value self t.schema t.name
|
||||
|
||||
## ALIAS sheet, get
|
||||
## ALIAS get, sheet
|
||||
GROUP Standard.Base.Input
|
||||
ICON data_input
|
||||
Read a table from the Hyper_File into a Table.
|
||||
@ -83,7 +83,7 @@ type Hyper_File
|
||||
"" -> self.read table self.schema limit
|
||||
"*" ->
|
||||
table_to_read = self.tables.find if_missing=Nothing t-> t.table == table
|
||||
if table_to_read.is_nothing then Error.throw (Table_Not_Found.Error "*" table) else
|
||||
if table_to_read.is_nothing then Error.throw (Hyper_Table_Not_Found.Error "*" table) else
|
||||
table_to_read.read limit
|
||||
_ -> Hyper_Table.Value self table schema . read limit
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
from Standard.Base import all
|
||||
import Standard.Base.Errors.File_Error.File_Error
|
||||
|
||||
from Standard.Table import Column, Table, Value_Type
|
||||
import Standard.Table.Rows_To_Read.Rows_To_Read
|
||||
import Standard.Table.Internal.Java_Problems
|
||||
import Standard.Table.Rows_To_Read.Rows_To_Read
|
||||
from Standard.Table import Column, Table, Value_Type
|
||||
|
||||
import project.Hyper_Column.Hyper_Column
|
||||
import project.Hyper_File.Hyper_File
|
||||
import project.Hyper_Errors
|
||||
import project.Hyper_File.Hyper_File
|
||||
|
||||
polyglot java import java.sql.Types
|
||||
polyglot java import org.enso.tableau.HyperReader
|
||||
|
@ -13,9 +13,9 @@ export project.Extensions.should_be_a
|
||||
export project.Extensions.should_be_false
|
||||
export project.Extensions.should_be_true
|
||||
export project.Extensions.should_contain
|
||||
export project.Extensions.should_equal_ignoring_order
|
||||
export project.Extensions.should_end_with
|
||||
export project.Extensions.should_equal
|
||||
export project.Extensions.should_equal_ignoring_order
|
||||
export project.Extensions.should_equal_type
|
||||
export project.Extensions.should_fail_with
|
||||
export project.Extensions.should_not_contain
|
||||
|
@ -507,7 +507,7 @@ public final class ValuesGenerator {
|
||||
v(null, "import Standard.Base.Data.Time.Date_Period.Date_Period", "Date_Period.Year")
|
||||
.type());
|
||||
collect.add(
|
||||
v(null, "import Standard.Base.Data.Time.Time_Period.Time_Period", "Time_Period.Day")
|
||||
v(null, "import Standard.Base.Data.Time.Time_Period.Time_Period", "Time_Period.Hour")
|
||||
.type());
|
||||
collect.add(
|
||||
v(null, "import Standard.Base.Data.Time.Period.Period", "Period.new 1 2 3").type());
|
||||
|
@ -17,6 +17,7 @@ expr: expr op=POWER expr # Power
|
||||
| '(' expr ')' # Paren
|
||||
| COLUMN_NAME # Column
|
||||
| MINUS expr # UnaryMinus
|
||||
| '..' IDENTIFIER # Atom
|
||||
| value # Literal
|
||||
;
|
||||
|
||||
|
@ -82,6 +82,7 @@ public class ExpressionVisitorImpl extends ExpressionBaseVisitor<Value> {
|
||||
private final Function<String, Value> getColumn;
|
||||
private final Function<Object, Value> makeConstantColumn;
|
||||
private final Function<String, Value> getMethod;
|
||||
private final Function<String, Value> makeConstructor;
|
||||
private final Set<String> variableArgumentFunctions;
|
||||
|
||||
private ExpressionVisitorImpl(
|
||||
@ -93,10 +94,11 @@ public class ExpressionVisitorImpl extends ExpressionBaseVisitor<Value> {
|
||||
this.getColumn = getColumn;
|
||||
this.makeConstantColumn = makeConstantColumn;
|
||||
|
||||
final Value module =
|
||||
Context.getCurrent().getBindings("enso").invokeMember("get_module", moduleName);
|
||||
var context = Context.getCurrent().getBindings("enso");
|
||||
final Value module = context.invokeMember("get_module", moduleName);
|
||||
final Value type = module.invokeMember("get_type", typeName);
|
||||
this.getMethod = name -> module.invokeMember("get_method", type, name);
|
||||
getMethod = name -> module.invokeMember("get_method", type, name);
|
||||
makeConstructor = name -> module.invokeMember("eval_expression", ".." + name);
|
||||
|
||||
this.variableArgumentFunctions = new HashSet<>(Arrays.asList(variableArgumentFunctions));
|
||||
}
|
||||
@ -135,7 +137,7 @@ public class ExpressionVisitorImpl extends ExpressionBaseVisitor<Value> {
|
||||
if (result.canExecute()) {
|
||||
throw new IllegalArgumentException("Insufficient arguments for method " + name + ".");
|
||||
}
|
||||
return result;
|
||||
return makeConstantColumn.apply(result);
|
||||
} catch (PolyglotException e) {
|
||||
if (e.getMessage().startsWith("Type error: expected a function")) {
|
||||
throw new IllegalArgumentException("Too many arguments for method " + name + ".");
|
||||
@ -224,6 +226,29 @@ public class ExpressionVisitorImpl extends ExpressionBaseVisitor<Value> {
|
||||
return executeMethod("*", visit(ctx.expr()), Value.asValue(-1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value visitAtom(ExpressionParser.AtomContext ctx) {
|
||||
var atomName = ctx.IDENTIFIER().getText();
|
||||
return makeConstructor.apply(toCamelCase(atomName));
|
||||
}
|
||||
|
||||
private static String toCamelCase(String name) {
|
||||
var builder = new StringBuilder(name.length());
|
||||
boolean convertNext = true;
|
||||
for (var c : name.toCharArray()) {
|
||||
if (convertNext) {
|
||||
builder.append(Character.toUpperCase(c));
|
||||
convertNext = c == '_';
|
||||
} else if (c == '_') {
|
||||
convertNext = true;
|
||||
builder.append(c);
|
||||
} else {
|
||||
builder.append(Character.toLowerCase(c));
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value visitNullOrNothing(ExpressionParser.NullOrNothingContext ctx) {
|
||||
return Value.asValue(null);
|
||||
|
@ -476,7 +476,7 @@ spec_with suite_builder name create_new_date parse_date pending=Nothing =
|
||||
d1.date_part Date_Period.Week . should_equal 52
|
||||
d1.date_part Date_Period.Day . should_equal 30
|
||||
|
||||
Test.expect_panic_with (d1.date_part Time_Period.Day) Type_Error
|
||||
Test.expect_panic_with (d1.date_part Time_Period.Hour) Type_Error
|
||||
|
||||
group_builder.specify "should allow computing date_diff" <|
|
||||
d1 = create_new_date 2021 11 3
|
||||
@ -505,7 +505,6 @@ spec_with suite_builder name create_new_date parse_date pending=Nothing =
|
||||
d3.date_diff (Date.new 2021 03 01) Date_Period.Day . should_equal 58
|
||||
d3.date_diff (Date.new 2021 03 01) Date_Period.Month . should_equal 1
|
||||
|
||||
Test.expect_panic_with (d1.date_diff d2 Time_Period.Day) Type_Error
|
||||
Test.expect_panic_with (d1.date_diff d2 Time_Period.Hour) Type_Error
|
||||
|
||||
group_builder.specify "should allow shifting with date_add" <|
|
||||
@ -521,7 +520,6 @@ spec_with suite_builder name create_new_date parse_date pending=Nothing =
|
||||
d1.date_add 2 Date_Period.Quarter . should_equal (Date.new 2021 07 31)
|
||||
|
||||
Test.expect_panic_with (d1.date_add 1 Time_Period.Hour) Type_Error
|
||||
Test.expect_panic_with (d1.date_add 1 Time_Period.Day) Type_Error
|
||||
Test.expect_panic_with (d1.date_add 1.5 Date_Period.Day) Type_Error
|
||||
Test.expect_panic_with (d1.date_add 1.0 Date_Period.Day) Type_Error
|
||||
|
||||
|
@ -318,7 +318,6 @@ spec_with suite_builder name create_new_datetime parse_datetime nanoseconds_loss
|
||||
|
||||
group_builder.specify "should support addition of Time_Period" <|
|
||||
time = create_new_datetime 1970 (zone = Time_Zone.utc)
|
||||
time+Time_Period.Day . should_equal <| create_new_datetime 1970 1 2 (zone = Time_Zone.utc)
|
||||
time+Time_Period.Hour . should_equal <| create_new_datetime 1970 1 1 1 (zone = Time_Zone.utc)
|
||||
time+Time_Period.Minute . should_equal <| create_new_datetime 1970 1 1 0 1 (zone = Time_Zone.utc)
|
||||
time+Time_Period.Second . should_equal <| create_new_datetime 1970 1 1 0 0 1 (zone = Time_Zone.utc)
|
||||
@ -329,7 +328,6 @@ spec_with suite_builder name create_new_datetime parse_datetime nanoseconds_loss
|
||||
|
||||
group_builder.specify "should support subtraction of Time_Period" <|
|
||||
time = create_new_datetime 1970 (zone = Time_Zone.utc)
|
||||
time-Time_Period.Day . should_equal <| create_new_datetime 1969 12 31 (zone = Time_Zone.utc)
|
||||
time-Time_Period.Hour . should_equal <| create_new_datetime 1969 12 31 23 (zone = Time_Zone.utc)
|
||||
time-Time_Period.Minute . should_equal <| create_new_datetime 1969 12 31 23 59 (zone = Time_Zone.utc)
|
||||
time-Time_Period.Second . should_equal <| create_new_datetime 1969 12 31 23 59 59 (zone = Time_Zone.utc)
|
||||
@ -346,20 +344,6 @@ spec_with suite_builder name create_new_datetime parse_datetime nanoseconds_loss
|
||||
time+Date_Period.Year-Time_Period.Minute . should_equal <| create_new_datetime 1970 12 31 23 59 (zone = Time_Zone.utc)
|
||||
time+Time_Period.Minute+Time_Period.Minute-Time_Period.Minute . should_equal <| create_new_datetime 1970 1 1 0 1 (zone = Time_Zone.utc)
|
||||
time+Date_Period.Quarter-Date_Period.Month . should_equal <| create_new_datetime 1970 3 1 (zone = Time_Zone.utc)
|
||||
time+Date_Period.Day-Time_Period.Day . should_equal <| create_new_datetime 1970 (zone = Time_Zone.utc)
|
||||
|
||||
group_builder.specify "will reflect that Time_Period.Day does not reflect daylight saving" <|
|
||||
tz = Time_Zone.parse "Europe/Warsaw"
|
||||
dt = Date_Time.new 2023 03 26 01 20 zone=tz
|
||||
|
||||
dt1 = dt + Time_Period.Day
|
||||
dt2 = dt + Date_Period.Day
|
||||
|
||||
# Time Period adds 24 hours which will be 1 hour later due to the DST hole.
|
||||
dt1 . should_equal (Date_Time.new 2023 03 27 02 20 zone=tz)
|
||||
|
||||
# Date Period shifts by 1 calendar day.
|
||||
dt2 . should_equal (Date_Time.new 2023 03 27 01 20 zone=tz)
|
||||
|
||||
group_builder.specify "should get the default comparator for datetimes" <|
|
||||
assert_comparator value comparator =
|
||||
@ -482,8 +466,6 @@ spec_with suite_builder name create_new_datetime parse_datetime nanoseconds_loss
|
||||
|
||||
group_builder.specify "should allow to find start/end of a Time_Period containing the current datetime" <|
|
||||
d1 = create_new_datetime 2022 9 12 15 37 58 123456789
|
||||
d1.start_of Time_Period.Day . should_equal (Date_Time.new 2022 9 12)
|
||||
d1.end_of Time_Period.Day . should_equal (Date_Time.new 2022 9 12 23 59 59 nanosecond=max_nanos)
|
||||
d1.start_of Time_Period.Hour . should_equal (Date_Time.new 2022 9 12 15 0 0 0)
|
||||
d1.end_of Time_Period.Hour . should_equal (Date_Time.new 2022 9 12 15 59 59 nanosecond=max_nanos)
|
||||
d1.start_of Time_Period.Minute . should_equal (Date_Time.new 2022 9 12 15 37 0 0)
|
||||
@ -501,8 +483,6 @@ spec_with suite_builder name create_new_datetime parse_datetime nanoseconds_loss
|
||||
d1.end_of Time_Period.Nanosecond . should_equal d1
|
||||
|
||||
d2 = create_new_datetime 1970 1 1 0 0 0
|
||||
d2.start_of Time_Period.Day . should_equal (Date_Time.new 1970)
|
||||
d2.end_of Time_Period.Day . should_equal (Date_Time.new 1970 1 1 23 59 59 nanosecond=max_nanos)
|
||||
d2.start_of Time_Period.Hour . should_equal (Date_Time.new 1970 1 1 0 0 0 0)
|
||||
d2.end_of Time_Period.Hour . should_equal (Date_Time.new 1970 1 1 0 59 59 nanosecond=max_nanos)
|
||||
d2.start_of Time_Period.Minute . should_equal (Date_Time.new 1970 1 1 0 0 0 0)
|
||||
@ -511,8 +491,6 @@ spec_with suite_builder name create_new_datetime parse_datetime nanoseconds_loss
|
||||
d2.end_of Time_Period.Second . should_equal (Date_Time.new 1970 1 1 0 0 0 nanosecond=max_nanos)
|
||||
|
||||
d3 = create_new_datetime 2100 12 31 23 59 59 max_nanos
|
||||
d3.start_of Time_Period.Day . should_equal (Date_Time.new 2100 12 31)
|
||||
d3.end_of Time_Period.Day . should_equal (Date_Time.new 2100 12 31 23 59 59 nanosecond=max_nanos)
|
||||
d3.start_of Time_Period.Hour . should_equal (Date_Time.new 2100 12 31 23 0 0 0)
|
||||
d3.end_of Time_Period.Hour . should_equal (Date_Time.new 2100 12 31 23 59 59 nanosecond=max_nanos)
|
||||
d3.start_of Time_Period.Minute . should_equal (Date_Time.new 2100 12 31 23 59 0 0)
|
||||
@ -536,8 +514,6 @@ spec_with suite_builder name create_new_datetime parse_datetime nanoseconds_loss
|
||||
check_dates_spring date =
|
||||
date.start_of Date_Period.Day . should_equal (Date_Time.new 2022 3 27 zone=tz)
|
||||
date.end_of Date_Period.Day . should_equal (Date_Time.new 2022 3 27 23 59 59 nanosecond=max_nanos zone=tz)
|
||||
date.start_of Time_Period.Day . should_equal (Date_Time.new 2022 3 27 zone=tz)
|
||||
date.end_of Time_Period.Day . should_equal (Date_Time.new 2022 3 27 23 59 59 nanosecond=max_nanos zone=tz)
|
||||
|
||||
date.start_of Date_Period.Month . should_equal (Date_Time.new 2022 3 1 zone=tz)
|
||||
date.end_of Date_Period.Month . should_equal (Date_Time.new 2022 3 31 23 59 59 nanosecond=max_nanos zone=tz)
|
||||
@ -575,9 +551,6 @@ spec_with suite_builder name create_new_datetime parse_datetime nanoseconds_loss
|
||||
Time_Utils.get_datetime_offset d4 . should_equal offset_1_h
|
||||
|
||||
check_dates_autumn date =
|
||||
date.start_of Time_Period.Day . should_equal (Date_Time.new 2022 10 30 zone=tz)
|
||||
date.end_of Time_Period.Day . should_equal (Date_Time.new 2022 10 30 23 59 59 nanosecond=max_nanos zone=tz)
|
||||
|
||||
date.start_of Date_Period.Month . should_equal (Date_Time.new 2022 10 1 zone=tz)
|
||||
date.end_of Date_Period.Month . should_equal (Date_Time.new 2022 10 31 23 59 59 nanosecond=max_nanos zone=tz)
|
||||
|
||||
@ -686,7 +659,6 @@ spec_with suite_builder name create_new_datetime parse_datetime nanoseconds_loss
|
||||
d1.date_part Date_Period.Month . should_equal 12
|
||||
d1.date_part Date_Period.Week . should_equal 52
|
||||
d1.date_part Date_Period.Day . should_equal 30
|
||||
d1.date_part Time_Period.Day . should_equal 30
|
||||
d1.date_part Time_Period.Hour . should_equal 15
|
||||
d1.date_part Time_Period.Minute . should_equal 37
|
||||
d1.date_part Time_Period.Second . should_equal 58
|
||||
@ -711,8 +683,6 @@ spec_with suite_builder name create_new_datetime parse_datetime nanoseconds_loss
|
||||
t1.date_diff t2 Date_Period.Year . should_equal 0
|
||||
t1.date_diff (Date_Time.new 2031 12 1 10 15 0) Date_Period.Year . should_equal 10
|
||||
|
||||
t1.date_diff t2 Time_Period.Day . should_equal 32
|
||||
|
||||
t1.date_diff t2 Time_Period.Hour . should_equal 770
|
||||
t1.date_diff (Date_Time.new 2021 11 3 12 15 0 zone=Time_Zone.utc) Time_Period.Hour . should_equal 2
|
||||
|
||||
@ -734,7 +704,6 @@ spec_with suite_builder name create_new_datetime parse_datetime nanoseconds_loss
|
||||
group_builder.specify "should allow shifting with date_add" <|
|
||||
t1 = Date_Time.new 2021 01 01 12 30 0
|
||||
t1.date_add 5 Date_Period.Day . should_equal (Date_Time.new 2021 01 06 12 30 0)
|
||||
t1.date_add -1 Time_Period.Day . should_equal (Date_Time.new 2020 12 31 12 30 0)
|
||||
t1.date_add 1 Date_Period.Month . should_equal (Date_Time.new 2021 02 01 12 30 0)
|
||||
t1.date_add 10 Date_Period.Year . should_equal (Date_Time.new 2031 01 01 12 30 0)
|
||||
|
||||
@ -759,21 +728,16 @@ spec_with suite_builder name create_new_datetime parse_datetime nanoseconds_loss
|
||||
|
||||
# But 1 day date shift will shift 1 day, keeping the time, even if that particular day is only 23 hours.
|
||||
dt1.date_add 1 Date_Period.Day . should_equal (Date_Time.new 2023 03 27 00 30 00 zone=zone)
|
||||
# Time_Period.Day will shift by 24 hours.
|
||||
dt1.date_add 1 Time_Period.Day . should_equal (Date_Time.new 2023 03 27 01 30 00 zone=zone)
|
||||
|
||||
dt2 = Date_Time.new 2023 03 27 00 30 00 zone=zone
|
||||
dt1.date_diff dt2 Time_Period.Hour . should_equal 23
|
||||
|
||||
dt1.date_diff dt2 Date_Period.Day . should_equal 1
|
||||
# But when counting in hours - 23 hours is not a full 24-hour day.
|
||||
dt1.date_diff dt2 Time_Period.Day . should_equal 0
|
||||
|
||||
dt3 = Date_Time.new 2023 03 28 01 30 00 zone=zone
|
||||
dt4 = Date_Time.new 2023 03 29 00 30 00 zone=zone
|
||||
|
||||
dt3.date_diff dt4 Date_Period.Day . should_equal 0
|
||||
dt3.date_diff dt4 Time_Period.Day . should_equal 0
|
||||
dt3.date_diff dt4 Time_Period.Hour . should_equal 23
|
||||
|
||||
Date_Part_Spec.add_specs suite_builder name create_new_datetime
|
||||
|
@ -137,7 +137,6 @@ specWith suite_builder name create_new_time parse_time nanoseconds_loss_in_preci
|
||||
|
||||
group_builder.specify "should support addition of Time_Period" <|
|
||||
time = create_new_time 0
|
||||
time+Time_Period.Day . should_equal <| create_new_time 0
|
||||
time+Time_Period.Hour . should_equal <| create_new_time 1
|
||||
time+Time_Period.Minute . should_equal <| create_new_time 0 1
|
||||
time+Time_Period.Second . should_equal <| create_new_time 0 0 1
|
||||
@ -148,7 +147,6 @@ specWith suite_builder name create_new_time parse_time nanoseconds_loss_in_preci
|
||||
|
||||
group_builder.specify "should support subtraction of Time_Period" <|
|
||||
time = create_new_time 12
|
||||
time-Time_Period.Day . should_equal <| create_new_time 12
|
||||
time-Time_Period.Hour . should_equal <| create_new_time 11
|
||||
time-Time_Period.Minute . should_equal <| create_new_time 11 59
|
||||
time-Time_Period.Second . should_equal <| create_new_time 11 59 59
|
||||
@ -183,8 +181,6 @@ specWith suite_builder name create_new_time parse_time nanoseconds_loss_in_preci
|
||||
max_nanos = 999999999
|
||||
group_builder.specify "should allow to find start/end of a Time_Period containing the current time of day" <|
|
||||
d1 = create_new_time 15 37 58 123456789
|
||||
d1.start_of Time_Period.Day . should_equal (Time_Of_Day.new)
|
||||
d1.end_of Time_Period.Day . should_equal (Time_Of_Day.new 23 59 59 nanosecond=max_nanos)
|
||||
d1.start_of Time_Period.Hour . should_equal (Time_Of_Day.new 15 0 0 0)
|
||||
d1.end_of Time_Period.Hour . should_equal (Time_Of_Day.new 15 59 59 nanosecond=max_nanos)
|
||||
d1.start_of Time_Period.Minute . should_equal (Time_Of_Day.new 15 37 0 0)
|
||||
@ -201,8 +197,6 @@ specWith suite_builder name create_new_time parse_time nanoseconds_loss_in_preci
|
||||
d1.end_of Time_Period.Nanosecond . should_equal d1
|
||||
|
||||
d2 = create_new_time 0 0 0
|
||||
d2.start_of Time_Period.Day . should_equal (Time_Of_Day.new)
|
||||
d2.end_of Time_Period.Day . should_equal (Time_Of_Day.new 23 59 59 nanosecond=max_nanos)
|
||||
d2.start_of Time_Period.Hour . should_equal (Time_Of_Day.new 0 0 0 0)
|
||||
d2.end_of Time_Period.Hour . should_equal (Time_Of_Day.new 0 59 59 nanosecond=max_nanos)
|
||||
d2.start_of Time_Period.Minute . should_equal (Time_Of_Day.new 0 0 0 0)
|
||||
@ -211,8 +205,6 @@ specWith suite_builder name create_new_time parse_time nanoseconds_loss_in_preci
|
||||
d2.end_of Time_Period.Second . should_equal (Time_Of_Day.new 0 0 0 nanosecond=max_nanos)
|
||||
|
||||
d3 = create_new_time 23 59 59 max_nanos
|
||||
d3.start_of Time_Period.Day . should_equal (Time_Of_Day.new)
|
||||
d3.end_of Time_Period.Day . should_equal (Time_Of_Day.new 23 59 59 nanosecond=max_nanos)
|
||||
d3.start_of Time_Period.Hour . should_equal (Time_Of_Day.new 23 0 0 0)
|
||||
d3.end_of Time_Period.Hour . should_equal (Time_Of_Day.new 23 59 59 nanosecond=max_nanos)
|
||||
d3.start_of Time_Period.Minute . should_equal (Time_Of_Day.new 23 59 0 0)
|
||||
@ -230,7 +222,6 @@ specWith suite_builder name create_new_time parse_time nanoseconds_loss_in_preci
|
||||
d1.date_part Time_Period.Microsecond . should_equal 456
|
||||
d1.date_part Time_Period.Nanosecond . should_equal 789
|
||||
|
||||
d1.date_part Time_Period.Day . should_fail_with Illegal_Argument
|
||||
Test.expect_panic_with (d1.date_part Date_Period.Day) Type_Error
|
||||
|
||||
group_builder.specify "should allow computing a date_diff" <|
|
||||
@ -240,7 +231,6 @@ specWith suite_builder name create_new_time parse_time nanoseconds_loss_in_preci
|
||||
# There is no default period:
|
||||
t1.date_diff t2 . should_be_a Function
|
||||
Test.expect_panic_with (t1.date_diff t2 Date_Period.Month) Type_Error
|
||||
t1.date_diff t2 Time_Period.Day . should_fail_with Illegal_Argument
|
||||
|
||||
t1.date_diff t2 Time_Period.Hour . should_equal 2
|
||||
t1.date_diff (Time_Of_Day.new 9 15 0) Time_Period.Hour . should_equal -1
|
||||
@ -275,7 +265,6 @@ specWith suite_builder name create_new_time parse_time nanoseconds_loss_in_preci
|
||||
t1.date_add -2 Time_Period.Nanosecond . should_equal (Time_Of_Day.new 23 44 59 999 999 998)
|
||||
|
||||
# No sense to shift Time_Of_Day by days
|
||||
t1.date_add 1 Time_Period.Day . should_fail_with Illegal_Argument
|
||||
Test.expect_panic_with (t1.date_add 1 Date_Period.Month) Type_Error
|
||||
|
||||
# There is no default period.
|
||||
|
@ -319,8 +319,6 @@ add_specs suite_builder setup =
|
||||
(t1.at "X1").date_diff (Date.new 2021 03 01) Date_Period.Day . to_vector . should_equal [58]
|
||||
(t1.at "X1").date_diff (Date.new 2021 03 01) Date_Period.Month . to_vector . should_equal [1]
|
||||
|
||||
# We do allow the `Time_Period.Day` as a kind of alias for `Date_Period.Day` here.
|
||||
(t1.at "X").date_diff (t1.at "Y") Time_Period.Day . to_vector . should_equal [32]
|
||||
(t1.at "X").date_diff (t1.at "Y") Time_Period.Hour . should_fail_with Illegal_Argument
|
||||
|
||||
t2 = dates1.get.select_columns ["dt_X", "dt_Y"] reorder=True . rename_columns ["X", "Y"]
|
||||
@ -335,8 +333,6 @@ add_specs suite_builder setup =
|
||||
(t2.at "X").date_diff (t2.at "Y") Date_Period.Year . to_vector . should_equal [0]
|
||||
(t2.at "X").date_diff (Date_Time.new 2031 12 1 10 15 0 zone=zone) Date_Period.Year . to_vector . should_equal [10]
|
||||
|
||||
(t2.at "X").date_diff (t2.at "Y") Time_Period.Day . to_vector . should_equal [32]
|
||||
|
||||
(t2.at "X").date_diff (t2.at "Y") Time_Period.Hour . to_vector . should_equal [770]
|
||||
(t2.at "X").date_diff (Date_Time.new 2021 11 3 12 15 0 zone=zone) Time_Period.Hour . to_vector . should_equal [2]
|
||||
|
||||
@ -365,9 +361,6 @@ add_specs suite_builder setup =
|
||||
# There is no default period:
|
||||
(t3.at "X").date_diff (t3.at "Y") Date_Period.Month . should_fail_with Illegal_Argument
|
||||
|
||||
# This will always be 0, should it be allowed?
|
||||
(t3.at "X").date_diff (t3.at "Y") Time_Period.Day . should_fail_with Illegal_Argument
|
||||
|
||||
(t3.at "X").date_diff (t3.at "Y") Time_Period.Hour . to_vector . should_equal [2]
|
||||
(t3.at "X").date_diff (Time_Of_Day.new 9 15 0) Time_Period.Hour . to_vector . should_equal [-1]
|
||||
|
||||
@ -434,14 +427,9 @@ add_specs suite_builder setup =
|
||||
(t1.at "X").date_add 1 Date_Period.Quarter . to_vector . should_equal [Date.new 2021 04 30, Date.new 2021 04 01, Date.new 2022 03 31]
|
||||
|
||||
(t1.at "X").date_add 1 Time_Period.Hour . should_fail_with Illegal_Argument
|
||||
# Will accept Time_Period.Day as alias of Date_Period.Day
|
||||
r1 = (t1.at "X").date_add 1 Time_Period.Day
|
||||
r1.value_type . should_equal Value_Type.Date
|
||||
r1.to_vector . should_equal [Date.new 2021 02 01, Date.new 2021 01 02, Date.new 2022 01 01]
|
||||
|
||||
t2 = table_builder [["X", [Date_Time.new 2021 01 31 12 30 0, Date_Time.new 2021 01 01 12 30 0, Date_Time.new 2021 12 31 12 30 0]], ["Y", [11, -1, 0]]]
|
||||
(t2.at "X").date_add (t2.at "Y") Date_Period.Day . to_vector . should_equal_tz_agnostic [Date_Time.new 2021 02 11 12 30 0, Date_Time.new 2020 12 31 12 30 0, Date_Time.new 2021 12 31 12 30 0]
|
||||
(t2.at "X").date_add -1 Time_Period.Day . to_vector . should_equal_tz_agnostic [Date_Time.new 2021 01 30 12 30 0, Date_Time.new 2020 12 31 12 30 0, Date_Time.new 2021 12 30 12 30 0]
|
||||
(t2.at "X").date_add (t2.at "Y") Date_Period.Month . to_vector . should_equal_tz_agnostic [Date_Time.new 2021 12 31 12 30 0, Date_Time.new 2020 12 01 12 30 0, Date_Time.new 2021 12 31 12 30 0]
|
||||
(t2.at "X").date_add 1 Date_Period.Month . to_vector . should_equal_tz_agnostic [Date_Time.new 2021 02 28 12 30 0, Date_Time.new 2021 02 01 12 30 0, Date_Time.new 2022 01 31 12 30 0]
|
||||
(t2.at "X").date_add (t2.at "Y") Date_Period.Year . to_vector . should_equal_tz_agnostic [Date_Time.new 2032 01 31 12 30 0, Date_Time.new 2020 01 01 12 30 0, Date_Time.new 2021 12 31 12 30 0]
|
||||
@ -478,7 +466,6 @@ add_specs suite_builder setup =
|
||||
(t3.at "X").date_add 1 Time_Period.Nanosecond . should_fail_with Unsupported_Database_Operation
|
||||
|
||||
# No sense to shift Time_Of_Day by days either or by a Date_Period
|
||||
(t3.at "X").date_add (t3.at "Y") Time_Period.Day . to_vector . should_fail_with Illegal_Argument
|
||||
(t3.at "X").date_add 1 Date_Period.Month . to_vector . should_fail_with Illegal_Argument
|
||||
|
||||
# Date period defaults to Day for date/date-time
|
||||
@ -509,9 +496,6 @@ add_specs suite_builder setup =
|
||||
# instead let's compare as local timestamps:
|
||||
plus_1_calendar_day.to_vector . map as_local_date_time_repr . should_equal ["2023-03-27 00:30:00.0"]
|
||||
|
||||
# Time_Period.Day will shift by 24 hours.
|
||||
x.date_add 1 Time_Period.Day . to_vector . should_equal_tz_agnostic [Date_Time.new 2023 03 27 01 30 00 zone=zone]
|
||||
|
||||
# Once we add 3 months, we should get the same hour back.
|
||||
plus_3_months = x.date_add 3 Date_Period.Month
|
||||
plus_3_months.to_vector.map as_local_date_time_repr . should_equal ["2023-06-26 00:30:00.0"]
|
||||
@ -528,15 +512,12 @@ add_specs suite_builder setup =
|
||||
cannot 'guess' that it should be a day of a difference and
|
||||
since it is 'just' 23 hours - there is 0 days.
|
||||
[[0], [1]] . should_contain (x.date_diff dt2 Date_Period.Day . to_vector)
|
||||
# Again consistent for both backends, when counting in hours - 23 hours is not a full 24-hour day.
|
||||
x.date_diff dt2 Time_Period.Day . to_vector . should_equal [0]
|
||||
|
||||
dt4 = Date_Time.new 2023 03 29 00 30 00 zone=zone
|
||||
y = t.at "Y"
|
||||
# No DST switch here, so all backends agree that 0 days elapsed in the 23 hours.
|
||||
# Snowflake returns 1...
|
||||
y.date_diff dt4 Date_Period.Day . to_vector . should_equal [0]
|
||||
y.date_diff dt4 Time_Period.Day . to_vector . should_equal [0]
|
||||
y.date_diff dt4 Time_Period.Hour . to_vector . should_equal [23]
|
||||
|
||||
if setup.test_selection.date_time.not then
|
||||
|
@ -11,7 +11,6 @@ from Standard.Database.Errors import SQL_Error
|
||||
|
||||
from Standard.Test import all
|
||||
|
||||
|
||||
from project.Util import all
|
||||
from project.Common_Table_Operations.Util import run_default_backend, build_sorted_table
|
||||
|
||||
@ -218,10 +217,6 @@ add_specs suite_builder detailed setup =
|
||||
expression_test "1_000.456/2" 500.228
|
||||
expression_test "2^4" 16
|
||||
expression_test "11%3" 2
|
||||
expression_test "truncate(3.3)" 3
|
||||
expression_test "ceil(5.3)" 6
|
||||
expression_test "floor(5.3)" 5
|
||||
expression_test "round(5.5)" 6
|
||||
|
||||
specify_test "should be able to do basic arithmetic with order" group_builder expression_test->
|
||||
expression_test "1+1*2+2" 5
|
||||
@ -375,6 +370,20 @@ add_specs suite_builder detailed setup =
|
||||
expression_test "min(10, 3, 8)" 3
|
||||
expression_test "max([A], [B], 3)" [3, 3, 3, 4, 6]
|
||||
|
||||
specify_test "should be able to use functions with constants" group_builder expression_test->
|
||||
expression_test "truncate(3.3)" 3
|
||||
expression_test "CEIL(5.3)" 6
|
||||
expression_test "floor(5.3)" 5
|
||||
expression_test "rOuNd(5.5)" 6
|
||||
|
||||
specify_test "should be able to use scalar functions" group_builder expression_test->
|
||||
expression_test "first([C])" "Hello"
|
||||
expression_test "at([C], 2)" "Hello World!"
|
||||
|
||||
specify_test "should be able to pass Atom constructors to functions" group_builder expression_test->
|
||||
expression_test "cast([A], ..Char)" ["1", "2", "3", "4", "5"]
|
||||
expression_test "starts_WITH([C], 'HELLO', ..INSENSITIVE)" [True, False, True, False, Nothing]
|
||||
|
||||
suite_builder.group prefix+"Expression Errors should be handled" group_builder->
|
||||
expect_error ctor expr =
|
||||
expr.should_fail_with Expression_Error
|
||||
|
@ -3,7 +3,7 @@ import Standard.Base.Errors.File_Error.File_Error
|
||||
|
||||
from Standard.Table import all
|
||||
from Standard.Tableau import Hyper_File
|
||||
import Standard.Tableau.Hyper_Errors.Table_Not_Found
|
||||
import Standard.Tableau.Hyper_Errors.Hyper_Table_Not_Found
|
||||
|
||||
from Standard.Test import all
|
||||
|
||||
@ -60,7 +60,7 @@ add_specs suite_builder = suite_builder.group "Read Tables" group_builder->
|
||||
|
||||
group_builder.specify "should handle a missing table when reading a table" <|
|
||||
r1 = Hyper_File.new names_file . read "NoTable"
|
||||
r1.should_fail_with Table_Not_Found
|
||||
r1.should_fail_with Hyper_Table_Not_Found
|
||||
|
||||
r2 = Hyper_File.new names_file . read "NoTable" schema="Extract"
|
||||
r2.should_fail_with Table_Not_Found
|
||||
r2.should_fail_with Hyper_Table_Not_Found
|
||||
|
Loading…
Reference in New Issue
Block a user