@@ -20,7 +20,7 @@ class SyntaxErrorListener<TSymbol> extends ErrorListener<TSymbol> {
2020 _offendingSymbol : TSymbol ,
2121 line : number ,
2222 column : number ,
23- msg : string
23+ msg : string ,
2424 ) {
2525 throw new SyntaxError ( `line ${ line } :${ column } : ${ msg } ` ) ;
2626 }
@@ -46,24 +46,85 @@ class UpperCaseCharStream extends CharStream {
4646 }
4747}
4848
49-
5049/**
51- * Validate a SQL string for syntax errors .
50+ * Creates a SQL parser for a given input string .
5251 *
53- * @param sqlString
54- * @throws { SyntaxError } with line, column, and message details if a syntax error is found .
52+ * @param input The SQL query string to be parsed.
53+ * @return The configured SQL parser instance ready to parse the input .
5554 */
56- const validate = ( sqlString : string ) => {
55+ const buildParser = ( input : string ) : SqlBaseParser => {
5756 const syntaxErrorListener = new SyntaxErrorListener ( ) ;
58- const lexer = new SqlBaseLexer ( new UpperCaseCharStream ( sqlString ) ) ;
57+ const lexer = new SqlBaseLexer ( new UpperCaseCharStream ( input ) ) ;
5958 lexer . removeErrorListeners ( ) ;
6059 lexer . addErrorListener ( syntaxErrorListener ) ;
6160 const parser = new SqlBaseParser ( new CommonTokenStream ( lexer ) ) ;
6261 parser . removeErrorListeners ( ) ;
6362 parser . addErrorListener ( syntaxErrorListener ) ;
64- parser . singleStatement ( ) ;
63+
64+ return parser ;
65+ } ;
66+
67+ /**
68+ * Validate a SQL string for syntax errors.
69+ *
70+ * @param sqlString
71+ * @throws {SyntaxError } with line, column, and message details if a syntax error is found.
72+ */
73+ const validate = ( sqlString : string ) => {
74+ buildParser ( sqlString ) . singleStatement ( ) ;
75+ } ;
76+
77+ interface BuildSearchQueryProps {
78+ selectItemList : string ;
79+ relationList : string ;
80+ booleanExpression ?: string | undefined ;
81+ sortItemList ?: string | undefined ;
82+ limitValue ?: string | undefined ;
83+ }
84+
85+ /**
86+ * Constructs a SQL search query string from a set of structured components.
87+ *
88+ * @param props
89+ * @param props.selectItemList
90+ * @param props.relationList
91+ * @param props.booleanExpression
92+ * @param props.sortItemList
93+ * @param props.limitValue
94+ * @return
95+ * @throws {Error } if the constructed SQL string is not valid.
96+ */
97+ const buildSearchQuery = ( {
98+ selectItemList,
99+ relationList,
100+ booleanExpression,
101+ sortItemList,
102+ limitValue,
103+ } : BuildSearchQueryProps ) : string => {
104+ let sqlString = `SELECT ${ selectItemList } FROM ${ relationList } ` ;
105+ if ( "undefined" !== typeof booleanExpression ) {
106+ sqlString += ` WHERE ${ booleanExpression } ` ;
107+ }
108+ if ( "undefined" !== typeof sortItemList ) {
109+ sqlString += ` ORDER BY ${ sortItemList } ` ;
110+ }
111+ if ( "undefined" !== typeof limitValue ) {
112+ sqlString += ` LIMIT ${ limitValue } ` ;
113+ }
114+
115+ try {
116+ validate ( sqlString ) ;
117+ } catch ( err : unknown ) {
118+ throw new Error ( `The constructed SQL is not valid: ${ sqlString } ` , { cause : err } ) ;
119+ }
120+
121+ return sqlString ;
65122} ;
66123
67124export {
68- SyntaxError , validate ,
125+ buildSearchQuery ,
126+ SyntaxError ,
127+ validate ,
69128} ;
129+
130+ export type { BuildSearchQueryProps } ;
0 commit comments