Skip to content

Commit

Permalink
Refactor Table problem handling to a more robust and hopefully cleane…
Browse files Browse the repository at this point in the history
…r approach (#7879)

Closes #7514
  • Loading branch information
radeusgd authored Oct 16, 2023
1 parent 209f4de commit 08b717e
Show file tree
Hide file tree
Showing 168 changed files with 2,317 additions and 1,964 deletions.
37 changes: 37 additions & 0 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import project.Function.Function
import project.Meta
import project.Nothing.Nothing
import project.Panic.Panic
import project.Runtime
import project.Runtime.Source_Location.Source_Location
from project.Data.Boolean import Boolean, False, True

polyglot java import java.lang.ArithmeticException
Expand Down Expand Up @@ -416,3 +418,38 @@ type Out_Of_Memory
handle_java_exception operation ~function =
Panic.catch OutOfMemoryError handler=(_-> Error.throw (Out_Of_Memory.Error operation)) <|
function

## Indicates that an expression cannot be evaluated because somewhere within it,
a function does not have all required arguments provided.
type Missing_Required_Argument
## PRIVATE
Indicates that an expression cannot be evaluated because somewhere within
it, a function does not have all required arguments provided.
Error (argument_name : Text) (function_name : Text) (call_location : Source_Location | Nothing)

## PRIVATE
to_display_text : Text
to_display_text self =
"Missing required argument `" + self.argument_name + "` in function `" + self.function_name + "`."

## PRIVATE
Throws an error saying that a required argument has not been provided.

This function is supposed to be used as a default value for arguments
that are supposed to be required and should prevent errors stemming from
a not-fully-applied function being passed around. Instead, this error is
raised and propagated to the top, so that the IDE can see that the node
still has some missing arguments within it.

> Example

my_function (arg1 = Missing_Required_Argument.ensure_present "arg1") (arg2 = 100) = arg1+arg2
ensure_present : Text -> Nothing ! Missing_Required_Argument
ensure_present (argument_name : Text = Missing_Required_Argument.ensure_present "argument_name") =
stack_trace = Runtime.get_stack_trace
function_frame = stack_trace . at 1
caller_frame = stack_trace . at 2

function_name = function_frame.name
call_location = caller_frame.source_location
Error.throw (Missing_Required_Argument.Error argument_name function_name call_location)
24 changes: 10 additions & 14 deletions distribution/lib/Standard/Database/0.0.0-dev/src/Data/Column.enso
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ import project.Internal.Replace_Params.Replace_Params
import project.Internal.SQL_Type_Reference.SQL_Type_Reference
from project.Errors import Integrity_Error, Unsupported_Database_Operation

polyglot java import org.enso.table.data.column.operation.map.MapOperationProblemBuilder

type Column
## PRIVATE

Expand Down Expand Up @@ -1730,19 +1728,17 @@ make_equality_check_with_floating_point_handling column other op =
other_column : Column -> "["+other_column.name+"]"
_ -> other.to_text
location = "["+column.name+"] "+op+" "+other_name
problem_builder = MapOperationProblemBuilder.new location
if column.value_type.is_floating_point then
problem_builder.reportFloatingPointEquality -1
case other of
other_column : Column ->
if other_column.value_type.is_floating_point then
problem_builder.reportFloatingPointEquality -1
_ : Float ->
Java_Problems.with_map_operation_problem_aggregator location Problem_Behavior.Report_Warning problem_builder->
if column.value_type.is_floating_point then
problem_builder.reportFloatingPointEquality -1
_ -> Nothing
result = column.make_binary_op op other
Problem_Behavior.Report_Warning.attach_problems_after result <|
Java_Problems.parse_aggregated_problems problem_builder.getProblems
case other of
other_column : Column ->
if other_column.value_type.is_floating_point then
problem_builder.reportFloatingPointEquality -1
_ : Float ->
problem_builder.reportFloatingPointEquality -1
_ -> Nothing
column.make_binary_op op other

## PRIVATE
adapt_unified_column : Column -> Value_Type -> Column
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ polyglot java import java.sql.ResultSet
polyglot java import java.time.LocalTime as Java_Local_Time

polyglot java import org.enso.database.JDBCUtils
polyglot java import org.enso.table.problems.ProblemAggregator

type Column_Fetcher
## PRIVATE
Expand All @@ -22,7 +23,9 @@ type Column_Fetcher
It takes an initial size as an argument. That size is only a suggestion
for initial capacity and the builder must be ready to accept more or
less rows than that.
Value (fetch_value : ResultSet -> Integer -> Any) (make_builder : Integer -> Column_Fetcher_Builder)
It also takes a ProblemAggregator used for reporting problems. Care has
to be taken to ensure that the builder does not outlive the aggregator.
Value (fetch_value : ResultSet -> Integer -> Any) (make_builder : Integer -> ProblemAggregator -> Column_Fetcher_Builder)

## We could use `Storage.make_builder` here, but this builder allows us to pass
raw Truffle values around (like `long`) instead of boxing them.
Expand All @@ -48,7 +51,7 @@ boolean_fetcher =
fetch_value rs i =
b = rs.getBoolean i
if rs.wasNull then Nothing else b
make_builder _ =
make_builder _ _ =
java_builder = Java_Exports.make_bool_builder
append v =
if v.is_nothing then java_builder.appendNulls 1 else
Expand All @@ -62,8 +65,8 @@ double_fetcher =
fetch_value rs i =
d = rs.getDouble i
if rs.wasNull then Nothing else d
make_builder initial_size =
java_builder = Java_Exports.make_double_builder initial_size
make_builder initial_size java_problem_aggregator =
java_builder = Java_Exports.make_double_builder initial_size java_problem_aggregator
append v =
if v.is_nothing then java_builder.appendNulls 1 else
java_builder.appendDouble v
Expand All @@ -76,8 +79,8 @@ long_fetcher bits =
fetch_value rs i =
l = rs.getLong i
if rs.wasNull then Nothing else l
make_builder initial_size =
java_builder = Java_Exports.make_long_builder initial_size bits=bits
make_builder initial_size java_problem_aggregator =
java_builder = Java_Exports.make_long_builder initial_size bits java_problem_aggregator
append v =
if v.is_nothing then java_builder.appendNulls 1 else
java_builder.appendLong v
Expand All @@ -91,8 +94,8 @@ big_integer_fetcher =
big_decimal = rs.getBigDecimal i
if rs.wasNull then Nothing else
big_decimal.toBigIntegerExact
make_builder initial_size =
java_builder = Java_Exports.make_biginteger_builder initial_size
make_builder initial_size java_problem_aggregator =
java_builder = Java_Exports.make_biginteger_builder initial_size java_problem_aggregator
make_builder_from_java_object_builder java_builder
Column_Fetcher.Value fetch_value make_builder

Expand All @@ -102,7 +105,7 @@ text_fetcher value_type =
fetch_value rs i =
t = rs.getString i
if rs.wasNull then Nothing else t
make_builder initial_size =
make_builder initial_size _ =
java_builder = Java_Exports.make_string_builder initial_size value_type=value_type
make_builder_from_java_object_builder java_builder
Column_Fetcher.Value fetch_value make_builder
Expand All @@ -119,8 +122,8 @@ fallback_fetcher =
fetch_value rs i =
v = rs.getObject i
if rs.wasNull then Nothing else v
make_builder initial_size =
java_builder = Java_Exports.make_inferred_builder initial_size
make_builder initial_size java_problem_aggregator =
java_builder = Java_Exports.make_inferred_builder initial_size java_problem_aggregator
make_builder_from_java_object_builder java_builder
Column_Fetcher.Value fetch_value make_builder

Expand All @@ -129,15 +132,15 @@ time_fetcher =
fetch_value rs i =
time = rs.getObject i Java_Local_Time.class
if rs.wasNull then Nothing else time
make_builder initial_size =
make_builder initial_size _ =
java_builder = Java_Exports.make_time_of_day_builder initial_size
make_builder_from_java_object_builder java_builder
Column_Fetcher.Value fetch_value make_builder

## PRIVATE
date_time_fetcher =
fetch_value rs i = JDBCUtils.getZonedDateTime rs i
make_builder initial_size =
make_builder initial_size _ =
java_builder = Java_Exports.make_date_time_builder initial_size
make_builder_from_java_object_builder java_builder
Column_Fetcher.Value fetch_value make_builder
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from Standard.Base import all

import Standard.Table.Data.Table.Table as Materialized_Table
import Standard.Table.Internal.Java_Problems

import project.Data.SQL_Type.SQL_Type
import project.Internal.Column_Fetcher.Column_Fetcher
Expand Down Expand Up @@ -42,34 +43,35 @@ result_set_to_table result_set make_column_fetcher type_overrides=Nothing last_r
effective_types
column_fetchers = column_types.map make_column_fetcher
initial_size = 10
column_builders = column_fetchers.map fetcher->
fetcher.make_builder initial_size
fetchers_and_builders = column_fetchers.zip column_builders
warnings_builder = Vector.new_builder
case last_row_only of
True ->
## Not using the `ResultSet.last` as not supported by all connection types.
go has_next current = case has_next.not of
True ->
if current.is_nothing then Nothing else
column_builders.each_with_index ix-> builder-> builder.append (current.at ix)
Nothing
False ->
values = column_fetchers.map_with_index ix-> fetcher-> fetcher.fetch_value result_set ix+1
Java_Problems.with_problem_aggregator Problem_Behavior.Report_Warning java_problem_aggregator->
column_builders = column_fetchers.map fetcher->
fetcher.make_builder initial_size java_problem_aggregator
fetchers_and_builders = column_fetchers.zip column_builders
warnings_builder = Vector.new_builder
case last_row_only of
True ->
## Not using the `ResultSet.last` as not supported by all connection types.
go has_next current = case has_next.not of
True ->
if current.is_nothing then Nothing else
column_builders.each_with_index ix-> builder-> builder.append (current.at ix)
Nothing
False ->
values = column_fetchers.map_with_index ix-> fetcher-> fetcher.fetch_value result_set ix+1
extract_warnings_into_builder warnings_builder result_set
@Tail_Call go result_set.next values
go result_set.next Nothing
False ->
go has_next = if has_next.not then Nothing else
fetchers_and_builders.each_with_index ix-> pair->
fetcher = pair.first
builder = pair.second
value = fetcher.fetch_value result_set ix+1
builder.append value
extract_warnings_into_builder warnings_builder result_set
@Tail_Call go result_set.next values
go result_set.next Nothing
False ->
go has_next = if has_next.not then Nothing else
fetchers_and_builders.each_with_index ix-> pair->
fetcher = pair.first
builder = pair.second
value = fetcher.fetch_value result_set ix+1
builder.append value
extract_warnings_into_builder warnings_builder result_set
@Tail_Call go result_set.next
go result_set.next
Problem_Behavior.Report_Warning.attach_problems_before warnings_builder.to_vector <|
columns = column_builders.zip column_names builder-> name->
builder.make_column name
Materialized_Table.new columns
@Tail_Call go result_set.next
go result_set.next
Problem_Behavior.Report_Warning.attach_problems_before warnings_builder.to_vector <|
columns = column_builders.zip column_names builder-> name->
builder.make_column name
Materialized_Table.new columns
Loading

0 comments on commit 08b717e

Please sign in to comment.