support having
This commit is contained in:
		
							parent
							
								
									20e7ae2ce9
								
							
						
					
					
						commit
						d65b541bbf
					
				| 
						 | 
					@ -121,6 +121,7 @@ typedef struct SInternalField {
 | 
				
			||||||
  bool            visible;
 | 
					  bool            visible;
 | 
				
			||||||
  SExprInfo      *pArithExprInfo;
 | 
					  SExprInfo      *pArithExprInfo;
 | 
				
			||||||
  SSqlExpr       *pSqlExpr;
 | 
					  SSqlExpr       *pSqlExpr;
 | 
				
			||||||
 | 
					  SColumn        *pFieldFilters;
 | 
				
			||||||
} SInternalField;
 | 
					} SInternalField;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct SFieldInfo {
 | 
					typedef struct SFieldInfo {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1031,6 +1031,41 @@ static bool validateTableColumnInfo(SArray* pFieldList, SSqlCmd* pCmd) {
 | 
				
			||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void exchangeExpr(tSQLExpr* pExpr) {
 | 
				
			||||||
 | 
					  tSQLExpr* pLeft = pExpr->pLeft;
 | 
				
			||||||
 | 
					  tSQLExpr* pRight = pExpr->pRight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((pRight->nSQLOptr == TK_ID || (pRight->nSQLOptr >= TK_COUNT && pRight->nSQLOptr <= TK_AVG_IRATE)) && 
 | 
				
			||||||
 | 
					     (pLeft->nSQLOptr == TK_INTEGER || pLeft->nSQLOptr == TK_FLOAT || pLeft->nSQLOptr == TK_STRING || pLeft->nSQLOptr == TK_BOOL)) {
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * exchange value of the left handside and the value of the right-handside
 | 
				
			||||||
 | 
					     * to make sure that the value of filter expression always locates in
 | 
				
			||||||
 | 
					     * right-handside and
 | 
				
			||||||
 | 
					     * the column-id/function is at the left handside.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    uint32_t optr = 0;
 | 
				
			||||||
 | 
					    switch (pExpr->nSQLOptr) {
 | 
				
			||||||
 | 
					      case TK_LE:
 | 
				
			||||||
 | 
					        optr = TK_GE;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case TK_LT:
 | 
				
			||||||
 | 
					        optr = TK_GT;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case TK_GT:
 | 
				
			||||||
 | 
					        optr = TK_LT;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case TK_GE:
 | 
				
			||||||
 | 
					        optr = TK_LE;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        optr = pExpr->nSQLOptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pExpr->nSQLOptr = optr;
 | 
				
			||||||
 | 
					    SWAP(pExpr->pLeft, pExpr->pRight, void*);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pCmd) {
 | 
					static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pCmd) {
 | 
				
			||||||
  assert(pTagsList != NULL);
 | 
					  assert(pTagsList != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3062,6 +3097,214 @@ int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, SArray* pList, SSqlCmd* pCmd)
 | 
				
			||||||
  return TSDB_CODE_SUCCESS;
 | 
					  return TSDB_CODE_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int32_t handleExprInHavingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SColumnIndex* pIndex, tSQLExpr* pExpr, int32_t sqlOptr) {
 | 
				
			||||||
 | 
					  STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, pIndex->tableIndex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
 | 
				
			||||||
 | 
					  SSchema*    pSchema = tscGetTableColumnSchema(pTableMeta, pIndex->columnIndex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const char* msg1 = "non binary column not support like operator";
 | 
				
			||||||
 | 
					  const char* msg2 = "binary column not support this operator";  
 | 
				
			||||||
 | 
					  const char* msg3 = "bool column not support this operator";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SColumn* pColumn = tscColumnListInsert(pQueryInfo->colList, pIndex);
 | 
				
			||||||
 | 
					  SColumnFilterInfo* pColFilter = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*
 | 
				
			||||||
 | 
					   * in case of TK_AND filter condition, we first find the corresponding column and build the query condition together
 | 
				
			||||||
 | 
					   * the already existed condition.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  if (sqlOptr == TK_AND) {
 | 
				
			||||||
 | 
					    // this is a new filter condition on this column
 | 
				
			||||||
 | 
					    if (pColumn->numOfFilters == 0) {
 | 
				
			||||||
 | 
					      pColFilter = addColumnFilterInfo(pColumn);
 | 
				
			||||||
 | 
					    } else {  // update the existed column filter information, find the filter info here
 | 
				
			||||||
 | 
					      pColFilter = &pColumn->filterInfo[0];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (pColFilter == NULL) {
 | 
				
			||||||
 | 
					      return TSDB_CODE_TSC_OUT_OF_MEMORY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else if (sqlOptr == TK_OR) {
 | 
				
			||||||
 | 
					    // TODO fixme: failed to invalid the filter expression: "col1 = 1 OR col2 = 2"
 | 
				
			||||||
 | 
					    pColFilter = addColumnFilterInfo(pColumn);
 | 
				
			||||||
 | 
					    if (pColFilter == NULL) {
 | 
				
			||||||
 | 
					      return TSDB_CODE_TSC_OUT_OF_MEMORY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else {  // error;
 | 
				
			||||||
 | 
					    return TSDB_CODE_TSC_INVALID_SQL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pColFilter->filterstr =
 | 
				
			||||||
 | 
					      ((pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) ? 1 : 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (pColFilter->filterstr) {
 | 
				
			||||||
 | 
					    if (pExpr->nSQLOptr != TK_EQ
 | 
				
			||||||
 | 
					      && pExpr->nSQLOptr != TK_NE
 | 
				
			||||||
 | 
					      && pExpr->nSQLOptr != TK_ISNULL
 | 
				
			||||||
 | 
					      && pExpr->nSQLOptr != TK_NOTNULL
 | 
				
			||||||
 | 
					      && pExpr->nSQLOptr != TK_LIKE
 | 
				
			||||||
 | 
					      ) {
 | 
				
			||||||
 | 
					      return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    if (pExpr->nSQLOptr == TK_LIKE) {
 | 
				
			||||||
 | 
					      return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (pSchema->type == TSDB_DATA_TYPE_BOOL) {
 | 
				
			||||||
 | 
					      if (pExpr->nSQLOptr != TK_EQ && pExpr->nSQLOptr != TK_NE) {
 | 
				
			||||||
 | 
					        return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pColumn->colIndex = *pIndex;
 | 
				
			||||||
 | 
					  return doExtractColumnFilterInfo(pCmd, pQueryInfo, pColFilter, pIndex, pExpr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int32_t getHavingExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr** pExpr, int32_t parentOptr) {
 | 
				
			||||||
 | 
					  if (pExpr == NULL || (*pExpr) == NULL) {
 | 
				
			||||||
 | 
					    return TSDB_CODE_SUCCESS;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const char* msg1 = "invalid having clause";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  tSQLExpr* pLeft = (*pExpr)->pLeft;
 | 
				
			||||||
 | 
					  tSQLExpr* pRight = (*pExpr)->pRight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((*pExpr)->nSQLOptr == TK_AND || (*pExpr)->nSQLOptr == TK_OR) {
 | 
				
			||||||
 | 
					    int32_t ret = getHavingExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, (*pExpr)->nSQLOptr);
 | 
				
			||||||
 | 
					    if (ret != TSDB_CODE_SUCCESS) {
 | 
				
			||||||
 | 
					      return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return getHavingExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, (*pExpr)->nSQLOptr);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((pLeft->nSQLOptr >= TK_COUNT && pLeft->nSQLOptr <= TK_AVG_IRATE) && 
 | 
				
			||||||
 | 
					    (pRight->nSQLOptr >= TK_COUNT && pRight->nSQLOptr <= TK_AVG_IRATE)) {
 | 
				
			||||||
 | 
					    return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (pLeft->nSQLOptr >= TK_BOOL
 | 
				
			||||||
 | 
					    && pLeft->nSQLOptr <= TK_BINARY
 | 
				
			||||||
 | 
					    && pRight->nSQLOptr >= TK_BOOL
 | 
				
			||||||
 | 
					    && pRight->nSQLOptr <= TK_BINARY) {
 | 
				
			||||||
 | 
					    return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  exchangeExpr(*pExpr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pLeft = (*pExpr)->pLeft;
 | 
				
			||||||
 | 
					  pRight = (*pExpr)->pRight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!(pLeft->nSQLOptr >= TK_COUNT && pLeft->nSQLOptr <= TK_AVG_IRATE)) {
 | 
				
			||||||
 | 
					    return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!(pRight->nSQLOptr >= TK_BOOL && pRight->nSQLOptr <= TK_BINARY)) {
 | 
				
			||||||
 | 
					    return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((*pExpr)->nSQLOptr >= TK_BITAND) {
 | 
				
			||||||
 | 
					    return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (pLeft->pParam == NULL || pLeft->pParam->nExpr < 1) {
 | 
				
			||||||
 | 
					    return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (int32_t i = 0; i < pLeft->pParam->nExpr; i++) {
 | 
				
			||||||
 | 
					    tSqlExprItem* pParamElem = &(pLeft->pParam->a[i]);
 | 
				
			||||||
 | 
					    if (pParamElem->pNode->nSQLOptr != TK_ALL && pParamElem->pNode->nSQLOptr != TK_ID) {
 | 
				
			||||||
 | 
					      return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    SColumnIndex index = COLUMN_INDEX_INITIALIZER;
 | 
				
			||||||
 | 
					    if ((getColumnIndexByName(pCmd, &pParamElem->pNode->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS)) {
 | 
				
			||||||
 | 
					      return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
 | 
				
			||||||
 | 
					    STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (index.columnIndex <= 0 || 
 | 
				
			||||||
 | 
					      index.columnIndex >= tscGetNumOfColumns(pTableMeta)) {
 | 
				
			||||||
 | 
					      return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  tSqlExprItem item = {.pNode = pLeft, .aliasName = NULL, .distinct = false};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int32_t outputIndex = (int32_t)tscSqlExprNumOfExprs(pQueryInfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // ADD TRUE FOR TEST
 | 
				
			||||||
 | 
					  if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, &item, true) != TSDB_CODE_SUCCESS) {
 | 
				
			||||||
 | 
					    return TSDB_CODE_TSC_INVALID_SQL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int32_t slot = tscNumOfFields(pQueryInfo) - 1;
 | 
				
			||||||
 | 
					  SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, slot);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (pInfo->pFieldFilters == NULL) {
 | 
				
			||||||
 | 
					    SColumn* pFieldFilters = calloc(1, sizeof(SColumn));
 | 
				
			||||||
 | 
					    if (pFieldFilters == NULL) {
 | 
				
			||||||
 | 
					      return TSDB_CODE_TSC_OUT_OF_MEMORY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    pInfo->pFieldFilters = pFieldFilters;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return handleExprInHavingClause(pCmd, pQueryInfo, pInfo->pFieldFilters, pExpr, parentOptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int32_t parseHavingClause(SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SSqlCmd* pCmd) {
 | 
				
			||||||
 | 
					  const char* msg1 = "having only works with group by";
 | 
				
			||||||
 | 
					  //const char* msg2 = "invalid column name in having clause";
 | 
				
			||||||
 | 
					  //const char* msg3 = "columns from one table allowed as having columns";
 | 
				
			||||||
 | 
					  //const char* msg4 = "no tag allowed in having clause";
 | 
				
			||||||
 | 
					  const char* msg5 = "invalid expression in having clause";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*  
 | 
				
			||||||
 | 
					  const char* msg1 = "too many columns in group by clause";
 | 
				
			||||||
 | 
					  const char* msg4 = "join query does not support group by";
 | 
				
			||||||
 | 
					  const char* msg7 = "not support group by expression";
 | 
				
			||||||
 | 
					  const char* msg8 = "not allowed column type for group by";
 | 
				
			||||||
 | 
					  const char* msg9 = "tags not allowed for table query";
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // todo : handle two tables situation
 | 
				
			||||||
 | 
					  //STableMetaInfo* pTableMetaInfo = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (pExpr == NULL || (*pExpr) == NULL) {
 | 
				
			||||||
 | 
					    return TSDB_CODE_SUCCESS;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (pQueryInfo->groupbyExpr.numOfGroupCols <= 0) {
 | 
				
			||||||
 | 
					    return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((*pExpr)->pLeft == NULL || (*pExpr)->pRight == NULL) {
 | 
				
			||||||
 | 
					    return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (pQueryInfo->colList == NULL) {
 | 
				
			||||||
 | 
					    pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int32_t ret = 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ((ret = getHavingExpr(pCmd, pQueryInfo, pExpr, TK_AND)) != TSDB_CODE_SUCCESS) {
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return TSDB_CODE_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static SColumnFilterInfo* addColumnFilterInfo(SColumn* pColumn) {
 | 
					static SColumnFilterInfo* addColumnFilterInfo(SColumn* pColumn) {
 | 
				
			||||||
  if (pColumn == NULL) {
 | 
					  if (pColumn == NULL) {
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
| 
						 | 
					@ -3715,40 +3958,7 @@ static bool isValidExpr(tSQLExpr* pLeft, tSQLExpr* pRight, int32_t optr) {
 | 
				
			||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void exchangeExpr(tSQLExpr* pExpr) {
 | 
					 | 
				
			||||||
  tSQLExpr* pLeft = pExpr->pLeft;
 | 
					 | 
				
			||||||
  tSQLExpr* pRight = pExpr->pRight;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (pRight->nSQLOptr == TK_ID && (pLeft->nSQLOptr == TK_INTEGER || pLeft->nSQLOptr == TK_FLOAT ||
 | 
					 | 
				
			||||||
                                    pLeft->nSQLOptr == TK_STRING || pLeft->nSQLOptr == TK_BOOL)) {
 | 
					 | 
				
			||||||
    /*
 | 
					 | 
				
			||||||
     * exchange value of the left handside and the value of the right-handside
 | 
					 | 
				
			||||||
     * to make sure that the value of filter expression always locates in
 | 
					 | 
				
			||||||
     * right-handside and
 | 
					 | 
				
			||||||
     * the column-id is at the left handside.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    uint32_t optr = 0;
 | 
					 | 
				
			||||||
    switch (pExpr->nSQLOptr) {
 | 
					 | 
				
			||||||
      case TK_LE:
 | 
					 | 
				
			||||||
        optr = TK_GE;
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      case TK_LT:
 | 
					 | 
				
			||||||
        optr = TK_GT;
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      case TK_GT:
 | 
					 | 
				
			||||||
        optr = TK_LT;
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      case TK_GE:
 | 
					 | 
				
			||||||
        optr = TK_LE;
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      default:
 | 
					 | 
				
			||||||
        optr = pExpr->nSQLOptr;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pExpr->nSQLOptr = optr;
 | 
					 | 
				
			||||||
    SWAP(pExpr->pLeft, pExpr->pRight, void*);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool validateJoinExprNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr, SColumnIndex* pLeftIndex) {
 | 
					static bool validateJoinExprNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr* pExpr, SColumnIndex* pLeftIndex) {
 | 
				
			||||||
  const char* msg1 = "illegal column name";
 | 
					  const char* msg1 = "illegal column name";
 | 
				
			||||||
| 
						 | 
					@ -6729,7 +6939,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  if (pQuerySql->from == NULL) {
 | 
					  if (pQuerySql->from == NULL) {
 | 
				
			||||||
    assert(pQuerySql->fillType == NULL && pQuerySql->pGroupby == NULL && pQuerySql->pWhere == NULL &&
 | 
					    assert(pQuerySql->fillType == NULL && pQuerySql->pGroupby == NULL && pQuerySql->pWhere == NULL &&
 | 
				
			||||||
           pQuerySql->pSortOrder == NULL);
 | 
					           pQuerySql->pSortOrder == NULL && pQuerySql->pHaving == NULL);
 | 
				
			||||||
    return doLocalQueryProcess(pCmd, pQueryInfo, pQuerySql);
 | 
					    return doLocalQueryProcess(pCmd, pQueryInfo, pQuerySql);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6817,6 +7027,11 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
 | 
				
			||||||
    return TSDB_CODE_TSC_INVALID_SQL;
 | 
					    return TSDB_CODE_TSC_INVALID_SQL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // parse the having clause in the first place
 | 
				
			||||||
 | 
					  if (parseHavingClause(pQueryInfo, &pQuerySql->pHaving, pCmd) != TSDB_CODE_SUCCESS) {
 | 
				
			||||||
 | 
					    return TSDB_CODE_TSC_INVALID_SQL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // set where info
 | 
					  // set where info
 | 
				
			||||||
  STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
 | 
					  STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1061,6 +1061,10 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      tfree(pInfo->pArithExprInfo);
 | 
					      tfree(pInfo->pArithExprInfo);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (pInfo->pFieldFilters != NULL) {
 | 
				
			||||||
 | 
					      tscColumnDestroy(pInfo->pFieldFilters);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  taosArrayDestroy(pFieldInfo->internalField);
 | 
					  taosArrayDestroy(pFieldInfo->internalField);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -233,6 +233,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TK_SPACE                          300
 | 
					#define TK_SPACE                          300
 | 
				
			||||||
#define TK_COMMENT                        301
 | 
					#define TK_COMMENT                        301
 | 
				
			||||||
#define TK_ILLEGAL                        302
 | 
					#define TK_ILLEGAL                        302
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,6 +71,7 @@ typedef struct SQuerySQL {
 | 
				
			||||||
  SLimitVal            slimit;       // group limit offset [optional]
 | 
					  SLimitVal            slimit;       // group limit offset [optional]
 | 
				
			||||||
  SArray *             fillType;     // fill type[optional], SArray<tVariantListItem>
 | 
					  SArray *             fillType;     // fill type[optional], SArray<tVariantListItem>
 | 
				
			||||||
  SStrToken            selectToken;  // sql string
 | 
					  SStrToken            selectToken;  // sql string
 | 
				
			||||||
 | 
					  struct tSQLExpr *    pHaving;      // having clause [optional]
 | 
				
			||||||
} SQuerySQL;
 | 
					} SQuerySQL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct SCreatedTableInfo {
 | 
					typedef struct SCreatedTableInfo {
 | 
				
			||||||
| 
						 | 
					@ -242,7 +243,7 @@ void tSqlExprListDestroy(tSQLExprList *pList);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SQuerySQL *tSetQuerySqlElems(SStrToken *pSelectToken, tSQLExprList *pSelection, SArray *pFrom, tSQLExpr *pWhere,
 | 
					SQuerySQL *tSetQuerySqlElems(SStrToken *pSelectToken, tSQLExprList *pSelection, SArray *pFrom, tSQLExpr *pWhere,
 | 
				
			||||||
                             SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval,
 | 
					                             SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval,
 | 
				
			||||||
                             SStrToken *pSliding, SArray *pFill, SLimitVal *pLimit, SLimitVal *pGLimit);
 | 
					                             SStrToken *pSliding, SArray *pFill, SLimitVal *pLimit, SLimitVal *pGLimit, tSQLExpr *pHaving);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SCreateTableSQL *tSetCreateSqlElems(SArray *pCols, SArray *pTags, SQuerySQL *pSelect, int32_t type);
 | 
					SCreateTableSQL *tSetCreateSqlElems(SArray *pCols, SArray *pTags, SQuerySQL *pSelect, int32_t type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -437,7 +437,7 @@ tagitem(A) ::= PLUS(X) FLOAT(Y).  {
 | 
				
			||||||
%type select {SQuerySQL*}
 | 
					%type select {SQuerySQL*}
 | 
				
			||||||
%destructor select {doDestroyQuerySql($$);}
 | 
					%destructor select {doDestroyQuerySql($$);}
 | 
				
			||||||
select(A) ::= SELECT(T) selcollist(W) from(X) where_opt(Y) interval_opt(K) fill_opt(F) sliding_opt(S) groupby_opt(P) orderby_opt(Z) having_opt(N) slimit_opt(G) limit_opt(L). {
 | 
					select(A) ::= SELECT(T) selcollist(W) from(X) where_opt(Y) interval_opt(K) fill_opt(F) sliding_opt(S) groupby_opt(P) orderby_opt(Z) having_opt(N) slimit_opt(G) limit_opt(L). {
 | 
				
			||||||
  A = tSetQuerySqlElems(&T, W, X, Y, P, Z, &K, &S, F, &L, &G);
 | 
					  A = tSetQuerySqlElems(&T, W, X, Y, P, Z, &K, &S, F, &L, &G, N);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%type union {SSubclauseInfo*}
 | 
					%type union {SSubclauseInfo*}
 | 
				
			||||||
| 
						 | 
					@ -455,7 +455,7 @@ cmd ::= union(X). { setSqlInfo(pInfo, X, NULL, TSDB_SQL_SELECT); }
 | 
				
			||||||
// select server_version(), select client_version(),
 | 
					// select server_version(), select client_version(),
 | 
				
			||||||
// select server_state();
 | 
					// select server_state();
 | 
				
			||||||
select(A) ::= SELECT(T) selcollist(W). {
 | 
					select(A) ::= SELECT(T) selcollist(W). {
 | 
				
			||||||
  A = tSetQuerySqlElems(&T, W, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
 | 
					  A = tSetQuerySqlElems(&T, W, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// selcollist is a list of expressions that are to become the return
 | 
					// selcollist is a list of expressions that are to become the return
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -531,7 +531,7 @@ void tSqlSetColumnType(TAOS_FIELD *pField, SStrToken *type) {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
SQuerySQL *tSetQuerySqlElems(SStrToken *pSelectToken, tSQLExprList *pSelection, SArray *pFrom, tSQLExpr *pWhere,
 | 
					SQuerySQL *tSetQuerySqlElems(SStrToken *pSelectToken, tSQLExprList *pSelection, SArray *pFrom, tSQLExpr *pWhere,
 | 
				
			||||||
                             SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval,
 | 
					                             SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval,
 | 
				
			||||||
                             SStrToken *pSliding, SArray *pFill, SLimitVal *pLimit, SLimitVal *pGLimit) {
 | 
					                             SStrToken *pSliding, SArray *pFill, SLimitVal *pLimit, SLimitVal *pGLimit, tSQLExpr *pHaving) {
 | 
				
			||||||
  assert(pSelection != NULL);
 | 
					  assert(pSelection != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SQuerySQL *pQuery = calloc(1, sizeof(SQuerySQL));
 | 
					  SQuerySQL *pQuery = calloc(1, sizeof(SQuerySQL));
 | 
				
			||||||
| 
						 | 
					@ -543,6 +543,7 @@ SQuerySQL *tSetQuerySqlElems(SStrToken *pSelectToken, tSQLExprList *pSelection,
 | 
				
			||||||
  pQuery->pGroupby = pGroupby;
 | 
					  pQuery->pGroupby = pGroupby;
 | 
				
			||||||
  pQuery->pSortOrder = pSortOrder;
 | 
					  pQuery->pSortOrder = pSortOrder;
 | 
				
			||||||
  pQuery->pWhere = pWhere;
 | 
					  pQuery->pWhere = pWhere;
 | 
				
			||||||
 | 
					  pQuery->pHaving = pHaving;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (pLimit != NULL) {
 | 
					  if (pLimit != NULL) {
 | 
				
			||||||
    pQuery->limit = *pLimit;
 | 
					    pQuery->limit = *pLimit;
 | 
				
			||||||
| 
						 | 
					@ -590,6 +591,9 @@ void doDestroyQuerySql(SQuerySQL *pQuerySql) {
 | 
				
			||||||
  tSqlExprDestroy(pQuerySql->pWhere);
 | 
					  tSqlExprDestroy(pQuerySql->pWhere);
 | 
				
			||||||
  pQuerySql->pWhere = NULL;
 | 
					  pQuerySql->pWhere = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  tSqlExprDestroy(pQuerySql->pHaving);
 | 
				
			||||||
 | 
					  pQuerySql->pHaving = NULL;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
  taosArrayDestroyEx(pQuerySql->pSortOrder, freeVariant);
 | 
					  taosArrayDestroyEx(pQuerySql->pSortOrder, freeVariant);
 | 
				
			||||||
  pQuerySql->pSortOrder = NULL;
 | 
					  pQuerySql->pSortOrder = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2864,7 +2864,7 @@ static YYACTIONTYPE yy_reduce(
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case 147: /* select ::= SELECT selcollist from where_opt interval_opt fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt */
 | 
					      case 147: /* select ::= SELECT selcollist from where_opt interval_opt fill_opt sliding_opt groupby_opt orderby_opt having_opt slimit_opt limit_opt */
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  yylhsminor.yy114 = tSetQuerySqlElems(&yymsp[-11].minor.yy0, yymsp[-10].minor.yy522, yymsp[-9].minor.yy247, yymsp[-8].minor.yy326, yymsp[-4].minor.yy247, yymsp[-3].minor.yy247, &yymsp[-7].minor.yy430, &yymsp[-5].minor.yy0, yymsp[-6].minor.yy247, &yymsp[0].minor.yy204, &yymsp[-1].minor.yy204);
 | 
					  yylhsminor.yy114 = tSetQuerySqlElems(&yymsp[-11].minor.yy0, yymsp[-10].minor.yy522, yymsp[-9].minor.yy247, yymsp[-8].minor.yy326, yymsp[-4].minor.yy247, yymsp[-3].minor.yy247, &yymsp[-7].minor.yy430, &yymsp[-5].minor.yy0, yymsp[-6].minor.yy247, &yymsp[0].minor.yy204, &yymsp[-1].minor.yy204, yymsp[-2].minor.yy326);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
  yymsp[-11].minor.yy114 = yylhsminor.yy114;
 | 
					  yymsp[-11].minor.yy114 = yylhsminor.yy114;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
| 
						 | 
					@ -2888,7 +2888,7 @@ static YYACTIONTYPE yy_reduce(
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case 153: /* select ::= SELECT selcollist */
 | 
					      case 153: /* select ::= SELECT selcollist */
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  yylhsminor.yy114 = tSetQuerySqlElems(&yymsp[-1].minor.yy0, yymsp[0].minor.yy522, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
 | 
					  yylhsminor.yy114 = tSetQuerySqlElems(&yymsp[-1].minor.yy0, yymsp[0].minor.yy522, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
  yymsp[-1].minor.yy114 = yylhsminor.yy114;
 | 
					  yymsp[-1].minor.yy114 = yylhsminor.yy114;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue