SQL Anweisung um eine Benutzereingabe erweitern



  • Hi C++ Community,

    ich bin noch relativ neu in der C++-Welt, arbeite mit Visual Studio 2012 und testweise mit einer MySQL-Datenbank.

    Die Datenbankverbindung steht (MySQL/C++ Connector). Jetzt würde ich gerne den Benutzer eine Suchanfrage starten lassen, doch ich bekomme die Benutzereingabe nicht zu der SQL-Query hinzugefügt.

    Ich habe hier im Forum folgenden Beitrag gefunden: http://www.c-plusplus.net/forum/viewtopic.php?t=39273. Doch leider weis ich nicht wie ich den Code in "meine" Version verbasteln kann.

    Fehler: Konvertierung des Parameters 2 von 'std::string' in 'const char *' nicht möglich.

    #include <mysql.h>
    #include <iostream>
    #include <string>
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #include <cppconn/driver.h>
    #include <cppconn/exception.h>
    #include <cppconn/resultset.h>
    #include <cppconn/statement.h>
    
    using namespace std;
    
    int main()
    {
    	MYSQL mDB;
    	MYSQL *conn; 
    	MYSQL_RES *res; 
    	MYSQL_ROW row; 
    	string tn = "";
    	unsigned int num_fields;
    	unsigned int i;
    
    	mysql_init(&mDB); 
    	conn = mysql_real_connect(&mDB,"localhost","root","","dbname",0,0,0); 
    	if (conn == NULL)  
    	{ 
    		printf("Es konnte keine Verbindung zur Datenbank hergestellt werden: %s",mysql_error(&mDB));
    		return 1; 
    	} 
    	else 
    	{ 
    		printf("Es wurde erfolgreich eine Verbindung hergestellt!"); 
    	}
    	cout << "Searchtopic: " << endl;
    	getline (cin, tn);
    	string s = "SELECT Topic_Topic FROM Topic WHERE Topic_Topic LIKE '%" + tn + "%'"; // [b]hier tritt der oben genannte Fehler auf.[/b]
    	mysql_query(conn, s);
    	res = mysql_store_result(conn);
    	num_fields = mysql_num_fields(res);
    	while ((row = mysql_fetch_row(res)))
    	{
    		unsigned long *lengths;
    		lengths = mysql_fetch_lengths(res);
    		for(i = 0; i < num_fields; i++)
    		{
    			printf("[%.*s] ", (int) lengths[i],
    				row[i] ? row[i] : "NULL");
    		}
    		printf("\n");
    	}
    	mysql_free_result(res);
    	mysql_close(conn);
    	return 0;
    }
    

    Ich gehe davon aus das hier auch das Thema der SQL-Injection nicht bedacht wurde, doch wie geht es denn richtig? Ich finde einfach nichts passendes, zu diesem "Problem". Falls euch sonst noch was aufällt, was gaaar nicht geht, sagt es bitte, denn man lernt ja wie üblich aus Fehlern 🙄 Anscheinend gibt es ja mehrere Möglichkeiten C++ an diese DB anzubinden. Welche Art ist denn die übliche?

    Hoffe auch die Informationen die ich euch geliefert habe sind ausreichend.

    Es wäre cool, wenn ihr mir etwas weiterhelfen könntet.

    Gruß
    Jan



  • Hallo,

    der Fehler kommt wohl eine Zeile später. Da fehlt dann noch ein .c_str():

    mysql_query(conn, s.c_str());
    

    Die mySql-Lib hat eine reine C-Schnittstelle und kennt daher den Datentyp std::string nicht. Mittels der Methode c_str() wird daraus dann ein "const char *".

    P.S. Und bzgl. SQL-Injection such mal nach "mysql sql parameterized query" o.ä., z.B. How to send C++ and mysql dynamic mysql queries (2. Antwort)



  • Perfekt, das wars! Vielen Dank für die schnelle Hilfe!

    Eine Frage noch: Ist das sicher gegen eine SQL-Injection? Möchte mir nichts falsches angewöhnen 😃

    Edit: Alles klar! Thanks!

    Gruß
    Jan



  • Nein das ist nicht sicher. Die Benutzereingabe geht ungefiltert und ungeprüft in das SQL-Query ein.



  • Guten Abend,

    dachte ich mir schon 😕 habe festgestellt, dass ich anscheinend irgendwie den C-Connector und nicht den C++-Connector verwendet habe. Darum habe ich den Code nochmal komplett umgemodelt, und stoße dabei jedesmal wieder auf das gleiche Problem, dass sich das Programm ausführen lässt, eine erste Ausgabe kommt, es sich aber bei der nächsten aufhängt.

    Das Problem liegt soweit ich verstanden habe irgendwie an dem res->next().

    Ich habe dann probiert (etwas unbeholfen ehrlich gesagt) mit cmake, dass Projekt neu zu kompilieren, da ich gelesen habe, dass es evtl. daran liegen kann.

    Das hört sich genau nach meinem Problem an:

    http://stackoverflow.com/questions/13620963/crashes-when-running-mysql-connector-c-from-visual-studio

    Beschreibung des Lösungsweges:
    http://dev.mysql.com/doc/refman/5.1/en/connector-cpp-installation-source-windows.html

    Doch leider wirds nicht besser.. ich habs dann irgendwann hinbekommen das Projekt mit dem cmake neu zu kompilieren, alle Link/includes usw. wieder eingefügt und selber Fehler wieder..

    Es kann auch gut sein, dass ich bei dem cmake was falsch gemacht habe, weil die da noch was von dem nmake schreiben, was ich nicht gemacht habe weil ich mir absolut unsicher war, ob das überhaupt noch was zu Sache tut..

    Kennt jemand zufällig das Problem bzw. kann was zu dem cmake sagen und kann mir dort weiterhelfen? Sitze jetzt schon den ganzen Tag dran und verzweifel solangsam 😡

    #include <mysql.h>
    #include <string>
    #include <iostream>
    #include <iomanip>
    #include <sstream>
    #include <memory>
    #include <stdexcept>
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #include <cppconn/driver.h>
    #include <cppconn/exception.h>
    #include <cppconn/resultset.h>
    #include <cppconn/statement.h>
    #include <cppconn/prepared_statement.h>
    #include <cppconn/exception.h>
    #include <cppconn/warning.h>
    #include <cppconn/metadata.h>
    #include <cppconn/resultset_metadata.h>
    
    using namespace std;
    using namespace sql;
    
    int main()
    {
    	cout << endl;
    	cout << "Connecting to Database...";
    	Statement *stmt;
    	PreparedStatement *prep_stmt;
    	Driver *driver;
    	Connection *con;
    	ResultSet *res;
    
    	std::string tn = "";
    	try 
    	{
    		driver = get_driver_instance();
    		if(!(con = driver->connect("localhost", "root", "") ))
    		{
    				cout << "failed!" << endl;
    		}
    		else 
    			cout << "successful!" << endl << endl;
    		con->setSchema("database");
    
    		stmt = con->createStatement();
    		res = stmt->executeQuery("SELECT Topic_Topic FROM Topic WHERE Topic_Topic='test'");
    		int row = 1;
    		while(res->next()) // Fehler während der Laufzeit, immer beim 2. Schleifendurchlauf!
    		{
    			cout << row << " " << res->getString("Topic_Topic") << endl;
    			++row;
    		}
    	}
    	catch (SQLException &e) {
    		cout << "ERROR: SQLException in " << __FILE__;
    		cout << " (" << __FUNCTION__<< ") on line " << __LINE__ << endl;
    		cout << "ERROR: " << e.what();
    		cout << " (MySQL error code: " << e.getErrorCode();
    		cout << ", SQLState: " << e.getSQLState() << ")" << endl;
    
    		if (e.getErrorCode() == 1047) {
    			/*
    			Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)
    			Message: Unknown command
    			*/
    			cout << "\nYour server does not seem to support Prepared Statements at all. ";
    			cout << "Perhaps MYSQL < 4.1?" << endl;
    		}
    		return EXIT_FAILURE;
    	} 
    	catch (runtime_error &e) {
    		cout << "ERROR: runtime_error in " << __FILE__;
    		cout << " (" << __FUNCTION__ << ") on line " << __LINE__ << endl;
    		cout << "ERROR: " << e.what() << endl;
    
    		return EXIT_FAILURE;
    	}
    
    	return EXIT_SUCCESS;
    }
    

    Gruß
    Jan



  • Hatte denn niemand dieses Problem schonmal :/?



  • Hast du schon das Beispiel von der Seite erfolgreich zum Laufen gebracht?



  • Leider nein.. Hast du vielleicht noch eine Idee?



  • Ich weiß nicht.. habe mich damit noch nicht wirklich auseinandergesetzt. Habs nur vor paar Tagen kompiliert (mit nmake vc110 (VS2012)) und das Example getestet. Stürzt es im Example auch einfach so ab? Dann hast du den MySQL Connector vielleicht wirklich falsch kompiliert.



  • Also das Programm lässt sich ganz nochmal debuggen ohne fehler, dann startet es, (in der testdatenbank habe ich 2 einträge, die er mit der sql anweisung ausgeben muss) und wirft nach dem ersten ergebnis ein Fehlerfenster aus "...exe funktioniert nicht mehr.."

    Er deutet dann auf einen Fehler im "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xutility" in folgendem Abschnitt hin

    #if _ITERATOR_DEBUG_LEVEL == 2
    	if (_Myproxy != 0)
    		{	// proxy allocated, drain it
    		_Lockit _Lock(_LOCK_DEBUG);
    
    		for (_Iterator_base12 **_Pnext = &_Myproxy->_Myfirstiter;
    			*_Pnext != 0; *_Pnext = (*_Pnext)->_Mynextiter)
    			(*_Pnext)->_Myproxy = 0;
    		_Myproxy->_Myfirstiter = 0;
    		}
    

    also irgendeine systemdatei, die was mit dem next() zu tun hat(?!). Wie muss man denn vorgehen um mit nmake das Projekt zu kompilieren? Hast du evtl. einen Beitrag der das anschaulich erklärt?


Anmelden zum Antworten