2009-11-14 15 views
16

mi prendo la più semplice delle funzioni SQL come esempio:Perché psycopg2 non sta eseguendo nessuna delle mie funzioni SQL? (IndexError: indice di tupla fuori campo)

CREATE OR REPLACE FUNCTION skater_name_match(INTEGER,VARCHAR) 
RETURNS BOOL AS 
$$ 
    SELECT $1 IN (SELECT skaters_skater.competitor_ptr_id FROM skaters_skater 
    WHERE name||' '||surname ILIKE '%'||$2||'%' 
    OR surname||' '||name ILIKE '%'||$2||'%'); 
$$ LANGUAGE SQL; 

Se Copio e incollo questo in psql (il guscio di PostgreSQL) allora esegue senza problemi .

Se scrivo un pezzo di codice Python come questo (con un vero nome del database e l'utente, naturalmente):

import psycopg2 

sql_function_above = '''CREATE OR REPLACE FUNCTION skater_name_match(INTEGER,VARCHAR) 
RETURNS BOOL AS 
$$ 
    SELECT $1 IN (SELECT skaters_skater.competitor_ptr_id FROM skaters_skater 
    WHERE name||' '||surname ILIKE '%'||$2||'%' 
    OR surname||' '||name ILIKE '%'||$2||'%'); 
$$ LANGUAGE SQL;''' 

try: 
    connection = psycopg2.connect("dbname='x' user='x' host='localhost' password='x'"); 
except: 
    print "I am unable to connect to the database" 

cursor = connection.cursor() 
cursor.execute(sql_function_above) 

E sembra da eseguire (che non mi dà un errore), ma quando guardo nel database la funzione non è lì.

Quando provo ad eseguire il codice in Django mettendolo in un file/model.sql applicazione sql/ottengo il seguente errore durante syncdb:

IndexError: tuple index out of range 

Quando tento di scrivere la mia gestire. comando py che eseguiva sql, ottengo lo stesso errore.

Cosa sta succedendo qui? Sarei molto grato a chiunque possa far luce su questo :) Sono ancora un principiante quando si tratta di Python e Django, quindi potrei aver trascurato qualcosa di ovvio.

+1

Sarebbe possibile aggiungere l'istruzione effettiva che si sta eseguendo in "cursore".execute (sql_function_above) "(o mostra dove definisci 'sql_function_above' se intendi letteralmente usare quell'identificatore) –

+1

Mostraci come hai definito sql_function_above 'nel tuo codice Python. – nos

+0

Scusa, è stata una semplificazione da parte mia. Ho provato a scrivere la variabile in vari modi, ho anche provato a leggere il testo da un file sql. Tutti questi hanno prodotto lo stesso errore: uno dei tanti modi in cui ho scritto la variabile modificata nella domanda originale ora. risposte: è la prima volta che utilizzo stackoverflow.com e la disponibilità e la velocità delle risposte da parte dei ragazzi è incredibile :) –

risposta

28

Per impostazione predefinita psycopg2 identifica segnaposti di argomento utilizzando il simbolo % (di solito avresti %s nella stringa).

Quindi, se si utilizza cursor.execute('... %s, %s ...', (arg1, arg2)), allora quelli %s vengono convertiti nei valori di arg1 e arg2 rispettivamente.

Ma poiché si chiama: cursor.execute(sql_function_above), senza argomenti aggiuntivi e il codice SQL include %, la libreria sta cercando di trovare il secondo argomento passato nella funzione, che è fuori intervallo, quindi un errore IndexError.

Soluzione: Invece di utilizzare %, scrivere %% nella variabile SQL. Questo viene tradotto in un letterale % prima di essere inviato a PostgreSQL.

1

L'indice fuori intervallo implica che si è tentato di accedere (ad esempio) al terzo elemento di una tupla che ha solo due elementi. Si noti che gli indici di Python partono da 0, quindi una tupla a due elementi denominata myTuple avrebbe elementi myTuple [0] e myTuple [1], ma nessun elemento myTuple [2].

+0

Sì ... è questo che mi confonde ancora di più. Sembra che ci sia una tupla nella libreria psycopg2 che è la colpevole e questo significherebbe che c'è un bug nella libreria psycopg2 (o sto saltando alle conclusioni sbagliate?). Ma se è così, cosa c'è di così speciale nel mio SQL che rompe una libreria che ople trova perfettamente stabile? Parte del problema qui è che non riesco nemmeno a isolare esattamente dove le cose stanno andando male perché quando provo a eseguire l'SQL all'esterno di Django non ottengo alcun messaggio di errore eppure l'SQL non viene eseguito. –

+0

Il tuo codice include letterati come $ 2 e%. Alcune librerie di database potrebbero interpretare thoe come detentori di parametri. Nel caso Python, probabilmente non hai ancora eseguito la transazione. – nos

3

Sembra che non si sta commettendo l'operazione:

provare a mettere:

 
cursor.execute("COMMIT") 

Dopo l'ultima riga e vedere se funziona.

È anche possibile impostare il livello di isolamento a autocommit come:

 
connection.set_isolation_level(0) 

Maggiori informazioni su che in questo answer

+0

Sebbene l'errore della tupla non abbia avuto nulla a che fare con le transazioni, una volta rimosso il problema del segno%, la funzione sql non veniva ancora caricata e questo era naturalmente il motivo, quindi grazie mille per questa risposta :) –

+0

PS: dovresti usare 'connection.commit()' invece di eseguire "COMMIT" manualmente - in questo modo psycopg2 conosce lo stato corrente della transazione. – intgr

Problemi correlati