#ifdef __cplusplus
extern "C"
{
#endif

#include "postgres.h" // 与 #include <iomanip> 冲突
//为了解决和libintl.h冲突的问题undef以下4个
#undef gettext
#undef dgettext
#undef ngettext
#undef dngettext

#include "utils/palloc.h"
#include "utils/memutils.h"

#include "nodes/nodes.h"
#include "nodes/parsenodes.h"
#include "nodes/value.h"

#include "base64.h"

#include <string.h>
#ifdef __cplusplus
}
#endif

#include "encryptsql/fieldmap.h"

#include <assert.h>
#include <stdexcept>
#include <set>
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <cstdio>
#include "libpq-fe.h"  // 改为使用引号包含

#include "crypto/crypto.h"
#include "crypto/openssl.h"
#include "encryptsql.h"

#include "en_config.h"
#include "kms/kms_interface.hpp"
#include "kmsAdapter/dek_interface.hpp"
#include "KeyDistribution/non_enc_client/client_interface.h"

namespace {
bool SendDekViaTls(const std::string& dek_plain)
{
    kd::client::ClientConfig cfg;
    cfg.server_host = DK_SERVER_HOST;  // 或者 "localhost"
    cfg.server_port = DK_SERVER_PORT;       // 只要服务器宿主端监听同一个端口即可
    cfg.dek.assign(dek_plain.begin(), dek_plain.end());

    kd::client::ClientResult result;
    std::string err;

    if (!kd::client::SendDekToServer(cfg, &result, &err))
    {
        elog(WARNING, "SendDekToServer failed: %s", err.c_str());
        return false;
    }
    return true;
}
} // anonymous namespace

extern thread_local std::string dek_for_decrypt;

static List *encryptValuesLists(List *valuesLists, List *cols, EncryptInfo *info);

static char *encryptRVField(PlainDataType p_type, bool *isCreate, char *name, EncryptInfo *info = nullptr);

static CaseExpr *encryptCaseExpr(CaseExpr *ce, EncryptInfo *info);

static Node *encryptDispatcher(Node *expr, T_Cipher t, EncryptInfo *info);

static JoinExpr *encryptJoinExpr(JoinExpr *joinExpr, EncryptInfo *info = nullptr);

static RangeVar *encryptRangeVar(RangeVar *rv, bool *isCreate, EncryptInfo *info);

static A_Const * // finished version 1
encryptAConst(A_Const *aconst, T_Cipher encryptCipher, EncryptInfo *info);

static ColumnRef * // finished version 1
encryptColumnRef(ColumnRef *cref, T_Cipher encryptCipher, EncryptInfo *info);

static Node *encryptExpr(Node *expr, T_Cipher t, EncryptInfo *info);

static Node *encryptAExpr(A_Expr *expr, EncryptInfo *info);

static Alias *encryptAlias(Alias *alias, EncryptInfo *info = nullptr);

static RangeSubselect *encryptRangeSubselect(RangeSubselect *rss, EncryptInfo *info = nullptr);

static List *encryptFunctionArgs(List *args, const char *funcName, EncryptInfo *info);

static List *encryptFunctionName(List *funcNames, EncryptInfo *info);

static FuncCall *encryptFuncCall(FuncCall *func, EncryptInfo *info);

static SubLink *encryptSubLink(SubLink *sl, EncryptInfo *info);

static List *encryptGroupClause(List *groupClause, EncryptInfo *info);

static List *encryptExtendTargetList(List *targetList, EncryptInfo *info);

static List *encryptTargetList(List *targetlist, bool, EncryptInfo *info);

static List *encryptFromClause(List *fromClause, EncryptInfo *info);

static List *encryptSortClause(List *SortClause, EncryptInfo *info);

static List *encryptColumnDefToList(ColumnDef *n, const char *_typename, char **err_msg_internal);

static List *encrypttableElts(List *tableElts, EncryptInfo *info);

static List *encryptList(List *list, EncryptInfo *info);

static List *encryptStar(EncryptInfo *info);

static void replaceColumnDefType(TypeName *_typename, const char *type, T_Cipher t, EncryptInfo *info = nullptr);

static Constraint *encryptExplicitConstraint(Constraint *con, EncryptInfo *info);

static T_Cipher getEncryptTypeFromNode(Node *n, EncryptInfo *info = nullptr); //根据n是表达式或者func来获取要加密的cipher。
static Node *dealWithSpecialFunction(FuncCall *func, EncryptInfo *info);

static InsertStmt *encryptInsertStmt(InsertStmt *parseTree, EncryptInfo *info);

static DeleteStmt *encryptDeleteStmt(DeleteStmt *parseTree, EncryptInfo *info);

static UpdateStmt *encryptUpdateStmt(UpdateStmt *parseTree, EncryptInfo *info);

static SelectStmt *encryptSelectStmt(SelectStmt *parseTree, List *cols, EncryptInfo *info);

static CreateStmt *encryptCreateStmt(CreateStmt *parseTree, EncryptInfo *info, char **err_msg_internal);

static IndexStmt *encryptIndexStmt(IndexStmt *parseTree, EncryptInfo *info, char **err_msg_internal);

static AlterTableStmt *encryptAlterTableStmt(AlterTableStmt *parseTree, EncryptInfo *info, char **err_msg_internal);

static ExplainStmt *encryptExplainStmt(ExplainStmt *parseTree, EncryptInfo *info);

static List *encryptAlterTableCmds(List *cmdList, EncryptInfo *info);

static DropStmt *encryptDropStmt(DropStmt *parseTree, EncryptInfo *info);

//Node *encryptStmt(Node *parseTree, EncryptInfo *info);
Node *encryptStmt(Node *parseTree, EncryptInfo *info, char **err_msg_internal);
////////////////////////////////////////
//// Problems
///////////////////////////////////////

// select pid, tid from persons, teacher WHERE pid=tid; 从语法树上无法区分
// pid属于哪一个表,当前的实现是将from子句中的表都存下来，然后在每个表中查看是否有这个列;

// 定义全局线程局部变量，用于传递密文列名
static thread_local std::string encrypted_col;

static void create_backup(bool is_transaction);
extern "C" void delete_backup(bool is_transaction) __attribute__((visibility("default")));
void recovery_backup(bool is_transaction);
static void solveTransaction(const EncryptInfo *info);

static A_Const *encryptAConst(A_Const *aconst, T_Cipher encryptCipher, EncryptInfo *info) {
    A_Const *newConst = nullptr;
    if (encryptCipher == CIPHER_NOCRYPT) {
        newConst = (A_Const *) copyObject(aconst);
        return newConst;
    }
    uint8_t *plainText = nullptr;
    Node *AConstValue = (Node *) &(aconst->val);
    size_t out_size = 0;
    size_t in_size = 0;
    uint8_t *cipherText = nullptr;
    // bool isFloat = info->isFloatorIntCol; //edit by lrn 增加了int类型也放缩
    bool isFloat = info->isFloatCol;
    newConst = makeNode(A_Const);
    // bool isFloatCol = false;
    if (IsA(AConstValue, Null)) {
        newConst = (A_Const *) copyObject((void *) AConstValue);
        return newConst;
    }

    if (IsA(AConstValue, String)) {
        plainText = (uint8_t *) strVal(AConstValue);
        in_size = strlen((char *) plainText);
    } else {
        auto tmpInt = (int64_t *) palloc(sizeof(int64_t));
        double tmpDouble;
        //fixed by qxy for RND encrypt
//         if (encryptCipher == CIPHER_RND) {
//             *tmpInt = intVal(AConstValue);
// //			isFloat = true;
// //			*tmpInt *= Float_Scale;
//         } else if (IsA(AConstValue, Float) || (info->isPeerColFloat)) //
//         {
//             isFloat = true;
//             tmpDouble = atof(strVal(AConstValue));
//             *tmpInt = tmpDouble * Float_Scale;
//             if (info->isPeerColFloat) {
//                 info->isPeerColFloat = false;
//             }
//         } else if (IsA(AConstValue, Integer)) {
//             *tmpInt = intVal(AConstValue);
//             isFloat = true;
//             *tmpInt *= Float_Scale;
//         } else {
//             *tmpInt = intVal(AConstValue);
//             if (info->isFloatorIntCol) { // 当前列是float或Int列
//                 isFloat = true;
//                 *tmpInt *= Float_Scale;
//             }
//         }
        
        // 去除放缩逻辑
		if (encryptCipher == CIPHER_RND) {
			*tmpInt = intVal(AConstValue);
//			isFloat = true;
//			*tmpInt *= Float_Scale;
			plainText = (uint8_t *) tmpInt;
			in_size = sizeof(int64_t);
		} else if (IsA(AConstValue, Float) || (info->isPeerColFloat)) //
		{
			isFloat = true;
			tmpDouble = atof(strVal(AConstValue));
			// *tmpInt = tmpDouble * Float_Scale;
			if (info->isPeerColFloat) {
				info->isPeerColFloat = false;
			}
			plainText = (uint8_t *) &tmpDouble;
			in_size = sizeof(double);
		} else if (IsA(AConstValue, Integer)) {
			*tmpInt = intVal(AConstValue);
			// isFloat = true;
			isFloat = false;
			// *tmpInt *= Float_Scale;
			plainText = (uint8_t *) tmpInt;
			in_size = sizeof(int64_t);
		} else {
			*tmpInt = intVal(AConstValue);
			// if (info->isFloatorIntCol) { // 当前列是float或Int列
			// 	isFloat = true;
			// 	*tmpInt *= Float_Scale;
			// } 
			isFloat = info->isFloatCol;  // 根据列类型决定是否为浮点数
			// *tmpInt *= Float_Scale;
			if(isFloat) {
				plainText = (uint8_t *) &tmpDouble;
				in_size = sizeof(double);
			} else {
				plainText = (uint8_t *) tmpInt;
				in_size = sizeof(int64_t);
			}
		}
    }

    //kms test start
//    std::string col_need_encrypt;
//    col_need_encrypt = cmk_mapperGetInfoCol();
//    std::string dek_tmp;
//    if (!col_need_encrypt.empty()) {
//        cmk_mapperGetDekByCol(col_need_encrypt, dek_tmp);
//        std::cout << dek_tmp << std::endl;
//        cmk_mapperSetInfoCol(col_need_encrypt);
//    }

    //kms test end
    std::string dek_tmp;
    //cmk_mapperGetDekTableLevel(dek_tmp);
    std::string col_need_encrypt;
    // col_need_encrypt = cmk_mapperGetInfoCol();
    // encrypted_col = col_need_encrypt;
    // std::cout << encrypted_col << std::endl;
    // if(cmk_mapperIsRotateCmd()) cmk_mapperGetDekStoreTmpForUpdate(col_need_encrypt, dek_tmp);
    // else cmk_mapperGetDekByCol(col_need_encrypt, dek_tmp);
    // if(!info->isFromAExpr && !info->isFromUpdate) cmk_mapperSetInfoCol(col_need_encrypt);
    col_need_encrypt = DekInterface::getInfoCol();
    if(DekInterface::isRotateCmd()) DekInterface::getDekColLevelForUpdate(col_need_encrypt, dek_tmp);
    else DekInterface::getDekColLevel(col_need_encrypt, dek_tmp);
    if(!info->isFromAExpr && !info->isFromUpdate) DekInterface::setInfoCol(col_need_encrypt);
    std::cout << dek_tmp << std::endl;

    // 通过 TLS 发送 DEK 到服务器侧分发 enclave
    if (!dek_tmp.empty())
    {
        if (!SendDekViaTls(dek_tmp))
        {
            elog(WARNING, "Failed to push DEK via TLS");
            // 根据需求决定是否继续沿用旧逻辑或抛错
        }
    }

    // 将dek存储到指定路径/etc/encryptsql/dek
    
    std::ofstream dekFile(DEK_FILE_PATH, std::ios::binary | std::ios::trunc);
    if (dekFile.is_open()) {
        dekFile.write(dek_tmp.c_str(), dek_tmp.size());
        dekFile.flush();
        dekFile.close();
    } else {
        std::cout << "Failed to open DEK file for writing. Check permissions." << std::endl;
        perror("Error details");
    }
    

    cipherText = encryptValue(encryptCipher, plainText, in_size, &out_size, dek_tmp.c_str(), true, isFloat);



#if defined(SGX_ORE)
    if (encryptCipher == CIPHER_SAHE || encryptCipher == CIPHER_SMHE)
#else
    if (encryptCipher == CIPHER_ORE || encryptCipher == CIPHER_SAHE || encryptCipher == CIPHER_SMHE)
#endif
    {
        // 不需要 buf2hex
        newConst->val = *makeString((char *) cipherText);
    } else if (encryptCipher == CIPHER_NOCRYPT) {
        newConst->val = *makeInteger(*(int64_t *) cipherText);
    } else {
        size_t bufEncodingStrSz = out_size * 2 + 1;
        uint8_t *bufEncodingStr = (uint8_t *) palloc0(bufEncodingStrSz);
        buf2hex(cipherText, out_size, (char *) bufEncodingStr, &bufEncodingStrSz);
        newConst->val = *makeString((char *) bufEncodingStr);
    }

    return newConst;
}

static List *encryptStar(EncryptInfo *info) { // 处理from表的第一个匹配项

    char **cols;
    int nColumn = 0;
    List *resList = NIL;
    resList = lappend(resList, makeNode(A_Star));
    getFirstTableColumnsAlloc(&cols, &nColumn);
    for (size_t i = 0; i < nColumn; i++) {
        //不能简单的选取AES，需要根据加密类型进行判断 加密情况如下
        //test begin
        int ncipher = 0;
        T_Cipher ciphers[CIPHER_COUNT];
        getColumnCiphers(cols[i], ciphers, &ncipher);

        T_Cipher ctype = CIPHER_NOCRYPT;
		for (int t = 0; t < ncipher; t++) {
			if (ciphers[t] == CIPHER_AES) {
				ctype = CIPHER_AES;
				break;
			}else if(ciphers[t] == CIPHER_AESHMAC){
				ctype = CIPHER_AESHMAC;	
				break;
			}else if(ciphers[t] == CIPHER_SM4){
				ctype = CIPHER_SM4;
				break;
            }else if(ciphers[t] == CIPHER_SM4CK){
				ctype = CIPHER_SM4CK;
                break;
            }else if(ciphers[t] == CIPHER_RND){
				ctype = CIPHER_RND;
                break;
            }else if(ciphers[t] == CIPHER_RNDSM4CK){
				ctype = CIPHER_RNDSM4CK;
                break;
            }
		}

        char *cipherColname = nullptr;
        char *plainColname = nullptr;
        if (ctype == CIPHER_AES || ctype == CIPHER_AESHMAC || ctype == CIPHER_SM4 || ctype == CIPHER_SM4CK || ctype == CIPHER_SAHE) {
			//处于加密状态且有AES加密 || AESHMAC加密
			plainColname = addEncryptSubfix(ctype, cols[i]);
			cipherColname = getMappedName(T_STRING_COLUMN, plainColname, "");
		} else if (ncipher == 1 && ciphers[0] == CIPHER_RND) {
            plainColname = addEncryptSubfix(CIPHER_RND, cols[i]);
            cipherColname = getMappedName(T_STRING_COLUMN, plainColname, "");
//			throw std::runtime_error("RND NOT IMPLEMENTED");
        } else if (ncipher == 0) {
            //不处于加密状态
            cipherColname = cols[i];
        } else {
            //处于加密状态但没AES加密，使用catch接受错误信息
            string err_msg = cols[i];
            err_msg = err_msg +
                      ": You are using a feature not assigned to this column. Please check the features added when the column was created.";
            throw std::runtime_error(err_msg);
        }
        //test end

        //---original---
//        char *plainColname = addEncryptSubfix(DEFALUT_STAR_EXPR_CIPHER, cols[i]);
//        char *cipherColname = getMappedName(T_STRING_COLUMN, plainColname, "");
        //未加密情况如下
//        if (!*cipherColname) // 此列没有默认要求的加密列，可能是serial数据类型，这种数据类型默认不加密。
//        {
//            plainColname = addEncryptSubfix(CIPHER_NOCRYPT, cols[i]);
//            cipherColname = getMappedName(T_STRING_COLUMN, plainColname, NULL);
//        }
        resList = lappend(resList, makeString(cipherColname));
    }
    return resList;
}

/*static ColumnRef *encryptColumnRef(ColumnRef *cref, T_Cipher encryptCipher, EncryptInfo *info) {

    char *name = NULL;
    char *patchedName = NULL;
    ColumnRef *newCref = (ColumnRef *) copyObject(cref);
    ListCell *p = list_head(cref->fields);
    int listSize = list_length(cref->fields);

    newCref->fields = NIL;

    for (int i = 0; i < listSize; ++i) {
        char *cipherColName;
        Value *cipherColNameValue;
        PlainDataType t = (PlainDataType) (listSize - 1 - i);
        // deal with '*'
        if (IsA(lfirst(p), A_Star)) {
            newCref->fields = encryptStar(info);
            break;
        }
        name = strVal(lfirst(p));
        int ncipher = 0;
        T_Cipher ciphers[CIPHER_COUNT];
        getColumnCiphers(name, ciphers, &ncipher);

        if (t == T_STRING_TABLE)
            setCurrentNodeOnce(name, "");

        else if (t == T_STRING_SCHEMA)
            setCurrentNodeOnce("", name);

        else if (t == T_STRING_COLUMN) {

            T_Cipher ctype = CIPHER_NOCRYPT;
			for (int t = 0; t < ncipher; t++) {
				if (ciphers[t] == CIPHER_AES) {
					ctype = CIPHER_AES;
					break;
				}else if(ciphers[t] == CIPHER_AESHMAC){
					ctype = CIPHER_AESHMAC;	
					break;
				}else if(ciphers[i] == CIPHER_SM4) {
					ctype = CIPHER_SM4;
					break;
				}else if(ciphers[i] == CIPHER_SM4CK){
					ctype = CIPHER_SM4CK;
					break;
				}else if(ciphers[i] == CIPHER_SAHE){
					ctype = CIPHER_SAHE;
					break;
				}
			}
            

            if (ncipher == 1 && ciphers[0] == CIPHER_RND) {
                patchedName = addEncryptSubfix(CIPHER_RND, name);
            } else if(ctype == CIPHER_AESHMAC){
				patchedName = addEncryptSubfix(ctype, name);
			} else if (ctype == CIPHER_SM4){
				patchedName = addEncryptSubfix(CIPHER_SM4, name);
			} else if (ctype == CIPHER_SM4CK){
				patchedName = addEncryptSubfix(CIPHER_SM4CK, name);
			} else if (ctype == CIPHER_SAHE){
				patchedName = addEncryptSubfix(CIPHER_SAHE, name);
			} else if (ctype == CIPHER_AES){
				patchedName = addEncryptSubfix(CIPHER_AES, name);
			} else {
                patchedName = addEncryptSubfix(encryptCipher, name);
            }

            //if(encryptCipher != CIPHER_AES){
            //    patchedName = addEncryptSubfix(encryptCipher, name);
            //} else if(ncipher == 1 && ciphers[0] == CIPHER_RND) {
            //    patchedName = addEncryptSubfix(CIPHER_RND, name);
            //} else{
            //    patchedName = addEncryptSubfix(ctype, name);
            //}
            
        }
        patchedName = patchedName ? patchedName : name;
        cipherColName = getMappedName(
                t, patchedName, name);
        if (strcmp(name, cipherColName) == 0) { // 这个字段没有encryptCipher， 可能是个NOCRYPT加密 q:判断是否加密，如果没加密复制原列名，如果加密了则报错
            //根据列的加密数来判断该列是否加密
            if (ncipher == 0) {
                cipherColName = name;
            } else {
                string err_msg = name;
                err_msg = err_msg +
                          ": You are using a feature not assigned to this column. Please check the features added when the column was created.";
                throw std::runtime_error(err_msg);
            }
//			original
//			patchedName = addEncryptSubfix(CIPHER_NOCRYPT, name);
//			cipherColName = getMappedName(
//					t, patchedName, nullptr);
        }
        cipherColNameValue = makeString((char *) cipherColName);
        newCref->fields = lappend(newCref->fields, cipherColNameValue);
        p = lnext(p);
        char typebuf[128];
        if (IsA((Node *) info->father, A_Expr)) {
            getColumnType(name, typebuf);
            if (!strcmp(typebuf, "float")) {
                info->isPeerColFloat = true;
            }
        }
    }
    return newCref;
}*/

static ColumnRef *encryptColumnRef(ColumnRef *cref, T_Cipher encryptCipher, EncryptInfo *info) {
    char *name = NULL;
    char *patchedName = NULL;
    ColumnRef *newCref = (ColumnRef *) copyObject(cref);
    ListCell *p = list_head(cref->fields);
    int listSize = list_length(cref->fields);

    newCref->fields = NIL;

    for (int i = 0; i < listSize; ++i) {
        char *cipherColName;
        Value *cipherColNameValue;
        PlainDataType t = (PlainDataType) (listSize - 1 - i);
        // deal with '*'
        if (IsA(lfirst(p), A_Star)) {
            newCref->fields = encryptStar(info);
            break;
        }
        name = strVal(lfirst(p));
        int ncipher = 0;
        T_Cipher ciphers[CIPHER_COUNT];
        getColumnCiphers(name, ciphers, &ncipher);

        if (t == T_STRING_TABLE)
            setCurrentNodeOnce(name, "");

        else if (t == T_STRING_SCHEMA)
            setCurrentNodeOnce("", name);

        else if (t == T_STRING_COLUMN) {
            if(encryptCipher == CIPHER_AES && ncipher > 0) {
                // 对于可能来自 encryptTargetList 的情况
                bool found_eq_cipher = false;
                for(int t = 0; t < ncipher; t++) {
                    if(ciphers[t] == CIPHER_AES) {
                        patchedName = addEncryptSubfix(CIPHER_AES, name);
                        found_eq_cipher = true;
                        break;
                    } else if(ciphers[t] == CIPHER_AESHMAC) {
                        patchedName = addEncryptSubfix(CIPHER_AESHMAC, name);
                        found_eq_cipher = true;
                        break;
                    } else if(ciphers[t] == CIPHER_SM4) {
                        patchedName = addEncryptSubfix(CIPHER_SM4, name);
                        found_eq_cipher = true;
                        break;
                    } else if(ciphers[t] == CIPHER_SM4CK) {
                        patchedName = addEncryptSubfix(CIPHER_SM4CK, name);
                        found_eq_cipher = true;
                        break;
                    } else if(ciphers[t] == CIPHER_RND) {
                        patchedName = addEncryptSubfix(CIPHER_RND, name);
                        found_eq_cipher = true;
                        break;
                    } else if(ciphers[t] == CIPHER_RNDSM4CK) {
                        patchedName = addEncryptSubfix(CIPHER_RNDSM4CK, name);
                        found_eq_cipher = true;
                        break;
                    }
                }
                if(!found_eq_cipher) {
                    string err_msg = name;
                    err_msg = err_msg + ": This column does not support decrytion or equality comparison. Please check the encryption features added when the column was created.";
                    throw std::runtime_error(err_msg);
                }
            } else {
                // 非相等比较使用指定的加密类型
                patchedName = addEncryptSubfix(encryptCipher, name);
            }
        }

        patchedName = patchedName ? patchedName : name;
        cipherColName = getMappedName(t, patchedName, name);
        if (strcmp(name, cipherColName) == 0) {
            //根据列的加密数来判断该列是否加密
            if (ncipher == 0) {
                cipherColName = name;
            } else {
                string err_msg = name;
                err_msg = err_msg +
                          ": You are using a feature not assigned to this column. Please check the features added when the column was created.";
                throw std::runtime_error(err_msg);
            }
        }
        cipherColNameValue = makeString((char *) cipherColName);
        newCref->fields = lappend(newCref->fields, cipherColNameValue);
        p = lnext(p);
        char typebuf[128];
        if (IsA((Node *) info->father, A_Expr)) {
            getColumnType(name, typebuf);
            if (!strcmp(typebuf, "float")) {
                info->isPeerColFloat = true;
            }
        }
    }
    return newCref;
}

static SubLink *encryptSubLink(SubLink *sl, EncryptInfo *info) {
    SubLink *newSl = makeNode(SubLink);
    *newSl = *sl;
    if (sl->subLinkType == EXPR_SUBLINK || sl->subLinkType == EXISTS_SUBLINK) {
        if (sl->subselect)
            newSl->subselect = (Node *) encryptSelectStmt((SelectStmt *) sl->subselect, NULL, info);
    } else {
        errmsg("unhandled sublink type: %d in encryptSubLink()", (int) EXPR_SUBLINK);
    }
    return newSl;
}

static Node *encryptExpr(Node *expr, T_Cipher t, EncryptInfo *info) {
    return encryptDispatcher(expr, t, info);
}

static bool isTransformToFunction(const string &name) {
    if (strcmp(name.c_str(), "=") == 0) // 赋值语句不需要转换
        return false;
    if (strcmp(name.c_str(), "<>") == 0)
        return false;
    if (strcmp(name.c_str(), "<") == 0)  // 赋值语句不需要转换
        return false;
    if (strcmp(name.c_str(), "<=") == 0)  // 赋值语句不需要转换
        return false;
    if (strcmp(name.c_str(), ">") == 0)  // 赋值语句不需要转换
        return false;
    if (strcmp(name.c_str(), ">=") == 0)  // 赋值语句不需要转换
        return false;
    if (strcmp(name.c_str(), "AND") == 0 || strcmp(name.c_str(), "OR") == 0) // 赋值语句不需要转换
        return false;
    return true;
}

static Node *encryptAExpr(A_Expr *expr, EncryptInfo *info) // 将表达式转为 UDF. TODO: 可以提供一个参数，意为这个UDF的结果的加密形式
{
    info->father = (void *) expr;
    Node *ans;
    const char *op = getAExprOp(expr);
    T_Cipher t1 = getCipherTypeByOp(op, false);
    T_Cipher t2 = t1;
    bool hasSecondCipherParams = true; // 第二个参数是否是密文， pow函数第二个不是密文

    if (strcmp(op, "pow") == 0) {
        t2 = CIPHER_NOCRYPT;
        hasSecondCipherParams = false;
    }
    Node *encLexpr = nullptr;
    Node *encRexpr = nullptr;

    //!ORE 将ORE换成AES
    if (t1 == CIPHER_SMHE) {
        encLexpr = encryptExpr(expr->lexpr, t1, info);
        encRexpr = encryptExpr(expr->rexpr, t2, info);

    } else {
        //判断是否有多层，比如BETWEEN AND等
        if (t1 != CIPHER_AES && t1 != CIPHER_ORE)
            encLexpr = encryptExpr(expr->lexpr, t1, info);
        if (t2 != CIPHER_AES && t2 != CIPHER_ORE)
            encRexpr = encryptExpr(expr->rexpr, t2, info);
    }

    //qxy:列加密中明文和RND的判断
    bool is_rexpr_plaintext = false;
    bool is_lexpr_plaintext = false;
    bool is_rexpr_column = false;
    bool is_lexpr_column = false;

    //colname 在加密之前需要跳过colname获取到列密钥
    char *encRname = NULL,*encLname = NULL;
    char *patchedName = NULL;
    if (nodeTag(expr->rexpr) == T_ColumnRef) {
        is_rexpr_column = true;
        auto tmp1 = (ColumnRef *) expr->rexpr;
        ListCell *tmp2 = list_head(tmp1->fields);
        char *rexpr_name = strVal(lfirst(tmp2));
        int ncipher = 0;
        T_Cipher ciphers[CIPHER_COUNT];
        getColumnCiphers(rexpr_name, ciphers, &ncipher);

        T_Cipher ctype=CIPHER_NOCRYPT;
		for(auto cipher : ciphers) {
			if(cipher == CIPHER_AES){
				ctype = cipher;
				break;
			}else if(cipher == CIPHER_SM4) {
				ctype = cipher;
				break;
			}else if(cipher == CIPHER_SM4CK){
				ctype = cipher;
				break;
			}else if(cipher == CIPHER_AESHMAC){
				ctype = cipher;
				break;
			}
		}

        if (ncipher == 0) {
            is_rexpr_plaintext = true;
        } else if(strcmp(op,"=") == 0){
			t1 = t2 = ctype;
            if(nodeTag(expr->lexpr) == T_A_Const){
                patchedName = addEncryptSubfix(ctype, rexpr_name);
                encRname = getMappedName(T_STRING_COLUMN, patchedName, rexpr_name);
                // cmk_mapperSetInfoCol(encRname);
                DekInterface::setInfoCol(encRname);
                info->isFromAExpr = true;
            }
		} else if(ncipher == 1 && ciphers[0] == CIPHER_RND) {
            string err_msg = rexpr_name;
            err_msg = err_msg +
                      ": You are using a feature not assigned to this column. Please check the features added when the column was created.";
            throw std::runtime_error(err_msg);
        }
    }
    if (nodeTag(expr->lexpr) == T_ColumnRef) {
        is_lexpr_column = true;
        auto tmp1 = (ColumnRef *) expr->lexpr;
        ListCell *tmp2 = list_head(tmp1->fields);
        char *lexpr_name = strVal(lfirst(tmp2));
        int ncipher = 0;
        T_Cipher ciphers[CIPHER_COUNT];
        getColumnCiphers(lexpr_name, ciphers, &ncipher);

        T_Cipher ctype=CIPHER_NOCRYPT;
		for(auto cipher : ciphers) {
			if(cipher == CIPHER_AESHMAC){
				ctype = cipher;
				break;
			}else if(cipher == CIPHER_SM4) {
				ctype = CIPHER_SM4;
				break;
			}else if(cipher == CIPHER_SM4CK){
				ctype = CIPHER_SM4CK;
				break;
			}else if(cipher == CIPHER_AES){
				ctype = CIPHER_AES;
				break;
			}
		}

        if (ncipher == 0) {
            is_lexpr_plaintext = true;
        } else if(strcmp(op,"=") == 0){
			t1 = t2 = ctype;
            if(nodeTag(expr->rexpr) == T_A_Const){
                patchedName = addEncryptSubfix(ctype, lexpr_name);
                encLname = getMappedName(T_STRING_COLUMN, patchedName, lexpr_name);
                // cmk_mapperSetInfoCol(encLname);
                DekInterface::setInfoCol(encLname);
                info->isFromAExpr = true;
            }
		}  else if(ncipher == 1 && ciphers[0] == CIPHER_RND) {
            string err_msg = lexpr_name;
            err_msg = err_msg +
                      ": You are using a feature not assigned to this column. Please check the features added when the column was created.";
            throw std::runtime_error(err_msg);
        }
    }
    if(encRname == encLname && encLname != NULL){
        string err_msg = string(encLname) + " and " + string(encRname);
        err_msg = err_msg +
                  " using the same column DEK. please check the features added when the column was created.";
        throw std::runtime_error(err_msg);
    }
    if (is_rexpr_column && is_lexpr_column) {
        if (is_rexpr_plaintext != is_lexpr_plaintext) {
            throw std::runtime_error("Cannot compare a plaintext column with an encrypted column.");
        }
    }
    //判断是否为明文的条件
    if (!is_rexpr_plaintext && !is_lexpr_plaintext) {
        if (isTransformToFunction(op)) // SAHE SMHE ORE need to be calced in UDF
        {
            FuncCall *funcCall = makeNode(FuncCall);
            char *newFuncName = getMappedName(T_STRING_UDF_FUNCTION, op, NULL);
            funcCall->funcname = lappend(NIL, makeString(newFuncName));
            // 如果定义了SGX_ORE则 ore_udf(col1_aes, col2_aes)
            // 如果没有定义 则为 ore_udf(col1_ore,col2_ore, col1_aes, col2_aes)
            // 类比于MHE
            if (!encLexpr)
                encLexpr = (Node *) makeString("null");
            if (!encRexpr) {
                if (hasSecondCipherParams)
                    encRexpr = (Node *) makeString("null");
                else
                    encRexpr = encryptExpr(expr->rexpr, t2, info);
            }

            funcCall->args = lappend(funcCall->args, encLexpr);
            funcCall->args = lappend(funcCall->args, encRexpr);

            //如果不使用SGX，添加AES列也没有意义, 但是ore_min必须要添加AES
            // #ifdef USE_SGX
            Node *encLAESexpr = encryptExpr(expr->lexpr, CIPHER_AES, info);
            funcCall->args = lappend(funcCall->args, encLAESexpr);
            if (hasSecondCipherParams) {
                Node *encRAESexpr = encryptExpr(expr->rexpr, CIPHER_AES, info);
                funcCall->args = lappend(funcCall->args, encRAESexpr);
            }

            // #else
            //     funcCall->args = lappend(funcCall->args, (Node*)makeString("null"));
            //     if(hasSecondCipherParams)
            //         funcCall->args = lappend(funcCall->args, (Node*)makeString("null"));
            // #endif
            ans = (Node *) funcCall;
        } else {
            info->isALeftOps = true;
            encLexpr = encryptExpr(expr->lexpr, t1, info);
            info->isALeftOps = false;
            info->isARightOps = true;
            encRexpr = encryptExpr(expr->rexpr, t2, info);
            info->isARightOps = false;
            info->isFromAExpr = false;
            assert(t1 == CIPHER_AES || t1 == CIPHER_NOCRYPT || t1 == CIPHER_ORE|| t1 == CIPHER_SM4 || t1 == CIPHER_SM4CK|| t1 == CIPHER_AESHMAC);
            A_Expr *newExpr = makeNode(A_Expr);
            *newExpr = *expr;
            newExpr->lexpr = encLexpr;
            newExpr->rexpr = encRexpr;
            ans = (Node *) newExpr;
        }
    } else {
        ans = (Node *) expr;
    }
    return ans;
}

static CaseExpr *encryptCaseExpr(CaseExpr *ce, EncryptInfo *info) {
    CaseExpr *newCe = (CaseExpr *) copyObject(ce);
    // newCe->arg = (Expr *)encryptDispatcher((Node *)ce->arg, CIPHER_DET);
    newCe->arg = (Expr *) encryptDispatcher((Node *) ce->arg, CIPHER_AES, info);
    ListCell *cell;
    newCe->args = NIL;
    foreach (cell, ce->args) {
        Node *n = (Node *) lfirst(cell);
        if (IsA(n, CaseWhen)) {
            CaseWhen *newCW = makeNode(CaseWhen);
            newCW->expr = (Expr *) encryptDispatcher((Node *) ((CaseWhen *) n)->expr, DEFALUT_ENCRYPT_CIPHER, info);
            newCW->result = (Expr *) encryptDispatcher((Node *) ((CaseWhen *) n)->result, DEFALUT_ENCRYPT_CIPHER, info);
            newCe->args = lappend(newCe->args, newCW);
        } else
            errmsg("unhandled CaseExpr %d in encryptCaseExpr()\n", nodeTag(n));
    }

    newCe->defresult = (Expr *) encryptDispatcher((Node *) ce->defresult, DEFALUT_ENCRYPT_CIPHER, info);
    return newCe;
}

static List *encryptList(List *list, EncryptInfo *info) {
    ListCell *cell;
    List *newList = NIL;
    foreach (cell, list) {
        newList = lappend(newList, encryptDispatcher((Node *) lfirst(cell), DEFALUT_ENCRYPT_CIPHER, info));
    }
    return newList;
}

static Node *encryptDispatcher(Node *expr, T_Cipher t, EncryptInfo *info) {
    Node *res = NULL;
    if (!expr)
        return res;
    switch (nodeTag(expr)) {
        case T_ColumnRef:
            res = (Node *) encryptColumnRef((ColumnRef *) expr, t, info);
            break;
        case T_A_Const:
            res = (Node *) encryptAConst((A_Const *) expr, t, info);
            break;
        case T_FuncCall:
            res = (Node *) encryptFuncCall((FuncCall *) expr, info);
            break;
        case T_A_Expr:
            res = (Node *) encryptAExpr((A_Expr *) expr, info);
            break;
        case T_SubLink:
            res = (Node *) encryptSubLink((SubLink *) expr, info);
            break;
        case T_CaseExpr:
            res = (Node *) encryptCaseExpr((CaseExpr *) expr, info);
            break;
        case T_List:
            res = (Node *) encryptList((List *) expr, info);
            break;
        default:
            errmsg("unrecognized node type: %d in encryptDispatcher()", (int) nodeTag(expr));
            break;
    }
    return res;
}

bool funcCallNeedAESCol(const char *funcName) {
    if (strcmp(funcName, "count") == 0)
        return false;
    return true;
}

static List *encryptFunctionArgs(List *args, const char *funcName, EncryptInfo *info) {
    List *newList = NIL;
    ListCell *arg;
    int cnt = 0;
    foreach (arg, args) {
        ++cnt;
        Node *n = (Node *) lfirst(arg);
        T_Cipher t = getCipherTypeByOp(funcName, false);
        if (cnt == 2) {
            if (!strcmp(funcName, "pow")) //pow(id,INT)
                t = CIPHER_NOCRYPT;
        }
        newList = lappend(newList, encryptDispatcher(n, t, info));
        if (t != CIPHER_NOCRYPT && funcCallNeedAESCol(funcName))
            newList = lappend(newList, encryptDispatcher(n, CIPHER_AES, info));
    }
    return newList;
}

static List *encryptFunctionName(List *funcNames, EncryptInfo *info) {
    List *newNameList = NIL;
    ListCell *funcNameCell;
    foreach (funcNameCell, funcNames) {
        Value *funcName = (Value *) lfirst(funcNameCell);
        Value *UDFfuncName = makeString(getMappedName(T_STRING_UDF_FUNCTION, strVal(funcName), strVal(funcName)));
        // 如果map文件里没有funcname的映射udf，则返回原来的名字
        newNameList = lappend(newNameList, UDFfuncName);
    }
    return newNameList;
}

static Node *dealWithSpecialFunction(FuncCall *func, EncryptInfo *info) {
    if (!func)
        return nullptr;
    char *funcname = (char *) strVal((Value *) llast(func->funcname));
    Node *ret = nullptr;
    if (!strcmp(funcname, "now")) {
        int64_t now = GetCurrentTimestamp();
        // std::string strNow = ltos(now);
        ret = (Node *) makeNode(A_Const);
        ((A_Const *) ret)->val = *makeInteger(now);
    }
    return ret;
}

// 辅助函数：判断是否为聚合函数
static bool isAggFunction(const char *funcname) {
    return (strcmp(funcname, "max") == 0 ||
            strcmp(funcname, "min") == 0 ||
            strcmp(funcname, "sum") == 0 ||
            strcmp(funcname, "avg") == 0 ||
            strcmp(funcname, "count") == 0);
}

static FuncCall *encryptFuncCall(FuncCall *func, EncryptInfo *info) {
    Node *tmp = dealWithSpecialFunction(func, info);
    if (tmp)
        return (FuncCall *) tmp;

    FuncCall *newFuncCall = makeNode(FuncCall);
    *newFuncCall = *func;

    // 针对未加密列的聚合，进行特殊处理
    if (isAggFunction(strVal(linitial(func->funcname)))) {
        if (func->args && list_length(func->args) > 0) {
            Node *arg = (Node *) linitial(func->args);
            if (IsA(arg, ColumnRef)) {
                ColumnRef *col = (ColumnRef *) arg;
                char *colname = strVal(llast(col->fields));
                int ncipher = 0;
                T_Cipher ciphers[CIPHER_COUNT];
                getColumnCiphers(colname, ciphers, &ncipher);
                if (ncipher == 0) {
                    newFuncCall->funcname = func->funcname;
                    newFuncCall->args = NIL;
                    newFuncCall->args = lappend(newFuncCall->args, encryptDispatcher(arg, CIPHER_NOCRYPT, info));
                    return newFuncCall;
                }
            }
        }
    }

    newFuncCall->funcname = encryptFunctionName(func->funcname, info);
    newFuncCall->args = encryptFunctionArgs(func->args, strVal(linitial(func->funcname)), info);

    return newFuncCall;
}

static List *encryptTargetList(List *targetlist, bool isInsert, EncryptInfo *info) // 如果是来自insert，则target列需要进行
{
    List *p_target = NIL;
    ListCell *o_target;

    foreach (o_target, targetlist) {
        ResTarget *res = (ResTarget *) lfirst(o_target);
        ResTarget *newRes = makeNode(ResTarget);

        *newRes = *res;
        pfree(newRes->val);

        if (IsA(res->val, FuncCall)) {
            FuncCall *func = (FuncCall *) res->val;
            if (isAggFunction(strVal(linitial(func->funcname))) &&
                func->args && list_length(func->args) > 0) {
                Node *arg = (Node *) linitial(func->args);
                if (IsA(arg, ColumnRef)) {
                    ColumnRef *col = (ColumnRef *) arg;
                    char *colname = strVal(llast(col->fields));
                    int ncipher = 0;
                    T_Cipher ciphers[CIPHER_COUNT];
                    getColumnCiphers(colname, ciphers, &ncipher);
                    if (ncipher == 0) {
                        // 对于非加密列的聚合函数，直接使用原始值
                        newRes->val = res->val;
                        // 对于非加密列的聚合函数，添加特殊的NOCRYPT后缀
                        newRes->name = setMappedName(T_STRING_RESTMP, "NOCRYPT",
                                                     getRandomBytesInHex(MAP_NAME_BUFFER_SIZE));
                        p_target = lappend(p_target, newRes);
                        continue;
                    }
                }
            } else {
                Node *tmpRes = dealWithSpecialFunction((FuncCall *) res->val, info);
                res->val = tmpRes ? tmpRes : res->val;
            }
        }
        //不知道干啥的，还没遇到，先不管
        if (isInsert) {
            ColumnRef *ref = (ColumnRef *) res->val;
            char *colname = (char *) strVal(
                    (Value *) llast(ref->fields)); // 假设来自insert语句的select，那么ref->fields里面存储的都是columnname
            int ncipher = 0;
            T_Cipher ciphers[CIPHER_COUNT];

            getColumnCiphers(colname, ciphers, &ncipher);

            for (int i = 0; i < ncipher; ++i) {
                newRes = makeNode(ResTarget);
                newRes->val = encryptDispatcher(res->val, ciphers[i], info);
                p_target = lappend(p_target, newRes);
            }
        } else {
            //从这里开始处理select语句中的目标列
            newRes->val = encryptDispatcher(res->val, DEFALUT_ENCRYPT_CIPHER, info);
            p_target = lappend(p_target, newRes);
        }

        char *aliasname = res->name;

        if (IsA(res->val, A_Expr) || IsA(res->val, FuncCall)) {
            T_Cipher t = getEncryptTypeFromNode(res->val);
            //TODO: BUG 如果是insert into stu(id) select id from stu1; 那么就不需要替换
            if (t == CIPHER_ORE)
                t = DEFALUT_ENCRYPT_CIPHER; // ORE 不能解密
            aliasname = aliasname ? addEncryptSubfix(t, aliasname) : addEncryptSubfix(t, "unnamedColumn");
        }
        if (aliasname) { // 加密 AS 别称
            newRes->name = setMappedName(T_STRING_RESTMP, aliasname, getRandomBytesInHex(MAP_NAME_BUFFER_SIZE));
        }
    }
    return p_target;
}

static void replaceColumnDefType(TypeName *_typename, const char *type, T_Cipher t, EncryptInfo *info) {
    char *oldType = strVal(llast(_typename->names)); // WARN typename 长度是多少呢？

    if (t == CIPHER_NOCRYPT) // 如果这一列不需要加密，也就不需要替换类型。
        return;

    if (strcmp(oldType, type)) { //不相等
        List *listType = _typename->names;
        listType = list_delete(listType, llast(listType));
        listType = lappend(listType, makeString((char *) type));
    }
    // A_Const* param = makeNode(A_Const);
    // param->val = *makeInteger(getCipherFormatSize(CIPHER_FORMAT, t));
    _typename->typmods = NULL;
}

static List *
encryptColumnDefToList(ColumnDef *columnDef, const char *_typename, char **err_msg_internal) // for create clause only
{
    // create stmt 中需要将一个列扩展成多个列
    List *ansList = NIL;
    Constraint *uniqueConstraint = NULL;
    Constraint *primaryConstraint = NULL;
    bool hasPrimary = hasConstraintAndReturn(columnDef->constraints, CONSTR_PRIMARY, &primaryConstraint);
    bool hasUnique = hasConstraintAndReturn(columnDef->constraints, CONSTR_UNIQUE, &uniqueConstraint);

    if (hasPrimary) {
        // 检查加密列的加密类型中是否包含eq
        bool hasEq = false;
        ListCell *encTypeCell;
        // 如果是非加密列
        if (columnDef->enctypes == NIL) {
            hasEq = true;
        }
        foreach(encTypeCell, columnDef->enctypes) {
            if (strcmp((char *) lfirst(encTypeCell), "eq") == 0) {
                hasEq = true;
                break;
            }
        }

        if (!hasEq) {
            const char *message = "Primary key constraint requires 'eq' encryption type";
            *err_msg_internal = (char *) malloc(strlen(message) + 1);
            strcpy(*err_msg_internal, message);
        }
        columnDef->constraints = removeConstraints(columnDef->constraints, CONSTR_PRIMARY);
    }

    if (hasUnique) {
        columnDef->constraints = removeConstraints(columnDef->constraints, CONSTR_UNIQUE);
    }

    std::vector<T_Cipher> cipherVec;
    int actualnCipher = 0;

    //创建装EncType的vector string类型
    std::vector<std::string> enc_type_from_columnDef;
    bool isColEncrypted[CIPHER_COUNT] = {false};
    //判断是否为明文数据
    bool is_plain_type = false;
    if (columnDef->enctypes == NIL) {
        is_plain_type = true;
    } else {
        //从columnDef中提取加密数据
        ListCell *encTypeCell;
        foreach(encTypeCell, columnDef->enctypes) {
            char* encType = (char *) lfirst(encTypeCell);
            if(strcmp(encType, "eq_c") == 0){
                encType = "eq";
                isColEncrypted[CIPHER_AES] = true;
            }else if(strcmp(encType, "eqsm4_c") == 0){
                encType = "eqsm4";
                isColEncrypted[CIPHER_SM4] = true;
            }else if(strcmp(encType, "rnd_c") == 0){
                encType = "rnd";
                isColEncrypted[CIPHER_RND] = true;
            }else if(strcmp(encType, "cmp_c") == 0){
                const char *message = "cmp_c encryption type is not supported!";
                *err_msg_internal = (char *) malloc(strlen(message) + 1);
                strcpy(*err_msg_internal, message);
            }else if(strcmp(encType, "cal_c") == 0){
                const char *message = "cal_c encryption type is not supported!";
                *err_msg_internal = (char *) malloc(strlen(message) + 1);
                strcpy(*err_msg_internal, message);
            }
            
            enc_type_from_columnDef.push_back(encType);
        }
    }
    getCiphersByEnctypes(enc_type_from_columnDef, cipherVec, &actualnCipher, _typename, err_msg_internal);

    if (!is_plain_type) {
        for (int i = 0; i < actualnCipher; i++) {
            T_Cipher tCipher = cipherVec[i];
            char *cryptName = nullptr;
            ColumnDef *newDef = (ColumnDef *) copyObject(columnDef);
            char *colname = addEncryptSubfix(tCipher, columnDef->colname);
            size_t size = MAP_NAME_BUFFER_SIZE;
            if (tCipher != CIPHER_NOCRYPT)
                cryptName = getRandomBytesInHex(size);
            else
                cryptName = columnDef->colname;
            if (tCipher == CIPHER_ORE) {
                replaceColumnDefType(newDef->typeName, DATABASE_CIPHER_TYPE1, tCipher);
            } else {
                replaceColumnDefType(newDef->typeName, DATABASE_CIPHER_TYPE, tCipher);
            }
            if (hasPrimary && (tCipher == DEFALUT_PRIMARY_KEY_CIPHER || tCipher == CIPHER_NOCRYPT))
                newDef->constraints = lappend(newDef->constraints, primaryConstraint);
            if (hasUnique && (tCipher == CIPHER_AES || tCipher == CIPHER_ORE))
                newDef->constraints = lappend(newDef->constraints, uniqueConstraint);
            cryptName = setMappedName(T_STRING_COLUMN, colname, cryptName);
            newDef->colname = cryptName;
            //设置kms中的col
            // if(isColEncrypted[tCipher]) cmk_mapperSetInfoCol(cryptName);
            if(isColEncrypted[tCipher]) DekInterface::setInfoCol(cryptName);
            ansList = lappend(ansList, newDef);
        }
    } else {
        ColumnDef *newDef = (ColumnDef *) copyObject(columnDef);
        if (hasPrimary) {
            newDef->constraints = lappend(newDef->constraints, primaryConstraint);
        }
        if (hasUnique) {
            newDef->constraints = lappend(newDef->constraints, uniqueConstraint);
        }
        char *cryptName = columnDef->colname;
        auto tmp = setMappedName(T_STRING_COLUMN, cryptName, cryptName);
        newDef->colname = cryptName;
        ansList = lappend(ansList, newDef);
    }
    return ansList;
}

static List *encrypttableElts(List *tableElts, EncryptInfo *info, char **err_msg_internal) // for create clause only
{
    List *newCdefList = NIL;
    ListCell *columnDefCell;
    foreach (columnDefCell, tableElts) {
        Node *n = (Node *) lfirst(columnDefCell);
        if (IsA(n, ColumnDef)) {
            ColumnDef *columnDef = (ColumnDef *) n;
            TypeName *_typeName = columnDef->typeName;              // 获取列的类型名
            char *__typename = strVal(llast(_typeName->names));     // 获取列的类型名的字符串表示
            addColumnAndType(columnDef->colname, __typename);       // 将明文列名和类型名添加到映射器中
            newCdefList = list_concat(newCdefList,
                                      encryptColumnDefToList(columnDef, __typename,
                                                             err_msg_internal));  //将加密后的columnDef元素附加在newCdefList后
        } else if (IsA(n, Constraint)) {
            newCdefList = lappend(newCdefList, (Node *) encryptExplicitConstraint((Constraint *) n, info));
        }
    }
    return newCdefList;
}

static Constraint *encryptExplicitConstraint(Constraint *con, EncryptInfo *info) // 将显示声明的constraint扩展多次
{
    // int a = 1;
    List *ansKeys = NIL;
    Constraint *newCon = (Constraint *) copyObject(con);
    ListCell *cell = NULL, *cell2 = NULL;
    List *colList = NIL;
    List *pkList = NIL;
    List *ansKeys2 = NIL;

    if (con->contype == CONSTR_PRIMARY || con->contype == CONSTR_UNIQUE)
        colList = con->keys;

    else if (con->contype == CONSTR_FOREIGN) {
        colList = con->fk_attrs;
        pkList = con->pk_attrs;
        cell2 = list_head(pkList);

        if (con->pktable)
            newCon->pktable = encryptRangeVar(con->pktable, NULL, info);
    }

    foreach (cell, colList) {
        const char *colname = strVal((Value *) lfirst(cell));
        int ncipher = 0;
        T_Cipher ciphers[CIPHER_COUNT];
        getColumnCiphers(colname, ciphers, &ncipher);
        std::set<T_Cipher> setCiphers(ciphers, ciphers + ncipher);

        std::vector<T_Cipher> vectCiphers;

        if (con->contype == CONSTR_PRIMARY || con->contype == CONSTR_UNIQUE ||
            con->contype == CONSTR_FOREIGN) { // 如果是 primary key，只添加到一个加密列上。
            // TODO: 外键是否也加到同一个列上?
            if (setCiphers.count(DEFALUT_PRIMARY_KEY_CIPHER))
                vectCiphers.push_back(DEFALUT_PRIMARY_KEY_CIPHER);
            else if (setCiphers.count(CIPHER_NOCRYPT))
                vectCiphers.push_back(CIPHER_NOCRYPT);
            else {
                throw ("we have no column to add constraint key \n");
            }
        } else { // 不是上述所有情况，默认添加到所有加密列上
            vectCiphers.assign(ciphers, ciphers + ncipher);
        }

        for (auto &x: vectCiphers) {
            char *ciphercolname = getMappedName(T_STRING_COLUMN, addEncryptSubfix(x, colname), NULL);
            ansKeys = lappend(ansKeys, makeString(ciphercolname));

            if (cell2) {
                char *fkcolname = strVal((Value *) lfirst(cell2));
                ansKeys2 = lappend(ansKeys2,
                                   makeString(getMappedName(T_STRING_COLUMN, addEncryptSubfix(x, fkcolname), NULL)));
            }
        }

        if (cell2 && cell2->next)
            cell2 = lnext(cell2);
    }

    if (con->contype == CONSTR_PRIMARY || con->contype == CONSTR_UNIQUE)
        newCon->keys = ansKeys;

    else if (con->contype == CONSTR_FOREIGN) {
        newCon->fk_attrs = ansKeys;
        newCon->pk_attrs = ansKeys2;
    }

    return newCon;
}

static RangeSubselect *encryptRangeSubselect(RangeSubselect *rss, EncryptInfo *info) {
    RangeSubselect *newRss = makeNode(RangeSubselect);
    newRss->alias = encryptAlias(rss->alias);
    newRss->subquery = encryptStmt(rss->subquery, info, nullptr);
    return newRss;
}

static Alias *encryptAlias(Alias *alias, EncryptInfo *info) {
    if (!alias)
        return NULL;
    Alias *newAlias = makeNode(Alias);
    newAlias->aliasname = setMappedName(T_STRING_TBLTMP, alias->aliasname, getRandomBytesInHex(MAP_NAME_BUFFER_SIZE));
    newAlias->colnames = (List *) copyObject(alias->colnames); // TEST: What the fuck is this?
    return newAlias;
}

static char *encryptRVField(PlainDataType p_type, bool *isCreate, char *name, EncryptInfo *info) {
    char *ans = NULL;
    if (!isCreate)
        ans = getMappedName(p_type, name, NULL);
    else {
        size_t size = MAP_NAME_BUFFER_SIZE;
        ans = getMappedName(p_type, name, "");
        if (!*ans) { // 如果没有记录
            char *cryptName;
            cryptName = getRandomBytesInHex(size);
            cryptName = setMappedName(p_type, name, cryptName);
            ans = cryptName;
        } else
            *isCreate = false;
    }
    return ans;
}

static RangeVar *encryptRangeVar(RangeVar *rv, bool *isCreate, EncryptInfo *info) // isCreate字段为nullptr代表false
{
    RangeVar *newrv = makeNode(RangeVar);
    if (rv->catalogname) {
        newrv->catalogname = encryptRVField(T_STRING_CATALOG, isCreate, rv->catalogname);
    }
    if (rv->schemaname) {
        if (strcmp(rv->schemaname, "pg_catalog") == 0)
            return nullptr;
        newrv->schemaname = encryptRVField(T_STRING_SCHEMA, isCreate, rv->schemaname);
        setCurrentNodeOnce("", rv->schemaname);
    }
    if (rv->relname) {
        newrv->relname = encryptRVField(T_STRING_TABLE, isCreate, rv->relname);
        if (newrv->relname != NOEXIST)
            setFromTable(rv->relname);
        if (rv->alias) {
            newrv->alias = encryptAlias(rv->alias);
            setTableAlias(rv->relname, rv->alias->aliasname);
        }
        // cmk_mapperSetInfoTable(newrv->relname);
        DekInterface::setInfoTable(newrv->relname);
        
        //判断表名是否一致
        // if(isCreate||cmk_mapperGetInfoTable() != rv->relname){
        //     cmk_mapperSetInfoTable(newrv->relname);
        //     cmk_mapperClearDek();
        // }
        if(isCreate||DekInterface::getInfoTable() != rv->relname){
            DekInterface::setInfoTable(newrv->relname);
            DekInterface::clearDek();
        }
        std::string dek_table_level_tmp;
        // cmk_mapperGetDekTableLevel(dek_table_level_tmp);
        // if(dek_table_level_tmp.length() == 0){
        //     connectionSelect();
        // }
        DekInterface::getDekTableLevel(dek_table_level_tmp);
        if(dek_table_level_tmp.length() == 0){
            // connectionSelect();
            DekInterface::connectionSelect();
        }
    }

    newrv->relpersistence = rv->relpersistence;
    newrv->inhOpt = rv->inhOpt; // TEST: Don't know whats this is?
    return newrv;
}

static JoinExpr *encryptJoinExpr(JoinExpr *joinExpr, EncryptInfo *info) {
    JoinExpr *newJoinExpr = makeNode(JoinExpr);
    newJoinExpr->jointype = joinExpr->jointype;
    newJoinExpr->isNatural = joinExpr->isNatural;
    newJoinExpr->larg = (Node *) encryptRangeVar((RangeVar *) joinExpr->larg, NULL, info);
    newJoinExpr->rarg = (Node *) encryptRangeVar((RangeVar *) joinExpr->rarg, NULL, info);
    newJoinExpr->usingClause = (List *) copyObject(joinExpr->usingClause); // TEST: not process yet.
    newJoinExpr->quals = (Node *) encryptAExpr((A_Expr *) joinExpr->quals, info); // ON keyword
    newJoinExpr->alias = encryptAlias(joinExpr->alias);
    newJoinExpr->rtindex = joinExpr->rtindex;
    return newJoinExpr;
}

static List *encryptSortClause(List *SortClause, EncryptInfo *info) {
    List *newSortList = NIL;
    ListCell *sort;

    foreach (sort, SortClause) {
        SortBy *n = (SortBy *) lfirst(sort);
        SortBy *newSort = (SortBy *) copyObject(n);

        if (IsA(n->node, A_Const)) {
            newSort->node = (Node *) copyObject(n->node);
        } else
#if defined(SGX_ORE)
            newSort->node = encryptDispatcher(n->node, CIPHER_AES, info);
#else
            newSort->node = encryptDispatcher(n->node, CIPHER_ORE, info);
#endif
        newSortList = lappend(newSortList, newSort); // TEST: order by 应该是一个判断大小的操作
    }
    return newSortList;
}

static List *encryptGroupClause(List *groupClause, EncryptInfo *info) {
    List *newGroupList = NIL;
    ListCell *group;

    foreach (group, groupClause) {
        Node *n = (Node *) lfirst(group);
        if (IsA(n, ColumnRef)) {
            newGroupList = lappend(
                    // newGroupList, encryptColumnRef((ColumnRef *)n, CIPHER_DET)); // TEST: group by 应该是一个判断等于的操作
                    newGroupList, encryptColumnRef((ColumnRef *) n, CIPHER_AES, info));
        } else {
            errmsg("unrecognized node type: %d in encryptGroupClause()", (int) nodeTag(n));
        }
    }
    return newGroupList;
}

static List *encryptFromClause(List *fromClause, EncryptInfo *info) {
    List *newfrmList = NIL;
    ListCell *from;
    int i = 0;
    foreach (from, fromClause) {
        Node *n = (Node *) lfirst(from);
        if (!n) // 解析完毕还有List里面的元素是NULL的情况。
            break;
        i++;
        if (IsA(n, RangeVar)) {
            auto node = encryptRangeVar((RangeVar *) n, NULL, info);
            if (node == nullptr)
                return (List *) node;
            newfrmList = lappend(newfrmList, node);
        } else if (IsA(n, RangeSubselect)) {
            newfrmList = lappend(newfrmList, encryptRangeSubselect((RangeSubselect *) n));
        }

            // else if (IsA(n, RangeFunction))
            // { // TEST: Not Known what is this;
            //     // newfrmList = lappend(newfrmList, encryptFuncCall((RangeFunction *)n));
            // }
        else if (IsA(n, JoinExpr)) {
            newfrmList = lappend(newfrmList, encryptJoinExpr((JoinExpr *) n));
        } else {
            errmsg("unrecognized node type: %d in encryptFromClause()", (int) nodeTag(n));
        }
    }
    return newfrmList;
}

static List *encryptExtendTargetList(List *targetList, EncryptInfo *info) // 用于处理updatestmt insertStmt 中的columnref
{
    ListCell *cell;
    List *ansList = NIL;
    foreach (cell, targetList) {
        ResTarget *o_target = (ResTarget *) lfirst(cell);
        T_Cipher ciphers[CIPHER_COUNT];
        //主要处理now()函数
        //TODO 根据明密文判断是否需要进入这个函数
        if (o_target->val && IsA(o_target->val, FuncCall)) {
            Node *tmpRes = dealWithSpecialFunction((FuncCall *) o_target->val, info);
            o_target->val = tmpRes ? tmpRes : o_target->val;
        }
        int nCiphers = 0;
        getColumnCiphers(o_target->name, ciphers, &nCiphers);
        //处理是明文的情况
        if (nCiphers == 0) {
            ansList = lappend(ansList, o_target);
        }
        for (int i = 0; i < nCiphers; ++i) {
            ResTarget *newRS = makeNode(ResTarget);
            *newRS = *o_target;
            if (o_target->name) {
                char *colname = o_target->name;
                colname = addEncryptSubfix(ciphers[i], colname);
                newRS->name = getMappedName(T_STRING_COLUMN, colname, colname);
                //将insert的列信息传入kms
                // cmk_mapperSetInfoCol(newRS->name);
                DekInterface::setInfoCol(newRS->name);
                if (o_target->val)                                                   // Is A Expr
                    newRS->val = encryptDispatcher(o_target->val, ciphers[i], info); //TODO:  wantt
                ansList = lappend(ansList, newRS);
            } else {
                errmsg("updateStmt has no name in encryptExtendTargetList()\n");
            }
        }
    }
    return ansList;
}

static List *encryptValuesLists(List *valuesLists, List *cols, EncryptInfo *info) {
    // Not CHange
    ListCell *outCell;
    List *ansList = NIL;
    ColumnInfo **colInfos = NULL;
    int nInfo = 0;
    if (!cols){ // 没有指定列名，默认用所有的列
        getFirstTableAllColumnsInfoAlloc(&colInfos, &nInfo);

        for (int i = 0;i < nInfo; i++) {
			char *col = colInfos[i]->name;
			
			for(int j = 0;j < colInfos[i]->len; j++) {
                T_Cipher ctype = colInfos[i]->ciphers[j];
				if(ctype == CIPHER_NOCRYPT) {
					continue;
				}
				char *ecolname = addEncryptSubfix(ctype, col);
				ecolname = getMappedName(T_STRING_COLUMN, ecolname, col);
				// cmk_mapperSetInfoCol(ecolname);
                DekInterface::setInfoCol(ecolname);
			}
		}
    }
    else {
        getSpecifyColumnsInfoAlloc(cols, &colInfos);
        nInfo = cols->length;
    }

    //kms test
    // connectionSelect();
    DekInterface::connectionSelect();

    if (!colInfos)
        return NIL;
    foreach (outCell, valuesLists) {
        List *valueList = (List *) lfirst(outCell);
        List *newValueList = NIL;
        ListCell *innerCell;
        int p_colval = 0;
        foreach (innerCell, valueList) {
            ColumnInfo *colInfo = colInfos[p_colval];
            Node *n = (Node *) lfirst(innerCell);
            //edit by lrn
            // if (string(colInfo->type).find("float") != string::npos ||
            //     string(colInfo->type).find("int") != string::npos) {
            //     info->isFloatorIntCol = true;
            // } else {
            //     info->isFloatorIntCol = false;
            // }
            if (string(colInfo->type).find("float") != string::npos)
            {
                info->isFloatCol = true;
            }
            else
            {
                info->isFloatCol = false;
            }
            if (IsA(n, FuncCall)) {
                Node *tmpRes = dealWithSpecialFunction((FuncCall *) n, info);
                n = tmpRes ? tmpRes : n;
            }
            //处理明文的情况，可能还要修改
            if (colInfo->len == 0) {
                newValueList = lappend(newValueList, n);
            }
            for (size_t i = 0; i < colInfo->len; i++) {
                Node *ans = encryptDispatcher(n, colInfo->ciphers[i], info);
                newValueList = lappend(newValueList, ans);
            }
            p_colval++;
        }
        ansList = lappend(ansList, newValueList);
    }
    return ansList;
}

// static inline T_Cipher getCipherByString(const std::string& info) {
//     if (!info.compare("sum") || !info.compare("sub") || !info.compare("+") || !info.compare("-"))
//         return CIPHER_SAHE;

//     if (!info.compare("div") ||  !info.compare("*") || !info.compare("/"))
//         return CIPHER_SMHE;

//     return DEFALUT_ENCRYPT_CIPHER;
// }

static T_Cipher getEncryptTypeFromNode(Node *n, EncryptInfo *info) {
    char *name = nullptr;
    switch (n->type) {

        case T_A_Expr:
            name = strVal(((Value *) llast(((A_Expr *) n)->name)));
            break;

        case T_FuncCall:
            name = strVal(((Value *) llast(((FuncCall *) n)->funcname)));
            break;

        default:
            break;
    }
    return getCipherTypeByOp(name, true);
}

static InsertStmt *encryptInsertStmt(InsertStmt *parseTree, EncryptInfo *info) {
    InsertStmt *newTree = makeNode(InsertStmt);
    *newTree = *parseTree;
    newTree->relation = encryptRangeVar(parseTree->relation, NULL, info);
    //加密目标列表(column1, column2, ...)
    if (parseTree->cols) {
        newTree->cols = encryptExtendTargetList(parseTree->cols, info);
    }
    //加密value
    if (parseTree->selectStmt) {
        newTree->selectStmt = (Node *) encryptSelectStmt((SelectStmt *) parseTree->selectStmt, parseTree->cols, info);
    }
    return newTree;
}

static DeleteStmt *encryptDeleteStmt(DeleteStmt *parseTree, EncryptInfo *info) {
    DeleteStmt *newTree = makeNode(DeleteStmt);
    *newTree = *parseTree;
    newTree->relation = encryptRangeVar(parseTree->relation, NULL, info);
    if (parseTree->whereClause)
        newTree->whereClause = encryptDispatcher(parseTree->whereClause, DEFALUT_ENCRYPT_CIPHER, info);
    return newTree;
}

static UpdateStmt *encryptUpdateStmt(UpdateStmt *parseTree, EncryptInfo *info) {
    UpdateStmt *newUpdateTree = makeNode(UpdateStmt);
    *newUpdateTree = *parseTree;
    newUpdateTree->relation = encryptRangeVar(parseTree->relation, NULL, info);
    if (parseTree->fromClause)
        newUpdateTree->fromClause = encryptFromClause(parseTree->fromClause, info);
    if (parseTree->whereClause)
        newUpdateTree->whereClause = encryptDispatcher(parseTree->whereClause, DEFALUT_ENCRYPT_CIPHER, info);
    info->isFromUpdate = true;
    newUpdateTree->targetList = encryptExtendTargetList(parseTree->targetList, info);
    info->isFromUpdate = false;
    return newUpdateTree;
}

static SelectStmt *encryptSelectStmt(SelectStmt *parseTree, List *cols, EncryptInfo *info) {
    info->father = (void *) parseTree;
    SelectStmt *newParseTree = makeNode(SelectStmt);
    *newParseTree = *parseTree;

    if (parseTree->fromClause) {
        newParseTree->fromClause = (List *) encryptFromClause(parseTree->fromClause, info);
        if (newParseTree->fromClause == nullptr)
            return nullptr;
    }

    if (parseTree->targetList) {
        newParseTree->targetList = (List *) encryptTargetList(parseTree->targetList, (bool) cols, info);
    }

    if (parseTree->whereClause) {
        Node *n = parseTree->whereClause;
        newParseTree->whereClause = encryptDispatcher(n, DEFALUT_ENCRYPT_CIPHER, info);
    }

    if (parseTree->groupClause) {
        newParseTree->groupClause = encryptGroupClause(parseTree->groupClause, info);
    }

    if (parseTree->havingClause) {
        // TEST: having 常见的应该是 表达式 > Const， 处理不了。
    }

    if (parseTree->sortClause) {
        newParseTree->sortClause = encryptSortClause(parseTree->sortClause, info);
    }

    if (parseTree->valuesLists) {
        newParseTree->valuesLists = encryptValuesLists(parseTree->valuesLists, cols, info);
    }

    if (parseTree->lockingClause)
        newParseTree->lockingClause = (List *) copyObject(parseTree->lockingClause);

    return newParseTree;
}

static CreateStmt *encryptCreateStmt(CreateStmt *parseTree, EncryptInfo *info, char **err_msg_internal) {
    CreateStmt *newParseTree = makeNode(CreateStmt);
    *newParseTree = *parseTree;
    bool isCreate = true;
    newParseTree->relation = encryptRangeVar(parseTree->relation, &isCreate, info);
    if (isCreate) {
        newParseTree->tableElts = encrypttableElts(parseTree->tableElts, info, err_msg_internal);
        //在上一步已经存好信息在map，如果出现错误信息需要删除之前保存的信息
        if (*err_msg_internal != nullptr) {
            deleteNode(parseTree->relation->relname, "");
        }
    } else {
        newParseTree->tableElts = NULL;
    }
    //test for dek
    std::cout << "---------------------DEK-TEST---------------------" << std::endl;
    // std::cout << cmk_mapperGetInfoUser() << " : " << cmk_mapperGetInfoDb() << " : " << cmk_mapperGetInfoTable()
    //           << std::endl;
    // connectionInsertTest();
    // connectionSelectTest();
    std::cout << DekInterface::getInfoUser() << " : " << DekInterface::getInfoDb() << " : " << DekInterface::getInfoTable()
              << std::endl;
    DekInterface::connectionInsertTest();
    DekInterface::connectionSelectTest();
    std::cout << "---------------------DEK-TEST---------------------" << std::endl;
    return newParseTree;
}

static List *encryptAlterTableCmds(List *cmdList, EncryptInfo *info, char **err_msg_internal) {
    List *ansList = NIL;
    ListCell *cell;
    foreach (cell, cmdList) {
        Node *n = (Node *) lfirst(cell);

        Node *ans = nullptr;
        if (IsA(n, AlterTableCmd)) {
            AlterTableCmd *atcmd = (AlterTableCmd *) n;
            AlterTableCmd *newCmd = makeNode(AlterTableCmd);
            *newCmd = *atcmd; // shallow copy

            if (atcmd->subtype == AT_AddConstraint) {
                // 非递归约束添加
                if (atcmd->def && IsA(atcmd->def, Constraint)) {
                    newCmd->def = (Node *) encryptExplicitConstraint((Constraint *) atcmd->def, info);
                }
            } else if (atcmd->subtype == AT_AddColumn) {
                // 添加列操作
                if (atcmd->def && IsA(atcmd->def, ColumnDef)) {
                    ColumnDef *colDef = (ColumnDef *) atcmd->def;
                    TypeName *typeName = colDef->typeName;
                    char *type = strVal(llast(typeName->names));
                    addColumnAndType(colDef->colname, type);

                    // 获取加密后的列定义列表
                    List *encryptedCols = encryptColumnDefToList(colDef, type, err_msg_internal);

                    // 为每个加密列创建一个新的 ALTER TABLE 命令
                    ListCell *encColCell;
                    foreach(encColCell, encryptedCols) {
                        AlterTableCmd *encCmd = makeNode(AlterTableCmd);
                        *encCmd = *atcmd; // 复制原命令的基本信息
                        encCmd->def = (Node *) lfirst(encColCell);
                        ansList = lappend(ansList, encCmd);
                    }

                    continue; // 跳过默认的添加操作
                }
            } else if (atcmd->subtype == AT_DropColumn) {
                // 删除列操作
                // 获取待删除列的所有信息
                T_Cipher ciphers[CIPHER_COUNT];
                int nCipher = 0;
                getColumnCiphers(atcmd->name, ciphers, &nCipher);
                // 为每个加密类型创建一个新的 ALTER TABLE 命令
                // 如果没有被加密，就直接删除
                if (nCipher == 0) {
                    // 删除加密列的映射关系
                    deleteColumn(atcmd->name);
                    ansList = lappend(ansList, atcmd);
                    continue;
                }

                for (int i = 0; i < nCipher; i++) {
                    AlterTableCmd *encCmd = makeNode(AlterTableCmd);
                    *encCmd = *atcmd; // 复制原命令的基本信息
                    // 获取该加密类型列的密文名字
                    char *colname = addEncryptSubfix(ciphers[i], atcmd->name);
                    encCmd->name = getMappedName(T_STRING_COLUMN, colname, colname);
                    ansList = lappend(ansList, encCmd);
                }

                // 删除加密列的映射关系
                deleteColumn(atcmd->name);

                continue; // 跳过默认的删除操作
            }

            ans = (Node *) newCmd;
        }

        ansList = lappend(ansList, ans);
    }
    return ansList;
}

static AlterTableStmt *encryptAlterTableStmt(AlterTableStmt *parseTree, EncryptInfo *info, char **err_msg_internal) {
    AlterTableStmt *newParseTree = (AlterTableStmt *) makeNode(AlterTableStmt);

    if (parseTree->relation)
        newParseTree->relation = encryptRangeVar(parseTree->relation, NULL, info);

    if (parseTree->cmds)
        newParseTree->cmds = encryptAlterTableCmds(parseTree->cmds, info, err_msg_internal);

    return newParseTree;
}

static IndexStmt *encryptIndexStmt(IndexStmt *parseTree, EncryptInfo *info, char **err_msg_internal) {
    IndexStmt *newParseTree = (IndexStmt *) copyObject(parseTree);
    newParseTree->indexParams = NIL;
    ListCell *cell = nullptr;
    newParseTree->relation = encryptRangeVar(parseTree->relation, nullptr, info);
    foreach (cell, parseTree->indexParams) {
        IndexElem *oldelem = (IndexElem *) lfirst(cell);
        IndexElem *elem = (IndexElem *) copyObject(oldelem);
        int ncipher = 0;
        T_Cipher ciphers[CIPHER_COUNT];
        getColumnCiphers(elem->name, ciphers, &ncipher);
        std::set<T_Cipher> setCiphers(ciphers, ciphers + ncipher);
        // 创建index索引的顺序，目前计划支持ore类型和明文类型
        if (ncipher == 0) {
            elem->name = oldelem->name;
        } else if (setCiphers.count(CIPHER_ORE)) {
            elem->name = getMappedName(T_STRING_COLUMN, addEncryptSubfix(CIPHER_ORE, elem->name), NULL);
        } else if (setCiphers.count(CIPHER_AES)) {
            elem->name = getMappedName(T_STRING_COLUMN, addEncryptSubfix(CIPHER_AES, elem->name), NULL);
        } else {
            const char *message = "CAN NOT CREATE INDEX IN THIS COLUMN!";
            *err_msg_internal = (char *) malloc(strlen(message) + 1);
            strcpy(*err_msg_internal, message);
        }
        newParseTree->indexParams = lappend(newParseTree->indexParams, elem);
    }
    return newParseTree;
}

static DropStmt *encryptDropStmt(DropStmt *parseTree, EncryptInfo *info) {
    DropStmt *newParseTree = makeNode(DropStmt);
    *newParseTree = *parseTree;
    ListCell *ocell;
    List *newList = NIL;
    foreach (ocell, parseTree->objects) {
        List *l = NIL;
        Value *v = (Value *) linitial((const List *) lfirst(ocell)); // WARN 只取第一个，不清楚是否还有其他
        Value *newValue;
        const char *newV = NULL;
        if (parseTree->removeType == OBJECT_TABLE) {
            newV = getMappedName(T_STRING_TABLE, strVal(v), NOEXIST);
            // cmk_mapperSetInfoTable(newV);
            DekInterface::setInfoTable(newV);
            deleteNode(strVal(v), "");
        } else if (parseTree->removeType == OBJECT_SCHEMA) {
            newV = getMappedName(T_STRING_SCHEMA, strVal(v), NOEXIST);
            deleteNode("", strVal(v));
        } else
            newV = strVal(v);

        newValue = makeString((char *) newV);
        l = lappend(l, newValue);
        newList = lappend(newList, l);
    }
    newParseTree->objects = newList;
    // connectionDelete();
    DekInterface::connectionDelete();

    return newParseTree;
}

static ExplainStmt *encryptExplainStmt(ExplainStmt *parseTree, EncryptInfo *info) {
    ExplainStmt *newParseTree = (ExplainStmt *) copyObject(parseTree);
    *newParseTree = *parseTree;

    newParseTree->query = encryptStmt(parseTree->query, info, nullptr);
    return newParseTree;
}



/**
 * 复制文件的辅助函数
 * @param src 源文件路径
 * @param dst 目标文件路径
 * @return 0表示成功，-1表示失败
 */
 static int copyFile(const char *src, const char *dst) {
    FILE *srcFile = NULL, *dstFile = NULL;
    char buffer[8192];
    size_t bytesRead, bytesWritten;
    int result = -1;
    
    // 检查源文件是否存在
    if (access(src, F_OK) != 0) {
        fprintf(stderr, "Source file does not exist: %s\n", src);
        return -1;
    }
    
    srcFile = fopen(src, "rb");
    if (!srcFile) {
        fprintf(stderr, "Failed to open source file: %s, error: %s\n", src, strerror(errno));
        return -1;
    }
    
    dstFile = fopen(dst, "wb");
    if (!dstFile) {
        fprintf(stderr, "Failed to create destination file: %s, error: %s\n", dst, strerror(errno));
        fclose(srcFile);
        return -1;
    }
    
    // 复制文件内容
    while ((bytesRead = fread(buffer, 1, sizeof(buffer), srcFile)) > 0) {
        bytesWritten = fwrite(buffer, 1, bytesRead, dstFile);
        if (bytesWritten != bytesRead) {
            fprintf(stderr, "Write error while copying file\n");
            goto cleanup;
        }
    }
    
    // 检查读取是否出错
    if (ferror(srcFile)) {
        fprintf(stderr, "Read error while copying file\n");
        goto cleanup;
    }
    
    result = 0; // 成功
    
cleanup:
    if (srcFile) fclose(srcFile);
    if (dstFile) fclose(dstFile);
    
    // 如果复制失败，删除可能不完整的目标文件
    if (result != 0) {
        unlink(dst);
    }
    
    return result;
}


/**
 * 创建映射文件、密钥文件和数据库表的备份
 * 开始事务 
 * 在事务开始时调用，为原文件和数据库表创建备份副本
 */
#ifdef ENCRYPTSQL_USE_RECOVERY
static void create_backup(bool is_transaction) {
    int mapResult = 0, kmsResult = 0, dbResult = 0;

    const char* map_path = MAP_JSON_PATH;
    const char* map_backup;
    if(is_transaction) map_backup = MAP_JSON_BACKUP_PATH".t";
    else map_backup = MAP_JSON_BACKUP_PATH; 
    const char* kms_path = CMK_FILE_PATH;
    const char* kms_backup;
    if(is_transaction) kms_backup = CMK_FILE_BACKUP_PATH".t";
    else kms_backup = CMK_FILE_BACKUP_PATH;
    
    char* msg;
    // 备份映射文件
    if (access(map_path, F_OK) == 0) {
        mapResult = copyFile(map_path, map_backup);
        if (mapResult != 0) {
            fprintf(stderr, "Failed to backup map file: %s\n", map_path);
        } else {
            msg = "Map file backed up successfully\n";
        }
    } else {
        msg = "Map file does not exist, skipping backup\n";
    }

    #ifndef NDEBUG
        // std::cout << msg << std::endl;
    #endif
    
    // 备份密钥文件
    if (access(kms_path, F_OK) == 0) {
        kmsResult = copyFile(kms_path, kms_backup);
        if (kmsResult != 0) {
            fprintf(stderr, "Failed to backup KMS file: %s\n", kms_path);
        } else {
            msg = "KMS file backed up successfully\n";
        }
    } else {
        msg = "KMS file does not exist, skipping backup\n";
    }

    #ifndef NDEBUG
       // std::cout << msg << std::endl;
    #endif
    
    // 备份数据库表
    dbResult = DekInterface::backupDekStore();
    
    #ifndef NDEBUG
    // // 如果任一备份失败，记录错误但不阻止事务继续
    // if (mapResult != 0 || kmsResult != 0 || dbResult != 0) {
    //     fprintf(stderr, "Warning: Some backups failed, transaction may not be fully recoverable\n");
    // } else {
    //     printf("All backups completed successfully\n");
    // }
    #endif

}

/**
 * 删除备份文件和数据库表
 * 提交事务
 * 在事务成功提交时调用，删除不再需要的备份文件和表
 */

extern __thread bool Encrypt;
extern __thread bool SkipDecryptRes;
void delete_backup(bool is_transaction) {
    if(SkipDecryptRes|| !Encrypt) {
        return;
    }
    int mapResult = 0, kmsResult = 0, dbResult = 0;

    const char* map_path = MAP_JSON_PATH;
    const char* map_backup;
    if(is_transaction) map_backup = MAP_JSON_BACKUP_PATH".t";
    else map_backup = MAP_JSON_BACKUP_PATH; 
    const char* kms_path = CMK_FILE_PATH;
    const char* kms_backup;
    if(is_transaction) kms_backup = CMK_FILE_BACKUP_PATH".t";
    else kms_backup = CMK_FILE_BACKUP_PATH;
    
    char* msg;
    // 删除映射文件备份
    if (access(map_backup, F_OK) == 0) {
        if (unlink(map_backup) != 0) {
            fprintf(stderr, "Failed to delete map backup file: %s, error: %s\n", 
                map_backup, strerror(errno));
            mapResult = -1;
        } else {
            msg = "Map backup file deleted successfully\n";
        }
    } else {
        msg = "Map backup file does not exist\n";
    }

    #ifndef NDEBUG
       // std::cout << msg << std::endl;
    #endif
    
    // 删除密钥文件备份
    if (access(kms_backup, F_OK) == 0) {
        if (unlink(kms_backup) != 0) {
            fprintf(stderr, "Failed to delete KMS backup file: %s, error: %s\n", 
                kms_backup, strerror(errno));
            kmsResult = -1;
        } else {
            msg = "KMS backup file deleted successfully\n";
        }
    } else {
        msg = "KMS backup file does not exist\n";
    }

    #ifndef NDEBUG
       // std::cout << msg << std::endl;
    #endif
    
    // 删除数据库备份表
    dbResult = DekInterface::deleteDekStoreBackup();
    
    #ifndef NDEBUG
        // if (mapResult == 0 && kmsResult == 0 && dbResult == 0) {
        //     printf("Transaction committed successfully - all backups cleaned up\n");
        // } else {
        //     fprintf(stderr, "Warning: Failed to clean up some backup files or database tables\n");
        // }
    #endif
}

/**
 * 恢复备份文件和数据库表
 * 回滚事务
 * 在事务需要回滚时调用，恢复文件和数据库表到事务开始前的状态
 */
void recovery_backup(bool is_transaction) {
    int mapResult = 0, kmsResult = 0, dbResult = 0;

    const char* map_path = MAP_JSON_PATH;
    const char* map_backup;
    if(is_transaction) map_backup = MAP_JSON_BACKUP_PATH".t";
    else map_backup = MAP_JSON_BACKUP_PATH; 
    const char* kms_path = CMK_FILE_PATH;
    const char* kms_backup;
    if(is_transaction) kms_backup = CMK_FILE_BACKUP_PATH".t";
    else kms_backup = CMK_FILE_BACKUP_PATH;
    
    char* msg;
    // 恢复映射文件
    if (access(map_backup, F_OK) == 0) {
        mapResult = copyFile(map_backup, map_path);
        if (mapResult != 0) {
            fprintf(stderr, "Failed to restore map file from backup\n");
        } else {            
            msg = "Map file restored from backup successfully\n";
            // 删除备份文件
            if (unlink(map_backup) != 0) {
                fprintf(stderr, "Warning: Failed to delete map backup file after restore\n");
            }
        }
    } else {
        msg = "No map backup file found for rollback\n";
    }
    #ifndef NDEBUG
       // std::cout << msg << std::endl;
    #endif

    // 恢复密钥文件
    if (access(kms_backup, F_OK) == 0) {
        kmsResult = copyFile(kms_backup, kms_path);
        if (kmsResult != 0) {
            fprintf(stderr, "Failed to restore KMS file from backup\n");
        } else {
            msg = "KMS file restored from backup successfully\n";
            // 删除备份文件
            if (unlink(kms_backup) != 0) {
                fprintf(stderr, "Warning: Failed to delete KMS backup file after restore\n");
            }
        }
    } else {
        msg = "No KMS backup file found for rollback\n";
    }

    #ifndef NDEBUG
       // std::cout << msg << std::endl;
    #endif
    
    // 恢复数据库表
    dbResult = DekInterface::restoreDekStore();

    #ifndef NDEBUG
        // if (mapResult == 0 && kmsResult == 0 && dbResult == 0) {
        //     printf("Transaction rolled back successfully - all data restored\n");
        // } else {
        //     fprintf(stderr, "Error: Failed to completely rollback transaction\n");
        // }
    #endif
}

static void solveTransaction(const EncryptInfo *info){
    //begin or commit or rollback
    // 假设info是包含sql字符串的结构体
    if (info->sql != NULL) {
        // 使用不区分大小写的比较
        if (strcasecmp(info->sql, "BEGIN;") == 0) {
            // 处理BEGIN事务
            create_backup(true);
        } 
        else if (strcasecmp(info->sql, "COMMIT;") == 0) {
            // 处理COMMIT事务
            delete_backup(true);
        } 
        else if (strcasecmp(info->sql, "ROLLBACK;") == 0) {
            // 处理ROLLBACK事务
            recovery_backup(true);
        }
    }
}

#else 
static void create_backup(bool is_transaction) {
}
void delete_backup(bool is_transaction) {
}
void recovery_backup(bool is_transaction) {
}
static void solveTransaction(const EncryptInfo *info){
}

#endif

Node *encryptStmt(Node *parseTree, EncryptInfo *info, char **err_msg_internal) {
    Node *newTree = NULL;
    info->father = (void *) parseTree;
    switch (nodeTag(parseTree)) {
        case T_InsertStmt:  //已支持列加密
            newTree = (Node *) encryptInsertStmt((InsertStmt *) parseTree, info);
            break;
        case T_DeleteStmt:
            newTree = (Node *) encryptDeleteStmt((DeleteStmt *) parseTree, info);
            mapperSave();
            break;
        case T_UpdateStmt:
            newTree = (Node *) encryptUpdateStmt((UpdateStmt *) parseTree, info);
            break;
        case T_SelectStmt:
            try {
                newTree = (Node *) encryptSelectStmt((SelectStmt *) parseTree, NULL, info);
            } catch (const std::exception &e) {
                *err_msg_internal = (char *) malloc(strlen(e.what()) + 1);
                strcpy(*err_msg_internal, e.what());
            }
//		    newTree = (Node *) encryptSelectStmt((SelectStmt *) parseTree, NULL, info);
            break;
        case T_CreateStmt:  //已支持列加密
            create_backup(false);   
            newTree = (Node *) encryptCreateStmt((CreateStmt *) parseTree, info, err_msg_internal);
            if (*err_msg_internal == nullptr) {
                mapperSave();
            }
            break;
        case T_IndexStmt:   //已支持列加密，目前支持在明文和有CMP加密功能的列上创建索引
            newTree = (Node *) encryptIndexStmt((IndexStmt *) parseTree, info, err_msg_internal);
            if (*err_msg_internal == nullptr) {
                mapperSave();
            }
            break;
        case T_DropStmt:    //已支持列加密，目前支持table、database
            create_backup(false);
            newTree = (Node *) encryptDropStmt((DropStmt *) parseTree, info);
            break;
        case T_AlterTableStmt:
            create_backup(false);   
            newTree = (Node *) encryptAlterTableStmt((AlterTableStmt *) parseTree, info, err_msg_internal);
            if (*err_msg_internal == nullptr) {
                mapperSave();
            }
            break;
        case T_ExplainStmt:
            newTree = (Node *) encryptExplainStmt((ExplainStmt *) parseTree, info);
            break;
        case T_TransactionStmt:
            solveTransaction(info);
            break;
        case T_VariableSetStmt:
        case T_VariableShowStmt:
            // no need to encrypt
            break;
        default:
            errdebug("unknown parseTree type: %d in encryptStmt()\n", nodeTag(parseTree));
            break;
    }
    return newTree;
}
