Started adding comparison functions
This commit is contained in:
parent
339fac17d2
commit
25d23b90d3
|
@ -76,12 +76,11 @@ extern "C" {
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_in);
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_in);
|
||||||
|
|
||||||
PGDLLEXPORT
|
PGDLLEXPORT Datum
|
||||||
Datum
|
phone_number_in(PG_FUNCTION_ARGS) {
|
||||||
phone_number_in(PG_FUNCTION_ARGS)
|
|
||||||
{
|
|
||||||
const char *number_str = PG_GETARG_CSTRING(0);
|
const char *number_str = PG_GETARG_CSTRING(0);
|
||||||
|
|
||||||
|
//TODO: use international format instead.
|
||||||
ShortPhoneNumber* number = parsePhoneNumber(number_str, "US");
|
ShortPhoneNumber* number = parsePhoneNumber(number_str, "US");
|
||||||
if(number) {
|
if(number) {
|
||||||
PG_RETURN_POINTER(number);
|
PG_RETURN_POINTER(number);
|
||||||
|
@ -92,10 +91,8 @@ extern "C" {
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(parse_phone_number);
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(parse_phone_number);
|
||||||
|
|
||||||
PGDLLEXPORT
|
PGDLLEXPORT Datum
|
||||||
Datum
|
parse_phone_number(PG_FUNCTION_ARGS) {
|
||||||
parse_phone_number(PG_FUNCTION_ARGS)
|
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
const text* number_text = PG_GETARG_TEXT_P(0);
|
const text* number_text = PG_GETARG_TEXT_P(0);
|
||||||
const text* country_text = PG_GETARG_TEXT_P(1);
|
const text* country_text = PG_GETARG_TEXT_P(1);
|
||||||
|
@ -112,7 +109,7 @@ extern "C" {
|
||||||
} else {
|
} else {
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
}
|
}
|
||||||
} catch(std::bad_alloc e) {
|
} catch(std::bad_alloc& e) {
|
||||||
reportOutOfMemory();
|
reportOutOfMemory();
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
reportGenericError(e);
|
reportGenericError(e);
|
||||||
|
@ -121,10 +118,8 @@ extern "C" {
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_out);
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_out);
|
||||||
|
|
||||||
PGDLLEXPORT
|
PGDLLEXPORT Datum
|
||||||
Datum
|
phone_number_out(PG_FUNCTION_ARGS) {
|
||||||
phone_number_out(PG_FUNCTION_ARGS)
|
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
const ShortPhoneNumber* short_number = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
const ShortPhoneNumber* short_number = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
PhoneNumber number = *short_number;
|
PhoneNumber number = *short_number;
|
||||||
|
@ -154,8 +149,7 @@ extern "C" {
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_recv);
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_recv);
|
||||||
|
|
||||||
PGDLLEXPORT
|
PGDLLEXPORT Datum
|
||||||
Datum
|
|
||||||
phone_number_recv(PG_FUNCTION_ARGS) {
|
phone_number_recv(PG_FUNCTION_ARGS) {
|
||||||
try {
|
try {
|
||||||
StringInfo buf = (StringInfo)PG_GETARG_POINTER(0);
|
StringInfo buf = (StringInfo)PG_GETARG_POINTER(0);
|
||||||
|
@ -176,8 +170,7 @@ extern "C" {
|
||||||
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_send);
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_send);
|
||||||
|
|
||||||
PGDLLEXPORT
|
PGDLLEXPORT Datum
|
||||||
Datum
|
|
||||||
phone_number_send(PG_FUNCTION_ARGS) {
|
phone_number_send(PG_FUNCTION_ARGS) {
|
||||||
try {
|
try {
|
||||||
const ShortPhoneNumber *number = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
const ShortPhoneNumber *number = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
@ -194,4 +187,101 @@ extern "C" {
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_equal);
|
||||||
|
|
||||||
|
PGDLLEXPORT Datum
|
||||||
|
phone_number_equal(PG_FUNCTION_ARGS) {
|
||||||
|
try {
|
||||||
|
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
||||||
|
|
||||||
|
PG_RETURN_BOOL(*number1 == *number2);
|
||||||
|
} catch(std::exception& e) {
|
||||||
|
reportGenericError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_not_equal);
|
||||||
|
|
||||||
|
PGDLLEXPORT Datum
|
||||||
|
phone_number_not_equal(PG_FUNCTION_ARGS) {
|
||||||
|
try {
|
||||||
|
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
||||||
|
|
||||||
|
PG_RETURN_BOOL(*number1 != *number2);
|
||||||
|
} catch(std::exception& e) {
|
||||||
|
reportGenericError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_less);
|
||||||
|
|
||||||
|
PGDLLEXPORT Datum
|
||||||
|
phone_number_less(PG_FUNCTION_ARGS) {
|
||||||
|
try {
|
||||||
|
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
||||||
|
|
||||||
|
PG_RETURN_BOOL(number1->compare_fast(*number2) < 0);
|
||||||
|
} catch(std::exception& e) {
|
||||||
|
reportGenericError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_less_or_equal);
|
||||||
|
|
||||||
|
PGDLLEXPORT Datum
|
||||||
|
phone_number_less_or_equal(PG_FUNCTION_ARGS) {
|
||||||
|
try {
|
||||||
|
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
||||||
|
|
||||||
|
PG_RETURN_BOOL(number1->compare_fast(*number2) <= 0);
|
||||||
|
} catch(std::exception& e) {
|
||||||
|
reportGenericError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_greater);
|
||||||
|
|
||||||
|
PGDLLEXPORT Datum
|
||||||
|
phone_number_greater(PG_FUNCTION_ARGS) {
|
||||||
|
try {
|
||||||
|
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
||||||
|
|
||||||
|
PG_RETURN_BOOL(number1->compare_fast(*number2) > 0);
|
||||||
|
} catch(std::exception& e) {
|
||||||
|
reportGenericError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(phone_number_greater_or_equal);
|
||||||
|
|
||||||
|
PGDLLEXPORT Datum
|
||||||
|
phone_number_greater_or_equal(PG_FUNCTION_ARGS) {
|
||||||
|
try {
|
||||||
|
const ShortPhoneNumber* number1 = (ShortPhoneNumber*)PG_GETARG_POINTER(0);
|
||||||
|
const ShortPhoneNumber* number2 = (ShortPhoneNumber*)PG_GETARG_POINTER(1);
|
||||||
|
|
||||||
|
PG_RETURN_BOOL(number1->compare_fast(*number2) >= 0);
|
||||||
|
} catch(std::exception& e) {
|
||||||
|
reportGenericError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
CREATE TYPE phone_number;
|
CREATE TYPE phone_number;
|
||||||
|
|
||||||
|
--Basic function definitions
|
||||||
|
|
||||||
CREATE FUNCTION phone_number_in(cstring) RETURNS phone_number
|
CREATE FUNCTION phone_number_in(cstring) RETURNS phone_number
|
||||||
LANGUAGE c IMMUTABLE STRICT
|
LANGUAGE c IMMUTABLE STRICT
|
||||||
AS 'pg_libphonenumber', 'phone_number_in';
|
AS 'pg_libphonenumber', 'phone_number_in';
|
||||||
|
@ -29,9 +31,111 @@ CREATE TYPE phone_number (
|
||||||
STORAGE = plain
|
STORAGE = plain
|
||||||
);
|
);
|
||||||
|
|
||||||
|
--Cast definitions
|
||||||
|
|
||||||
CREATE CAST (phone_number AS text)
|
CREATE CAST (phone_number AS text)
|
||||||
WITH INOUT;
|
WITH INOUT;
|
||||||
|
|
||||||
|
--Operator definitions
|
||||||
|
|
||||||
|
CREATE FUNCTION phone_number_equal(phone_number, phone_number) RETURNS bool
|
||||||
|
LANGUAGE c IMMUTABLE STRICT
|
||||||
|
AS 'pg_libphonenumber', 'phone_number_equal';
|
||||||
|
|
||||||
|
CREATE OPERATOR = (
|
||||||
|
leftarg = phone_number,
|
||||||
|
rightarg = phone_number,
|
||||||
|
procedure = phone_number_equal,
|
||||||
|
commutator = =,
|
||||||
|
negator = <>,
|
||||||
|
restrict = eqsel,
|
||||||
|
join = eqjoinsel,
|
||||||
|
hashes = true,
|
||||||
|
merges = true
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE FUNCTION phone_number_not_equal(phone_number, phone_number) RETURNS bool
|
||||||
|
LANGUAGE c IMMUTABLE STRICT
|
||||||
|
AS 'pg_libphonenumber', 'phone_number_not_equal';
|
||||||
|
|
||||||
|
CREATE OPERATOR <> (
|
||||||
|
leftarg = phone_number,
|
||||||
|
rightarg = phone_number,
|
||||||
|
procedure = phone_number_not_equal,
|
||||||
|
commutator = <>,
|
||||||
|
negator = =,
|
||||||
|
restrict = neqsel,
|
||||||
|
join = neqjoinsel
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE FUNCTION phone_number_less(phone_number, phone_number) RETURNS bool
|
||||||
|
LANGUAGE c IMMUTABLE STRICT
|
||||||
|
AS 'pg_libphonenumber', 'phone_number_less';
|
||||||
|
|
||||||
|
CREATE OPERATOR < (
|
||||||
|
leftarg = phone_number,
|
||||||
|
rightarg = phone_number,
|
||||||
|
procedure = phone_number_less,
|
||||||
|
commutator = >,
|
||||||
|
negator = >=,
|
||||||
|
restrict = scalarltsel,
|
||||||
|
join = scalarltjoinsel
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE FUNCTION phone_number_less_or_equal(phone_number, phone_number) RETURNS bool
|
||||||
|
LANGUAGE c IMMUTABLE STRICT
|
||||||
|
AS 'pg_libphonenumber', 'phone_number_less_or_equal';
|
||||||
|
|
||||||
|
CREATE OPERATOR <= (
|
||||||
|
leftarg = phone_number,
|
||||||
|
rightarg = phone_number,
|
||||||
|
procedure = phone_number_less_or_equal,
|
||||||
|
commutator = >=,
|
||||||
|
negator = >,
|
||||||
|
restrict = scalarltsel,
|
||||||
|
join = scalarltjoinsel
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE FUNCTION phone_number_greater(phone_number, phone_number) RETURNS bool
|
||||||
|
LANGUAGE c IMMUTABLE STRICT
|
||||||
|
AS 'pg_libphonenumber', 'phone_number_greater';
|
||||||
|
|
||||||
|
CREATE OPERATOR > (
|
||||||
|
leftarg = phone_number,
|
||||||
|
rightarg = phone_number,
|
||||||
|
procedure = phone_number_greater,
|
||||||
|
commutator = >,
|
||||||
|
negator = <=,
|
||||||
|
restrict = scalargtsel,
|
||||||
|
join = scalargtjoinsel
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE FUNCTION phone_number_greater_or_equal(phone_number, phone_number) RETURNS bool
|
||||||
|
LANGUAGE c IMMUTABLE STRICT
|
||||||
|
AS 'pg_libphonenumber', 'phone_number_greater_or_equal';
|
||||||
|
|
||||||
|
CREATE OPERATOR >= (
|
||||||
|
leftarg = phone_number,
|
||||||
|
rightarg = phone_number,
|
||||||
|
procedure = phone_number_greater_or_equal,
|
||||||
|
commutator = >=,
|
||||||
|
negator = <,
|
||||||
|
restrict = scalargtsel,
|
||||||
|
join = scalargtjoinsel
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE OPERATOR CLASS phone_number_ops
|
||||||
|
DEFAULT FOR TYPE phone_number USING btree AS
|
||||||
|
OPERATOR 1 <,
|
||||||
|
OPERATOR 2 <=,
|
||||||
|
OPERATOR 3 =,
|
||||||
|
OPERATOR 4 >=,
|
||||||
|
OPERATOR 5 >,
|
||||||
|
FUNCTION 1 phone_number_cmp(phone_number, phone_number);
|
||||||
|
|
||||||
|
--General functions
|
||||||
|
|
||||||
CREATE FUNCTION parse_phone_number(text, text) RETURNS phone_number
|
CREATE FUNCTION parse_phone_number(text, text) RETURNS phone_number
|
||||||
LANGUAGE c IMMUTABLE STRICT
|
LANGUAGE c IMMUTABLE STRICT
|
||||||
AS 'pg_libphonenumber', 'parse_phone_number';
|
AS 'pg_libphonenumber', 'parse_phone_number';
|
||||||
|
|
|
@ -41,3 +41,4 @@ ShortPhoneNumber::operator PhoneNumber() const {
|
||||||
number.set_number_of_leading_zeros(leading_zeros);
|
number.set_number_of_leading_zeros(leading_zeros);
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,27 +18,50 @@ class ShortPhoneNumber {
|
||||||
public:
|
public:
|
||||||
enum : size_t {
|
enum : size_t {
|
||||||
MAX_COUNTRY_CODE = 999,
|
MAX_COUNTRY_CODE = 999,
|
||||||
|
MAX_LEADING_ZEROS = 15,
|
||||||
//15 digits
|
//15 digits
|
||||||
MAX_NATIONAL_NUMBER = 999999999999999,
|
MAX_NATIONAL_NUMBER = 999999999999999,
|
||||||
MAX_LEADING_ZEROS = 15,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum : size_t {
|
enum : size_t {
|
||||||
COUNTRY_CODE_BITS = 10,
|
COUNTRY_CODE_BITS = 10,
|
||||||
NATIONAL_NUMBER_BITS = 50,
|
|
||||||
LEADING_ZEROS_BITS = 4,
|
LEADING_ZEROS_BITS = 4,
|
||||||
|
NATIONAL_NUMBER_BITS = 50,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum : size_t {
|
enum : size_t {
|
||||||
COUNTRY_CODE_OFFSET = 0,
|
COUNTRY_CODE_OFFSET = 0,
|
||||||
NATIONAL_NUMBER_OFFSET = COUNTRY_CODE_OFFSET + COUNTRY_CODE_BITS,
|
LEADING_ZEROS_OFFSET = COUNTRY_CODE_OFFSET + COUNTRY_CODE_BITS,
|
||||||
LEADING_ZEROS_OFFSET = NATIONAL_NUMBER_OFFSET + NATIONAL_NUMBER_BITS,
|
NATIONAL_NUMBER_OFFSET = LEADING_ZEROS_OFFSET + LEADING_ZEROS_BITS,
|
||||||
};
|
};
|
||||||
|
|
||||||
ShortPhoneNumber(i18n::phonenumbers::PhoneNumber number);
|
ShortPhoneNumber(i18n::phonenumbers::PhoneNumber number);
|
||||||
|
|
||||||
|
bool operator == (const ShortPhoneNumber other) const {
|
||||||
|
return this->_data == other._data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator != (const ShortPhoneNumber other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
operator i18n::phonenumbers::PhoneNumber() const;
|
operator i18n::phonenumbers::PhoneNumber() const;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compares to another PhoneNumber using a fast collation heuristic
|
||||||
|
*
|
||||||
|
* May not produce intuitive results for numbers with the same
|
||||||
|
* country code but different lengths
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* - <0 (if a < b)
|
||||||
|
* - 0 (if a == b)
|
||||||
|
* - >0 (if a > b)
|
||||||
|
*/
|
||||||
|
google::protobuf::int64 compare_fast(ShortPhoneNumber other) const {
|
||||||
|
return other._data - this->_data;
|
||||||
|
}
|
||||||
|
|
||||||
google::protobuf::uint32 country_code() const {
|
google::protobuf::uint32 country_code() const {
|
||||||
return getMasked(_data, COUNTRY_CODE_BITS, COUNTRY_CODE_OFFSET);
|
return getMasked(_data, COUNTRY_CODE_BITS, COUNTRY_CODE_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue