Skip to content

Commit

Permalink
added basic string manipulation functions (#777)
Browse files Browse the repository at this point in the history
* added basic string manipulation functions

* fixed build tag

* fixed edge case in substring where regex can be used

* added tests for variable args
  • Loading branch information
brennanjl authored May 30, 2024
1 parent 533ccf8 commit f8a7dd5
Show file tree
Hide file tree
Showing 3 changed files with 444 additions and 179 deletions.
80 changes: 80 additions & 0 deletions internal/engine/integration/procedure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,86 @@ func Test_Procedures(t *testing.T) {
{"satoshi", "hello world"},
},
},
{
name: "string functions",
procedure: `procedure string_funcs() public view {
$val := 'hello world';
$val := $val || '!!!';
$val := upper($val);
if $val != 'HELLO WORLD!!!' {
error('upper failed');
}
$val := lower($val);
if $val != 'hello world!!!' {
error('lower failed');
}
if bit_length($val) != 112 {
error('bit_length failed');
}
if char_length($val) != 14 or character_length($val) != 14 or length($val) != 14 {
error('length failed');
}
if octet_length($val) != 14 {
error('octet_length failed');
}
$val := rtrim($val, '!');
if $val != 'hello world' {
error('rtrim failed');
}
if rtrim($val||' ') != 'hello world' {
error('rtrim 2 failed');
}
$val := ltrim($val, 'h');
if $val != 'ello world' {
error('ltrim failed');
}
if ltrim(' '||$val) != 'ello world' { // add a space and trim it off
error('ltrim 2 failed');
}
$val := lpad($val, 11, 'h');
if $val != 'hello world' {
error('lpad failed');
}
if lpad($val, 12) != ' hello world' {
error('lpad 2 failed');
}
$val := rpad($val, 12, '!');
if $val != 'hello world!' {
error('rpad failed');
}
if rpad($val, 13) != 'hello world! ' {
error('rpad 2 failed');
}
if overlay($val, 'xx', 2, 5) != 'hxxworld!' {
error('overlay failed');
}
if overlay($val, 'xx', 2) != 'hxxlo world!' {
error('overlay 2 failed');
}
if position('world', $val) != 7 {
error('position failed');
}
if substring($val, 7, 5) != 'world' {
error('substring failed');
}
if substring($val, 7) != 'world!' {
error('substring 2 failed');
}
if trim(' ' || $val || ' ') != 'hello world!' {
error('trim failed');
}
if trim('a'||$val||'a', 'a') != 'hello world!' {
error('trim 2 failed');
}
}`,
},
}

for _, test := range tests {
Expand Down
18 changes: 13 additions & 5 deletions parse/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -848,17 +848,25 @@ func (s *sqlAnalyzer) VisitExpressionArithmetic(p0 *ExpressionArithmetic) any {
return s.expressionTypeErr(p0.Right)
}

if !left.Equals(right) {
return s.typeErr(p0.Right, right, left)
}

// both must be numeric UNLESS it is a concat
if p0.Operator == ArithmeticOperatorConcat {
s.expect(p0.Left, left, types.TextType)
if !left.Equals(types.TextType) || !right.Equals(types.TextType) {
// Postgres supports concatenation on non-text types, but we do not,
// so we give a more descriptive error here.
// see the note at the top of: https://www.postgresql.org/docs/16.1/functions-string.html
s.errs.AddErr(p0.Left, ErrType, "concatenation only allowed on text types. received %s and %s", left.String(), right.String())
return cast(p0, types.UnknownType)
}
} else {
s.expectedNumeric(p0.Left, left)
}

// we check this after to return a more helpful error message if
// the user is not concatenating strings.
if !left.Equals(right) {
return s.typeErr(p0.Right, right, left)
}

return cast(p0, left)
}

Expand Down
Loading

0 comments on commit f8a7dd5

Please sign in to comment.