Skip to content

Query execution metadata

When you are implementing your own query runner, there is some metadata available about the query that is trying to be executed.

Tip

These features are optional and are mainly intended for logging, debugging, or advanced monitoring purposes.

Get the query execution stack

The getQueryExecutionStack will return a string with the stack trace where the query was requested to be executed and return undefined if the information is unavailable.

import { getQueryExecutionStack } from 'ts-sql-query/queryRunners/QueryRunner';
import { InterceptorQueryRunner, QueryType } from "ts-sql-query/queryRunners/InterceptorQueryRunner";

class DurationLogginQueryRunner extends InterceptorQueryRunner<void> {
    onQuery(queryType: QueryType, query: string, params: any[]): DurationPlayload {
        const stack: string | undefined = getQueryExecutionStack(query, params)
        console.log('query execution stack', stack)
    }
    onQueryResult(queryType: QueryType, query: string, params: any[], result: any, playload: void): void {
        ...    
    }
    onQueryError(queryType: QueryType, query: string, params: any[], error: any, playload: void): void {
        ...
    }
}

The stack strace will looks like:

Error: Query executed at
    at CompoundSelectQueryBuilder.executeSelectMany (ts-sql-query/src/queryBuilders/SelectQueryBuilder.ts:187:24)
    at myFunction (myFolder/myFile.ts:112:10)
    at myOuterFunction (myFolder/myFile.ts:147:23)
    at ...

Get the function that requested the query

The getFunctionExecutingQuery will return an object with information related to the function that requests to execute the query and return undefined if the information is unavailable. Each property can be undefined if that information is unavailable.

import { getFunctionExecutingQuery, FunctionExecutingQueryInformation } from 'ts-sql-query/queryRunners/QueryRunner';
import { InterceptorQueryRunner, QueryType } from "ts-sql-query/queryRunners/InterceptorQueryRunner";

class DurationLogginQueryRunner extends InterceptorQueryRunner<void> {
    onQuery(queryType: QueryType, query: string, params: any[]): DurationPlayload {
        const info : FunctionExecutingQueryInformation | undefined = getFunctionExecutingQuery(query, params)
        if (!info) {
            return
        }
        const functionName: string | undefined = info.functionName
        const fileName: string | undefined = info.fileName
        const lineNumber: string | undefined = info.lineNumber
        const positionNumber: string | undefined = info.positionNumber
        console.log('Name of the function where the query was requested to be executed', functionName)
        console.log('Name of the file where the query was requested to be executed', fileName)
        console.log('Line number where the query was requested to be executed', lineNumber)
        console.log('Position in the line where the query was requested to be executed', positionNumber)
    }
    onQueryResult(queryType: QueryType, query: string, params: any[], result: any, playload: void): void {
        ...    
    }
    onQueryError(queryType: QueryType, query: string, params: any[], error: any, playload: void): void {
        ...
    }
}

Properties of the returned object:

  • functionName: string with the function name that requested the execution of the query, undefined if that information is unavailable.
  • fileName: string with the file name (including path) that requested the execution of the query, undefined if that information is unavailable.
  • lineNumber: string with the line number in the file that requested the execution of the query, undefined if that information is unavailable.
  • positionNumber: string with the position in the line that requested the execution of the query, undefined if that information is unavailable.

Detect if the query is for select page count

The Select page is the only place where ts-sql-query executes a second query to return the count of elements. The function isSelectPageCountQuery allows you to identify if the requested query corresponds to the select count in a select page.

import { isSelectPageCountQuery } from 'ts-sql-query/queryRunners/QueryRunner';
import { InterceptorQueryRunner, QueryType } from "ts-sql-query/queryRunners/InterceptorQueryRunner";

class DurationLogginQueryRunner extends InterceptorQueryRunner<void> {
    onQuery(queryType: QueryType, query: string, params: any[]): DurationPlayload {
        const isCount: boolean = isSelectPageCountQuery(query, params)
        console.log('the query is a select count in a select page', isCount)
    }
    onQueryResult(queryType: QueryType, query: string, params: any[], result: any, playload: void): void {
        ...    
    }
    onQueryError(queryType: QueryType, query: string, params: any[], error: any, playload: void): void {
        ...
    }
}

Retrieve the execution name of a query

Before you execute a query, you can customize the query; in the customization possible, you can specify a property called queryExecutionName to put an informative name for that query execution. You can use the getQueryExecutionName to get that name (or undefined if it was not provided).

import { getQueryExecutionName } from 'ts-sql-query/queryRunners/QueryRunner';
import { InterceptorQueryRunner, QueryType } from "ts-sql-query/queryRunners/InterceptorQueryRunner";

class DurationLogginQueryRunner extends InterceptorQueryRunner<void> {
    onQuery(queryType: QueryType, query: string, params: any[]): DurationPlayload {
        const name: string | undefined = getQueryExecutionName(query, params)
        console.log('query execution name', name)
    }
    onQueryResult(queryType: QueryType, query: string, params: any[], result: any, playload: void): void {
        ...    
    }
    onQueryError(queryType: QueryType, query: string, params: any[], error: any, playload: void): void {
        ...
    }
}

You can specify the informative name in this way:

const customizedSelect = connection.selectFrom(tCustomer)
    .where(tCustomer.id.equals(10))
    .select({
        id: tCustomer.id,
        firstName: tCustomer.firstName,
        lastName: tCustomer.lastName,
        birthday: tCustomer.birthday
    }).customizeQuery({
        queryExecutionName: 'My query name'
    })
    .executeSelectOne()

Retrieve additional execution metadata

Before executing a query, you can customize it by specifying options using queryExecutionMetadata to put additional metadata for that query execution. You can use the getQueryExecutionMetadata to get that metadata (or undefined if it was not provided).

import { getQueryExecutionMetadata } from 'ts-sql-query/queryRunners/QueryRunner';
import { InterceptorQueryRunner, QueryType } from "ts-sql-query/queryRunners/InterceptorQueryRunner";

class DurationLogginQueryRunner extends InterceptorQueryRunner<void> {
    onQuery(queryType: QueryType, query: string, params: any[]): DurationPlayload {
        const metadata: unknown = getQueryExecutionMetadata(query, params)
        console.log('query execution metadata', metadata)
    }
    onQueryResult(queryType: QueryType, query: string, params: any[], result: any, playload: void): void {
        ...    
    }
    onQueryError(queryType: QueryType, query: string, params: any[], error: any, playload: void): void {
        ...
    }
}

You can specify the metadata in this way:

const customizedSelect = connection.selectFrom(tCustomer)
    .where(tCustomer.id.equals(10))
    .select({
        id: tCustomer.id,
        firstName: tCustomer.firstName,
        lastName: tCustomer.lastName,
        birthday: tCustomer.birthday
    }).customizeQuery({
        queryExecutionMetadata: { myMetadataProp: 'my metadata value' }
    })
    .executeSelectOne()