Collegare MySQL a MQ4 - pagina 5

 
sergeev:

Sì, tutto funziona perfettamente, ma finora l'ho fatto solo per MQL5

un esempio di come funziona da sopra nel mio post


Puoi mandarmi un pezzo di codice riguardante mysql_fetch_row, non è chiaro dal tuo esempio come recuperare le celle quando il risultato consiste di diverse righe e colonne.
 
Graff:

Puoi inviare un pezzo di codice riguardante mysql_fetch_row, non è chiaro dal tuo esempio come ottenere le celle quando il risultato consiste di diverse righe e colonne.

allo stesso modo.

1. prendere mysql_num_rows, mysql_num_fields

2. ottenere un puntatore a un array di puntatori alla prossima stringa mysql_fetch_row, e un puntatore alle lunghezze dei campi mysql_fetch_lengths

3. tiriamo queste lunghezze dall'array delle lunghezze nel nostro array (tramite memcpy).

4. Da un puntatore a un array di puntatori di campo, tirare questo array di puntatori di campo (dato che conosciamo mysql_num_fields).

5. Conoscendo le lunghezze dei campi (array di lunghezze ottenute da fetch_lengths) e i puntatori ai campi stessi stiamo tirando i dati nell'array uchar di ogni campo con memcpy

6. tornare al punto 2.

 
HIDDEN:
L'ho girato e rigirato in entrambi i modi, niente ha funzionato per me sul 4. A volte il terminale si blocca anche completamente.

Kirill, tutto funziona in MQL4. L'ho provato sulla build 409 .

Ecco un esempio per ottenere una stringa

#import "libmysql.dll"
    int mysql_get_client_info(); // функция вернула char*
#import "msvcrt.dll"
    int strcpy(string strDestination, int strSource); // копируем NULL-строку из source в байтовый массив 
#import

void start()
{
    int ptr; string data="123456789"; 
    ptr=mysql_get_client_info(); // получили указатель на строку
    strcpy(data, ptr); // скопировали его в массив
    Print("client_info="+data); // вывели на печать
}

risultato
sql USDCHF,M30: client_info=6.0.0

lo stesso per un array di interi
sostituire con

    int strcpy(int &strDestination[], int strSource); // копируем NULL-строку из source в байтовый массив 
 
sergeev:

Kirill, tutto funziona in MQL4. L'ho provato sulla build 409 .

Ecco un esempio per ottenere la stringa

risultato
sql USDCHF,M30: client_info=6.0.0

lo stesso se lo fate per un array
sostituire con

Ho la stessa build, ma il mio terminale si blocca.... Devo provarlo su diversi terminali di diverse società di intermediazione.

Anche se può dipendere dal sistema, sto testando con win7 x64.

 

HIDDEN:


xp/32

Poi scovate le diverse opzioni di chiamata e contattate il Service Desk per il bug.

Forse vi consiglieranno cosa fare.

 
sergeev:

allo stesso modo.

1. prendere mysql_num_rows, mysql_num_fields

2. ottenere un puntatore a un array di puntatori alla prossima stringa mysql_fetch_row, e un puntatore alle lunghezze dei campi mysql_fetch_lengths

3. tiriamo queste lunghezze dall'array delle lunghezze nel nostro array (tramite memcpy).

4. Da un puntatore a un array di puntatori di campo, tirare questo array di puntatori di campo (dato che conosciamo mysql_num_fields).

5. Conoscendo le lunghezze dei campi (array di lunghezze ottenute da fetch_lengths) e i puntatori ai campi stessi stiamo tirando i dati nell'array uchar di ogni campo con memcpy

6. Tornare al punto 2.



Ci siamo quasi. In questa fase, possiamo ottenere solo la prima cella di ogni riga. memcpy per qualche motivo copia solo il primo elemento nei miei array. Ha ucciso un'intera serata. Cosa sto facendo di sbagliato?

Fonte, scarico, registro in appendice.

File:
 
Graff:


Ci sono quasi. In questa fase, posso ottenere solo la prima cella di ogni riga. memcpy copia solo il primo elemento nei miei array per qualche motivo. Ha ucciso un'intera serata. Cosa sto facendo di sbagliato?

Codice sorgente, dump, log in appendice.


ci sono commenti

1. Non c'è affatto bisogno di usare le funzioni UNICODE2ANSI. Avete CharArrayToStr e ShortArrayToStr per questo scopo.

2. Non ho provato a usare la stringa nella funzione strcpy(string strDestination, int strSource);, tutto è stato fatto attraverso gli array. Se sapete cosa state copiando dalla codifica UTF, è meglio memorizzare i dati in un array breve.

3. Qui avete un errore tecnico (che è il motivo per cui tutto va male)
memcpy(alens,lens,num_fields);

Non è un array a byte singolo come uchar. Ho bisogno di memcpy(alens,lens,num_fields*sizeof(int));

 
sergeev:

ci sono commenti

1. Non c'è affatto bisogno di usare le funzioni UNICODE2ANSI. Avete CharArrayToStr e ShortArrayToStr per questo scopo.

2. Non ho provato a usare la stringa nella funzione strcpy(string strDestination, int strSource);, tutto è fatto attraverso gli array. Se sapete cosa state copiando dalla codifica UTF, è meglio memorizzare i dati in un array breve.

3. qui è dove si ha un errore tecnico (che fa andare tutto storto)
memcpy(alens,lens,num_fields);

Non è un array a byte singolo come uchar. avete bisogno di memcpy(alens,lens,num_fields*sizeof(int));



Grazie! Funziona. Ci sono piani per rilasciare una classe o una libreria per lavorare con il muscolo?
 
Graff:

Grazie! Funziona. Qualche piano per rilasciare una classe o una libreria per lavorare con musl?

Se c'è bisogno, posso farlo, ma non ho bisogno di spiegare ciò che è già chiaro...

Ci sono solo 50 funzioni in questa libmysql...

e la maggior parte di loro sono funzioni puramente di servizio. delle dozzine di cui hai bisogno.

--------

Come vedete questa classe o libreria? Quali funzioni dovrebbe avere?

Basta fare dei duplicati delle funzioni api, o mettere alcuni insiemi di azioni in una sola funzione?

 
sergeev:

Se c'è bisogno, posso farlo, ma non ho bisogno di spiegare ciò che è già chiaro...

Ci sono solo 50 funzioni in questa libmysql...

La maggior parte di esse sono funzioni puramente di servizio. dieci di esse sono essenziali per il lavoro.

--------

In generale, come vedete questa classe o libreria? Quali funzioni dovrebbe avere?



Credo che descrivere semplicemente le funzioni di libmysql.dll non sia sufficiente. La classe deve permettere all'utente di lavorare con il database in modo semplice e senza sforzo.

Esempio 1: connessione DB. Per connettersi al database tramite la mia debole classe, si deve chiamare il costruttore della classe, anche se tutta una serie di azioni, non sempre necessarie e nemmeno richieste, si svolgono all'interno della classe.

CMYSQL2::CMYSQL2(const string host="localhost",const string user="root",const string password="",const string database="database",const uint port=3306)
  {
   uchar _host[],_user[],_password[],_database[],_socket[];
   StringToCharArray(host,_host);
   StringToCharArray(user,_user);
   StringToCharArray(password,_password);
   StringToCharArray(database,_database);
// Connecting
   mysql=mysql_init(NULL);
   uint conn=mysql_real_connect(mysql,_host,_user,_password,_database,port,_socket,0);
   if(mysql==NULL || conn==NULL || mysql!=conn){ Print(__FUNCTION__,"-> MySQL connetion failure.");}
  }

Esempio 2: ottenere un risultato su più righe e più colonne. Tutto ciò di cui l'utente ha bisogno è di alimentare la query e un array (struttura) per scrivere il risultato.

//+------------------------------------------------------------------+
//|  Returns string array as sql_results struct param and rows count
//+------------------------------------------------------------------+
uint CMYSQL2::GetArray(string query,sql_results &out[])
  {
   Query2(query);
   StoreResult();
   uint rows=GetNumRows();
   uint fields=GetNumFields();
   ArrayResize(out,rows);

   for(uint r=0;r<rows;r++)
     {
      ArrayResize(out[r].value,fields);
      string fr_res=mysql_fetch_row(result);
      
      for(uint f=0;f<fields;f++)
        {
         out[r].value[f]=get_cell_u(fr_res,f);//Print("3,",f,",",fields);
        }
     }
   FreeLastResult();
   return(rows);
  }

^ questo è un vecchio codice, solo per avere l'idea.

Ci potrebbero essere anche molti esempi su come aggiungere informazioni al database.

Se usate solo un insieme di funzioni senza controlli, è molto facile ottenere una violazione di accesso letta a 0x00000000 in 'libmysql.dll' e mandare in crash l'intero sistema.

Pronto a considerare la possibilità di creare una classe aperta per lavorare con il muscolo.