Skip to content

Commit

Permalink
More efficient memory usage of Values (#147)
Browse files Browse the repository at this point in the history
This doesn't change any behavior. The Value now uses a union to use a
lot less memory. This also does some minor refactoring to prepare for
the "scale" property of SQL types.
  • Loading branch information
elliotchance authored Mar 1, 2023
1 parent 4c304eb commit 28157a4
Show file tree
Hide file tree
Showing 20 changed files with 338 additions and 272 deletions.
2 changes: 1 addition & 1 deletion docs/custom-functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ You can create custom functions to use in expressions:
// no_pennies will round to 0.05 denominations.
db.register_function('no_pennies(float) float', fn (a []vsql.Value) !vsql.Value {
amount := math.round(a[0].f64_value / 0.05) * 0.05
amount := math.round(a[0].f64_value() / 0.05) * 0.05
return vsql.new_double_precision_value(amount)
}) !
Expand Down
3 changes: 3 additions & 0 deletions docs/snippets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,9 @@
.. |v.Type.not_null| replace::
Is NOT NULL?

.. |v.Type.scale| replace::
The scale is only for numeric types.

.. |v.Type.size| replace::
The size specified for the type.

Expand Down
2 changes: 1 addition & 1 deletion examples/custom-functions.v
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn example() ! {

// no_pennies will round to 0.05 denominations.
db.register_function('no_pennies(float) float', fn (a []vsql.Value) !vsql.Value {
amount := math.round(a[0].f64_value / 0.05) * 0.05
amount := math.round(a[0].f64_value() / 0.05) * 0.05
return vsql.new_double_precision_value(amount)
})!

Expand Down
16 changes: 8 additions & 8 deletions vsql/agg.v
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ fn func_min(values []Value) !Value {
return new_null_value(.is_double_precision)
}

mut min := values[0].f64_value
mut min := values[0].f64_value()
for value in values {
// If any values are NULL, the result is also NULL.
if value.is_null {
return new_null_value(.is_double_precision)
}

if value.f64_value < min {
min = value.f64_value
if value.f64_value() < min {
min = value.f64_value()
}
}

Expand All @@ -41,15 +41,15 @@ fn func_max(values []Value) !Value {
return new_null_value(.is_double_precision)
}

mut max := values[0].f64_value
mut max := values[0].f64_value()
for value in values {
// If any values are NULL, the result is also NULL.
if value.is_null {
return new_null_value(.is_double_precision)
}

if value.f64_value > max {
max = value.f64_value
if value.f64_value() > max {
max = value.f64_value()
}
}

Expand All @@ -69,7 +69,7 @@ fn func_sum(values []Value) !Value {
return new_null_value(.is_double_precision)
}

sum += value.f64_value
sum += value.f64_value()
}

return new_double_precision_value(sum)
Expand All @@ -88,7 +88,7 @@ fn func_avg(values []Value) !Value {
return new_null_value(.is_double_precision)
}

sum += value.f64_value
sum += value.f64_value()
}

return new_double_precision_value(sum / values.len)
Expand Down
106 changes: 53 additions & 53 deletions vsql/cast.v
Original file line number Diff line number Diff line change
Expand Up @@ -115,213 +115,213 @@ fn cast_passthru(conn &Connection, v Value, to Type) !Value {
}

fn cast_bigint_to_smallint(conn &Connection, v Value, to Type) !Value {
check_integer_range(v.int_value, .is_smallint)!
check_integer_range(v.int_value(), .is_smallint)!

return new_smallint_value(i16(v.int_value))
return new_smallint_value(i16(v.int_value()))
}

fn cast_bigint_to_integer(conn &Connection, v Value, to Type) !Value {
check_integer_range(v.int_value, .is_integer)!
check_integer_range(v.int_value(), .is_integer)!

return new_integer_value(int(v.int_value))
return new_integer_value(int(v.int_value()))
}

fn cast_bigint_to_real(conn &Connection, v Value, to Type) !Value {
return new_real_value(f32(v.int_value))
return new_real_value(f32(v.int_value()))
}

fn cast_bigint_to_double_precision(conn &Connection, v Value, to Type) !Value {
return new_double_precision_value(f64(v.int_value))
return new_double_precision_value(f64(v.int_value()))
}

fn cast_smallint_to_integer(conn &Connection, v Value, to Type) !Value {
return new_integer_value(int(v.int_value))
return new_integer_value(int(v.int_value()))
}

fn cast_smallint_to_bigint(conn &Connection, v Value, to Type) !Value {
return new_bigint_value(int(v.int_value))
return new_bigint_value(int(v.int_value()))
}

fn cast_smallint_to_real(conn &Connection, v Value, to Type) !Value {
return new_real_value(f32(v.int_value))
return new_real_value(f32(v.int_value()))
}

fn cast_smallint_to_double_precision(conn &Connection, v Value, to Type) !Value {
return new_double_precision_value(f64(v.int_value))
return new_double_precision_value(f64(v.int_value()))
}

fn cast_integer_to_smallint(conn &Connection, v Value, to Type) !Value {
check_integer_range(v.int_value, .is_smallint)!
check_integer_range(v.int_value(), .is_smallint)!

return new_smallint_value(i16(v.int_value))
return new_smallint_value(i16(v.int_value()))
}

fn cast_integer_to_bigint(conn &Connection, v Value, to Type) !Value {
return new_bigint_value(int(v.int_value))
return new_bigint_value(int(v.int_value()))
}

fn cast_integer_to_real(conn &Connection, v Value, to Type) !Value {
return new_real_value(f32(v.int_value))
return new_real_value(f32(v.int_value()))
}

fn cast_integer_to_double_precision(conn &Connection, v Value, to Type) !Value {
return new_double_precision_value(f64(v.int_value))
return new_double_precision_value(f64(v.int_value()))
}

fn cast_real_to_smallint(conn &Connection, v Value, to Type) !Value {
check_floating_range(v.f64_value, .is_smallint)!
check_floating_range(v.f64_value(), .is_smallint)!

return new_smallint_value(i16(v.f64_value))
return new_smallint_value(i16(v.f64_value()))
}

fn cast_real_to_integer(conn &Connection, v Value, to Type) !Value {
check_floating_range(v.f64_value, .is_integer)!
check_floating_range(v.f64_value(), .is_integer)!

return new_integer_value(int(v.f64_value))
return new_integer_value(int(v.f64_value()))
}

fn cast_real_to_bigint(conn &Connection, v Value, to Type) !Value {
check_floating_range(v.f64_value, .is_bigint)!
check_floating_range(v.f64_value(), .is_bigint)!

return new_bigint_value(i64(v.f64_value))
return new_bigint_value(i64(v.f64_value()))
}

fn cast_real_to_double_precision(conn &Connection, v Value, to Type) !Value {
return new_double_precision_value(f64(v.f64_value))
return new_double_precision_value(f64(v.f64_value()))
}

fn cast_double_precision_to_smallint(conn &Connection, v Value, to Type) !Value {
check_floating_range(v.f64_value, .is_smallint)!
check_floating_range(v.f64_value(), .is_smallint)!

return new_smallint_value(i16(v.f64_value))
return new_smallint_value(i16(v.f64_value()))
}

fn cast_double_precision_to_integer(conn &Connection, v Value, to Type) !Value {
check_floating_range(v.f64_value, .is_integer)!
check_floating_range(v.f64_value(), .is_integer)!

return new_integer_value(int(v.f64_value))
return new_integer_value(int(v.f64_value()))
}

fn cast_double_precision_to_bigint(conn &Connection, v Value, to Type) !Value {
check_floating_range(v.f64_value, .is_bigint)!
check_floating_range(v.f64_value(), .is_bigint)!

return new_bigint_value(i64(v.f64_value))
return new_bigint_value(i64(v.f64_value()))
}

fn cast_double_precision_to_real(conn &Connection, v Value, to Type) !Value {
return new_real_value(f32(v.f64_value))
return new_real_value(f32(v.f64_value()))
}

fn cast_varchar_to_varchar(conn &Connection, v Value, to Type) !Value {
if to.size > 0 && v.string_value.len > to.size {
if to.size > 0 && v.string_value().len > to.size {
return sqlstate_22001(to)
}

return new_varchar_value(v.string_value, to.size)
return new_varchar_value(v.string_value(), to.size)
}

fn cast_varchar_to_character(conn &Connection, v Value, to Type) !Value {
if to.size > 0 && v.string_value.len > to.size {
if to.size > 0 && v.string_value().len > to.size {
return sqlstate_22001(to)
}

return new_character_value(v.string_value, to.size)
return new_character_value(v.string_value(), to.size)
}

fn cast_character_to_varchar(conn &Connection, v Value, to Type) !Value {
if to.size > 0 && v.string_value.len > to.size {
if to.size > 0 && v.string_value().len > to.size {
return sqlstate_22001(to)
}

return new_varchar_value(v.string_value, to.size)
return new_varchar_value(v.string_value(), to.size)
}

fn cast_character_to_character(conn &Connection, v Value, to Type) !Value {
if to.size > 0 && v.string_value.len > to.size {
if to.size > 0 && v.string_value().len > to.size {
return sqlstate_22001(to)
}

return new_character_value(v.string_value, to.size)
return new_character_value(v.string_value(), to.size)
}

// '2022-06-30' => '2022-06-30 00:00:00.000000'
fn cast_date_to_timestamp_without(conn &Connection, v Value, to Type) !Value {
return new_timestamp_value(v.time_value.str_full_timestamp(to.size, false, true))
return new_timestamp_value(v.time_value().str_full_timestamp(to.size, false, true))
}

// '2022-06-30' => '2022-06-30 00:00:00.000000+05:00'
fn cast_date_to_timestamp_with(conn &Connection, v Value, to Type) !Value {
return new_timestamp_value(v.time_value.str_full_timestamp(to.size, false, true) +
return new_timestamp_value(v.time_value().str_full_timestamp(to.size, false, true) +
time_zone_value(conn))
}

// '12:34:56.000000+0500' => '12:34:56.000000'
fn cast_time_with_to_time_without(conn &Connection, v Value, to Type) !Value {
return new_time_value(v.time_value.str_full_time(to.size, false, true))
return new_time_value(v.time_value().str_full_time(to.size, false, true))
}

// '12:34:56.999999' => '12:34:56.999999+0500'
fn cast_time_without_to_time_with(conn &Connection, v Value, to Type) !Value {
return new_time_value(v.time_value.str_full_time(to.size, false, true) + time_zone_value(conn))
return new_time_value(v.time_value().str_full_time(to.size, false, true) + time_zone_value(conn))
}

// '2022-06-30 12:34:56.999999+0500' => '2022-06-30'
fn cast_timestamp_with_to_date(conn &Connection, v Value, to Type) !Value {
return new_date_value(v.time_value.str_date())
return new_date_value(v.time_value().str_date())
}

// '2022-06-30 12:34:56.999999+0500' => '12:34:56.999999+0500'
fn cast_timestamp_with_to_time_with(conn &Connection, v Value, to Type) !Value {
return new_time_value(v.time_value.str_full_time(to.size, true, true))
return new_time_value(v.time_value().str_full_time(to.size, true, true))
}

// '2022-06-30 12:34:56.999999+0500' => '12:34:56.999999'
fn cast_timestamp_with_to_time_without(conn &Connection, v Value, to Type) !Value {
return new_time_value(v.time_value.str_full_time(to.size, false, true))
return new_time_value(v.time_value().str_full_time(to.size, false, true))
}

// '2022-06-30 12:34:56.999999+0500' => '2022-06-30 12:34:56.999999'
fn cast_timestamp_with_to_timestamp_without(conn &Connection, v Value, to Type) !Value {
return new_timestamp_value(v.time_value.str_full_timestamp(to.size, false, true))
return new_timestamp_value(v.time_value().str_full_timestamp(to.size, false, true))
}

// '12:34:56.999999+0500' => '12:34:56.999999+0500'
fn cast_time_with_to_time_with(conn &Connection, v Value, to Type) !Value {
return new_time_value(v.time_value.str_full_time(to.size, true, true))
return new_time_value(v.time_value().str_full_time(to.size, true, true))
}

// '12:34:56.999999' => '12:34:56.999999'
fn cast_time_without_to_time_without(conn &Connection, v Value, to Type) !Value {
return new_time_value(v.time_value.str_full_time(to.size, false, true))
return new_time_value(v.time_value().str_full_time(to.size, false, true))
}

// '2022-06-30 12:34:56.999999+0500' => '2022-06-30 12:34:56.999999+0500'
fn cast_timestamp_with_to_timestamp_with(conn &Connection, v Value, to Type) !Value {
return new_timestamp_value(v.time_value.str_full_timestamp(to.size, true, true))
return new_timestamp_value(v.time_value().str_full_timestamp(to.size, true, true))
}

// '2022-06-30 12:34:56.999999' => '2022-06-30'
fn cast_timestamp_without_to_date(conn &Connection, v Value, to Type) !Value {
return new_date_value(v.time_value.str_date())
return new_date_value(v.time_value().str_date())
}

// '2022-06-30 12:34:56.999999' => '12:34:56.999999+0500'
fn cast_timestamp_without_to_time_with(conn &Connection, v Value, to Type) !Value {
return new_time_value(v.time_value.str_full_time(to.size, false, true) + time_zone_value(conn))
return new_time_value(v.time_value().str_full_time(to.size, false, true) + time_zone_value(conn))
}

// '2022-06-30 12:34:56.999999' => '12:34:56.999999'
fn cast_timestamp_without_to_time_without(conn &Connection, v Value, to Type) !Value {
return new_time_value(v.time_value.str_full_time(to.size, false, true))
return new_time_value(v.time_value().str_full_time(to.size, false, true))
}

// '2022-06-30 12:34:56.999999' => '2022-06-30 12:34:56.999999+0500'
fn cast_timestamp_without_to_timestamp_with(conn &Connection, v Value, to Type) !Value {
return new_timestamp_value(v.time_value.str_full_timestamp(to.size, false, true) +
return new_timestamp_value(v.time_value().str_full_timestamp(to.size, false, true) +
time_zone_value(conn))
}

// '2022-06-30 12:34:56.999999' => '2022-06-30 12:34:56.999999'
fn cast_timestamp_without_to_timestamp_without(conn &Connection, v Value, to Type) !Value {
return new_timestamp_value(v.time_value.str_full_timestamp(to.size, false, true))
return new_timestamp_value(v.time_value().str_full_timestamp(to.size, false, true))
}
4 changes: 2 additions & 2 deletions vsql/connection.v
Original file line number Diff line number Diff line change
Expand Up @@ -332,11 +332,11 @@ pub fn (mut c Connection) register_function(prototype string, func fn ([]Value)
mut arg_types := []Type{}
for arg in raw_args {
if arg.trim_space() != '' {
arg_types << new_type(arg.trim_space().to_upper(), 0)
arg_types << new_type(arg.trim_space().to_upper(), 0, 0)
}
}

return_type := new_type(parts[2].trim_space().to_upper(), 0)
return_type := new_type(parts[2].trim_space().to_upper(), 0, 0)
c.register_func(Func{function_name, arg_types, false, func, return_type})!
}

Expand Down
Loading

0 comments on commit 28157a4

Please sign in to comment.