/*++ Copyright (C) 1997-2001 Microsoft Corporation Module Name: WQLNODE.H Abstract: WQL Parse Node Definitions History: raymcc 29-Sep-97 Created --*/ #ifndef _WQLNODE_H_ #define _WQLNODE_H_ #define WQL_FLAG_ALIAS 0x1 #define WQL_FLAG_TABLE 0x2 #define WQL_FLAG_ASTERISK 0x4 #define WQL_FLAG_DISTINCT 0x8 #define WQL_FLAG_ALL 0x10 #define WQL_FLAG_COUNT 0x20 #define WQL_FLAG_CONST 0x40 #define WQL_FLAG_COLUMN 0x80 #define WQL_FLAG_COMPLEX_NAME 0x100 #define WQL_FLAG_FUNCTIONIZED 0x200 #define WQL_FLAG_ARRAY_REF 0x400 #define WQL_FLAG_UPPER 0x800 #define WQL_FLAG_LOWER 0x1000 #define WQL_FLAG_FIRSTROW 0x2000 #define WQL_FLAG_CONST_RANGE 0x4000 #define WQL_FLAG_SORT_ASC 0x8000 #define WQL_FLAG_SORT_DESC 0x10000 #define WQL_FLAG_AGGREGATE 0x20000 #define WQL_FLAG_NULL 0x40000 #define WQL_FLAG_INNER_JOIN 1 #define WQL_FLAG_LEFT_OUTER_JOIN 2 #define WQL_FLAG_RIGHT_OUTER_JOIN 3 #define WQL_FLAG_FULL_OUTER_JOIN 4 //*************************************************************************** // // SWQLNode // // Base node type for all parser output. // //*************************************************************************** struct SWQLNode { DWORD m_dwNodeType; SWQLNode *m_pLeft; SWQLNode *m_pRight; SWQLNode() { m_pLeft = 0; m_pRight = 0; m_dwNodeType = 0; } virtual ~SWQLNode() { delete m_pLeft; delete m_pRight; } virtual void DebugDump() = 0; }; //*************************************************************************** // // SWQLTypedConst // // Typed constant container (similar to OA VARIANT). // //*************************************************************************** union UWQLTypedConst { LPWSTR m_pString; // VT_LPWSTR for WQL_TOK_QSTRING and WQL_TOK_PROMPT LONG m_lValue; // VT_LONG double m_dblValue; // VT_DOUBLE BOOL m_bValue; // VT_BOOL, use TRUE/FALSE (not VARIANT_TRUE, VARIANT_FALSE) }; struct SWQLTypedConst { DWORD m_dwType; // A VT_ type UWQLTypedConst m_Value; // One of the union fields bool m_bPrompt; // Only true if token was WQL_TOK_PROMPT SWQLTypedConst(); SWQLTypedConst(SWQLTypedConst &Src) { m_dwType = VT_NULL; *this = Src; } SWQLTypedConst & operator = (SWQLTypedConst &Src); ~SWQLTypedConst() { Empty(); } void Empty(); void DebugDump(); }; struct SWQLConstList { CFlexArray m_aValues; // ptrs to SWQLTypedConst SWQLConstList() {} SWQLConstList(SWQLConstList &Src) { *this = Src; } SWQLConstList & operator = (SWQLConstList & Src); ~SWQLConstList() { Empty(); } void Add(SWQLTypedConst *pTC) { m_aValues.Add(pTC); } void Empty(); }; struct SWQLQualifiedNameField { LPWSTR m_pName; // Name BOOL m_bArrayRef; // TRUE if this is an array reference DWORD m_dwArrayIndex; // If this is the array index SWQLQualifiedNameField() { m_pName = 0; m_bArrayRef = 0; m_dwArrayIndex = 0; } SWQLQualifiedNameField(SWQLQualifiedNameField &Src) { m_pName = 0; *this = Src; } SWQLQualifiedNameField & operator = (SWQLQualifiedNameField &Src); ~SWQLQualifiedNameField() { Empty(); } void Empty() { delete [] m_pName; } }; struct SWQLQualifiedName { CFlexArray m_aFields; // [0] = left most, last entry is column SWQLQualifiedName() {} SWQLQualifiedName(SWQLQualifiedName &Src) { *this = Src; } SWQLQualifiedName & operator = (SWQLQualifiedName &Src); ~SWQLQualifiedName() { Empty(); } int GetNumNames() { return m_aFields.Size(); } const LPWSTR GetName(int nIndex) { return (LPWSTR) ((SWQLQualifiedNameField*) m_aFields[nIndex])->m_pName; } int Add(SWQLQualifiedNameField *pQN) { return m_aFields.Add(pQN); } void Empty(); }; #define WQL_TOK_BASE 100 //*************************************************************************** // // SWQLNode_Select // // This is the root of the parse tree or the root of a subselect. // // SWQLNode_Select // / \ // SWQLNode_TableRefs SWQLNode_WhereClause // / \ / \ // x x x x // //*************************************************************************** #define TYPE_SWQLNode_Select (WQL_TOK_BASE + 1) struct SWQLNode_Select : SWQLNode { // Left Node is of type SWQLNode_TableRefs // Right Node is of type SWQLNode_WhereClause int m_nStPos; int m_nEndPos; SWQLNode_Select() : m_nStPos(-1), m_nEndPos(-1) { m_dwNodeType = TYPE_SWQLNode_Select; } void DebugDump(); }; //*************************************************************************** // // SWQLNode_TableRefs // // This contains everything prior to the WHERE clause: the target // column list and the FROM clause. // // Also contains the SELECT type, i.e., ALL vs. DISTINCT vs. COUNT. // // SWQLNode_TableRefs // / \ // SWQLNode_ColumnList SWQLNode_FromClause // // In all cases, SWQLNode_ColumnList is present. Note that if the // user did a "select *...", then the SWQLNode_ColumnList will only // have a single column in it clearly marked as an asterisk. If // a "select count(...) " was done, then m_nSelectType is set to // WQL_FLAG_COUNT and the SWQLNode_ColumnList will have a single // column in it, whether an * or a qualified name. // //*************************************************************************** #define TYPE_SWQLNode_TableRefs (WQL_TOK_BASE + 2) struct SWQLNode_TableRefs : SWQLNode { // Left Node is SWQLNode_ColumnList // Right Node is SWQLNode_FromClause int m_nSelectType; // WQL_FLAG_ALL means ALL was used. // WQL_FLAG_DISTINCT means DISTINCT was used. // WQL_FLAG_COUNT means COUNT was used. SWQLNode_TableRefs() { m_nSelectType = WQL_FLAG_ALL; m_dwNodeType = TYPE_SWQLNode_TableRefs; } ~SWQLNode_TableRefs() {} void DebugDump(); }; //*************************************************************************** // // SWQLNode_ColumnList // // This contains the selected list of columns. // // SWQLNode_ColumnList // / \ // NULL NULL // //*************************************************************************** #define TYPE_SWQLNode_ColumnList (WQL_TOK_BASE + 3) struct SWQLNode_ColumnList : SWQLNode { // Left Node is NULL // Right Node is NULL CFlexArray m_aColumnRefs ; // Pointers to SWQLColRef entries. SWQLNode_ColumnList() { m_dwNodeType = TYPE_SWQLNode_ColumnList; } ~SWQLNode_ColumnList() { Empty(); } void Empty(); void DebugDump(); }; struct SWQLColRef { LPWSTR m_pColName; // The column name or "*" or NULL LPWSTR m_pTableRef; // The table/alias name or NULL if there is none DWORD m_dwArrayIndex; DWORD m_dwFlags; // WQL_FLAG_TABLE bit set if m_pTableRef // is a table name // WQL_FLAG_ALIAS bit set if m_pTableRef // is a table alias // WQL_FLAG_ASTERISK bit set if m_pColName is // * (this is faster than to check than a // string compare on for "*". // WQL_FLAG_NULL if the column name was "NULL" // WQL_FLAG_FUNCTIONIZED is set if the column // is wrapped in a function call. // The function bits WQL_FLAG_UPPER or // WQL_FLAG_LOWER will be set. // WQL_FLAG_ARRAY_REF is set if the column // is an array column, in which case // m_dwArrayIndex is set to the array offset. // WQL_FLAG_COMPLEX_NAME is set if the name // is qualified in a deeply nested way, // which requires examination of the // object. In this case is // set to the last name, but m_pTableRef // is left blank. // WQL_FLAG_SORT_ASC to sort ascending (Order by only) // WQL_FLAG_SORT_DESC to sort descending (Order by only) SWQLQualifiedName *m_pQName; // The full qualified name SWQLColRef() { m_pColName = NULL; m_pTableRef = 0; m_dwFlags = 0; m_dwArrayIndex = 0; m_pQName = 0; } ~SWQLColRef() { delete [] m_pColName; delete [] m_pTableRef; delete m_pQName; } void DebugDump(); }; //*************************************************************************** // // SWQLNode_FromClause // // The subtree containing the tables selected from and any joins. // // SWQLNode_FromClause // / \ // SWQLNode_TableRef NULL // or SWQLNode_Join // or SWQLNode_Sql89Join // //*************************************************************************** #define TYPE_SWQLNode_FromClause (WQL_TOK_BASE + 4) struct SWQLNode_FromClause : SWQLNode { // Left is SWQLNode_TableRef or SWQLNode_Join // Right is NULL SWQLNode_FromClause() { m_dwNodeType = TYPE_SWQLNode_FromClause; } ~SWQLNode_FromClause() {} void DebugDump(); }; //*************************************************************************** // // SWQLNode_Sql89Join // // A subtree which expresses a SQL-89 join. // // SWQLNode_Sql89Join // / \ // NULL NULL // //*************************************************************************** #define TYPE_SWQLNode_Sql89Join (WQL_TOK_BASE + 5) struct SWQLNode_Sql89Join : SWQLNode { CFlexArray m_aValues; // Array of pointers to SWQLNode_TableRef // objects SWQLNode_Sql89Join() { m_dwNodeType = TYPE_SWQLNode_Sql89Join; } ~SWQLNode_Sql89Join() {Empty();}; void DebugDump(); void Empty(); }; //*************************************************************************** // // SWQLNode_Join // // A subtree which expresses a join. // // SWQLNode_Join // / \ // SWQLNode_JoinPair SWQLNode_OnClause or NULL. // //*************************************************************************** #define TYPE_SWQLNode_Join (WQL_TOK_BASE + 6) struct SWQLNode_Join : SWQLNode { // Left ptr is SWQLNode_JoinPair // Right ptr is ON clause. If NULL, there is no ON clause // and the JOIN was a SQL-89 style join with the join condition // present in the WHERE clause. DWORD m_dwJoinType; // One of WQL_FLAG_INNER_JOIN, WQL_FLAG_LEFT_OUTER_JOIN, // WQL_FLAG_RIGHT_OUTER_JOIN or WQL_FLAG_FULL_OUTER_JOIN DWORD m_dwFlags; // Contains WQL_FLAG_FIRSTROW if used SWQLNode_Join() { m_dwNodeType = TYPE_SWQLNode_Join; m_dwJoinType = m_dwFlags = 0; } ~SWQLNode_Join() {} void DebugDump(); }; //*************************************************************************** // // SWQLNode_JoinPair // // SWQLNode_JoinPair // / \ // // //*************************************************************************** #define TYPE_SWQLNode_JoinPair (WQL_TOK_BASE + 7) struct SWQLNode_JoinPair : SWQLNode { // Left ptr is SWQLNode_Join or SWQLNode_TableRef // Right ptr is SWQLNodeNode_Join or SWQL_NodeTableRef SWQLNode_JoinPair() { m_dwNodeType = TYPE_SWQLNode_JoinPair; } ~SWQLNode_JoinPair() {} void DebugDump(); }; //*************************************************************************** // // SWQLNode_TableRef // // A node representing a table name and its alias, if any. // // SWQLNode_TableRef // / \ // NULL NULL // //*************************************************************************** #define TYPE_SWQLNode_TableRef (WQL_TOK_BASE + 8) struct SWQLNode_TableRef : SWQLNode { LPWSTR m_pTableName; // The table LPWSTR m_pAlias; // Table alias. NULL if not used. SWQLNode_TableRef() { m_pTableName = 0; m_pAlias = 0; m_dwNodeType = TYPE_SWQLNode_TableRef; } ~SWQLNode_TableRef() { delete [] m_pTableName; delete [] m_pAlias; } void DebugDump(); }; //*************************************************************************** // // SWQLNode_OnClause // // SWQLNode_OnClause // / \ // NULL // //*************************************************************************** #define TYPE_SWQLNode_OnClause (WQL_TOK_BASE + 9) struct SWQLNode_OnClause : SWQLNode { // Left ptr is which contains the ON clause. // Right ptr is always NULL. SWQLNode_OnClause() { m_dwNodeType = TYPE_SWQLNode_OnClause; } ~SWQLNode_OnClause() {} void DebugDump(); }; //*************************************************************************** // // SWQLNode_WhereClause // // SWQLNode_WhereClause // / \ // SWQLNode_RelExpr SWQLNode_WhereOptions or NULL // or // NULL if no conditions // //*************************************************************************** #define TYPE_SWQLNode_WhereClause (WQL_TOK_BASE + 10) struct SWQLNode_WhereClause : SWQLNode { // Left ptr is SWQLNode_RelExpr. // Right ptr is SQLNode_QueryOptions or NULL if none SWQLNode_WhereClause() { m_dwNodeType = TYPE_SWQLNode_WhereClause; } ~SWQLNode_WhereClause() {} void DebugDump(); }; //*************************************************************************** // // struct SWQLTypedExpr // // This represents a typed subexpression in a where clause: // // mycol < 2 // 33 <= tbl1.col2 // tbl3.col4 = tbl4.col5 // ...etc. // //*************************************************************************** struct SWQLTypedExpr { LPWSTR m_pTableRef; // For qualified column names, // NULL if not used LPWSTR m_pColRef; // Column name DWORD m_dwRelOperator; // The operator used: WQL_TOK_LE, // WQL_TOK_GE, WQL_TOK_LIKE etc. // WQL_TOK_IN_CONST_LIST // WQL_TOK_NOT_IN_CONST_LIST // WQL_TOK_IN_SUBSELECT // WQL_TOK_NOT_IN_SUBSELECT SWQLTypedConst *m_pConstValue; // A const value SWQLTypedConst *m_pConstValue2; // The other const value used with BETWEEN LPWSTR m_pJoinTableRef; // The joined table name or its alias, // NULL if not used LPWSTR m_pJoinColRef; // The joined column name LPWSTR m_pIntrinsicFuncOnColRef; LPWSTR m_pIntrinsicFuncOnJoinColRef; LPWSTR m_pIntrinsicFuncOnConstValue; SWQLNode *m_pLeftFunction; // More detail for DATEPART, etc. SWQLNode *m_pRightFunction; // More detail for DATEPART, etc. DWORD m_dwLeftArrayIndex; DWORD m_dwRightArrayIndex; SWQLQualifiedName *m_pQNRight; SWQLQualifiedName *m_pQNLeft; DWORD m_dwLeftFlags; DWORD m_dwRightFlags; // Each of the above to Flags shows the expression layout on each side // of the operator. // WQL_FLAG_CONST = A typed constant was used // WQL_FLAG_COLUMN = Column field was used // WQL_FLAG_TABLE = Table/Alias was used // WQL_FLAG_COMPLEX = Complex qualified name and/or array was used // WQL_FLAG_FUNCTIONIZED = Function was applied over the const or col. // For IN and NOT IN clauses. // ========================== SWQLNode *m_pSubSelect; SWQLConstList *m_pConstList; // For IN clause with constant-list /* (1) If a const is tested against a column, then will be used to represent it, and the table+col referenced will be in and . (2) If a join occurs, then will be NULL. (3) Intrinsic functions (primarily UPPER() and LOWER()) can be applied to the column references or the constant. The function names will be placed in the pointers when applied. (4) If is WQL_TOK_IN_CONST_LIST or WQL_TOK_NOT_IN_CONST_LIST then is an array of pointers to SWQLTypedConst structs representing the set of constants that the referenced column must intersect with. (5) If is WQL_TOK_IN_SUBSELECT or WQL_TOK_NOT_IN_SUBSELECT then m_pSubSelect is a pointer to an embedded subselect tree in the form of a SWQLNode_Select struct, beginning the root of an entirely new select statement. */ SWQLTypedExpr(); ~SWQLTypedExpr() { Empty(); } void DebugDump(); void Empty(); }; //*************************************************************************** // // SWQLNode_RelExpr // // SWQLNode_RelExpr // / \ // SWQLNode_RelExpr SWQLNode_RelExpr // or NULL or NULL // //*************************************************************************** #define TYPE_SWQLNode_RelExpr (WQL_TOK_BASE + 11) struct SWQLNode_RelExpr : SWQLNode { DWORD m_dwExprType; // WQL_TOK_OR // WQL_TOK_AND // WQL_TOK_NOT // WQL_TOK_TYPED_EXPR SWQLTypedExpr *m_pTypedExpr; /* (1) If the is WQL_TOK_AND or WQL_TOK_OR, then each of the two subnodes are themselves SWQLNode_RelExpr nodes and points to NULL. (2) If is WQL_TOK_NOT, then points to a SWQLNode_RelExpr containing the subclause to which to apply the NOT operation and points to NULL. (3) If is WQL_TOK_TYPED_EXPR, then and both point to NULL, and contains a typed relational subexpression. (4) Parentheses have been removed and are implied by the nesting. */ SWQLNode_RelExpr() { m_dwNodeType = TYPE_SWQLNode_RelExpr; m_pTypedExpr = 0; m_dwExprType = 0; } ~SWQLNode_RelExpr() { delete m_pTypedExpr; } void DebugDump(); }; //*************************************************************************** // // SWQLNode_WhereOptions // // SWQLNode_WhereOptions // / \ // SWQLNode_GroupBy SWQLNode_OrderBy // //*************************************************************************** #define TYPE_SWQLNode_WhereOptions (WQL_TOK_BASE + 12) struct SWQLNode_WhereOptions : SWQLNode { // left ptr is SWQLNode_GroupBy, or NULL if not used // right ptr is SWQLNode_OrderBy, or NULL if not used SWQLNode_WhereOptions() { m_dwNodeType = TYPE_SWQLNode_WhereOptions; } void DebugDump(); }; //*************************************************************************** // // SWQLNode_GroupBy // // SWQLNode_GroupBy // / \ // SWQLNode_ColumnList SWQLNode_Having // or NULL // //*************************************************************************** #define TYPE_SWQLNode_GroupBy (WQL_TOK_BASE + 13) struct SWQLNode_GroupBy : SWQLNode { // left ptr is SWQLNode_ColumnList of columns to group by // right ptr is Having clause, if any SWQLNode_GroupBy() { m_dwNodeType = TYPE_SWQLNode_GroupBy; } void DebugDump(); }; //*************************************************************************** // // SWQLNode_Having // // SWQLNode_Having // / \ // SWQLNode_RelExpr NULL // //*************************************************************************** #define TYPE_SWQLNode_Having (WQL_TOK_BASE + 14) struct SWQLNode_Having : SWQLNode { // left ptr is SQLNode_RelExpr pointing to HAVING expressions // right ptr is NULL SWQLNode_Having() { m_dwNodeType = TYPE_SWQLNode_Having; } void DebugDump(); }; //*************************************************************************** // // SWQLNode_OrderBy // // SWQLNode_OrderBy // / \ // SWQLNode_ColumnList NULL // //*************************************************************************** #define TYPE_SWQLNode_OrderBy (WQL_TOK_BASE + 15) struct SWQLNode_OrderBy : SWQLNode { // left ptr is SWQLNode_ColumnList // right ptr is NULL SWQLNode_OrderBy() { m_dwNodeType = TYPE_SWQLNode_OrderBy; } void DebugDump(); }; //*************************************************************************** // // SWQLNode_Datepart // // Contains a datepart call. // //*************************************************************************** #define TYPE_SWQLNode_Datepart (WQL_TOK_BASE + 16) struct SWQLNode_Datepart : SWQLNode { int m_nDatepart; // One of WQL_TOK_YEAR, WQL_TOK_MONTH, // WQL_TOK_DAY, WQL_TOK_HOUR, WQL_TOK_MINUTE // WQL_TOK_SECOND SWQLColRef *m_pColRef; // The column to which DATEPART applies SWQLNode_Datepart() { m_dwNodeType = TYPE_SWQLNode_Datepart; m_nDatepart = 0; } ~SWQLNode_Datepart() { delete m_pColRef; } void DebugDump(); }; #endif