Mysql embedded Server von VCC 7.0 läuft nicht an
-
mal eine blöde Frage:
Was ist eigentlich VCC 7.0?
Hab bisher nur schnell drübergeschaut und bin von Visual Studio
ausgegangen.
Google bringt für "VCC 7.0" nur wirres Zeug.Egal.
Habs jetzt grad mal ausprobiert mit Dev-C++ (eigentlich wxDev-C++, aber sollte
eigentlich egal sein).
Ausserdem dürfte es auch in anderen Compilern ähnlich funktioniern,
der Unterschied liegt in der Importlib für die libmysqld.dll.
(
Erstellung der importlib für gcc: siehe hier:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-100731-and-highlight-is-.html#719609für Borland Compiler:
http://www.c-plusplus.net/forum/viewtopic.php?t=88356für Visual Studio:
die libmysqld.lib wird mit mysql schon mitgeliefert
)#include <iostream> #include <stdexcept> #include <winsock.h> #include "../include/mysql/mysql.h" int run(); int main() { try { run(); std::cin.get(); return 0; } catch (std::exception & Ex) { std::cerr<<Ex.what()<<std::endl; std::cin.get(); return 1; } catch (...) { std::cerr<<"unknown exception detected"<<std::endl; std::cin.get(); return 2; } } int run() { static char *server_args[] = { "myNiceProgram", // program "--defaults-extra-file=my.ini" }; static char *server_groups[] = { "embedded", "server", "myNiceProgram_settings", (char *)NULL }; // Server initialisieren mysql_server_init(sizeof(server_args) / sizeof(char *), server_args, server_groups); // Datenbankhandle initialisieren MYSQL * m_dbHandle = mysql_init(NULL); // Verbindung herstellen mysql_real_connect(m_dbHandle, "", "", "", "", 0, NULL, 0); // Fehler abfangen if (mysql_errno(m_dbHandle) > 0) { std::string errorMsg = mysql_error(m_dbHandle); throw std::runtime_error(errorMsg.c_str()); } int errorNumber; std::string query = "create database if not exists myDatabase"; errorNumber = mysql_real_query(m_dbHandle, query.c_str(), query.length()); // Fehler abfangen if (errorNumber > 0) { std::string errorMsg = mysql_error(m_dbHandle); throw std::runtime_error(errorMsg.c_str()); } query = "use myDatabase"; errorNumber = mysql_real_query(m_dbHandle, query.c_str(), query.length()); // Fehler abfangen if (errorNumber > 0) { std::string errorMsg = mysql_error(m_dbHandle); throw std::runtime_error(errorMsg.c_str()); } query = "create table if not exists myTable (id int not null primary key auto_increment, name varchar(255))"; errorNumber = mysql_real_query(m_dbHandle, query.c_str(), query.length()); // Fehler abfangen if (errorNumber > 0) { std::string errorMsg = mysql_error(m_dbHandle); throw std::runtime_error(errorMsg.c_str()); } query = "insert into myTable (name) values('Huaba'), ('Meier')"; errorNumber = mysql_real_query(m_dbHandle, query.c_str(), query.length()); // Fehler abfangen if (errorNumber > 0) { std::string errorMsg = mysql_error(m_dbHandle); throw std::runtime_error(errorMsg.c_str()); } query = "select name from myTable"; errorNumber = mysql_real_query(m_dbHandle, query.c_str(), query.length()); // Fehler abfangen if (errorNumber != 0) { std::string errorMsg = mysql_error(m_dbHandle); throw std::runtime_error(errorMsg.c_str()); } // Abfrageergebnis // Vorsicht: hier normalerweise mysql_store_result verwenden // näheres siehe Doku der mysql c-api MYSQL_RES * result = mysql_use_result(m_dbHandle); errorNumber = mysql_errno(m_dbHandle); // Fehler abfangen if (errorNumber != 0) { std::string errorMsg = mysql_error(m_dbHandle); throw std::runtime_error(errorMsg.c_str()); } // Wenn ein Ergebnis vorliegt if (result != NULL) { int numberCols = mysql_num_fields(result); // über alle Zeilen drüberlaufen while (MYSQL_ROW row = mysql_fetch_row(result)) { // die Datenlängen der einzelnen Felder // (für Binärdaten?) unsigned long * lengths = mysql_fetch_lengths(result); // über alle Spalten drüberlaufen for (int col = 0; col < numberCols; col ++) { std::cout<<row[col]<<", "; } std::cout<<std::endl; } } // Ergebnis freigeben mysql_free_result(result); // Verbindung trennen mysql_close(m_dbHandle); // embedded server beenden mysql_server_end(); return EXIT_SUCCESS; }
Zwei Anmerkungen:
War grad zu faul, mir ne neue Importlib zu erstellen,
drum wird oben mysql_real_query() und mysql_use_result() anstatt
mysql_query() und mysql_store_result() verwendet.Weiteres vorgehen:
eine my.ini erstellen und ins selbe Verzeichnis wie die entstandene exe kopieren
(Inhalt: siehe Beitrag oben)im mysql-Installationsverzeichnis nach errmsg.sys und errmsg.txt suchen, beide Dateien auch zu der exe ins Verzeichnis kopieren
Im Verzeichnis mit der exe einen Unterordner "data" erstellen
Fertig.
-
Hi,
es tut
Ich kanns noch nicht ganz glauben, aber es tut! So lang hab ich noch selten gebraucht, um ein Problem zu lösen. Und wie erwartet, wars was ganz Banales:
Das Data-Verzeichnis hat gefehlt! Steht aber irgendwie auch nix davon in meinem Buch oder sonstwo, wo ich geschaut hab. Na, egal.
Vielen Dank für eure ausdauernde Hilfe.Gruß Squeegee
-
anonymus schrieb:
Zwei Anmerkungen:
War grad zu faul, mir ne neue Importlib zu erstellen,
drum wird oben mysql_real_query() und mysql_use_result() anstatt
mysql_query() und mysql_store_result() verwendet.Das will mir jetzt nicht einleuchten...
Die MySQL-Hilfe sagt zu mysql_real_query nur:You must use mysql_real_query() rather than mysql_query() for queries that contain binary data, because binary data may contain the ‘\0’ character. In addition, mysql_real_query() is faster than mysql_query() because it does not call strlen() on the query string.
und ob mysql_use_result und mysql_store_result ist auch eine Frage dessen, was mach machen möchte/welche Umstände gegeben sind:
mysql_store_result() reads the entire result of a query to the client, allocates a MYSQL_RES structure, and places the result into this structure.
mysql_use_result() initiates a result set retrieval but does not actually read the result set into the client like mysql_store_result() does. Instead, each row must be retrieved individually by making calls to mysql_fetch_row(). This reads the result of a query directly from the server without storing it in a temporary table or local buffer, which is somewhat faster and uses much less memory than mysql_store_result(). The client allocates memory only for the current row and a communication buffer that may grow up to max_allowed_packet bytes.
On the other hand, you shouldn't use mysql_use_result() if you are doing a lot of processing for each row on the client side, or if the output is sent to a screen on which the user may type a ^S (stop scroll). This ties up the server and prevent other threads from updating any tables from which the data is being fetched.
When using mysql_use_result(), you must execute mysql_fetch_row() until a NULL value is returned, otherwise, the unfetched rows are returned as part of the result set for your next query. The C API gives the error Commands out of sync; you can't run this command now if you forget to do this!
You may not use mysql_data_seek(), mysql_row_seek(), mysql_row_tell(), mysql_num_rows(), or mysql_affected_rows() with a result returned from mysql_use_result(), nor may you issue other queries until the mysql_use_result() has finished. (However, after you have fetched all the rows, mysql_num_rows() accurately returns the number of rows fetched.)
-
Hallo Squeegee
Ist zwar schon ne Weile her, dass du die Fragen hier gestellt hast, aber vielleicht antwortest du ja noch mal
Wie ich gelesen habe, hast du dir vor einiger Zeit genau die selbe Frage gestellt wie ich. Und zwar das Problem mit den Linkererrors beim Versuch die C API in Visual Studio einzubinden.Ich habe MySQL ganz normal installiert, die lymaysql.dll ins system32 Verzeichnis kopiert und die Libs und Header eingebunden. Trotzdem ne lange Liste voller Headerfehler. Was hast du damals für #defines eintragen müssen um das los zu bekommen?
Gruß Curry
-
Hi Curry,
was genau willst du denn machen? Über die C-Api Zugriff auf einen laufenden Mysql-Server realisieren (dazu benötigst du die von dir beschriebene libmysql.dll und die libmysql.lib) oder willst du einen embedded Server erstellen, also einen mysql-Server mit in dein Programme integrieren (dazu benötigst du die libmysld.dll und die libmysld.lib). Was für Fehlermeldungen bekommst du denn genau? Ich hatte da ne ganze Reihe von verschiedenen Fehlern.
Defines hab ich allerdings gar keine gebraucht.
Welche Version von Visual benützt du? .net?Gruß Squeegee
-
Squeegee schrieb:
Das Data-Verzeichnis hat gefehlt! Steht aber irgendwie auch nix davon in meinem Buch oder sonstwo, wo ich geschaut hab.
Dann hast du also das hier
http://www.c-plusplus.net/forum/viewtopic-var-t-is-119360-and-postdays-is-0-and-postorder-is-asc-and-start-is-0.html#862525oder auch das hier (untere Hälfte)
http://www.c-plusplus.net/forum/viewtopic-var-t-is-119360-and-postdays-is-0-and-postorder-is-asc-and-start-is-0.html#862591nicht angeschaut
@ -=]xXx[=-:
hast schon recht, es kommt drauf an, was man machen möchte.
Aber ich denk mal, dass ein mysql_store_result() die besser Lösung
ist, wenn man nicht vorhat, das ganze Recordset selber zu verwalten...
(Wiederverwendung von Speicher...)
-
Nimm mysql_store_result wenn es nichts ausmacht die ganze Ergebnismenge in den Speicher des Clients zu lesen.
Dadurch hat man auch bestimmte feature (mysql_funktionen) die weitere Infos liefern. (Anzahl der Datensätze aus der Ergebnismenge, Spalteninfos, man kann selbst vor und zurück durch das Ergebnis gehen). Das geht mit use__result nicht.
Es gibt sicher Fälle wo use_result verwendung findet. use_reult kann aber den Server blockieren.
-
Hi anonymos,
das Datadir hatte ich, aber da war wohl ein Fehler im Syntax / und \ ...
siehe einen meiner ersten Beiträge...Gruß Squeegee
-
Ich hatte vor den Server mit ins Programm einzubinden. Leider bekamm ich hunderte von Linkererrors. Vermute, das er die Bibliothek gar nicht oder Fehlerhaft einbindet. Habe aber absolut keine Ahnung was ich da machen sollte. Erst hatte ichs unter Visual Studie 2003 .Net probiert, dann unter Visual Studio 6. Muss man da außer dem MySQL Server noch was anderes Installieren und wenn ja, muss man da noch irgendwelche Datein umherkopieren? Und zu guter letzt, wo binde ich in Visual die Datein ein? Bin mir sicher das bei mir bei einem falschen Vorgehen hier irgendwas durcheinander gekommen ist.
Jo, und weil das alles nicht lief, hab ich erst mal angefangen den ganzen schmarrn unter Dev C++ zu schreiben. Und dort hab ich jetzt ähnliches Prob wie Sqeegee. Ich muss eine txt auslesen, in der das Verzeichnis zur Tabelle liegt. Muss das also irgendwie über mysql_server_init() machen.Kurze Frage noch an dich Sqeegee. Mich verdutzt es, dass ich in letzter Zeit genau die selben Fragen wie mich beschäftigen. Du studierst nicht zufälliger Weise unter Prof. Eisenecker in Leipzig Winf oder?
-
Vermutlich hast du die importlib nicht dazugelinkt.
Im VisualStudio .Net 2k3:
Rechts in der Projektmappe rechtsklick auf den Projektnamen
->Hinzufügen->Vorhandenes Element hinzufügenIm Dateiauswahldialog umstellen auf "Alle Dateien (.)" und dann im
MySQL Installationsverzeichnis->Embedded->DLL->debug(bzw. release)->libmysqld.lib
(siehe hierzu auch http://www.c-plusplus.net/forum/viewtopic-var-t-is-117543-and-highlight-is-.html#851179unter Dev-CPP
die Importlib von oben geht nur im Visual Studio.
Der gcc kann damit nix anfangen.
Drum die importlib selber erstellen,
siehe hier: http://www.c-plusplus.net/forum/viewtopic-var-t-is-100731-and-highlight-is-.html#719609
Anstatt die def-Datei mit pexport zu erstellen, sollte auch die def-Datei funktionieren, die bei den ganzen Mysql-include Dateien dabei ist funktionieren
(libmysqld.def), aber hab ich ned getestet. Allerdings muss auch diese mit den @XX angepasst werden.Wenn die importlib erstellt ist, muss diese zum Projekt hinzugelinkt werden:
Project->Project Options->Parameters
da sind drei listboxen; unter der rechten gibt's einen Button "Add Library or Object". Da draufklicken und die oben erstellte importlib auswählen.
-
Hi curry,
so machen, wie anonymos es schrieb, so hab ichs bei Visual auch gemacht. Dann halt das Data-Verzeichnis in dem Verzeichnis wo deine Exe liegt nicht vergessen und die my.ini wie in einem der vorigen Beiträge dieser Diskussion beschrieben verändern, dann sollte es tun.
Ach so, die libmysqld.dll sollte natürlich unter windows\system32 zu finden sein...Evtl. bekommst du dann in der mysgl.h und/oder der mysql_com.h noch ein paar Compilerfehler, schau dir den Code dort mal an, das müssten dann Codeteile sein, die für andere Betriebssysteme sind, diese Teile einfach auskommentieren, dann sollte es tun
Ich studier nicht in Leipzig, versuch mich aber grade an ner Diplomarbeit an der FHT Esslingen und versuche mit bescheidenen MFC-Kenntnissen ein Winprog zu schreiben.
Gruß Squeegee
-
Kurze Fage??
Bei mir existiert im MySQL Installationsverzeichnis kein Ordner Names Embedded und somit hab ich auch keine libmysqld.dll auf meinem Rechner gefunden. Woher bekomme ich diese Datei?Zweites Problem: Den Rest hab ich wie benannt dazugelinkt (In dem ganzen Microsoftverzeichniswirrwar) jetzt kann ich zwar mit VS.Net kompilieren und er führt das Programm auch aus und wandert vorbildlich über den Quelltext, er fügt aber nichts in meine Datenbank ein.
Wenn Dev nicht so nen lausigen Debugger hätte würde ich's wahrscheinlich mitlerweile lieber darüber zu ende programmieren.Und drittens: Da ich ja nun mitlerweile mal auf ne Gruppe von Leutchen gestoßen bin, die meine Probleme verstehen, wollte ich gleich mal noch fragen, wie ich mir zurück geben lassen kann, wieviele Zeilen bei einer Selectabfrage betroffen waren. So wie ich das programmiert habe funktionierts irgendwie nicht. Hatte mir das so gedacht, dass ich zu begin einer Datenaktualisierung (Quellcode hiervon fehlt) oder dem Hinzufügen eines neuen Datensatzes überprüfe, ob dieser schon existiert. Wenn ja, soll ein weites hinzufügen verboten werden.
bool data_connection::check_entry(const Notice &n){ std::stringstream check_query; check_query << "SELECT * FROM notice_table WHERE date = '" << dateToString(n) << "' AND time = '" << timeToString(n) << "'"; // Anfrage an die Datenbank mysql_real_query(mysql, check_query.str().c_str(), check_query.str().size()); PRUEFE_SQL_STATUS(mysql); unsigned int i = mysql_affected_rows(mysql); if( i == 0){ return 0; } else{ return 1; } }; void data_connection::notice_add(const Notice &n){ if(check_entry(n)){ std::stringstream insert_query; insert_query << "INSERT INTO notice_table (date, time, notice_entry) VALUES ('" << dateToString(n) << "','" << timeToString(n) << "','" << n.notice() << "')"; // Anfrage an die Datenbank mysql_real_query(mysql, insert_query.str().c_str(), insert_query.str().size()); PRUEFE_SQL_STATUS(mysql); } else {message("Der von Ihnen eingegebene \n Datensatz existiert bereits");} }
Danke für eure Hilfen
Gruß Curry
-
von MySQL gibts verschiedene Versionen
(zip, kleiner und grosser Installer)Beim "kleinen" Installer kann's durchaus möglich sein,
dass dorten der embedded Server nicht mit dabei ist.Beim "grossen" Installer muss man bei der Installation auswählen,
dass auch der embedded Server mitinstalliert wird.Zip-Version weiss ich ned
Wie kann das Programm korrekt laufen, wenn du die libmysqld.dll nicht hast?
Schau dir mal den Unterschied zwischen
mysql_affected_rows()
und
mysql_num_rows()
anNochwas:
wenn Datensätze eindeutig sein sollen, wäre es imho sinnvoller, die entsprechende
Spalte in der Datenbank als "unique" zu kennzeichnen.
Dann prüft das die Datenbank automatisch und liefert einen entsprechenden Fehler, falls der Eintrag schon vorhanden ist.
-
Ohne mein dazutun und ohne libmysqld.dll läuft jetzt mysql unter .Net. Fragt mich net warum, ich hab einfach alles eingebunden und Rechner neu gestartet. Jetzt aktualisiert er auch die Daten in der Datenbank. alles nur mit der libmysql.dll die bei Visual Studio schon dabei war. Ich vermute, dass er aus dieser die unterschiede der libmysql.def und libmysqld.def schon kennt, welche im include - Verzeichnis von mysql liegen.
Danke für den Tip mit unique. Werde ich gleich mal umsetzen. Hab mir bisweilen damit geholfen MYSQL_RS * mysql_RS = mysql_store_result() zu misbrauchen, indem ich abgefragte habe, wieviele row_count vom zurücksetzen der Abfrage betroffen waren.Gruß Curry
-
Hi curry,
die Funktionen der libmysqld.dll sind auch in der libmysql vorhanden, machen dort allerdings nichts. Damit hat man die Möglichkeit leicht zwischen embedded und normalem Server zu wechseln indem man einfach die jeweilige lib includiert. Also ich vermute mal, dass du jetzt gerade einfach keinen embedded server nützt. LÄsst sich aber einfach festestellen: Im Task-Manager läuft bei dir wahrscheinlich ein Prozess mysqld -nt. Kill den mal ganz unprofessionell und schau obs dann noch tut.
Vermute mal, dass es dann nicht mehr funzt. Wenn du also einen ebedded Server willst, dann noch mal von vorneWegen dll: Die ist im Packet "mysql-noinstall-4.1.14-win32" mit drin. Dort findest du auch die ensprechende lib dazu, die passt.
Irgendwie beruhigts mich ja, dass damit auch andere Probleme haben, ich kam mir schon etwas blöd dabei vor, weil ichs auch ewig net hinbekommen hab. :p
Gruß Squeegee
-
Hi Squeegee, hab den Dienst etwas professioneller beendet indem ich ihn einfach herunter gefahren habe Dann tut er's nicht mehr. Das Programm stürzt wie erwartet ab.
Jetzt muss ich's nur noch irgendwie hinbekommen, dass ich das Verzeichnis des Datenpfades in dem die Tabelle liegt temporär umlagere.Ok, danke für eure Hilfe. Wenns noch was von mir gibt, werde ich sicherlich im Portal posten, wo ihr euch über die mysql_server_init() ausgelassen habt.
Gruß Curry!