Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
erikbra committed Aug 11, 2023
1 parent e5217a7 commit 9f56e72
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using FluentAssertions;
using System.Linq;
using FluentAssertions;
using grate.Infrastructure;
using grate.Migration;
using Microsoft.Extensions.Logging.Abstractions;
Expand Down Expand Up @@ -36,5 +37,107 @@ USING btree

batches.Should().HaveCount(4);
}

[Test]
public void Ignores_semicolons_in_backslash_escaped_strings()
{
var original = @"
DO E'
BEGIN
IF NOT EXISTS(
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name = \'random\'
)
THEN
EXECUTE \'CREATE SCHEMA random\';
END IF;
END
';
";
var batches = Splitter.Split(original);

batches.Should().HaveCount(1);
}

[TestCase("$$")]
[TestCase("$sometag$")]
public void Ignores_semicolons_in_dollar_quoted_strings(string tag)
{
var original = @$"
DO
{tag}
BEGIN
IF NOT EXISTS(
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name = 'random'
)
THEN
EXECUTE 'CREATE SCHEMA random';
END IF;
END
{tag};
";
var batches = Splitter.Split(original);
batches.Should().HaveCount(1);
}

[Test]
public void Splits_on_semicolon_after_single_quotes_when_there_is_another_semicolon_in_the_quote()
{
var original = @"SELECT 1 WHERE whatnot = '; ' ; MOO";
var batches = Splitter.Split(original);
batches.Should().HaveCount(2);

batches.First().Should().Be("SELECT 1 WHERE whatnot = '; ' ");
batches.Last().Should().Be(" MOO");
}

[Test]
public void Ignores_semicolon_in_single_quotes_when_there_is_no_other_semicolon()
{
var original = @"SELECT 1 WHERE whatnot = '; ' ;;";
var batches = Splitter.Split(original);
batches.Should().HaveCount(1);
}

[Test]
public void Ignores_semicolon_in_strings_with_directly_appended_operator()
{
var original = @"
CREATE VIEW wgs.wgs_pages_branches AS
SELECT branches.instrumentid,
branches.plabel AS from_plabel,
CASE
WHEN (NOT (branches.branch ~~* '%?%'::text)) THEN ""substring""(branches.branch, (""position""(branches.branch, '->'::text) + 3), length(branches.branch))
ELSE NULL::text
END AS to_plabel,
CASE
WHEN (branches.branch ~~* '?%'::text) THEN branches.branch
WHEN (branches.branch ~~* '%?%'::text) THEN ""substring""(branches.branch, (""position""(branches.branch, '->'::text) + 2), length(branches.branch))
ELSE NULL::text
END AS to_other,
branches.rank AS condition_rank,
CASE
WHEN (""substring""(branches.branch, 0, ""position""(branches.branch, '->'::text)) ~~* 'ELSE'::text) THEN 'TRUE'::text
ELSE ""substring""(branches.branch, 0, ""position""(branches.branch, '->'::text))
END AS condition
FROM ( SELECT foo.instrumentid,
foo.plabel,
foo.branch,
row_number() OVER (PARTITION BY foo.instrumentid, foo.plabel ORDER BY foo.rankgroup) AS rank
FROM ( SELECT wgs_pages.instrumentid,
wgs_pages.plabel,
unnest(string_to_array(wgs_pages.nextbranch, ';'::text)) AS branch,
row_number() OVER (ORDER BY wgs_pages.instrumentid, wgs_pages.plabel) AS rankgroup
FROM wgs.wgs_pages) foo) branches;
";

var batches = Splitter.Split(original);

Check failure on line 137 in grate.unittests/Basic/Infrastructure/PostgreSQL/Statement_Splitting/StatementSplitter_.cs

View workflow job for this annotation

GitHub Actions / Test report Basic

grate.unittests.Basic.Infrastructure.PostgreSQL.Statement_Splitting.StatementSplitter_ ► Ignores_semicolon_in_strings_with_directly_appended_operator

Failed test found in: test-results-Basic.xml Error: Expected collection to contain 1 item(s), but found 2: {" CREATE VIEW wgs.wgs_pages_branches AS SELECT branches.instrumentid, branches.plabel AS from_plabel, CASE WHEN (NOT (branches.branch ~~* '%?%'::text)) THEN "substring"(branches.branch, ("position"(branches.branch, '->'::text) + 3), length(branches.branch)) ELSE NULL::text END AS to_plabel, CASE WHEN (branches.branch ~~* '?%'::text) THEN branches.branch WHEN (branches.branch ~~* '%?%'::text) THEN "substring"(branches.branch, ("position"(branches.branch, '->'::text) + 2), length(branches.branch)) ELSE NULL::text END AS to_other, branches.rank AS condition_rank, CASE WHEN ("substring"(branches.branch, 0, "position"(branches.branch, '->'::text)) ~~* 'ELSE'::text) THEN 'TRUE'::text ELSE "substring"(branches.branch, 0, "position"(branches.branch, '->'::text)) END AS condition FROM ( SELECT foo.instrumentid, foo.plabel, foo.branch, row_number() OVER (PARTITION BY foo.instrumentid, foo.plabel ORDER BY foo.rankgroup) AS rank FROM ( SELECT wgs_pages.instrumentid, wgs_pages.plabel, unnest(string_to_array(wgs_pages.nextbranch, '", "'::text)) AS branch, row_number() OVER (ORDER BY wgs_pages.instrumentid, wgs_pages.plabel) AS rankgroup FROM wgs.wgs_pages) foo) branches"}.
Raw output
Expected collection to contain 1 item(s), but found 2: {"
CREATE VIEW wgs.wgs_pages_branches AS
 SELECT branches.instrumentid,
    branches.plabel AS from_plabel,
        CASE
            WHEN (NOT (branches.branch ~~* '%?%'::text)) THEN "substring"(branches.branch, ("position"(branches.branch, '->'::text) + 3), length(branches.branch))
            ELSE NULL::text
        END AS to_plabel,
        CASE
            WHEN (branches.branch ~~* '?%'::text) THEN branches.branch
            WHEN (branches.branch ~~* '%?%'::text) THEN "substring"(branches.branch, ("position"(branches.branch, '->'::text) + 2), length(branches.branch))
            ELSE NULL::text
        END AS to_other,
    branches.rank AS condition_rank,
        CASE
            WHEN ("substring"(branches.branch, 0, "position"(branches.branch, '->'::text)) ~~* 'ELSE'::text) THEN 'TRUE'::text
            ELSE "substring"(branches.branch, 0, "position"(branches.branch, '->'::text))
        END AS condition
   FROM ( SELECT foo.instrumentid,
            foo.plabel,
            foo.branch,
            row_number() OVER (PARTITION BY foo.instrumentid, foo.plabel ORDER BY foo.rankgroup) AS rank
           FROM ( SELECT wgs_pages.instrumentid,
                    wgs_pages.plabel,
                    unnest(string_to_array(wgs_pages.nextbranch, '", "'::text)) AS branch,
                    row_number() OVER (ORDER BY wgs_pages.instrumentid, wgs_pages.plabel) AS rankgroup
                   FROM wgs.wgs_pages) foo) branches"}.
   at FluentAssertions.Execution.LateBoundTestFramework.Throw(String message)
   at FluentAssertions.Execution.TestFrameworkProvider.Throw(String message)
   at FluentAssertions.Execution.DefaultAssertionStrategy.HandleFailure(String message)
   at FluentAssertions.Execution.AssertionScope.FailWith(Func`1 failReasonFunc)
   at FluentAssertions.Execution.AssertionScope.FailWith(Func`1 failReasonFunc)
   at FluentAssertions.Execution.AssertionScope.FailWith(String message, Object[] args)
   at FluentAssertions.Collections.GenericCollectionAssertions`3.HaveCount(Int32 expected, String because, Object[] becauseArgs)
   at grate.unittests.Basic.Infrastructure.PostgreSQL.Statement_Splitting.StatementSplitter_.Ignores_semicolon_in_strings_with_directly_appended_operator() in /home/runner/work/grate/grate/grate.unittests/Basic/Infrastructure/PostgreSQL/Statement_Splitting/StatementSplitter_.cs:line 137

batches.Should().HaveCount(1);

}


}
6 changes: 4 additions & 2 deletions grate/Infrastructure/PostgreSqlSyntax.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ public string StatementSeparatorRegex
{
get
{
const string strings = @"(?<KEEP1>'[^']*')";
const string strings = @"(?<KEEP1>'([^']|\'\')*')";
const string backslashEscapedSrings = @"(?<KEEP1>E(?<!\\)('[\S\s]*?(?<!\\)'))";
const string dollarQuotedStrings = @"(?<KEEP1>\$(?'tag'\w*)\$[\S\s]*?\$\k'tag'\$)";
const string dashComments = @"(?<KEEP1>--.*$)";
const string starComments = @"(?<KEEP1>/\*[\S\s]*?\*/)";
const string separator = @"(?<KEEP1>.*)(?<BATCHSPLITTER>;)(?<KEEP2>.*)";
return strings + "|" + dashComments + "|" + starComments + "|" + separator;
return strings + "|" + backslashEscapedSrings + "|" + dollarQuotedStrings + "|" + dashComments + "|" + starComments + "|" + separator;
}
}

Expand Down

0 comments on commit 9f56e72

Please sign in to comment.