Skip to main content
TBISQL is a record type that provides static methods to convert between SQL syntax and TeeBI query objects (TDataSelect, TSummary, TBIQuery).

Overview

TBISQL acts as a bidirectional translator:
  • SQL to Objects: Parse SQL strings into query provider objects
  • Objects to SQL: Generate SQL syntax from query objects
This enables both programmatic query construction and SQL-based data manipulation.

Class Definition

TBISSQL = record
public
  // Convert provider to SQL
  class function From(const AProvider: TDataProvider): String; overload; static;
  
  // Convert TDataSelect to SQL
  class function From(const ASelect: TDataSelect): String; overload; static;
  
  // Convert TSummary to SQL
  class function From(const ASummary: TSummary): String; overload; static;
  
  // Convert TDataItem to SQL
  class function From(const AData: TDataItem): String; overload; static;
  
  // Parse and execute SQL
  class function From(const AData: TDataItem; 
                      const SQL: String;
                      const GetData: TGetDataProc = nil;
                      const ErrorProc: TBIErrorProc = nil): TDataItem; overload; static;
  
  // Parse SQL to provider
  class function ProviderFrom(const AData: TDataItem; 
                              const SQL: String;
                              const GetData: TGetDataProc = nil;
                              const ErrorProc: TBIErrorProc = nil): TDataProvider; static;
end;

Methods

From (Provider to SQL)

Converts a data provider object to its SQL representation.
AProvider
TDataProvider
required
The provider object to convert (TDataSelect or TSummary)
Returns: SQL string representation
var
  Summary: TSummary;
  SQL: String;
begin
  Summary := TSummary.Create(nil);
  Summary.AddMeasure(Data['Sales'], TAggregate.Sum);
  Summary.AddGroupBy(Data['Country']);
  
  SQL := TBISQL.From(Summary);
  // Result: "select Country, Sum(Sales) from Data group by Country"
end;

From (SQL to Data)

Parses SQL syntax, executes the query, and returns the result.
AData
TDataItem
required
Source data item to query
SQL
String
required
SQL query string
GetData
TGetDataProc
Optional callback to resolve data names
ErrorProc
TBIErrorProc
Optional error handling callback
Returns: TDataItem with query results
var
  Result: TDataItem;
begin
  Result := TBISQL.From(MyData, 'select Country, Sum(Sales) from Data group by Country');
  // Result contains aggregated data
end;

ProviderFrom

Parses SQL syntax and returns the provider object without executing.
AData
TDataItem
required
Source data item for context
SQL
String
required
SQL query string to parse
GetData
TGetDataProc
Optional callback to resolve data names
ErrorProc
TBIErrorProc
Optional error handling callback
Returns: TDataProvider (TDataSelect or TSummary)
var
  Provider: TDataProvider;
begin
  Provider := TBISQL.ProviderFrom(MyData, 'select * from Customers where Country="USA"');
  // Provider is a TDataSelect object
end;

Supported SQL Syntax

TBISQL supports a subset of standard SQL:

SELECT Queries

select [distinct] <columns> 
from <table>
[where <condition>]
[order by <columns> [asc|desc]]
[limit <number>]
[offset <number>]

GROUP BY Queries (Summaries)

select <dimensions>, <aggregates>
from <table>
[where <condition>]
group by <dimensions>

Aggregate Functions

  • Count(field)
  • Sum(field)
  • Average(field) or Avg(field)
  • Minimum(field) or Min(field)
  • Maximum(field) or Max(field)
  • First(field)
  • Last(field)

Date/Time Parts

select Year(OrderDate), Sum(Amount)
from Orders
group by Year(OrderDate)
Supported parts: Year, Month, Quarter, Day, Hour, Minute, Second, WeekDay, DayOfYear, etc.

Examples

Simple SELECT

var
  Result: TDataItem;
begin
  Result := TBISQL.From(Customers, 'select Name, City from Customers');
end;

SELECT with WHERE

Result := TBISQL.From(Orders, 
  'select OrderID, Amount from Orders where Amount > 1000');

SELECT with DISTINCT

Result := TBISQL.From(Products, 
  'select distinct Category from Products');

Aggregation

Result := TBISQL.From(Sales, 
  'select Country, Sum(Revenue) from Sales group by Country');

Multiple Grouping

Result := TBISQL.From(Sales,
  'select Year(Date), Country, Sum(Revenue) ' +
  'from Sales ' +
  'group by Year(Date), Country');

Sorting

Result := TBISQL.From(Products,
  'select Name, Price from Products order by Price desc');

Pagination

Result := TBISQL.From(Customers,
  'select * from Customers limit 10 offset 20');

Converting Objects to SQL

var
  Select: TDataSelect;
  SQL: String;
begin
  Select := TDataSelect.Create(nil);
  Select.Add(Data['Name']);
  Select.Add(Data['Price']);
  Select.Filter := TDataFilter.FromString(Data, 'Price > 100');
  
  SQL := TBISQL.From(Select);
  // Result: "select Name, Price from Data where Price > 100"
end;

Error Handling

Provide a custom error handler to gracefully handle parse errors:
function MyErrorHandler(const Sender: TObject; const Error: String): Boolean;
begin
  ShowMessage('SQL Error: ' + Error);
  Result := True; // Return True to suppress exception
end;

var
  Result: TDataItem;
begin
  Result := TBISQL.From(MyData, 'select invalid syntax', nil, MyErrorHandler);
end;

See Also

Build docs developers (and LLMs) love