@@ -125,9 +125,11 @@ console.log(rows)
125125* <a href =" #usage " >Usage</a >
126126 * <a href =" #create-connection " >Create connection</a >
127127 * <a href =" #connectionoptions " >ConnectionOptions</a >
128- * <a href =" #accesstoken " >AccessToken</a >
129- * <a href =" #clientcredentials " >Client credentials</a >
130- * <a href =" #enginename " >engineName</a >
128+ * <a href =" #accesstoken " >AccessToken</a >
129+ * <a href =" #clientcredentials " >Client credentials</a >
130+ * <a href =" #enginename " >engineName</a >
131+ * <a href =" #token-caching " >Token caching</a >
132+ * <a href =" #serverSidePreparedStatementConnectionOption " >Server-side prepared statement</a >
131133 * <a href =" #test-connection " >Test connection</a >
132134 * <a href =" #engine-url " >Engine URL</a >
133135 * <a href =" #execute-query " >Execute query</a >
@@ -146,14 +148,21 @@ console.log(rows)
146148 * <a href =" #engine-management " >Engine management</a >
147149 * <a href =" #getbyname " >getByName</a >
148150 * <a href =" #engine " >Engine</a >
149- * <a href =" #start " >start</a >
150- * <a href =" #stop " >stop</a >
151+ * <a href =" #start " >Start</a >
152+ * <a href =" #stop " >Stop</a >
153+ * <a href =" #create-engine " >Engine create</a >
154+ * <a href =" #attach-to-database " >Attach to database</a >
155+ * <a href =" #delete-engine " >Engine delete</a >
151156 * <a href =" #database-management " >Database management</a >
152157 * <a href =" #database-getbyname " >getByName</a >
153158 * <a href =" #database " >Database</a >
159+ * <a href =" #create-database " >Database create</a >
160+ * <a href =" #get-attached-engines " >Get attached engines</a >
161+ * <a href =" #delete-database " >Database delete</a >
154162* <a href =" #recipes " >Recipes</a >
155163 * <a href =" #streaming-results " >Streaming results</a >
156164 * <a href =" #custom-stream-transformers " >Custom stream transformers</a >
165+ * <a href =" #in-memory-stream " >In-memory stream</a >
157166* <a href =" #special-considerations " >Special Considerations</a >
158167
159168<a id =" About " ></a >
@@ -187,20 +196,18 @@ type ClientCredentialsAuth = {
187196 client_secret: string ;
188197};
189198
199+ type PreparedStatementParamStyle = " native" | " fb_numeric" ;
200+
190201type ConnectionOptions = {
191202 auth: AccessTokenAuth | ServiceAccountAuth ;
192203 database: string ;
193204 engineName? : string ;
194205 engineEndpoint? : string ;
195206 account? : string ;
207+ preparedStatementParamStyle? : PreparedStatementParamStyle ;
196208};
197209```
198210
199-
200- <a id =" enginename " ></a >
201- #### engineName
202- You can omit ` engineName ` and execute AQL queries on such connection.
203-
204211<a id =" accesstoken " ></a >
205212#### AccessToken
206213Instead of passing client id/secret directly,
@@ -234,6 +241,10 @@ const connection = await firebolt.connect({
234241});
235242```
236243
244+ <a id =" enginename " ></a >
245+ #### engineName
246+ You can omit ` engineName ` and execute AQL queries on such connection.
247+
237248<a id =" token-caching " ></a >
238249#### Token caching
239250Driver implements a caching mechanism for access tokens. If you are using the same client id or secret for multiple connections, the driver will cache the access token and reuse it for subsequent connections.
@@ -251,6 +262,23 @@ const connection = await firebolt.connect({
251262});
252263```
253264
265+ <a id =" serverSidePreparedStatementConnectionOption " ></a >
266+ #### Server-side prepared statement
267+ Driver has the option to use server-side prepared statements, so all parameters are set on the server side, preventing SQL injection attacks.
268+ This behavior can be enabled by setting ` preparedStatementParamStyle ` to ` fb_numeric ` in the connection options, otherwise, prepared statements will retain default behavior(same behavior if value is set to ` native ` ) and queries will be formatted client side.
269+ ``` typescript
270+ const connection = await firebolt .connect ({
271+ auth: {
272+ client_id: ' b1c4918c-e07e-4ab2-868b-9ae84f208d26' ,
273+ client_secret: ' secret' ,
274+ },
275+ engineName: ' engine_name' ,
276+ account: ' account_name' ,
277+ database: ' database' ,
278+ preparedStatementParamStyle: ' fb_numeric'
279+ });
280+ ```
281+
254282
255283<a id =" test-connection " ></a >
256284### Test connection
@@ -291,7 +319,7 @@ const statement = await connection.execute(query, {
291319
292320``` typescript
293321export type ExecuteQueryOptions = {
294- parameters: ? unknown [];
322+ parameters? : unknown [];
295323 settings? : QuerySettings ;
296324 response? : ResponseSettings ;
297325};
@@ -444,8 +472,82 @@ const token = statement.asyncQueryToken; // can only be fetched for async query
444472await connection .cancelAsyncQuery (token );
445473```
446474
475+ <a id =" serverSidePreparedStatement " ></a >
476+ ## Server-side prepared statement
477+
478+ Firebolt supports server-side prepared statement execution. This feature allows for safer execution of parameterized queries by escaping parameters on the server side. This is useful for preventing SQL injection attacks.
479+
480+ <a id =" difference-server-side-client-side-prepared-statement " ></a >
481+ ### Difference between client-side and server-side prepared statement
482+
483+ The main difference between client-side and server-side prepared statement is the way parameters appear in queries. In client-side prepared statement, parameters are inserted in place of ` ? ` symbols in the case of normal parameters, or ` :name ` in the case of named parameters.
484+ In server-side prepared statement, parameters are represented by ` $number ` tokens.
485+
486+ ``` typescript
487+ // client-side prepared statement with normal parameters
488+ const statement = await connection .execute (" select ?, ?" , {
489+ parameters: [" foo" , 1 ]
490+ });
491+ ```
492+ ``` typescript
493+ // client-side prepared statement with named parameters
494+ const statement = await connection .execute (" select :foo, :bar" , {
495+ namedParameters: { foo: " foo" , bar: 123 }
496+ });
497+ ```
498+ ``` typescript
499+ // server-side prepared statement via parameters field of ExecuteQueryOptions
500+ const statement = await connection .execute (" select $1, $2" , {
501+ parameters: [" foo" , 1 ]
502+ });
503+ ```
504+ ``` typescript
505+ // server-side prepared statement via namedParameters field of ExecuteQueryOptions
506+ const statement = await connection .execute (" select $1, $2" , {
507+ namedParameters: { $1: " foo" , $2: 123 }
508+ });
509+ ```
510+
511+ <a id =" server-side-prepared-statement-parameters " ></a >
512+ ### Usage with parameters field
513+
514+ When using the ` parameters ` field, the driver will automatically set the number value to the corresponding ` $number ` token in the query.
515+
516+ ``` typescript
517+ // Even though the query contains $1 twice, we only need to set it once
518+ const statement = await connection .execute (" select $1, $1" , {
519+ parameters: [" foo" ]
520+ });
521+
522+ // The order is important, so the first parameter will be set to $1 and the second to $2
523+ const statement1 = await connection .execute (" select $2, $1" , {
524+ parameters: [" foo" , 1 ]
525+ });
526+
527+ const statement2 = await connection .execute (" select $1, $2" , {
528+ parameters: [" foo" , 1 ]
529+ });
530+ // statement1 and statement2 will NOT produce the same query
531+ ```
532+
533+ <a id =" server-side-prepared-statement-named-parameters " ></a >
534+ ### Usage with namedParameters field
535+
536+ When using the ` namedParameters ` field, the driver will use the value provided as the name of the parameter when sending the query to the server.
537+ Considering this, we can more easily recognize the parameters in the query.
538+
539+ ``` typescript
540+ const statement = await connection .execute (" select $1, $2" , {
541+ namedParameters: { $1: " foo" , $2: 123 }
542+ });
543+ // The order is not important, so we can set the parameters in any order
544+ const statement1 = await connection .execute (" select $2, $1" , {
545+ namedParameters: { $2: " foo" , $1: 123 }
546+ });
547+ ```
548+
447549<a id =" engine-management " ></a >
448- ### Engine management
550+ ## Engine management
449551
450552Engines can be managed by using the ` resourceManager ` object.
451553
@@ -457,7 +559,7 @@ const enginesService = firebolt.resourceManager.engine
457559```
458560
459561<a id =" getbyname " ></a >
460- #### getByName
562+ ### getByName
461563
462564Returns engine using engine name.
463565
@@ -469,7 +571,7 @@ const engine = await firebolt.resourceManager.engine.getByName("engine_name")
469571```
470572
471573<a id =" engine " ></a >
472- #### Engine
574+ ### Engine
473575
474576| Property | Type | Notes |
475577| --------------------------| -------------------------------------------| -------|
@@ -478,7 +580,7 @@ const engine = await firebolt.resourceManager.engine.getByName("engine_name")
478580| ` current_status_summary ` | ` string ` | |
479581
480582<a id =" start " ></a >
481- ##### Start
583+ #### Start
482584
483585Starts an engine.
484586
@@ -491,7 +593,7 @@ await engine.start()
491593```
492594
493595<a id =" stop " ></a >
494- ##### Stop
596+ #### Stop
495597
496598Stops an engine.
497599
@@ -504,7 +606,7 @@ await engine.stop()
504606```
505607
506608<a id =" create-engine " ></a >
507- ##### Engine create
609+ #### Engine create
508610
509611Creates an engine.
510612
@@ -516,7 +618,7 @@ const engine = await firebolt.resourceManager.engine.create("engine_name");
516618```
517619
518620<a id =" attach-to-database " ></a >
519- ##### Attach to database
621+ #### Attach to database
520622
521623Attaches an engine to a database.
522624
@@ -528,7 +630,7 @@ const engine = await firebolt.resourceManager.engine.attachToDatabase("engine_na
528630```
529631
530632<a id =" delete-engine " ></a >
531- ##### Engine delete
633+ #### Engine delete
532634
533635Deletes an engine.
534636
@@ -574,7 +676,7 @@ const database = await firebolt.resourceManager.database.getByName("database_nam
574676
575677
576678<a id =" create-database " ></a >
577- ##### Database create
679+ #### Database create
578680
579681Creates a database.
580682
@@ -586,7 +688,7 @@ const database = await firebolt.resourceManager.database.create("database_name")
586688```
587689
588690<a id =" get-attached-engines " ></a >
589- ##### Get attached engines
691+ #### Get attached engines
590692
591693Get engines attached to a database.
592694
@@ -599,7 +701,7 @@ const engines = database.getAttachedEngines();
599701```
600702
601703<a id =" delete-database " ></a >
602- ##### Database delete
704+ #### Database delete
603705
604706Deletes a database.
605707
0 commit comments