2012-08-05 7 views
5

Postgresのsmallintカラムに値32767を挿入する際に問題が発生しました。これは、エラーsmallintが範囲外の範囲外になることになります。私ができるので、これは奇妙でした:PostgreSQL - 複数の列にインデックスを作成するときにSmallintがオーバーフローします。これはバグですか?

SELECT 32767::int2; 

これはうまくいくでしょう。ちょっとした髪が引っ張られた後、私は最終的にこれを問題の列の索引にトラッキングしました。

CREATE TABLE Test 
(
    id uuid NOT NULL, 
    cooktime smallint, 
    preptime smallint, 
    CONSTRAINT test_pkey PRIMARY KEY (id) 
) 
WITH (
    OIDS=FALSE 
); 

が、私は今、次のインデックス作成:まず、ここでのスキーマ(まあ、実際に私はREPRO場合には、このダウンを簡略化してきたではない)のです

CREATE INDEX idx_test_totaltime 
    ON Test 
    USING btree 
    ((cooktime + preptime)); 

次に、私が作成しよう次の行:

INSERT INTO Test (CookTime, PrepTime, Id) 
VALUES (
    (32767)::int2, 
    (10)::int2, 
    (E'fd47dc1e-c3c6-42c1-b058-689e926a72a4')::uuid 
); 

私はエラーを取得する:

​​

idx_test_totaltimeは、インデックスが2つのsmallintsの合計に適用されても、最大値がint2であると思われます。

これはPostgresのバグですか、それとも簡単なものがありませんか?この制限を回避する方法がありますか、これらの列をint4にしてCHECK制約を使用して各値を32767に制限する必要がありますか? Postgres 9.0.0を使用しています(アップグレードする必要があります)。しかし、SQL Fiddleを作成しました。これは9.1.4でこのエラーを示しています。

答えて

4

が別のint2であるため、インデックスの式(cooktime + preptime)(32767, 10)のためにオーバーフローすることがあります。あなたはインデックス式でキャストのビットでこの問題を回避することができます

CREATE INDEX idx_test_totaltime 
    ON Test 
    USING btree 
    ((cooktime::int4 + preptime::int4)); 

をあなただけのキャストの1を必要とするが、使用して、両方の害はありません。

+0

これは機能します。しかし、私はあなたが 'SELECT * FROM Test Where CookTime + PrepTime> 100'をしてインデックスを使用しないことに気付きました。代わりに 'WHERE CookTime :: Int4 + PrepTime :: Int4> 100'を指定する必要があります。今私は私の検索コードを更新する必要があります:) –

+1

@MikeChristensen:それはインデックスに使用されていない良い点です。私はすべての 'int2'ビジネスを忘れて、適切なCHECK制約を持つ列に' int'を使用することをお勧めします。 –

+1

計算結果をインデックスの列ではなくINT2にキャストします。 –

3

なぜINTERVALを時間間隔で使用しないのですか?それはあなたの問題のための完璧な解決策です。

+0

これはおそらく素晴らしい解決策でもあります。この変更を行うのはいくらか面倒かもしれませんが、何が起こるのかを見るためにいくつか試してみることもあります。しかし、Muのソリューションは完璧に機能し、最小限のコードを更新する必要がありました。 –

関連する問題