mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 14:09:20 +02:00
sql parser: support LIMIT for FireBird/MSSQL/Postgres/MySQL
git-svn-id: trunk@46426 -
This commit is contained in:
parent
dfca0bf9c8
commit
6caf046df2
@ -126,6 +126,7 @@ Type
|
|||||||
procedure ParseFromClause(AParent: TSQLSelectStatement; AList: TSQLElementList);
|
procedure ParseFromClause(AParent: TSQLSelectStatement; AList: TSQLElementList);
|
||||||
procedure ParseGroupBy(AParent: TSQLSelectStatement; AList: TSQLElementList);
|
procedure ParseGroupBy(AParent: TSQLSelectStatement; AList: TSQLElementList);
|
||||||
procedure ParseOrderBy(AParent: TSQLSelectStatement; AList: TSQLElementList);
|
procedure ParseOrderBy(AParent: TSQLSelectStatement; AList: TSQLElementList);
|
||||||
|
procedure ParseLimit(AParent: TSQLSelectStatement; ALimit: TSQLSelectLimit);
|
||||||
procedure ParseSelectFieldList(AParent: TSQLSelectStatement; AList: TSQLElementList; Singleton : Boolean);
|
procedure ParseSelectFieldList(AParent: TSQLSelectStatement; AList: TSQLElementList; Singleton : Boolean);
|
||||||
function ParseForUpdate(AParent: TSQLSelectStatement): TSQLElementList;
|
function ParseForUpdate(AParent: TSQLSelectStatement): TSQLElementList;
|
||||||
function ParseSelectPlan(AParent: TSQLElement): TSQLSelectPlan;
|
function ParseSelectPlan(AParent: TSQLElement): TSQLSelectPlan;
|
||||||
@ -436,6 +437,29 @@ begin
|
|||||||
GetNextToken;
|
GetNextToken;
|
||||||
If B then
|
If B then
|
||||||
begin
|
begin
|
||||||
|
if (CurrentToken=tsqlTop) then
|
||||||
|
begin
|
||||||
|
GetNextToken;
|
||||||
|
Expect(tsqlIntegerNumber);
|
||||||
|
AParent.Limit.Style := lsMSSQL;
|
||||||
|
AParent.Limit.Top := StrToInt(CurrentTokenString);
|
||||||
|
GetNextToken;
|
||||||
|
end;
|
||||||
|
if (CurrentToken=tsqlFIRST) then
|
||||||
|
begin
|
||||||
|
GetNextToken;
|
||||||
|
Expect(tsqlIntegerNumber);
|
||||||
|
AParent.Limit.Style := lsFireBird;
|
||||||
|
AParent.Limit.First := StrToInt(CurrentTokenString);
|
||||||
|
GetNextToken;
|
||||||
|
if (CurrentToken=tsqlSKIP) then
|
||||||
|
begin
|
||||||
|
GetNextToken;
|
||||||
|
Expect(tsqlIntegerNumber);
|
||||||
|
AParent.Limit.Skip := StrToInt(CurrentTokenString);
|
||||||
|
GetNextToken;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
if (CurrentToken=tsqlDistinct) then
|
if (CurrentToken=tsqlDistinct) then
|
||||||
begin
|
begin
|
||||||
AParent.Distinct:=True;
|
AParent.Distinct:=True;
|
||||||
@ -721,6 +745,8 @@ begin
|
|||||||
begin
|
begin
|
||||||
if (CurrentToken=tsqlOrder) then
|
if (CurrentToken=tsqlOrder) then
|
||||||
ParseOrderBy(Result,Result.OrderBy);
|
ParseOrderBy(Result,Result.OrderBy);
|
||||||
|
if CurrentToken in [tsqlLimit,tsqlOFFSET] then
|
||||||
|
ParseLimit(Result,Result.Limit);
|
||||||
if (CurrentToken=tsqlFOR) then
|
if (CurrentToken=tsqlFOR) then
|
||||||
Result.ForUpdate:=ParseForUpdate(Result);
|
Result.ForUpdate:=ParseForUpdate(Result);
|
||||||
end;
|
end;
|
||||||
@ -1319,6 +1345,46 @@ begin
|
|||||||
Until (CurrentToken<>tsqlComma);
|
Until (CurrentToken<>tsqlComma);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TSQLParser.ParseLimit(AParent: TSQLSelectStatement; ALimit: TSQLSelectLimit);
|
||||||
|
|
||||||
|
procedure DoOffset;
|
||||||
|
begin
|
||||||
|
if CurrentToken=tsqlOFFSET then
|
||||||
|
begin
|
||||||
|
GetNextToken;
|
||||||
|
Expect(tsqlIntegerNumber);
|
||||||
|
ALimit.Offset := StrToInt(CurrentTokenString);
|
||||||
|
GetNextToken;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
begin
|
||||||
|
ALimit.Style:=lsPostgres;
|
||||||
|
if CurrentToken=tsqlLIMIT then
|
||||||
|
begin
|
||||||
|
GetNextToken;
|
||||||
|
if CurrentToken=tsqlALL then
|
||||||
|
ALimit.RowCount := -1
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Expect(tsqlIntegerNumber);
|
||||||
|
ALimit.RowCount := StrToInt(CurrentTokenString);
|
||||||
|
end;
|
||||||
|
GetNextToken;
|
||||||
|
if CurrentToken=tsqlCOMMA then
|
||||||
|
begin
|
||||||
|
GetNextToken;
|
||||||
|
Expect(tsqlIntegerNumber);
|
||||||
|
ALimit.Offset := ALimit.RowCount;
|
||||||
|
ALimit.RowCount := StrToInt(CurrentTokenString);
|
||||||
|
GetNextToken;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
DoOffset;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
DoOffset;
|
||||||
|
end;
|
||||||
|
|
||||||
function TSQLParser.ParseForStatement(AParent: TSQLElement): TSQLForStatement;
|
function TSQLParser.ParseForStatement(AParent: TSQLElement): TSQLForStatement;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
@ -54,20 +54,20 @@ type
|
|||||||
tsqlCOLLATE, tsqlCONTAINING, tsqlCOUNT, tsqlCREATE, tsqlCOLUMN, tsqlCONSTRAINT, tsqlChar,tsqlCHARACTER, tsqlCHECK, tsqlComputed,tsqlCASCADE, tsqlCast, tsqlCommit,tsqlConnect,tsqlCache,tsqlConditional,tsqlCString,
|
tsqlCOLLATE, tsqlCONTAINING, tsqlCOUNT, tsqlCREATE, tsqlCOLUMN, tsqlCONSTRAINT, tsqlChar,tsqlCHARACTER, tsqlCHECK, tsqlComputed,tsqlCASCADE, tsqlCast, tsqlCommit,tsqlConnect,tsqlCache,tsqlConditional,tsqlCString,
|
||||||
tsqlDESC, tsqlDESCENDING, tsqlDISTINCT, tsqlDEFAULT, tsqlDELETE, tsqlDO, tsqlDouble, tsqlDECLARE, tsqlDROP, tsqlDomain, tsqlDecimal, tsqlDate,tsqlDatabase,
|
tsqlDESC, tsqlDESCENDING, tsqlDISTINCT, tsqlDEFAULT, tsqlDELETE, tsqlDO, tsqlDouble, tsqlDECLARE, tsqlDROP, tsqlDomain, tsqlDecimal, tsqlDate,tsqlDatabase,
|
||||||
tsqlESCAPE, tsqlEXISTS, tsqlELSE, tsqlException, tsqlExternal, tsqlExecute, tsqlEnd,tsqlExit,tsqlEntrypoint,tsqlExtract,
|
tsqlESCAPE, tsqlEXISTS, tsqlELSE, tsqlException, tsqlExternal, tsqlExecute, tsqlEnd,tsqlExit,tsqlEntrypoint,tsqlExtract,
|
||||||
tsqlFROM, tsqlFULL, tsqlFOREIGN, tsqlFOR, tsqlFUNCTION, tsqlFLOAT, tsqlFile,tsqlFreeIt,
|
tsqlFIRST, tsqlFROM, tsqlFULL, tsqlFOREIGN, tsqlFOR, tsqlFUNCTION, tsqlFLOAT, tsqlFile,tsqlFreeIt,
|
||||||
tsqlGenerator, tsqlGROUP, tsqlGenID,tsqlGDSCODE,tsqlGrant,
|
tsqlGenerator, tsqlGROUP, tsqlGenID,tsqlGDSCODE,tsqlGrant,
|
||||||
tsqlHAVING,
|
tsqlHAVING,
|
||||||
tsqlIF, tsqlIN, tsqlINNER, tsqlINSERT, tsqlINT, tsqlINTEGER, tsqlINTO, tsqlIS, tsqlINDEX, tsqlInactive,
|
tsqlIF, tsqlIN, tsqlINNER, tsqlINSERT, tsqlINT, tsqlINTEGER, tsqlINTO, tsqlIS, tsqlINDEX, tsqlInactive,
|
||||||
tsqlJOIN,
|
tsqlJOIN,
|
||||||
tsqlKEY,
|
tsqlKEY,
|
||||||
tsqlLEFT, tsqlLIKE, tsqlLength,
|
tsqlLEFT, tsqlLIKE, tsqlLIMIT, tsqlLength,
|
||||||
tsqlMAX, tsqlMIN, tsqlMERGE, tsqlManual, tsqlModuleName,
|
tsqlMAX, tsqlMIN, tsqlMERGE, tsqlManual, tsqlModuleName,
|
||||||
tsqlNOT, tsqlNULL, tsqlNUMERIC , tsqlNChar, tsqlNATIONAL,tsqlNO, tsqlNatural,
|
tsqlNOT, tsqlNULL, tsqlNUMERIC , tsqlNChar, tsqlNATIONAL,tsqlNO, tsqlNatural,
|
||||||
tsqlOFF {not an FB reserved word; used in isql scripts}, tsqlON, tsqlOR, tsqlORDER, tsqlOUTER, tsqlOption,
|
tsqlOFF {not an FB reserved word; used in isql scripts}, tsqlOFFSET, tsqlON, tsqlOR, tsqlORDER, tsqlOUTER, tsqlOption,
|
||||||
tsqlPrecision, tsqlPRIMARY, tsqlProcedure, tsqlPosition, tsqlPlan, tsqlPassword, tsqlPage,tsqlPages,tsqlPageSize,tsqlPostEvent,tsqlPrivileges,tsqlPublic,
|
tsqlPrecision, tsqlPRIMARY, tsqlProcedure, tsqlPosition, tsqlPlan, tsqlPassword, tsqlPage,tsqlPages,tsqlPageSize,tsqlPostEvent,tsqlPrivileges,tsqlPublic,
|
||||||
tsqlRIGHT, tsqlROLE, tsqlReferences, tsqlRollBack, tsqlRelease, tsqlretain, tsqlReturningValues,tsqlReturns, tsqlrevoke,
|
tsqlRIGHT, tsqlROLE, tsqlReferences, tsqlRollBack, tsqlRelease, tsqlretain, tsqlReturningValues,tsqlReturns, tsqlrevoke,
|
||||||
tsqlSELECT, tsqlSET, tsqlSINGULAR, tsqlSOME, tsqlSTARTING, tsqlSUM, tsqlSKIP,tsqlSUBTYPE,tsqlSize,tsqlSegment, tsqlSORT, tsqlSnapShot,tsqlSchema,tsqlShadow,tsqlSuspend,tsqlSQLCode,tsqlSmallint,
|
tsqlSELECT, tsqlSET, tsqlSINGULAR, tsqlSOME, tsqlSTARTING, tsqlSUM, tsqlSKIP,tsqlSUBTYPE,tsqlSize,tsqlSegment, tsqlSORT, tsqlSnapShot,tsqlSchema,tsqlShadow,tsqlSuspend,tsqlSQLCode,tsqlSmallint,
|
||||||
tSQLTABLE, tsqlText, tsqlTrigger, tsqlTime, tsqlTimeStamp, tsqlType, tsqlTo, tsqlTransaction, tsqlThen,
|
tSQLTABLE, tsqlText, tsqlTrigger, tsqlTime, tsqlTimeStamp, tsqlType, tsqlTo, tsqlTop, tsqlTransaction, tsqlThen,
|
||||||
tsqlUNION, tsqlUPDATE, tsqlUPPER, tsqlUNIQUE, tsqlUSER,
|
tsqlUNION, tsqlUPDATE, tsqlUPPER, tsqlUNIQUE, tsqlUSER,
|
||||||
tsqlValue, tsqlVALUES, tsqlVARIABLE, tsqlVIEW, tsqlVARCHAR,TSQLVARYING,
|
tsqlValue, tsqlVALUES, tsqlVARIABLE, tsqlVIEW, tsqlVARCHAR,TSQLVARYING,
|
||||||
tsqlWHERE, tsqlWITH, tsqlWHILE, tsqlWork, tsqlWhen,tsqlSequence,tsqlRestart,tsqlrecreate,tsqlterm
|
tsqlWHERE, tsqlWITH, tsqlWHILE, tsqlWork, tsqlWhen,tsqlSequence,tsqlRestart,tsqlrecreate,tsqlterm
|
||||||
@ -100,20 +100,20 @@ const
|
|||||||
'COLLATE', 'CONTAINING', 'COUNT', 'CREATE', 'COLUMN', 'CONSTRAINT', 'CHAR','CHARACTER','CHECK', 'COMPUTED','CASCADE','CAST', 'COMMIT', 'CONNECT', 'CACHE','CONDITIONAL', 'CSTRING',
|
'COLLATE', 'CONTAINING', 'COUNT', 'CREATE', 'COLUMN', 'CONSTRAINT', 'CHAR','CHARACTER','CHECK', 'COMPUTED','CASCADE','CAST', 'COMMIT', 'CONNECT', 'CACHE','CONDITIONAL', 'CSTRING',
|
||||||
'DESC', 'DESCENDING', 'DISTINCT', 'DEFAULT', 'DELETE', 'DO', 'DOUBLE', 'DECLARE', 'DROP', 'DOMAIN', 'DECIMAL', 'DATE','DATABASE',
|
'DESC', 'DESCENDING', 'DISTINCT', 'DEFAULT', 'DELETE', 'DO', 'DOUBLE', 'DECLARE', 'DROP', 'DOMAIN', 'DECIMAL', 'DATE','DATABASE',
|
||||||
'ESCAPE', 'EXISTS', 'ELSE', 'EXCEPTION', 'EXTERNAL','EXECUTE', 'END','EXIT','ENTRY_POINT','EXTRACT',
|
'ESCAPE', 'EXISTS', 'ELSE', 'EXCEPTION', 'EXTERNAL','EXECUTE', 'END','EXIT','ENTRY_POINT','EXTRACT',
|
||||||
'FROM', 'FULL','FOREIGN', 'FOR', 'FUNCTION', 'FLOAT','FILE', 'FREE_IT',
|
'FIRST', 'FROM', 'FULL','FOREIGN', 'FOR', 'FUNCTION', 'FLOAT','FILE', 'FREE_IT',
|
||||||
'GENERATOR', 'GROUP', 'GEN_ID','GDSCODE','GRANT',
|
'GENERATOR', 'GROUP', 'GEN_ID','GDSCODE','GRANT',
|
||||||
'HAVING',
|
'HAVING',
|
||||||
'IF', 'IN', 'INNER', 'INSERT', 'INT', 'INTEGER', 'INTO', 'IS', 'INDEX', 'INACTIVE',
|
'IF', 'IN', 'INNER', 'INSERT', 'INT', 'INTEGER', 'INTO', 'IS', 'INDEX', 'INACTIVE',
|
||||||
'JOIN',
|
'JOIN',
|
||||||
'KEY',
|
'KEY',
|
||||||
'LEFT', 'LIKE', 'LENGTH',
|
'LEFT', 'LIKE', 'LIMIT', 'LENGTH',
|
||||||
'MAX', 'MIN', 'MERGE', 'MANUAL', 'MODULE_NAME',
|
'MAX', 'MIN', 'MERGE', 'MANUAL', 'MODULE_NAME',
|
||||||
'NOT', 'NULL', 'NUMERIC','NCHAR','NATIONAL', 'NO', 'NATURAL',
|
'NOT', 'NULL', 'NUMERIC','NCHAR','NATIONAL', 'NO', 'NATURAL',
|
||||||
'OFF', 'ON', 'OR', 'ORDER', 'OUTER', 'OPTION',
|
'OFF', 'OFFSET', 'ON', 'OR', 'ORDER', 'OUTER', 'OPTION',
|
||||||
'PRECISION', 'PRIMARY', 'PROCEDURE','POSITION','PLAN', 'PASSWORD','PAGE','PAGES','PAGE_SIZE','POST_EVENT','PRIVILEGES','PUBLIC',
|
'PRECISION', 'PRIMARY', 'PROCEDURE','POSITION','PLAN', 'PASSWORD','PAGE','PAGES','PAGE_SIZE','POST_EVENT','PRIVILEGES','PUBLIC',
|
||||||
'RIGHT', 'ROLE', 'REFERENCES', 'ROLLBACK','RELEASE', 'RETAIN', 'RETURNING_VALUES', 'RETURNS','REVOKE',
|
'RIGHT', 'ROLE', 'REFERENCES', 'ROLLBACK','RELEASE', 'RETAIN', 'RETURNING_VALUES', 'RETURNS','REVOKE',
|
||||||
'SELECT', 'SET', 'SINGULAR', 'SOME', 'STARTING', 'SUM', 'SKIP','SUB_TYPE', 'SIZE', 'SEGMENT', 'SORT', 'SNAPSHOT','SCHEMA','SHADOW','SUSPEND','SQLCODE','SMALLINT',
|
'SELECT', 'SET', 'SINGULAR', 'SOME', 'STARTING', 'SUM', 'SKIP','SUB_TYPE', 'SIZE', 'SEGMENT', 'SORT', 'SNAPSHOT','SCHEMA','SHADOW','SUSPEND','SQLCODE','SMALLINT',
|
||||||
'TABLE', 'TEXT', 'TRIGGER', 'TIME', 'TIMESTAMP', 'TYPE', 'TO', 'TRANSACTION', 'THEN',
|
'TABLE', 'TEXT', 'TRIGGER', 'TIME', 'TIMESTAMP', 'TYPE', 'TO', 'TOP', 'TRANSACTION', 'THEN',
|
||||||
'UNION', 'UPDATE', 'UPPER', 'UNIQUE', 'USER',
|
'UNION', 'UPDATE', 'UPPER', 'UNIQUE', 'USER',
|
||||||
'VALUE','VALUES','VARIABLE', 'VIEW','VARCHAR','VARYING',
|
'VALUE','VALUES','VARIABLE', 'VIEW','VARCHAR','VARYING',
|
||||||
'WHERE', 'WITH', 'WHILE','WORK','WHEN','SEQUENCE','RESTART','RECREATE','TERM'
|
'WHERE', 'WITH', 'WHILE','WORK','WHEN','SEQUENCE','RESTART','RECREATE','TERM'
|
||||||
|
@ -726,11 +726,32 @@ Type
|
|||||||
Property OrderBy : TSQLOrderDirection Read FOrderBy write FOrderBy;
|
Property OrderBy : TSQLOrderDirection Read FOrderBy write FOrderBy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TSQLSelectLimit }
|
||||||
|
|
||||||
|
TSQLSelectLimitStyle = (lsNone, lsFireBird, lsMSSQL, lsPostgres{lsMySQL});
|
||||||
|
|
||||||
|
TSQLSelectLimit = Class
|
||||||
|
private
|
||||||
|
FRowCount: Integer;
|
||||||
|
FSkip: Integer;
|
||||||
|
FStyle: TSQLSelectLimitStyle;
|
||||||
|
public
|
||||||
|
constructor Create;
|
||||||
|
public
|
||||||
|
property Style: TSQLSelectLimitStyle read FStyle write FStyle;
|
||||||
|
property First: Integer read FRowCount write FRowCount; // lsFireBird
|
||||||
|
property Skip: Integer read FSkip write FSkip; // lsFireBird
|
||||||
|
property Top: Integer read FRowCount write FRowCount; // lsMSSQL
|
||||||
|
property RowCount: Integer read FRowCount write FRowCount; // lsPostgres
|
||||||
|
property Offset: Integer read FSkip write FSkip; // lsPostgres
|
||||||
|
end;
|
||||||
|
|
||||||
{ TSQLSelectStatement }
|
{ TSQLSelectStatement }
|
||||||
|
|
||||||
TSQLSelectStatement = Class(TSQLDMLStatement)
|
TSQLSelectStatement = Class(TSQLDMLStatement)
|
||||||
private
|
private
|
||||||
FAll: Boolean;
|
FAll: Boolean;
|
||||||
|
FLimit: TSQLSelectLimit;
|
||||||
FDistinct: Boolean;
|
FDistinct: Boolean;
|
||||||
FEndAt: TSQLExpression;
|
FEndAt: TSQLExpression;
|
||||||
FFields: TSQLElementList;
|
FFields: TSQLElementList;
|
||||||
@ -760,6 +781,7 @@ Type
|
|||||||
Property ForUpdate : TSQLElementList Read FForUpdate Write FForUpdate;
|
Property ForUpdate : TSQLElementList Read FForUpdate Write FForUpdate;
|
||||||
Property Union : TSQLSelectStatement Read FUnion Write FUnion;
|
Property Union : TSQLSelectStatement Read FUnion Write FUnion;
|
||||||
Property Plan : TSQLSelectPlan Read FPlan Write FPlan;
|
Property Plan : TSQLSelectPlan Read FPlan Write FPlan;
|
||||||
|
Property Limit: TSQLSelectLimit Read FLimit;
|
||||||
Property Distinct : Boolean Read FDistinct Write FDistinct;
|
Property Distinct : Boolean Read FDistinct Write FDistinct;
|
||||||
Property All : Boolean Read FAll Write FAll;
|
Property All : Boolean Read FAll Write FAll;
|
||||||
Property UnionAll : Boolean Read FUnionAll Write FUnionAll;
|
Property UnionAll : Boolean Read FUnionAll Write FUnionAll;
|
||||||
@ -1915,6 +1937,15 @@ begin
|
|||||||
Sep:=', ';
|
Sep:=', ';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TSQLSelectLimit }
|
||||||
|
|
||||||
|
constructor TSQLSelectLimit.Create;
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FSkip:=-1;
|
||||||
|
FRowCount:=-1;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TSQLSetTermStatement }
|
{ TSQLSetTermStatement }
|
||||||
|
|
||||||
function TSQLSetTermStatement.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer): TSQLStringType;
|
function TSQLSetTermStatement.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer): TSQLStringType;
|
||||||
@ -1994,6 +2025,7 @@ begin
|
|||||||
FTables:=TSQLElementList.Create(True);
|
FTables:=TSQLElementList.Create(True);
|
||||||
FGroupBy:=TSQLElementList.Create(True);
|
FGroupBy:=TSQLElementList.Create(True);
|
||||||
FOrderBy:=TSQLElementList.Create(True);
|
FOrderBy:=TSQLElementList.Create(True);
|
||||||
|
FLimit:=TSQLSelectLimit.Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TSQLSelectStatement.Destroy;
|
destructor TSQLSelectStatement.Destroy;
|
||||||
@ -2011,6 +2043,7 @@ begin
|
|||||||
FreeAndNil(FForUpdate);
|
FreeAndNil(FForUpdate);
|
||||||
FreeAndNil(FTN);
|
FreeAndNil(FTN);
|
||||||
FreeAndNil(FInto);
|
FreeAndNil(FInto);
|
||||||
|
FreeAndNil(FLimit);
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2078,6 +2111,15 @@ Var
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
Result:=SQLKeyWord('SELECT',Options);
|
Result:=SQLKeyWord('SELECT',Options);
|
||||||
|
If Limit.Style=lsMSSQL then
|
||||||
|
Result:=Result+' '+SQLKeyword('TOP',Options)+' '+IntToStr(Limit.Top)
|
||||||
|
else
|
||||||
|
If Limit.Style=lsFireBird then
|
||||||
|
begin
|
||||||
|
Result:=Result+' '+SQLKeyword('FIRST',Options)+' '+IntToStr(Limit.First);
|
||||||
|
if Limit.Skip>=0 then
|
||||||
|
Result:=Result+' '+SQLKeyword('SKIP',Options)+' '+IntToStr(Limit.Skip);
|
||||||
|
end;
|
||||||
If Distinct then
|
If Distinct then
|
||||||
Result:=Result+' '+SQLKeyword('DISTINCT',Options);
|
Result:=Result+' '+SQLKeyword('DISTINCT',Options);
|
||||||
NewLinePending:=(sfoOneFieldPerLine in Options);
|
NewLinePending:=(sfoOneFieldPerLine in Options);
|
||||||
@ -2093,6 +2135,13 @@ begin
|
|||||||
NewLinePending:=NewLinePending or (sfoPlanOnSeparateLine in Options);
|
NewLinePending:=NewLinePending or (sfoPlanOnSeparateLine in Options);
|
||||||
AddExpression('PLAN',Plan,(sfoPlanOnSeparateLine in Options),(sfoIndentPlan in Options));
|
AddExpression('PLAN',Plan,(sfoPlanOnSeparateLine in Options),(sfoIndentPlan in Options));
|
||||||
AddList('ORDER BY',OrderBy,(sfoOneOrderByFieldPerLine in Options),(sfoIndentOrderByFields in Options));
|
AddList('ORDER BY',OrderBy,(sfoOneOrderByFieldPerLine in Options),(sfoIndentOrderByFields in Options));
|
||||||
|
If Limit.Style=lsPostgres then
|
||||||
|
begin
|
||||||
|
if Limit.RowCount>=0 then
|
||||||
|
Result:=Result+' '+SQLKeyword('LIMIT',Options)+' '+IntToStr(Limit.RowCount);
|
||||||
|
if Limit.Offset>=0 then
|
||||||
|
Result:=Result+' '+SQLKeyword('OFFSET',Options)+' '+IntToStr(Limit.Offset);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TSQLInsertStatement }
|
{ TSQLInsertStatement }
|
||||||
|
@ -97,6 +97,7 @@ type
|
|||||||
procedure TestPlanExpression;
|
procedure TestPlanExpression;
|
||||||
procedure TestOrderBy;
|
procedure TestOrderBy;
|
||||||
Procedure TestSelect;
|
Procedure TestSelect;
|
||||||
|
Procedure TestLimit;
|
||||||
procedure TestInsert;
|
procedure TestInsert;
|
||||||
procedure TestUpdatePair;
|
procedure TestUpdatePair;
|
||||||
procedure TestUpdate;
|
procedure TestUpdate;
|
||||||
@ -995,6 +996,33 @@ begin
|
|||||||
AssertSQL(J,'(E JOIN F ON (G = H)) FULL OUTER JOIN A ON (C = D)',[sfoBracketLeftJoin]);
|
AssertSQL(J,'(E JOIN F ON (G = H)) FULL OUTER JOIN A ON (C = D)',[sfoBracketLeftJoin]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestGenerateSQL.TestLimit;
|
||||||
|
|
||||||
|
Var
|
||||||
|
S : TSQLSelectStatement;
|
||||||
|
|
||||||
|
begin
|
||||||
|
S:=CreateSelect(CreateIdentifierExpression('A'),'B');
|
||||||
|
|
||||||
|
S.Limit.Style:=lsFireBird;
|
||||||
|
S.Limit.First := 10;
|
||||||
|
AssertSQL(S,'SELECT FIRST 10 A FROM B');
|
||||||
|
S.Limit.Style:=lsMSSQL;
|
||||||
|
AssertSQL(S,'SELECT TOP 10 A FROM B');
|
||||||
|
S.Limit.Style:=lsPostgres;
|
||||||
|
AssertSQL(S,'SELECT A FROM B LIMIT 10');
|
||||||
|
|
||||||
|
S.Limit.Skip := 20;
|
||||||
|
S.Limit.Style:=lsFireBird;
|
||||||
|
AssertSQL(S,'SELECT FIRST 10 SKIP 20 A FROM B');
|
||||||
|
S.Limit.Style:=lsPostgres;
|
||||||
|
AssertSQL(S,'SELECT A FROM B LIMIT 10 OFFSET 20');
|
||||||
|
|
||||||
|
S.Limit.RowCount := -1;
|
||||||
|
S.Limit.Style:=lsPostgres;
|
||||||
|
AssertSQL(S,'SELECT A FROM B OFFSET 20');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestGenerateSQL.TestPlanNatural;
|
procedure TTestGenerateSQL.TestPlanNatural;
|
||||||
|
|
||||||
Var
|
Var
|
||||||
|
@ -413,6 +413,15 @@ type
|
|||||||
procedure TestSelectTwoFieldsThreeBracketTablesJoin;
|
procedure TestSelectTwoFieldsThreeBracketTablesJoin;
|
||||||
procedure TestSelectTableWithSchema;
|
procedure TestSelectTableWithSchema;
|
||||||
procedure TestSelectFieldWithSchema;
|
procedure TestSelectFieldWithSchema;
|
||||||
|
procedure TestSelectFirst;
|
||||||
|
procedure TestSelectFirstSkip;
|
||||||
|
procedure TestSelectTop;
|
||||||
|
procedure TestSelectLimit;
|
||||||
|
procedure TestSelectLimitAll;
|
||||||
|
procedure TestSelectLimitAllOffset;
|
||||||
|
procedure TestSelectLimitOffset1;
|
||||||
|
procedure TestSelectLimitOffset2;
|
||||||
|
procedure TestSelectOffset;
|
||||||
procedure TestAggregateCount;
|
procedure TestAggregateCount;
|
||||||
procedure TestAggregateCountAsterisk;
|
procedure TestAggregateCountAsterisk;
|
||||||
procedure TestAggregateCountAll;
|
procedure TestAggregateCountAll;
|
||||||
@ -3758,6 +3767,73 @@ begin
|
|||||||
AssertEquals('Schema name = S','S',(Select.Tables[0] as TSQLSimpleTableReference).ObjectNamePath[0].Name);
|
AssertEquals('Schema name = S','S',(Select.Tables[0] as TSQLSimpleTableReference).ObjectNamePath[0].Name);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestSelectParser.TestSelectFirst;
|
||||||
|
begin
|
||||||
|
// FireBird
|
||||||
|
TestSelect('SELECT FIRST 100 A FROM B');
|
||||||
|
AssertEquals('Limit style',Ord(lsFireBird),Ord(Select.Limit.Style));
|
||||||
|
AssertEquals('Limit FIRST 100',100,Select.Limit.First);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestSelectParser.TestSelectFirstSkip;
|
||||||
|
begin
|
||||||
|
// FireBird
|
||||||
|
TestSelect('SELECT FIRST 100 SKIP 200 A FROM B');
|
||||||
|
AssertEquals('Limit style',Ord(lsFireBird),Ord(Select.Limit.Style));
|
||||||
|
AssertEquals('Limit FIRST 100',100,Select.Limit.First);
|
||||||
|
AssertEquals('Limit SKIP 200',200,Select.Limit.Skip);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestSelectParser.TestSelectLimit;
|
||||||
|
begin
|
||||||
|
// MySQL&Postgres
|
||||||
|
TestSelect('SELECT A FROM B LIMIT 100');
|
||||||
|
AssertEquals('Limit style',Ord(lsPostgres),Ord(Select.Limit.Style));
|
||||||
|
AssertEquals('Limit RowCount 100',100,Select.Limit.RowCount);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestSelectParser.TestSelectLimitAll;
|
||||||
|
begin
|
||||||
|
// Postgres
|
||||||
|
TestSelect('SELECT A FROM B LIMIT ALL');
|
||||||
|
AssertEquals('Limit style',Ord(lsPostgres),Ord(Select.Limit.Style));
|
||||||
|
AssertEquals('Limit RowCount -1',-1,Select.Limit.RowCount);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestSelectParser.TestSelectLimitAllOffset;
|
||||||
|
begin
|
||||||
|
// Postgres
|
||||||
|
TestSelect('SELECT A FROM B LIMIT ALL OFFSET 200');
|
||||||
|
AssertEquals('Limit style',Ord(lsPostgres),Ord(Select.Limit.Style));
|
||||||
|
AssertEquals('Limit Offset 200',200,Select.Limit.Offset);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestSelectParser.TestSelectLimitOffset1;
|
||||||
|
begin
|
||||||
|
// MySQL
|
||||||
|
TestSelect('SELECT A FROM B LIMIT 200, 100');
|
||||||
|
AssertEquals('Limit style',Ord(lsPostgres),Ord(Select.Limit.Style));
|
||||||
|
AssertEquals('Limit RowCount 100',100,Select.Limit.RowCount);
|
||||||
|
AssertEquals('Limit Offset 200',200,Select.Limit.Offset);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestSelectParser.TestSelectLimitOffset2;
|
||||||
|
begin
|
||||||
|
// MySQL&Postgres
|
||||||
|
TestSelect('SELECT A FROM B LIMIT 100 OFFSET 200');
|
||||||
|
AssertEquals('Limit style',Ord(lsPostgres),Ord(Select.Limit.Style));
|
||||||
|
AssertEquals('Limit RowCount 100',100,Select.Limit.RowCount);
|
||||||
|
AssertEquals('Limit Offset 200',200,Select.Limit.Offset);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestSelectParser.TestSelectOffset;
|
||||||
|
begin
|
||||||
|
// Postgres
|
||||||
|
TestSelect('SELECT A FROM B OFFSET 200');
|
||||||
|
AssertEquals('Limit style',Ord(lsPostgres),Ord(Select.Limit.Style));
|
||||||
|
AssertEquals('Limit Offset 200',200,Select.Limit.Offset);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestSelectParser.TestSelectOneFieldOneTable;
|
procedure TTestSelectParser.TestSelectOneFieldOneTable;
|
||||||
begin
|
begin
|
||||||
TestSelect('SELECT B FROM A');
|
TestSelect('SELECT B FROM A');
|
||||||
@ -3850,6 +3926,14 @@ begin
|
|||||||
AssertEquals('Schema name = S','S',(Select.Tables[0] as TSQLSimpleTableReference).ObjectNamePath[0].Name);
|
AssertEquals('Schema name = S','S',(Select.Tables[0] as TSQLSimpleTableReference).ObjectNamePath[0].Name);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestSelectParser.TestSelectTop;
|
||||||
|
begin
|
||||||
|
// MSSQL
|
||||||
|
TestSelect('SELECT TOP 100 A FROM B');
|
||||||
|
AssertEquals('Limit style',Ord(lsMSSQL),Ord(Select.Limit.Style));
|
||||||
|
AssertEquals('Limit TOP 100',100,Select.Limit.Top);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestSelectParser.TestSelectOneDistinctFieldOneTable;
|
procedure TTestSelectParser.TestSelectOneDistinctFieldOneTable;
|
||||||
begin
|
begin
|
||||||
TestSelect('SELECT DISTINCT B FROM A');
|
TestSelect('SELECT DISTINCT B FROM A');
|
||||||
|
Loading…
Reference in New Issue
Block a user