Я пишу пользовательский тип в 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';"
снова работает нормально.
Я определяю свою функцию равенства следующим образом: в 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);
Я запутался в группе, в официальном документе говорится, что она использует '=', но '=' работает нормально, когда я выбираю и группирую в результате выбора, но возникают проблемы при группировке по всей таблице. Посоветуйте кто нибудь подскажите где я делаю не так? Чем вы так сильно.