Vous n'êtes pas identifié(e).

#1 23/07/2010 14:50:06

Fooshi
Membre

Message d'erreur Bind

Bonjour,
je developpe acutellement un client postgreSQL il est parfaitement operationel pour les commandes SELECT, j'essaie d'inclure la commande COPY.

Ma commande
const char * sql_query = "SELECT intval, floatval, strval FROM test_sqlclient WHERE name=$1;";

se transforme en :

const char * sql_query = "COPY ( SELECT intval, floatval, strval FROM test_sqlclient WHERE name=$1 ) TO STDOUT;";

Lors de l'envoie d'une commande j'envoie un message 'Parse' , 'Bind', 'Describe', 'Execute' puis 'Sync'

si joins ma fonction qui crée le message Bind  :

/* Construct the 'Bind' message        */
    msg_len = 0;
    msg[msg_len++] = 0;                // An empty string selects the non-portal named.
    msg[msg_len++] = 0;                // An empty string selects the non-prepared statement named.
    if (count > 0 && formats)        // Send parameter formats.
    {
        sql_put_int(sizeof(int16), count, msg + msg_len);            // Number format codes following parameters.
        msg_len  += sizeof(int16);
        for (i = 0; i < count; ++i)
        {
            sql_put_int(sizeof(int16), formats[i], msg + msg_len);    // Format codes parameters. All must be zero (text) or one (binary).
            msg_len  += sizeof(int16);
        }           
    }
    else
    {
        sql_put_int(sizeof(int16), 0, msg + msg_len);    // Number format codes following parameters = 0
        msg_len  += sizeof(int16);
    }
    sql_put_int(sizeof(int16), count, msg + msg_len);    // Number of parameter values.
    msg_len  += sizeof(int16);
    /* Send parameters    */
    for (i = 0; i < count; ++i)
    {
        if (values && values[i])
        {
            int nbytes;
            if (formats && formats[i] != 0)
            {
                nbytes = lengths[i];        // Binary parameter
            }
            else
            {
                nbytes = strlen(values[i]);    // Text parameter, do not use lengths.
            }               
            sql_put_int(sizeof(int32), nbytes, msg + msg_len);    // Size parameter (this number does not include the length itself). Can be zero.
            msg_len  += sizeof(int32);
            memcpy(msg + msg_len, values[i], nbytes);            // Parameter value.
            msg_len += nbytes;
        }
        else
        {
            sql_put_int(sizeof(int32), -1, msg + msg_len);        // -1 indicates a NULL parameter value. No byte value does not follow the NULL case.
            msg_len  += sizeof(int32);
        }
    }
    sql_put_int(sizeof(int16), 1, msg + msg_len);                // Number format codes result columns following.
    msg_len  += sizeof(int16);
    sql_put_int(sizeof(int16), result_format, msg + msg_len);    // Format codes result columns.
    msg_len  += sizeof(int16);   
    msg[msg_len] = '\0';
    sql_add_start_msg(sql_conn, 'B', msg_len);
    block_list_write_buffer(&sql_conn->send, msg, msg_len);   

Cette fonction apelle toujours un nom d'instruction vide.

le serveur me renvoie une erreur :

bind message supplies 1 parameters , but prepared statement "" requires 0

Dois je passer par une fonction PQprepare puis PQExedPrepared puis passer en parametre de ma foncton le nom de l'instruction préparée ?

Merci d'avance pour vos reponses !

Hors ligne

#2 23/07/2010 15:04:58

Marc Cousin
Membre

Re : Message d'erreur Bind

Pour un COPY, il faut passer soit par PQPrepare puis PQExecPrepared, soit directement par PQExec (il n'y a pas vraiment d'intérer à préparer une requête COPY, elle ne prend pas de paramètre).

Par contre, après le chemin de COPY diverge de celui d'un ordre normal : il faut passer par http://docs.postgresql.fr/8.4/libpq-copy.html. COPY ne fonctionne pas vraiment comme les autres ordres SQL, dans le sens qu'il ouvre une socket dédiée aux données, donc un canal supplémentaire.

En tout cas, votre message d'erreur signifie simplement que vous avez essayé de préparer votre ordre COPY avec un paramètre, alors qu'il n'en attend aucun (ce qui est normal).


Marc.

Hors ligne

#3 23/07/2010 15:16:06

Fooshi
Membre

Re : Message d'erreur Bind

Oui mais ici ma fonction COPY prend en compte 1 parametre ($1) donc il veut mieux que je passe par PQprepare puis PQExecPrepared non ?

Hors ligne

#4 23/07/2010 16:01:07

Marc Cousin
Membre

Re : Message d'erreur Bind

Ah, compris.

Je pense qu'à partir du moment où vous préparez un COPY, l'ordre à l'intérieur est statique. Je doute que vous puissiez le passer en paramètre. C'est d'ailleurs ce que vous dit Postgresql, il ne voit pas de paramètre dans la requête. Je crois donc que vous n'avez pas trop le choix, il va falloir la passer en PQExec, ou en dur dans cette requête (en protégeant la chaîne avec PQescapeString)


Marc.

Hors ligne

Pied de page des forums