Bug #451: Multiple Inserts where should be unique - Mailing list pgsql-bugs

From pgsql-bugs@postgresql.org
Subject Bug #451: Multiple Inserts where should be unique
Date
Msg-id 200109140856.f8E8uc496298@hub.org
Whole thread Raw
List pgsql-bugs
Paul Green (traktion@webleicester.co.uk) reports a bug with a severity of 1
The lower the number the more severe it is.

Short Description
Multiple Inserts where should be unique

Long Description
Hi,

I have been having problems with my indexes and I have discussed this with people on the mailing lists and they don't
seemto be able to help me find a solution, so I'm guessing that it must be a bug. I'm saying it is very severe because
itcompletely breaks my database as my data becomes corrupt, my indexes become broken and vacuum starts to take *days*
tocomplete, if at all. 

The problem occurs when inserting a large (around 180,000) records consecutively. I am finding that duplicates are
creepingthrough the unique index. If I then drop the index and attempt to recreate it, I then get the standard message
sayingthere are duplicates and the index cannot be created. Initially, there were thoughts that the index may be
corrupted,so I created a new table + index and attempted to insert all of the values of the previous table. This still
leadto duplicates slipping through even though *some* were now rejected. Out of the 180,000 records, around 500-1000
oftenare inserted as duplicates. 

System information:
O/S: Linux, Redhat 7.1, kernel 2.4.2-2
Hardware: AMD K6-2 300, 3 gig IDE disk, 128mb RAM.
PostgreSQL: Version 7.1.3 (was 7.0, but upgraded due to bug)
JDBC Driver: jdbc7.1-1.2.jar (also tried jdbc7.0-1.1.jar)

Below are the steps I made:

player_stats=> CREATE SEQUENCE player1_serial START 1;

player_stats=> create table player1 (id int4 default
nextval('player1_serial'::text) NOT NULL, name varchar(50) not null,
password varchar(50), icqnumber varchar(20), emailaddress varchar(255),
flatname varchar(50), PRIMARY KEY (id));

player_stats=> create unique index player1_name_key on player1 using btree
(name);
(NOTE: I also tried using UNIQUE (name) in the create table statement - no difference to result)

Then I ran the java program 'RecreatePlayer' (see code below). This returned at the end of output:

177967 players inserted
611 players FAILED to be inserted

So clearly the index is rejecting some of the names which have already been inserted. Then I tried this query:

player_stats=> select count(distinct name) from player1;
 count
--------
 176835
(1 row)

player_stats=> select count(name) from player1;
 count
--------
 177356
(1 row)

Clearly, there are differing opinions being returned. Droping + creating a new index returns:
create unique index player1_name_key on player1 using btree (name);
ERROR:  Cannot create unique index. Table contains non-unique values

This is all causing major problems for my database and I have no idea whether the bug is in the JDBC driver or the
posgresqlengine, but there definately seems to be a major problem here. 

Regards,
Paul Green

Sample Code
RecreatePlayer code:

import java.io.*;
import java.lang.*;
import java.sql.*;

public class RecreatePlayer {
    private final static boolean DEBUG=true;

    public static void main(String args[]) {
        try
        {
            DBConn db = new DBConn("/home/httpd/conf/DBConn.conf");

            String SQLString = "SELECT * FROM Player";
            ResultSet rs = db.doSQL(SQLString);

            int counter=0;
            int failed=0;
            while(rs.next()) {
                counter++;
                if(DEBUG) System.out.println("INSERTING
PLAYER "+counter+": "+rs.getString("name"));
                SQLString = "INSERT INTO player1 (id,name,flatname)
VALUES
("+rs.getString("id")+",'"+replaceChars(rs.getString("name")).trim()+"',LOWER('"+replaceChars(rs.getString("name")).trim()+"'))";
                if (!db.doSQLUpdate(SQLString))
                    failed++;
            }
            System.out.println(counter+" players inserted");
            System.out.println(failed+" players FAILED to be
inserted");
        }
        catch(SQLException e)
        {
            System.err.println("SQLException: "+e);
        }
    }

    private static String replaceChars(String input) {
        if (input == null)
            return "";
        StringBuffer tempString = new StringBuffer();
        int x=0;
        while(x < input.length()) {
            if(input.charAt(x) == '\'') tempString.append('\'');
            tempString.append(input.charAt(x));
            x++;
        }
        return tempString.toString().trim();
    }
}

DBConn fragment (NOTE: all statements sent through an existing, open connection, conn):

Statement stmt = conn.createStatement();
stmt.setQueryTimeout(120);
if(stmt.executeUpdate(sqlStr) > 0)
    return true;
else
    return false;

No file was uploaded with this report

pgsql-bugs by date:

Previous
From: "Rainer Mager"
Date:
Subject: Re: Re: timestamps cannot be created without time zones
Next
From: Tom Lane
Date:
Subject: Re: Re: timestamps cannot be created without time zones