Skip to content

Commit

Permalink
Fix #111 - support semicolons in values in SQL script files
Browse files Browse the repository at this point in the history
  • Loading branch information
amochin committed Jul 13, 2023
1 parent 7ff91a6 commit a49f7e1
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 5 deletions.
18 changes: 13 additions & 5 deletions src/DatabaseLibrary/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,16 +272,14 @@ def execute_sql_script(self, sqlScriptFileName, sansTran=False):
# semicolons inside the line? use them to separate statements
# ... but not if they are inside a begin/end block (aka. statements group)
sqlFragments = line.split(';')

# no semicolons
if len(sqlFragments) == 1:
current_statement += line + ' '
continue

quotes = 0
# "select * from person;" -> ["select..", ""]
for sqlFragment in sqlFragments:
sqlFragment = sqlFragment.strip()
if len(sqlFragment) == 0:
if len(sqlFragment.strip()) == 0:
continue
if inside_statements_group:
# if statements inside a begin/end block have semicolns,
Expand All @@ -291,10 +289,20 @@ def execute_sql_script(self, sqlScriptFileName, sansTran=False):
inside_statements_group = False
elif sqlFragment.lower().startswith("begin"):
inside_statements_group = True

# check if the semicolon is a part of the value (quoted string)
quotes += sqlFragment.count("'")
quotes -= sqlFragment.count("\\'")
quotes -= sqlFragment.count("''")
inside_quoted_string = quotes % 2 != 0
if inside_quoted_string:
sqlFragment += ";" # restore the semicolon

current_statement += sqlFragment
if not inside_statements_group:
if not inside_statements_group and not inside_quoted_string:
statements_to_execute.append(current_statement.strip())
current_statement = ''
quotes = 0

current_statement = current_statement.strip()
if len(current_statement) != 0:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO person VALUES(5, 'Miles', 'O''Brian');
2 changes: 2 additions & 0 deletions test/resources/script_file_tests/semicolons_in_values.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
INSERT INTO person VALUES(3, 'Hello; world', 'Another; value');
INSERT INTO person VALUES(4, 'May the Force; ', 'be with you;');
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO person VALUES(6, 'Julian', 'Bashir'); INSERT INTO person VALUES(7, 'Jadzia', 'Dax');
42 changes: 42 additions & 0 deletions test/tests/common_tests/script_files.robot
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
*** Settings ***
Resource ../../resources/common.resource

Suite Setup Connect To DB
Suite Teardown Disconnect From Database
Test Setup Create Person Table
Test Teardown Drop Tables Person And Foobar


*** Test Cases ***
Semicolons As Statement Separators In One Line
Run SQL Script File statements_in_one_line
${sql}= Catenate select * from person
... where id=6 or id=7
${results}= Query ${sql}
Length Should Be ${results} 2
Should Be Equal As Strings ${results}[0] (6, 'Julian', 'Bashir')
Should Be Equal As Strings ${results}[1] (7, 'Jadzia', 'Dax')

Semicolons In Values
Run SQL Script File semicolons_in_values
${sql}= Catenate select * from person
... where id=3 or id=4
${results}= Query ${sql}
Length Should Be ${results} 2
Should Be Equal As Strings ${results}[0] (3, 'Hello; world', 'Another; value')
Should Be Equal As Strings ${results}[1] (4, 'May the Force; ', 'be with you;')

Semicolons And Quotes In Values
Run SQL Script File semicolons_and_quotes_in_values
${sql}= Catenate select * from person
... where id=5
${results}= Query ${sql}
Length Should Be ${results} 1
Should Be Equal As Strings ${results}[0] (5, 'Miles', "O'Brian")


*** Keywords ***
Run SQL Script File
[Arguments] ${File Name}
${Script files dir}= Set Variable ${CURDIR}/../../resources/script_file_tests
Execute Sql Script ${Script files dir}/${File Name}.sql

0 comments on commit a49f7e1

Please sign in to comment.