PostgreSQL 源码解读 node的模拟实现

 

node的实现是PostgreSQL的查询解析的基础,实现的关键是两个宏,makeNode和newNode。其他节点继承自Node节点,如果增加新的结构体,需要添加NodeTag中添加对应的枚举值,并在equal和nodetoString中添加对于的处理代码。当结构体少是很容易处理,如果结构体过多,维护会比较麻烦。PostgreSQL中大约有300个继承自node的结构体,写代码的人真是需要相当的勇气和毅力呀。

 

#include <iostream>

#include <string.h>

#include <assert.h>

#include <stdlib.h>

#include <stdio.h>

using namespace std;

 

enum NodeTag

{

    T_Stmt,

    T_Value

};

 

typedef struct Node

{

    NodeTag type;

}Node;

 

Node *newNodeMacroHolder ;

#define newNode(size, tag) \

    ( \

         assert((size) >= sizeof(Node)),        /* need the tag, at least */ \

         newNodeMacroHolder = (Node *) malloc(size), \

         newNodeMacroHolder->type = (tag), \

         newNodeMacroHolder \

    )

 

#define makeNode(_type_) ((_type_ *)newNode(sizeof(_type_),T_##_type_))

#define nodeTag(nodeptr) (((const Node *)(nodeptr))->type)

 

typedef struct Stmt

{

    NodeTag type;

    char *text;

}Stmt;

typedef struct Value

{

    NodeTag type;

    long val;

}Value;

 

bool equal(void *a,void *b)

{

    if(a == b)

        return true;

    if (a == NULL || b == NULL)

        return false;

    if(nodeTag(a) != nodeTag(b))

        return false;

 

    switch(nodeTag(a)){

        case T_Stmt:

            return strcmp(((const Stmt*)a)->text,((const Stmt *)b)->text)==0? true:false;

        case T_Value:

            return ((const Value *)a)->val==((const Value *)b)->val;

        default:

            cout<<"error:unknown type"<<endl;

    }

 

    return false;

}

char * nodetoString(void *obj)

{

    char *r =(char *)malloc(1024);

 

    if (obj == NULL){

        strcpy(r,"<>");

    }

 

    switch(nodeTag(obj)){

        case T_Stmt:

            sprintf(r,"<Stmt:%s>",((const Stmt *)obj)->text);

            break;

        case T_Value:

            sprintf(r,"<Value:%ld>",((const Value *)obj)->val);

            break;

        default:

            strcpy(r,"<unknown node type>");

    }

 

    return r;

}

 

int main(int argc,char *argv[])

{

    Stmt *s= makeNode(Stmt);

    if(s){

        char str[]="select * from a";

        s->text=str;

    }

        

    Stmt *t= makeNode(Stmt);

    if(t){

        char str[]="select * from b";

        t->text=str;

    }

    Value *v=makeNode(Value);

    if(v){

        v->val=100;

    }

 

    cout<<"t->text:"<<t->text<<endl;

    

    cout<<"equal:"<<equal(s,t)<<endl;

 

    cout<<nodetoString(t)<<endl;

 

    free(s);

    free(t);

    free(v);

    return 0;

}

 

如果准备使用C语言来实现node结构体的话,尤其是准备采用gcc编译的话,要注意将newNode的宏设置为

/* 针对gcc版本的newNode */

#define newNode(size, tag) \

({    Node *_result; \

    AssertMacro((size) >= sizeof(Node));/* 检测申请的内存大小,>>=sizeof(Node) */ \

    _result = (Node *) palloc0fast(size); /* 申请内存 */ \

    _result->type = (tag); /*设置TypeTag */ \

    _result; /*返回值*/\

})

 

参见我的另一篇笔记《PostgreSQL源码解读 基础结构 node

posted @ 2013-11-11 20:54  蝴蝶忽然  阅读(629)  评论(0编辑  收藏  举报