/*-------------------------------------------------------------------------
 * Copyright (c) Microsoft Corporation.  All rights reserved.
 *
 * include/planner/documentdb_plan_cache.h
 *
 * Common declarations for the pg_documentdb plan cache.
 *
 *-------------------------------------------------------------------------
 */

#ifndef BSON_PLAN_CACHE_H
#define BSON_PLAN_CACHE_H

#include <executor/spi.h>

/*
 * ID prefixes for different types of query.
 *
 * The first 32 bits of a query ID are used to identity the operation,
 * and the latter 32 bits to identify different query variants.
 */
#define QUERY_ID_INSERT (1L << 32)
#define QUERY_ID_UPDATE_BY_TID (2L << 32)
#define QUERY_ID_DELETE_BY_TID (3L << 32)

/* TODO: remove once we fully support let and collation with delete */
#define QUERY_DELETE_WITH_FILTER (4L << 32);
#define QUERY_DELETE_WITH_FILTER_SHARDKEY (5L << 32)
#define QUERY_DELETE_WITH_FILTER_ID (6L << 32)
#define QUERY_DELETE_WITH_FILTER_SHARDKEY_ID (7L << 32)

#define QUERY_CALL_UPDATE_ONE (8L << 32)

#define QUERY_DELETE_ONE (9L << 32)
#define QUERY_DELETE_ONE_ID (10L << 32)
#define QUERY_DELETE_ONE_ID_RETURN_DOCUMENT (11L << 32)

/* TODO: remove once we fully support let and collation with delete */
#define QUERY_UPDATE_SELECT_UPDATE_CANDIDATE (12L << 32)
#define QUERY_UPDATE_SELECT_UPDATE_CANDIDATE_NON_OBJECT_ID (13L << 32)
#define QUERY_UPDATE_SELECT_UPDATE_CANDIDATE_ONLY_OBJECT_ID (14L << 32)
#define QUERY_UPDATE_SELECT_UPDATE_CANDIDATE_BOTH_FILTER (15L << 32)


#define QUERY_ID_RETRY_RECORD_INSERT (20L << 32)
#define QUERY_ID_RETRY_RECORD_DELETE (21L << 32)
#define QUERY_ID_RETRY_RECORD_SELECT (22L << 32)

#define QUERY_ID_INSERT_OR_REPLACE (24L << 32)

#define QUERY_ID_GLOBAL_RETRY_RECORD_INSERT (25L << 32)
#define QUERY_ID_GLOBAL_RETRY_RECORD_DELETE (26L << 32)
#define QUERY_ID_GLOBAL_RETRY_RECORD_SELECT (27L << 32)

#define QUERY_DELETE_WITH_FILTER_LET_AND_COLLATION (30L << 32)
#define QUERY_DELETE_WITH_FILTER_SHARDKEY_LET_AND_COLLATION (31L << 32)
#define QUERY_DELETE_WITH_FILTER_ID_LET_AND_COLLATION (32L << 32)
#define QUERY_DELETE_WITH_FILTER_SHARDKEY_ID_LET_AND_COLLATION (33L << 32)

#define QUERY_DELETE_ONE_LET_AND_COLLATION (34L << 32)
#define QUERY_DELETE_ONE_ID_LET_AND_COLLATION (35L << 32)

#define QUERY_UPDATE_SELECT_UPDATE_CANDIDATE_LET_AND_COLLATION (36L << 32)
#define QUERY_UPDATE_SELECT_UPDATE_CANDIDATE_NON_OBJECT_ID_LET_AND_COLLATION (37L << 32)
#define QUERY_UPDATE_SELECT_UPDATE_CANDIDATE_BOTH_FILTER_LET_AND_COLLATION (38L << 32)


#define QUERY_UPDATE_MANY_SHARD_KEY_QUERY_OFFSET (1L << 32)
#define QUERY_UPDATE_MANY_OBJECTID_QUERY_OFFSET (2L << 32)
#define QUERY_UPDATE_MANY_SHARD_KEY_OBJECT_ID_QUERY_OFFSET \
	QUERY_UPDATE_MANY_SHARD_KEY_QUERY_OFFSET + QUERY_UPDATE_MANY_OBJECTID_QUERY_OFFSET

/* 40L << 32 to 43L << 32 */
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION (40L << 32)
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION_WITH_SHARD_KEY \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION + \
	QUERY_UPDATE_MANY_SHARD_KEY_QUERY_OFFSET
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION_WITH_OBJECT_ID \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION + QUERY_UPDATE_MANY_OBJECTID_QUERY_OFFSET
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION_WITH_SHARD_KEY_AND_OBJECT_ID \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION + \
	QUERY_UPDATE_MANY_SHARD_KEY_OBJECT_ID_QUERY_OFFSET

/* 44L << 32 to 47L << 32 */
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR (44L << 32)
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR_WITH_SHARD_KEY \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR + \
	QUERY_UPDATE_MANY_SHARD_KEY_QUERY_OFFSET
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR_WITH_OBJECT_ID \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR + QUERY_UPDATE_MANY_OBJECTID_QUERY_OFFSET
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR_WITH_SHARD_KEY_AND_OBJECT_ID \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR + \
	QUERY_UPDATE_MANY_SHARD_KEY_OBJECT_ID_QUERY_OFFSET

#define QUERY_UPDATE_MANY_WITH_NEW_UPDATE_BSON_OFFSET (8L << 32)

/* 48L << 32 to 51L << 32 */
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION_NEW_FUNC \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION + \
	QUERY_UPDATE_MANY_WITH_NEW_UPDATE_BSON_OFFSET
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION_WITH_SHARD_KEY_NEW_FUNC \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION_WITH_SHARD_KEY + \
	QUERY_UPDATE_MANY_WITH_NEW_UPDATE_BSON_OFFSET
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION_WITH_OBJECT_ID_NEW_FUNC \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION_WITH_OBJECT_ID + \
	QUERY_UPDATE_MANY_WITH_NEW_UPDATE_BSON_OFFSET
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION_WITH_SHARD_KEY_AND_OBJECT_ID_NEW_FUNC \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_FUNCTION_WITH_SHARD_KEY_AND_OBJECT_ID + \
	QUERY_UPDATE_MANY_WITH_NEW_UPDATE_BSON_OFFSET

/* 52L << 32 to 55L << 32 */
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR_NEW_FUNC \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR + \
	QUERY_UPDATE_MANY_WITH_NEW_UPDATE_BSON_OFFSET
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR_WITH_SHARD_KEY_NEW_FUNC \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR_WITH_SHARD_KEY + \
	QUERY_UPDATE_MANY_WITH_NEW_UPDATE_BSON_OFFSET
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR_WITH_OBJECT_ID_NEW_FUNC \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR_WITH_OBJECT_ID + \
	QUERY_UPDATE_MANY_WITH_NEW_UPDATE_BSON_OFFSET
#define QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR_WITH_SHARD_KEY_AND_OBJECT_ID_NEW_FUNC \
	QUERY_UPDATE_MANY_WITH_QUERY_FILTER_OPERATOR_WITH_SHARD_KEY_AND_OBJECT_ID + \
	QUERY_UPDATE_MANY_WITH_NEW_UPDATE_BSON_OFFSET

/* Plan IDs for delete_one with _id-only filter (no @@ operator) 56L << 32 to 59L << 32 */
#define QUERY_DELETE_ONE_NO_FILTER (56L << 32)
#define QUERY_DELETE_ONE_ID_ONLY (57L << 32)
#define QUERY_DELETE_ONE_ID_ONLY_RETURN_DOCUMENT (58L << 32)
#define QUERY_DELETE_ONE_NO_FILTER_RETURN_DOCUMENT (59L << 32)

/* Plan IDs for delete_one with returnDeletedDocument 60L << 32 to 62L << 32 */
#define QUERY_DELETE_ONE_RETURN_DOCUMENT (60L << 32)
#define QUERY_DELETE_ONE_LET_AND_COLLATION_RETURN_DOCUMENT (61L << 32)
#define QUERY_DELETE_ONE_ID_LET_AND_COLLATION_RETURN_DOCUMENT (62L << 32)

/* GUC that controls the query plan cache size */
extern int QueryPlanCacheSizeLimit;


void InitializeQueryPlanCache(void);
SPIPlanPtr GetSPIQueryPlan(uint64 collectionId, uint64 queryId,
						   const char *query, Oid *argTypes, int argCount);

SPIPlanPtr GetSPIQueryPlanWithLocalShard(uint64 collectionId, const char *shardTableName,
										 uint64 queryId,
										 const char *query, Oid *argTypes, int argCount);

#endif
