📄 xqyacc.y
字号:
with Column do
begin
ColumnExpr := ColText;
if Assigned(Self.fAggregateList) then
begin
AggregateList.Free; { free previous aggregate list}
AggregateList := Self.fAggregateList; { assign the current list}
Self.fAggregateList:= nil; { define as nil the current }
end;
{ mark also as a temporary column that will be deleted after result set is
generated }
IsTemporaryCol := True;
end;
end;
procedure TxqParser.AddUpdateColumn(const ColumnName, ColumnExpr: String);
var
UpdateItem: TUpdateItem;
begin
UpdateItem := CurrentAnalizer.UpdateColumnList.Add;
with UpdateItem do
begin
ColName := ColumnName;
ColExpr := ColumnExpr;
end;
end;
procedure TxqParser.AddWhereOptimize( const AFieldName, ARangeStart,
ARangeEnd: String; ARelOperator: TRelationalOperator );
var
WhereOptimize : TWhereOptimizeItem;
N : Integer;
function DeleteStringDelim(const s: String): String;
begin
Result := s;
if Length(Result) > 1 then
begin
if (Result[1] in xqbase.SQuote) and (Result[Length(Result)] in xqbase.SQuote) then
Result:= Copy(Result, 2, Length(Result) - 2);
end;
end;
begin
if Not (yyLexer as TxqLexer).IsWhereActive then Exit;
N := CurrentAnalizer.WhereOptimizeList.Count - 1;
if ((ARelOperator in [ropLE, ropLT]) or (ARelOperator in [ropGE, ropGT]) ) and (N > 0) then
begin
{ I will check if the previous command was something like (CustNo >= 1000)
and if so, and this is something like (CustNo <= 3000) then
I will add to the previous optimize and will generate a ropBETWEEN range }
WhereOptimize:= CurrentAnalizer.WhereOptimizeList[N - 1];
if ( ((ARelOperator in [ropLE, ropLT]) and (WhereOptimize.RelOperator in [ropGE, ropGT])) or
((ARelOperator in [ropGE, ropGT]) and (WhereOptimize.RelOperator in [ropLE, ropLT])) ) and
(AnsiCompareText(WhereOptimize.FieldNames, AFieldName) = 0) then
begin
WhereOptimize.RangeEnd := DeleteStringDelim( ARangeEnd );
WhereOptimize.RelOperator := ropBETWEEN;
Exit;
end;
end;
WhereOptimize := CurrentAnalizer.WhereOptimizeList.Add;
with WhereOptimize do
begin
FieldNames := AFieldName;
RangeStart := DeleteStringDelim(ARangeStart);
RangeEnd := DeleteStringDelim(ARangeEnd);
RelOperator := ARelOperator;
CanOptimize := False;
end;
end;
{ ALTER TABLE }
function TxqParser.CurrentAlterTable: TCreateTableItem;
begin
if FNumTables > CurrentAnalizer.AlterTableList.Count - 1 then
Result := CurrentAnalizer.AlterTableList.Add
else
Result:= CurrentAnalizer.AlterTableList[ FNumTables ];
end;
{ CREATE TABLE }
function TxqParser.CurrentCreateTable: TCreateTableItem;
begin
if FNumTables > CurrentAnalizer.CreateTableList.Count - 1 then
Result := CurrentAnalizer.CreateTableList.Add
else
Result:= CurrentAnalizer.CreateTableList[ FNumTables ];
end;
procedure TxqParser.SetTableName(const TableName: String);
begin
CurrentCreateTable.TableName := TableName;
end;
procedure TxqParser.SetAlterTableName(const TableName: String);
begin
CurrentAlterTable.TableName := TableName;
end;
procedure TxqParser.SetFieldParams(AFieldType, AScale, APrecision, ASize, ABlobType: Integer);
begin
FFieldType := AFieldType;
FScale := AScale;
FPrecision := APrecision;
FSize := ASize;
FBlobType := ABlobType;
end;
procedure TxqParser.AddAlterField(const FieldName: String; DropField: Boolean);
var
I: Integer;
begin
{ check if field exists }
with CurrentAlterTable do
for I := 0 to FieldCount - 1 do
if (AnsiCompareText(Fields[I].FieldName, FieldName) = 0)
and (Fields[I].MustDrop=DropField) then
begin
yyerror(SDuplicateFieldName);
yyabort;
Exit;
end;
if (FFieldType = RW_BLOB) and not (FBlobType in [1..5]) then
begin
yyerror(SBlobFieldWrongType);
yyabort;
end;
CurrentAlterTable.Fields.AddField(FieldName, FFieldType, FScale, FPrecision,
FSize, FBlobType, DropField);
end;
procedure TxqParser.AddCreateField(const FieldName: String);
var
I: Integer;
begin
{ check if field exists }
with CurrentCreateTable do
for I := 0 to FieldCount - 1 do
if AnsiCompareText(Fields[I].FieldName, FieldName) = 0 then
begin
yyerror(SDuplicateFieldName);
yyabort;
Exit;
end;
if (FFieldType = RW_BLOB) and not (FBlobType in [1..5]) then
begin
yyerror(SBlobFieldWrongType);
yyabort;
end;
CurrentCreateTable.Fields.AddField(FieldName,FFieldType, FScale, FPrecision,
FSize, FBlobType, False);
end;
procedure TxqParser.AddPrimaryKeyField(const FieldName: String);
var
I : Integer;
Found : Boolean;
begin
{ check that the field exists in the list of field names }
Found := False;
with CurrentCreateTable do
for I := 0 to FieldCount - 1 do
if AnsiCompareText(Fields[I].FieldName, FieldName) = 0 then
begin
Found:= True;
Break;
end;
if Not Found then
begin
yyerror(SFieldNameNotFound);
yyabort;
end;
CurrentCreateTable.PrimaryKey.Add( FieldName );
end;
function TxqParser.CurrentInsertItem: TInsertItem;
begin
if fNumInserts >= CurrentAnalizer.InsertList.Count then
Result := CurrentAnalizer.InsertList.Add
else
Result := CurrentAnalizer.InsertList[fNumInserts];
end;
function TxqParser.CreateInListExpression( const Expr : String ) : String;
var
I : Integer;
begin
{ This subroutine helps to change the syntax:
custno IN (1000, 2000, 3000)
to this :
(custno = 1000) OR (custno = 2000) OR (custno = 3000) }
Result := '';
for i := 0 to fInPredicateList.Count - 1 do
begin
Result := Result + Format('(%s = %s)', [Expr, fInPredicateList[i]]);
if i < fInPredicateList.Count - 1 then
Result := Result + ' OR ';
end;
if fIsNotInList then
Result := 'NOT ( ' + Result + ' )'
else
Result := '( ' + Result + ' )';
fInPredicateList.Clear;
end;
%}
%start sql
%token _IDENTIFIER
%token _UINTEGER
%token _SINTEGER
%token _NUMERIC
%token _STRING
%token _COMA
%token _LPAREN
%token _RPAREN
%token _LSQUARE
%token _RSQUARE
%token _PERIOD
%token _SEMICOLON
%token _COLON
%left RW_OR
%left RW_AND
%left _EQ _NEQ _GT _LT _GE _LE RW_BETWEEN RW_IN RW_LIKE
%left _PLUS _SUB
%left _DIV _MULT RW_MOD RW_IDIV RW_SHL RW_SHR
%right UMINUS /* Negation--unary minus */
%right _EXP /* exponentiation */
%left RW_NOT
%token _ILLEGAL
/* other reserved words and tokens */
%token _COMMENT
_BLANK
_TAB
_NEWLINE
RW_TRUE
RW_FALSE
RW_SELECT
RW_DISTINCT
RW_FROM
RW_WHERE
RW_ORDER
RW_BY
RW_ASC
RW_DESC
RW_AS
RW_INNER
RW_OUTER
RW_FULL
RW_JOIN
RW_ON
RW_GROUP
RW_HAVING
RW_ANY
RW_ALL
RW_SUM
RW_AVG
RW_COUNT
RW_MIN
RW_MAX
RW_STDEV
RW_LEFT
RW_RIGHT
RW_LEADING
RW_TRAILING
RW_BOTH
RW_TRIM
RW_EXTRACT
RW_YEAR
RW_MONTH
RW_DAY
RW_HOUR
RW_MINUTE
RW_SECOND
RW_FOR
RW_SUBSTRING
RW_DELETE
RW_UPDATE
RW_INSERT
RW_INTO
RW_VALUES
RW_SET
RW_CAST
RW_CHAR
RW_INTEGER
RW_BOOLEAN
RW_DATE
RW_TIME
RW_DATETIME
RW_FLOAT
RW_ESCAPE
RW_CREATE
RW_TABLE
RW_SMALLINT
RW_MONEY
RW_AUTOINC
RW_PRIMARY
RW_KEY
RW_BLOB
RW_INDEX
RW_UNIQUE
RW_DROP
RW_TRANSFORM
RW_PIVOT
RW_UNION
RW_WITH
RW_IS
RW_NULL
RW_ALTER
RW_COLUMN
RW_ADD
RW_APPEND
RW_CASE
RW_WHEN
RW_THEN
RW_ELSE
RW_END
RW_PACK
RW_ZAP
RW_REINDEX
RW_RANGE
RW_USING
RW_FIELDS
RW_TO
RW_RANGE
RW_TO
RW_TOP
%type <string>
%%
sql : select_statement { fAnalizer.Statement := ssSelect; }
| transform_statement { fAnalizer.Statement := ssSelect; }
| union_statement { fAnalizer.Statement := ssUnion; }
| update_statement { fAnalizer.Statement := ssUpdate; }
| delete_statement { fAnalizer.Statement := ssDelete; }
| insert_statement { fAnalizer.Statement := ssInsert; }
| createtable_statement { fAnalizer.Statement := ssCreateTable; }
| altertable_statement { fAnalizer.Statement := ssAlterTable; }
| createindex_statement { fAnalizer.Statement := ssCreateIndex; }
| droptable_statement { fAnalizer.Statement := ssDropTable; }
| dropindex_statement { fAnalizer.Statement := ssDropIndex; }
| packtable_statement { fAnalizer.Statement := ssPacktable; }
| zaptable_statement { fAnalizer.Statement := ssZapTable; }
| reindextable_statement { fAnalizer.Statement := ssReindexTable; }
;
/* SELECT statement */
select_statement : select_clause from_clause where_clause userdef_range_clause
groupby_clause orderby_clause for_copy_append end_statement
;
union_statement : select_statement RW_UNION second_select_statement end_statement
;
for_copy_append : /* empty */
| RW_INTO _IDENTIFIER RW_FOR RW_APPEND
{ CurrentAnalizer.IntoTable:= $<string>2; }
;
/* SELECT clause */
select_clause : select_case _MULT
{ CurrentAnalizer.DoSelectAll := True;
CurrentAnalizer.AddFieldIfNot('*');}
| select_case list_expr_field
;
select_case : topn_groupby RW_SELECT topn_select
| topn_groupby RW_SELECT topn_select RW_DISTINCT
{CurrentAnalizer.IsDistinct:= True;}
;
topn_select : /* empty */
| RW_TOP _UINTEGER
{ CurrentAnalizer.TopNInSelect:= StrToInt( $<string>2 ) ; }
;
topn_groupby : /* empty */
| RW_TOP _UINTEGER
{ CurrentAnalizer.TopNInGroupBy:= StrToInt( $<string>2 ) ; }
;
list_expr_field : expr_field
| list_expr_field _COMA expr_field
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -