MCPcopy Index your code
hub / github.com/bytebase/dbhub / executeSQL

Method executeSQL

src/connectors/sqlserver/index.ts:609–703  ·  view source on GitHub ↗
(sqlQuery: string, options: ExecuteOptions, parameters?: any[])

Source from the content-addressed store, hash-verified

607 }
608
609 async executeSQL(sqlQuery: string, options: ExecuteOptions, parameters?: any[]): Promise<SQLResult> {
610 if (!this.connection) {
611 throw new Error("Not connected to SQL Server database");
612 }
613
614 // SQL Server has no native EXPLAIN statement. Translate a leading `EXPLAIN`
615 // into a SHOWPLAN_XML request so callers get a Postgres/MySQL-like
616 // experience. SHOWPLAN_XML compiles the statement without executing it, so
617 // this is read-only safe (further enforced in explainQuery).
618 const afterNoise = sqlQuery.slice(
619 sqlQuery.match(SQLServerConnector.LEADING_NOISE)![0].length
620 );
621 if (/^explain\b/i.test(afterNoise)) {
622 return this.explainQuery(afterNoise.slice("explain".length).trim());
623 }
624
625 try {
626 // Apply maxRows limit to SELECT queries if specified
627 let processedSQL = sqlQuery;
628 if (options.maxRows) {
629 processedSQL = SQLRowLimiter.applyMaxRowsForSQLServer(sqlQuery, options.maxRows);
630 }
631
632 // Engine-level read-only enforcement: SQL Server has no
633 // BEGIN TRANSACTION READ ONLY, so we wrap in a transaction and
634 // unconditionally ROLLBACK to prevent any modifications from persisting.
635 // This is defense-in-depth behind the keyword classifier.
636 if (options.readonly) {
637 return await this.executeReadOnly(processedSQL, parameters);
638 }
639
640 // Create request and collect informational messages (e.g. SET STATISTICS TIME/IO, PRINT)
641 const request = this.connection.request();
642 const messages: DatabaseMessage[] = [];
643 request.on(
644 'info',
645 (info: { message: string; number?: number; class?: number; lineNumber?: number }) => {
646 messages.push({
647 text: info.message,
648 // SQL Server reports severity as a numeric class; info messages are < 10.
649 severity: info.class !== undefined ? String(info.class) : undefined,
650 code: info.number,
651 line: info.lineNumber,
652 });
653 }
654 );
655
656 if (parameters && parameters.length > 0) {
657 // SQL Server uses @p1, @p2, etc. for parameters
658 parameters.forEach((param, index) => {
659 const paramName = `p${index + 1}`;
660 // Infer SQL Server type from JavaScript type
661 if (typeof param === 'string') {
662 request.input(paramName, sql.VarChar, param);
663 } else if (typeof param === 'number') {
664 if (Number.isInteger(param)) {
665 request.input(paramName, sql.Int, param);
666 } else {

Callers

nothing calls this directly

Calls 3

explainQueryMethod · 0.95
executeReadOnlyMethod · 0.95

Tested by

no test coverage detected