DOMAINS hakkındaki konuşma ilginçtir, ancak bu sorunun tek olası kaynağıyla ilgili değildir. İmzalanmamış bütünler için arzu, aynı sayıda bit ile tamsayıların aralığını ikiye katlamaktır, bu bir verimlilik argümanıdır, negatif sayıları dışlama arzusu değildir, herkes bir kontrol kısıtlamasının nasıl ekleneceğini bilir.
Ne zaman bu konuda birileri tarafından sorulan , Tome Lane belirtti:
Temel olarak, pek çok mevcut uygulamayı bozmayan sayısal promosyon hiyerarşisine uydurmanın bir yolunu bulamazsanız, bunun gerçekleşmesi ihtimali sıfırdır. Bellek hizmet ederse, buna birden fazla kez baktık ve POLA'yı ihlal etmeyen uygulanabilir bir tasarım bulamadık.
"POLA" nedir? Google bana anlamsız 10 sonuç verdi . Politik olarak yanlış bir düşünce ve bu nedenle sansürlendiğinden emin değilim. Bu arama terimi neden hiçbir sonuç vermiyor? Her neyse.
İmzasız girişleri çok fazla sorun yaşamadan uzantı türleri olarak uygulayabilirsiniz. Bunu C işlevleriyle yaparsanız, o zaman hiçbir performans cezası olmayacaktır. Değişmez değerlerle uğraşmak için ayrıştırıcıyı genişletmenize gerek kalmayacak çünkü PgSQL dizeleri değişmez değerler olarak yorumlamak için çok kolay bir yola sahiptir, sadece '4294966272' :: uint4'ü değişmez değerler olarak yazın. Oyuncular da çok önemli olmamalı. Aralık istisnaları yapmanıza bile gerek yok, sadece '4294966273' :: uint4 :: int'in anlamını -1024 olarak ele alabilirsiniz. Veya bir hata atabilirsiniz.
Bunu isteseydim, yapardım. Ama Java'yı SQL'in diğer tarafında kullandığım için, Java'nın da bu işaretsiz tamsayılara sahip olmadığı için benim için çok az değeri var. Yani hiçbir şey kazanmıyorum. Uzun sığması gereken bir bigint sütunundan bir BigInteger alırsam zaten sinirleniyorum.
Başka bir şey, 32 bit veya 64 bit türleri saklama ihtiyacım olsaydı, sırayla PostgreSQL int4 veya int8 kullanabilirim, sadece doğal sıranın veya aritmetiğin güvenilir bir şekilde çalışmayacağını hatırlıyorum. Ancak depolama ve geri alma bundan etkilenmez.
İşte basit bir işaretsiz int8'i nasıl uygulayabilirim:
İlk kullanacağım
CREATE TYPE name (
INPUT = uint8_in,
OUTPUT = uint8_out
[, RECEIVE = uint8_receive ]
[, SEND = uint8_send ]
[, ANALYZE = uint8_analyze ]
, INTERNALLENGTH = 8
, PASSEDBYVALUE ]
, ALIGNMENT = 8
, STORAGE = plain
, CATEGORY = N
, PREFERRED = false
, DEFAULT = null
)
en az 2 işlevi uint8_in
ve uint8_out
önce tanımlamalıyım.
CREATE FUNCTION uint8_in(cstring)
RETURNS uint8
AS 'uint8_funcs'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION uint64_out(complex)
RETURNS cstring
AS 'uint8_funcs'
LANGUAGE C IMMUTABLE STRICT;
bunu C uint8_funcs.c'de uygulamanız gerekir. Bu yüzden buradan karmaşık örneği kullanıyorum ve basitleştiriyorum:
PG_FUNCTION_INFO_V1(complex_in);
Datum complex_in(PG_FUNCTION_ARGS) {
char *str = PG_GETARG_CSTRING(0);
uint64_t result;
if(sscanf(str, "%llx" , &result) != 1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for uint8: \"%s\"", str)));
return (Datum)SET_8_BYTES(result);
}
ah peki, yoksa zaten bitmiş olduğunu görebilirsin .