Having somewhat a strange issue with python, not unsure if this is something to do with psycopg2 or some rookie error im making with python.
Essentially i have a function that copy's data from a csv and attempts to insert it into a pgsql database using psycopg2. If there is an a data type error i want the code to try and rectify it and then re-attempt to insert the data into the data base. here is the code:
def copy(self, csvFile):
error = True
i = 0
while error:
try:
i += 1
print(f'attempt {i}')
self.connect()
csr = self.conn.cursor()
csr.copy_expert("COPY foo.bar FROM STDOUT NULL '' CSV HEADER", csvFile)
except psycopg2.DataError as err:
print(err)
print(err.pgcode)
csr.close()
self.conn.close()
#self.conn.rollback()
if err.pgcode == '22001':
if 'character varying' in err.args[0]:
currlength = re.search(r'\((.*?)\)', err.args[0]).group(1)
newlength = int(currlength) * 2
s = err.args[0].split()
col = s[s.index('column') + 1].replace(':','')
sql = f'alter table foo.bar alter column {col} type varchar({newlength})'
print(f'Column Length too short adjusting {col} from {currlength} to {newlength}\n {sql}')
self.execute(sql)
elif err.pgcode == '22p02':
s = err.args[0].split()
col = s[s.index('column') + 1].replace(':', '')
sql = f'alter table foo.bar alter column {col} varchar(64)'
print(f'numeric column {col} contains text altering to varchar')
self.execute(sql)
else:
self.conn.commit()
csr.close()
error = False
What happens is that the first try executes as expected and throws the error, then the alter table statement runs correctly, on the second attempt the copy_expert function does nothing but doesnt error and the code completes without inserting the csv data into the database. This is the output showing it tries for the second time.
> attempt 1
> value too long for type character varying(1) CONTEXT: COPY
table, line 3, column id: "12345678"
>
> 22001
> Column Length too short adjusting assetid from 1 to 2
> alter table foo.bar alter column id type varchar(2)
> Executing query alter table foo.bar alter column assetid type varchar(2)
> attempt 2
> Download and insert of file.csv Complete
COPY foo.bar FROM STDOUT [...]: shouldn't that readCOPY foo.bar FROM STDIN [...]?