Группа проблем при определении типа Postgres - PullRequest
0 голосов
/ 12 марта 2020

Я пишу пользовательский тип в PostgreSQL на C языке с именем personname:

в C:

#define FLXIBLE_ARRAY_MEMBER 0

PG_MODULE_MAGIC;

typedef struct personname{
    char size[4];
    int familyLen;
    int givenLen;
    int givenStart;
    char pname[FLXIBLE_ARRAY_MEMBER];
}personname;

и в sql

CREATE TYPE personname (
   internallength = VARIABLE,
   input = pname_in,
   output = pname_out
);

Теперь у меня есть таблица с именем users, в ней есть идентификатор и реальное имя типа personname, я могу правильно сделать "select * from users where realname = 'XXX';", но не могу сделать "select count(*) from users group by realname;", и если я сгруппирую результат из "select * from users where realname = 'XXX';" снова работает нормально. enter image description here

Я определяю свою функцию равенства следующим образом: в C:

char* getFamily(personname *name){
    int famLen = name->familyLen;
    char *family = (char*) palloc(sizeof(char) * famLen + 1);

    for(int i = 0; i < famLen; i++){
        family[i] = name->pname[i];
    }

    family[famLen] = '\0';
    return family;
}

char* getGiven(personname *name){
    int givenLen = name->givenLen;
    char *given = (char*) palloc(sizeof(char) * givenLen + 1);
    int givenStart = name->givenStart;

    for(int i = 0; i < givenLen; i++){
        given[i] = name->pname[givenStart + i];
    }

    given[givenLen] = '\0';
    return given;
}
PG_FUNCTION_INFO_V1(personname_equal);

Datum
personname_equal(PG_FUNCTION_ARGS)
{
    personname *name1 = (personname *) PG_GETARG_POINTER(0);
    personname *name2 = (personname *) PG_GETARG_POINTER(1);

    bool result;
    char *family1 = getFamily(name1);
    char *family2 = getFamily(name2);
    char *given1 = getGiven(name1);
    char *given2 = getGiven(name2);

    if(strcmp(family1, family2) == 0 && strcmp(given1, given2) == 0){
        result = true;
    }else{
        result = false;
    }

    pfree(family1);
    pfree(family2);
    pfree(given1);
    pfree(given2);

    PG_RETURN_BOOL(result);
}

в sql:

CREATE FUNCTION personname_equal(personname, personname) 
   RETURNS bool
   AS '_OBJWD_/pname' 
   LANGUAGE C IMMUTABLE STRICT;

CREATE OPERATOR = (
   leftarg = personname, rightarg = personname, procedure = personname_equal,
   commutator = = ,
   negator = <> ,
   restrict = eqsel, join = eqjoinsel
);
...
CREATE OPERATOR CLASS personname_cmp_ops
    DEFAULT FOR TYPE personname USING btree AS
        OPERATOR        1       < ,
        OPERATOR        2       <= ,
        OPERATOR        3       = ,
        OPERATOR        4       >= ,
        OPERATOR        5       > ,
        FUNCTION        1       personname_cmp(personname, personname);

CREATE OPERATOR CLASS personname_ops
    DEFAULT FOR TYPE personname USING hash AS
        OPERATOR        1       = ,
        FUNCTION        1       hash_personname(personname);

Я запутался в группе, в официальном документе говорится, что она использует '=', но '=' работает нормально, когда я выбираю и группирую в результате выбора, но возникают проблемы при группировке по всей таблице. Посоветуйте кто нибудь подскажите где я делаю не так? Чем вы так сильно.

...