📄 absexpressions.pas
字号:
// return Size of Data (for strings and arrays)
function GetPrecision: Integer;
// is expression contains no nodes
function IsEmpty: Boolean;
// is expression a Field (for join)
function IsField: Boolean;
// is expression a fields combination
function IsFieldsExpression: Boolean;
// Move AndNodes To RootNode
procedure MoveAndNodesToRoot;
// Field Name, Table Name
procedure GetFieldInfo(var TableName: String; var FieldName: String);
// makes filter string from related parts and sets it to AO
procedure ApplyFilterParts(AO: TABSAO; ParentQueryAO: TABSAO;
ParentCursor: TABSCursor;
AllowRecurse: Boolean = True; ForHavingClause: Boolean = False);
// replace pseudonyms to original names (f1 -> table1.field1)
procedure ReplacePseudonyms(SelectList: array of TABSSelectListItem);
// makes join field lists
function ExtractJoinConditions(
AO1, AO2: TABSAO;
FieldList1, FieldList2: TABSFields
): Integer;
// create conditions for index scan
procedure TryCreateIndexScanConditionsFromNode(
Node: TABSExprNode;
IndexDefs: TABSIndexDefs;
ScanConditions: TABSScanSearchConditionArray;
SessionID: TABSSessionID);
// remove extracted nodes (they included in list, but list contains more)
procedure RemoveExtractedNodes(ScanConditions: TABSScanSearchConditionArray;
ScanConditionNo, ScanEndConditionNo: Integer);
// create conditions for index scan
procedure CreateIndexScanConditions(
IndexDefs: TABSIndexDefs;
ScanConditions: TABSScanSearchConditionArray;
SessionID: TABSSessionID);
// try to add conditions on another index fields
function ExtendMultiFieldIndexConditionFromNode(Node: TABSExprNode;
ScanCondition: TABSScanSearchCondition; IndexDef: TABSIndexDef): Boolean;
// try to add conditions on another index fields
function ExtendMultiFieldIndexCondition(ScanCondition: TABSScanSearchCondition;
IndexDef: TABSIndexDef): Boolean;
// add extracted node
procedure AddNode(Node: TABSExprNode);
// add and move nodes from another expression: self => (self AND Expr2)
procedure AddAndMoveNodesFromExpression(Expr: TABSExpression);
// check if agregate expr, const or only grouped fields are used
function CanBeUsedInGroupBy(GroupByFields: String): Boolean;
public
property InMemory: Boolean read FInMemory write FInMemory;
end;
TABSExprNode = class(TObject)
private
Children: TList; // Children nodes
Operator: TABSDataOperator; // '<', '>', AND, NOT, ...
Value: TABSVariant;
FCaseInsensitive: boolean;
FPartialKey: boolean;
private
// converts some WideStrings to Strings
procedure PatchWideStrings; virtual;
public
// constructors
constructor Create(
CaseInsensitive: boolean = true;
PartialKey: boolean = false
); overload;
constructor Create(
Op: TABSDataOperator;
CaseInsensitive: boolean = true;
PartialKey: boolean = false
); overload;
constructor Create(
Op: TABSDataOperator;
Node: TABSExprNode;
CaseInsensitive: boolean = true;
PartialKey: boolean = false
); overload;
constructor Create(
Op: TABSDataOperator;
Node1, Node2: TABSExprNode;
CaseInsensitive: boolean = true;
PartialKey: boolean = false
); overload;
constructor Create(
Op: TABSDataOperator;
Node1, Node2, Node3: TABSExprNode;
CaseInsensitive: boolean = true;
PartialKey: boolean = false
); overload;
// destroys
destructor Destroy; override;
// return Value
function GetDataValue: TABSVariant; virtual; abstract;
// calc subquery field values again
procedure ResetSubqueryFieldValues; virtual;
// Return subquery field value
function GetSubqueryFieldValue(FieldNo: Integer): TABSVariant; virtual;
// is expression contains aggregated function
function IsAggregated: Boolean; virtual;
function IsAggregatedCountAll: Boolean; virtual;
// Init for group function
procedure Init; virtual;
// Accumulate for group functions
procedure Accumulate; virtual;
procedure SetCountAll(RecordCount: Integer); virtual;
// process assign AO
procedure AssignAO(AO, ParentQueryAO: TABSAO; ParentCursor: TABSCursor); virtual;
// process assign Cursor
procedure AssignCursor(Cursor: TABSCursor; ParentQueryAO: TABSAO; ParentCursor: TABSCursor); virtual;
// process assign New Cursor Buffer
procedure AssignCursorBuffer(Buffer: TABSRecordBuffer; ApplyToParentQueryFields: Boolean); virtual;
// return Type of Data
function GetDataType: TABSAdvancedFieldType; virtual;
// return Size of Data (for strings and arrays)
function GetDataSize: Integer; virtual;
// return Data Precision
function GetPrecision: Integer; virtual;
// can be used by the AO?
function CanBeAssigned(AO, ParentQueryAO: TABSAO; ParentCursor: TABSCursor; ForHavingClause: Boolean = False): Boolean; virtual;
// node is field?
function CanUseNodeAsField(Node: TABSExprNode): Boolean;
// node is const or correlated field fomr parent query?
function CanUseNodeAsConst(Node: TABSExprNode): Boolean;
// can use index for comparison?
function CanUseIndex(IndexColumnNo: Integer; ConditionSearchOperator: TABSSearchCondition; IndexDef: TABSIndexDef; SessionID: TABSSessionID = INVALID_SESSION_ID): Boolean; virtual;
private
// fill scan condition props
procedure FillScanCondition(Value: TABSVariant;
Cursor: TABSCursor;
IndexColumnNo: Integer;
FieldNo: Integer;
IndexDef: TABSIndexDef;
Expression: TABSExpression;
ScanCondition: TABSScanSearchCondition);
public
// add index scan condition
procedure AddAsIndexScanCondition(
ScanConditions: TABSScanSearchConditionArray;
IndexDef: TABSIndexDef;
Expression: TABSExpression); virtual;
// add checks to multi-field index scan condition
procedure ExtendIndexScanCondition(
ScanCondition: TABSScanSearchCondition;
IndexDef: TABSIndexDef;
Expression: TABSExpression); virtual;
// is node a join condition?
function IsJoinCondition(AO1, AO2: TABSAO): Boolean; virtual;
// replace pseudonyms to original names (f1 -> table1.field1)
procedure ReplacePseudonyms(SelectList: array of TABSSelectListItem); virtual;
// check if agregate expr, const or only grouped fields are used
function CanBeUsedInGroupBy(GroupByFields: String): Boolean; virtual;
end;
TABSExprNodeConst = class(TABSExprNode)
public
// return Value
function GetDataValue: TABSVariant; override;
// return Type of Data
function GetDataType: TABSAdvancedFieldType; override;
// return Size of Data (for strings and arrays)
function GetDataSize: Integer; override;
function IsLikePatternEqualToPartialComparePattern: Boolean;
procedure TruncateForPartialCompare;
// can be used by the AO?
function CanBeAssigned(AO, ParentQueryAO: TABSAO; ParentCursor: TABSCursor; ForHavingClause: Boolean = False): Boolean; override;
function IsUpperCase: Boolean;
function IsLowerCase: Boolean;
end;
TABSExprNodeField = class(TABSExprNode)
private
LCursor: TABSCursor; // Cursor
LAO: TABSAO;
LRecordBuffer: PChar;
FTableName: string; // table name - Table1 (Table1.Field1)
FFieldName: string; // field name - Field1
FFieldNameInAO: string; // field name - could be like Field1_1
FFieldNo: Integer;
FFieldOffsetInBuffer: Integer;
FFieldType: TABSAdvancedFieldType;
FBaseFieldType: TABSBaseFieldType;
FFieldSize: Integer;
FFieldPrecision: Integer;
FGetFromParent: Boolean;
FScanOnlyVisibleFieldsInAO: Boolean;
public
constructor Create(Cursor: TABSCursor; FieldName: String; TableName: string = ''); overload;
// Return Data Value
function GetDataValue: TABSVariant; override;
// try to assign AO
function TryAssignAO(AOToAssign: TABSAO): Boolean;
// process assign AO
procedure AssignAO(AO, ParentQueryAO: TABSAO; ParentCursor: TABSCursor); override;
// find field No in cursor
function FindFieldInCursor(Cursor: TABSCursor; var FieldNo: Integer): Boolean;
// process assign Cursor and its buffer
procedure AssignCursor(Cursor: TABSCursor; ParentQueryAO: TABSAO; ParentCursor: TABSCursor); override;
// process assign New Cursor Buffer
procedure AssignCursorBuffer(Buffer: TABSRecordBuffer; ApplyToParentQueryFields: Boolean); override;
// return Type of Data
function GetDataType: TABSAdvancedFieldType; override;
// return Data Size
function GetDataSize: Integer; override;
// can be used by the AO?
function CanBeAssigned(AO, ParentQueryAO: TABSAO;
ParentCursor: TABSCursor; ForHavingClause: Boolean = False): Boolean; override;
// fills Field Item
procedure FillItem(var Item: TABSSelectListItem);
// replace pseudonyms to original names (f1 -> table1.field1)
procedure ReplacePseudonyms(SelectList: array of TABSSelectListItem); override;
// check if agregate expr, const or only grouped fields are used
function CanBeUsedInGroupBy(GroupByFields: String): Boolean; override;
public
property TableName: String read FTableName;
property FieldName: String read FFieldName;
property FieldNo: Integer read FFieldNo;
property FieldSize: Integer read FFieldSize;
property BaseFieldType: TABSBaseFieldType read FBaseFieldType;
end;
TABSExprNodeComparison = class(TABSExprNode)
private
F3ValueLogic: Boolean; // 3 Value Logic (TRUE, FALSE, NULL)
FQuantifier: TABSQuantifier;
private
procedure PatchWideStrings; override;
// x > y
function GetDataValueByCompare: TABSVariant;
// x > all (select ...)
function GetDataValueByQuantifiedCompare: TABSVariant;
public
// Constructor
constructor Create(
Op: TABSDataOperator;
Node1, Node2: TABSExprNode;
TrueFalseNullLogic: boolean = true;
CaseInsensitive: boolean = true;
PartialKey: boolean = false
); overload;
// Constructor
constructor Create(
Op: TABSDataOperator;
Quantifier: TABSQuantifier;
Node1, Node2: TABSExprNode;
TrueFalseNullLogic: boolean = true;
CaseInsensitive: boolean = true;
PartialKey: boolean = false
); overload;
// Return Data Value
function GetDataValue: TABSVariant; override;
procedure GetFieldAndConstNodes(var FieldNode: TABSExprNodeField; var ConstNode: TABSExprNodeConst);
// can use index for comparison?
function CanUseIndex(IndexColumnNo: Integer; ConditionSearchOperator: TABSSearchCondition; IndexDef: TABSIndexDef; SessionID: TABSSessionID = INVALID_SESSION_ID): Boolean; override;
// add index scan condition
procedure AddAsIndexScanCondition(
ScanConditions: TABSScanSearchConditionArray;
IndexDef: TABSIndexDef;
Expression: TABSExpression); override;
// add checks to multi-field index scan condition
procedure ExtendIndexScanCondition(
ScanCondition: TABSScanSearchCondition;
IndexDef: TABSIndexDef;
Expression: TABSExpression); override;
// is node a join condition?
function IsJoinCondition(AO1, AO2: TABSAO): Boolean; override;
end;
TABSExprNodeBoolean = class(TABSExprNode)
private
TempVal: TABSVariant;
EscapeStr: String;
private
// process a Like b
procedure Like;
// process IN (SELECT ...)
procedure bInSubquery;
// process IN (...)
procedure bIn;
// process A BETWEEN B AND C
procedure Between;
// process EXISTS
procedure Exists;
public
constructor Create(
CaseInsensitive: boolean = true;
PartialKey: boolean = false
); overload;
constructor Create(
Op: TABSDataOperator;
CaseInsensitive: boolean = true;
PartialKey: boolean = false;
aEscapeStr: String=''
); overload;
constructor Create(
Op: TABSDataOperator;
Node: TABSExprNode;
CaseInsensitive: boolean = true;
PartialKey: boolean = false
); overload;
constructor Create(
Op: TABSDataOperator;
Node1, Node2: TABSExprNode;
CaseInsensitive: boolean = true;
PartialKey: boolean = false
); overload;
constructor Create(
Op: TABSDataOperator;
Node1, Node2, Node3: TABSExprNode;
CaseInsensitive: boolean = true;
PartialKey: boolean = false
); overload;
destructor Destroy; override;
// Return Data Value
function GetDataValue: TABSVariant; override;
// can use index for comparison?
function CanUseIndex(ColumnNo: Integer; ConditionSearchOperator: TABSSearchCondition;
IndexDef: TABSIndexDef; SessionID: TABSSessionID = INVALID_SESSION_ID): Boolean; override;
// add index scan condition
procedure AddAsIndexScanCondition(
ScanConditions: TABSScanSearchConditionArray;
IndexDef: TABSIndexDef;
Expression: TABSExpression); override;
// add checks to multi-field index scan condition
procedure ExtendIndexScanCondition(
ScanCondition: TABSScanSearchCondition;
IndexDef: TABSIndexDef;
Expression: TABSExpression); override;
end;
TABSExprNodeArithmetic = class(TABSExprNode)
protected
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -