@@ -736,6 +736,80 @@ public static Object[][] testCTEStmtsDP() {
736736 };
737737 }
738738
739+ @ Test (dataProvider = "testCommentsAndHeredocsDP" )
740+ public void testCommentsAndHeredocs (String sql , int args ) {
741+ // The ANTLR4_PARAMS_PARSER backend collects placeholders from the grammar, whose lexer has no
742+ // token for '//' comments and heredocs, so it is not covered by this scan. The other backends
743+ // must agree with the server on which '?' is a placeholder.
744+ if (grammarParamsBackend ) {
745+ return ;
746+ }
747+ ParsedPreparedStatement stmt = parser .parsePreparedStatement (sql );
748+ Assert .assertEquals (stmt .getArgCount (), args , "Args mismatch for: " + sql );
749+ }
750+
751+ @ DataProvider
752+ public static Object [][] testCommentsAndHeredocsDP () {
753+ return new Object [][] {
754+ // '//' line comments
755+ {"SELECT 1 // ?" , 0 },
756+ {"SELECT 1 //" , 0 },
757+ {"SELECT ? // ?\n , ?" , 2 },
758+ {"SELECT 1 // ? -- ? /* ? */ $$?$$\n , ?" , 1 },
759+ // an empty line comment ends at its own newline, so later placeholders are still counted
760+ {"SELECT ? //\n , ?" , 2 },
761+ {"SELECT ? //\n // ?\n , ?" , 2 },
762+ {"SELECT ? //\n ?" , 2 },
763+ {"SELECT ? --\n , ?" , 2 },
764+ {"SELECT ? -- ?\n --\n , ?" , 2 },
765+ {"SELECT ? #\n , ?" , 2 },
766+ {"SELECT ? #!\n , ?" , 2 },
767+ {"SELECT ? //\n --\n #\n , ?" , 2 },
768+ {"//\n SELECT ?" , 1 },
769+ // a comment that is never terminated still ends the scan
770+ {"SELECT ? //\n " , 1 },
771+ {"SELECT ? --" , 1 },
772+ // a comment marker inside a string, a heredoc or a block comment does not start a comment
773+ {"SELECT '--\n ' AS v, ?" , 1 },
774+ {"SELECT $$//\n $$ AS v, ?" , 1 },
775+ {"SELECT ? /* --\n */, ?" , 2 },
776+ // heredocs (dollar quoted strings)
777+ {"SELECT $$?$$ AS v" , 0 },
778+ {"SELECT $tag$ ? $tag$ AS v" , 0 },
779+ {"SELECT $1$ ? $1$ AS v" , 0 },
780+ {"SELECT $$$$ AS v, ?" , 1 },
781+ {"SELECT $$a$b$$ AS v, ?" , 1 },
782+ {"SELECT $t$ ?\n -- ?\n // ?\n /* ? */ $t$ AS v, ?" , 1 },
783+ {"SELECT $$?$$, ?, $$?$$" , 1 },
784+ {"SELECT $$it's ?$$ AS v, ?" , 1 },
785+ {"SELECT $$ /* ? $$ AS v, ?" , 1 },
786+ // '//' and heredoc markers that are not comments or heredocs
787+ {"SELECT '// ?' AS v, ?" , 1 },
788+ {"SELECT '$$?$$' AS v, ?" , 1 },
789+ {"SELECT -- '// ?'\n ?" , 1 },
790+ {"SELECT /* $$?$$ */ ?" , 1 },
791+ {"SELECT 4 / 2 AS v, ?" , 1 },
792+ {"SELECT ? AS a$b, ? AS c$d, 3" , 2 },
793+ {"SELECT ? AS a$x$, ? AS b$x$" , 2 },
794+ {"SELECT 1 AS a$x$, ?" , 1 },
795+ // a dollar sign is an identifier character too, so a pair of them inside a name does not
796+ // open a heredoc, even when the same character sequence occurs again later
797+ {"SELECT ? AS a$$b$, ? AS x$$b$" , 2 },
798+ {"SELECT a$$b$, ?, x$$b$ FROM t" , 1 },
799+ {"SELECT ? AS a$$b$$c, ? AS x$$b$$c" , 2 },
800+ {"SELECT ? AS a$$b$" , 1 },
801+ // an identifier ending with a dollar sign does not swallow the heredoc that follows it
802+ {"SELECT 1 AS a$$b$, $$?$$ AS v, ?" , 1 },
803+ {"SELECT 1 AS a$$b$,$$?$$ AS v, ?" , 1 },
804+ {"SELECT $$ ? AS v, ?" , 2 },
805+ // already supported comment styles keep working
806+ {"SELECT 1 -- ?" , 0 },
807+ {"SELECT 1 # ?" , 0 },
808+ {"SELECT 1 #! ?" , 0 },
809+ {"SELECT /* ? /* ? */ ? */ ?" , 1 },
810+ };
811+ }
812+
739813 @ Test (dataProvider = "testDoubleSlashLineCommentDp" )
740814 public void testDoubleSlashLineComments (String sql , int args , boolean insert , boolean hasResultSet ) {
741815 ParsedPreparedStatement prepared = parser .parsePreparedStatement (sql );
0 commit comments