Ich war schon immer neugierig auf neue Programmiersprachen und deren Frameworks. Die ganze Zeit über erstreckte sich meine Erfahrung und Neugier nur auf die Front-End-Entwicklung (habe ich aber auch einige Backend-Entwicklungen gemacht?). Ich habe mich der Herausforderung gestellt, meine Fähigkeiten zu erweitern, und bin auf die Programmiersprache D gestoßen. D ist in einfachen Worten die erweiterte Version von C und CPP.
Was ist D? Auf der Website heißt es: „**D ist eine Allzweck-Programmiersprache mit statischer Typisierung, Zugriff auf Systemebene und C-ähnlicher Syntax. Mit der D-Programmiersprache können Sie schnell schreiben, schnell lesen und schnell ausführen.“
Ich habe PostgreSQL als Datenbank für meine Arbeiten verwendet und habe es deshalb auch für diese Bibliothek ausgewählt. PostgreSQL ist eines der wichtigsten Open-Source-SQL-Datenbanksysteme, das Unternehmen derzeit verwenden, und seine Funktionen werden immer weiter erweitert.
Als ich mich mit der D-Sprache beschäftigt habe, konnte ich kein Paket finden, das meine Erwartungen erfüllt. Entweder wurde die Wartung der Pakete eingestellt oder sie können für direkte Abfragen verwendet werden. Aus einem JavaScript-Hintergrund heraus habe ich Sequalize ORM verwendet. Das bringt mich auf eine Idee. Wie wäre es mit einer ähnlichen in D.
Also habe ich etwas recherchiert und herausgefunden, dass Postgres eine Bibliothek für C bereitstellt. Dann dachte ich, wie wäre es, wenn ich die C-Bindungen in D verwenden und sie für die Entwicklung des ORM verwenden würde. Ich habe den Quellcode von https://github.com/adamdruppe/arsd/blob/master/postgres.d zum Binden der C-Bibliothek an D gefunden.
Anforderungen:
Um ein neues Projekt zu erstellen, verwenden Sie den folgenden Befehl in Ihrem Terminal:
dub init <project_name>
Dieser Befehl erstellt ein neues Projektverzeichnis mit dem angegebenen Namen und richtet die Grundstruktur für ein D-Projekt ein.
Nach Abschluss dieser Schritte haben Sie eine grundlegende D-Projektstruktur eingerichtet und sind bereit für die Entwicklung.
Unter Windows muss der folgende Abschnitt zur dub.json hinzugefügt werden.
dub init <project_name>
oder
Ich habe alle notwendigen DLL-Dateien in den lib-Ordner (manuell erstellt) kopiert und dann den folgenden Code hinzugefügt:
"libs": [ "pq" ], "lflags-windows-x86_64": [ "-LIBPATH:C:/Program Files/PostgreSQL/16/lib/" ], "copyFiles-windows-x86_64": [ "C:/Program Files/PostgreSQL/16/lib/libpq.dll", "C:/Program Files/PostgreSQL/16/bin/libintl-9.dll", "C:/Program Files/PostgreSQL/16/bin/libssl-3-x64.dll", "C:/Program Files/PostgreSQL/16/bin/libcrypto-3-x64.dll", "C:/Program Files/PostgreSQL/16/bin/libwinpthread-1.dll", "C:/Program Files/PostgreSQL/16/bin/libiconv-2.dll" ],
Unter Linux oder macOS müssen Sie sicherstellen, dass die PostgreSQL-Entwicklungsbibliotheken installiert und ordnungsgemäß verknüpft sind. Normalerweise können Sie dies tun, indem Sie die entsprechenden Pakete über den Paketmanager Ihres Systems installieren. Auf Ubuntu- oder Debian-basierten Systemen könnten Sie beispielsweise Folgendes verwenden:
"copyFiles-windows": [ "libs/*.dll" ], "lflags-windows": [ "/LIBPATH:$PACKAGE_DIR/libs" ], "libs": [ "pq" ]
Sobald Sie die erforderlichen Bibliotheken installiert und ordnungsgemäß verknüpft haben, können Sie mit der Einrichtung Ihres D-Projekts für die Arbeit mit PostgreSQL fortfahren.
Hier sind die C-Bindungen für D.
sudo apt-get install libpq-dev
Jetzt können wir diese Funktionen problemlos in D verwenden.
Dies ist der Code für einige grundlegende Ausnahmebehandlungen:
module postgres.implementation.implementationc; extern (C) { struct PGconn { } struct PGresult { } void PQfinish(PGconn*); PGconn* PQconnectdb(const char*); int PQstatus(PGconn*); // FIXME check return value const(char*) PQerrorMessage(PGconn*); char* PQresultVerboseErrorMessage(const PGresult* res, PGVerbosity verbosity, PGContextVisibility show_context); PGresult* PQexec(PGconn*, const char*); void PQclear(PGresult*); PGresult* PQprepare(PGconn*, const char* stmtName, const char* query, ulong nParams, const void* paramTypes); PGresult* PQexecPrepared(PGconn*, const char* stmtName, int nParams, const char** paramValues, const int* paramLengths, const int* paramFormats, int resultFormat); int PQresultStatus(PGresult*); // FIXME check return value int PQnfields(PGresult*); // number of fields in a result const(char*) PQfname(PGresult*, int); // name of field int PQntuples(PGresult*); // number of rows in result const(char*) PQgetvalue(PGresult*, int row, int column); size_t PQescapeString(char* to, const char* from, size_t length); enum int CONNECTION_OK = 0; enum int PGRES_COMMAND_OK = 1; enum int PGRES_TUPLES_OK = 2; enum int PGRES_FATAL_ERROR = 7; enum PGContextVisibility { PQSHOW_CONTEXT_NEVER, PQSHOW_CONTEXT_ERRORS, PQSHOW_CONTEXT_ALWAYS } enum PGVerbosity { PQERRORS_TERSE, PQERRORS_DEFAULT, PQERRORS_VERBOSE, PQERRORS_SQLSTATE } int PQgetlength(const PGresult* res, int row_number, int column_number); int PQgetisnull(const PGresult* res, int row_number, int column_number); int PQfformat(const PGresult* res, int column_number); alias Oid = int; enum BYTEAOID = 17; Oid PQftype(const PGresult* res, int column_number); char* PQescapeByteaConn(PGconn* conn, const ubyte* from, size_t from_length, size_t* to_length); char* PQunescapeBytea(const char* from, size_t* to_length); void PQfreemem(void* ptr); char* PQcmdTuples(PGresult* res); }
Ich werde weitere Ausnahmen und andere Situationen hinzufügen, während ich an diesem Projekt arbeite
Erstellen Sie nun eine Datei „implementation/core/core.d“ zum Schreiben des Verbindungscodes.
module postgres.implementation.exception; public: import std.conv; private import postgres.implementation.implementationc; class PGSqlException : Exception { string code; string sqlState; string message; this(PGconn* conn, PGresult* res = null) { if (res != null) { char* c = PQresultVerboseErrorMessage(res, PGVerbosity.PQERRORS_VERBOSE, PGContextVisibility .PQSHOW_CONTEXT_ALWAYS); char* s = PQresultVerboseErrorMessage(res, PGVerbosity.PQERRORS_SQLSTATE, PGContextVisibility .PQSHOW_CONTEXT_ALWAYS); string ss = to!string(c); import std.string:split; this.code = to!string(ss.split(':')[1]); this.sqlState = to!string(s); } const char* m = PQerrorMessage(conn); this.message = to!string(m); super(this.message); } } class DuplicateKeyException : Exception { this(string message) { super(message); } }
Wichtige Punkte des obigen Codes:
Diese Implementierung bietet eine High-Level-Schnittstelle für D-Anwendungen zur Interaktion mit PostgreSQL-Datenbanken und abstrahiert viele der Low-Level-Details der C-API.
Möglicherweise erhalten Sie jetzt eine IDE-Warnung/Fehlermeldung „Verbindungsmodul nicht gefunden“
Lassen Sie uns ein Verbindungsmodul erstellen:
Erstellen Sie die Datei _internal/connection.d und fügen Sie diesen Code hinzu:
dub init <project_name>
Konstanten und andere Optionen für SQL hinzufügen:
_internal/consts.d
"libs": [ "pq" ], "lflags-windows-x86_64": [ "-LIBPATH:C:/Program Files/PostgreSQL/16/lib/" ], "copyFiles-windows-x86_64": [ "C:/Program Files/PostgreSQL/16/lib/libpq.dll", "C:/Program Files/PostgreSQL/16/bin/libintl-9.dll", "C:/Program Files/PostgreSQL/16/bin/libssl-3-x64.dll", "C:/Program Files/PostgreSQL/16/bin/libcrypto-3-x64.dll", "C:/Program Files/PostgreSQL/16/bin/libwinpthread-1.dll", "C:/Program Files/PostgreSQL/16/bin/libiconv-2.dll" ],
D unterstützt Template-Metaprogrammierung, eine Funktion, die es Ihnen ermöglicht, sehr generischen Code zu schreiben. Das bedeutet, dass D über Vorlagen verfügt, die denen in C ähneln, jedoch leistungsfähiger und flexibler sind.
Das ABC der Vorlagen in D | Der D-Blog
Jetzt erstellen wir eine Vorlagenklasse.
model.d
Verwenden Sie jetzt den Code von https://github.com/rodevasia/sequelized/blob/main/source/postgres/model.d und fügen Sie ihn in Ihre Datei ein
Sehen wir uns den Code über den bereitgestellten GitHub-Link an:
"copyFiles-windows": [ "libs/*.dll" ], "lflags-windows": [ "/LIBPATH:$PACKAGE_DIR/libs" ], "libs": [ "pq" ]
Dieser Code definiert ein Vorlagenklassenmodell in D. Hier ist eine Aufschlüsselung seiner Schlüsselkomponenten:
Wir haben den gesamten Code für die Arbeit geschrieben. Machen wir daraus eine Bibliothek. füge dies zu deiner dub.json hinzu
dub init <project_name>
Lassen Sie uns ein neues Projekt erstellen:
"libs": [ "pq" ], "lflags-windows-x86_64": [ "-LIBPATH:C:/Program Files/PostgreSQL/16/lib/" ], "copyFiles-windows-x86_64": [ "C:/Program Files/PostgreSQL/16/lib/libpq.dll", "C:/Program Files/PostgreSQL/16/bin/libintl-9.dll", "C:/Program Files/PostgreSQL/16/bin/libssl-3-x64.dll", "C:/Program Files/PostgreSQL/16/bin/libcrypto-3-x64.dll", "C:/Program Files/PostgreSQL/16/bin/libwinpthread-1.dll", "C:/Program Files/PostgreSQL/16/bin/libiconv-2.dll" ],
Fügen Sie die Bibliothek als Abhängigkeit in dub.json hinzu
"copyFiles-windows": [ "libs/*.dll" ], "lflags-windows": [ "/LIBPATH:$PACKAGE_DIR/libs" ], "libs": [ "pq" ]
app.d
sudo apt-get install libpq-dev
Lassen Sie uns den Code aufschlüsseln und seine Hauptkomponenten erklären:
Der Code importiert notwendige Module aus der Standardbibliothek und der Sequalized-Bibliothek:
Die Hauptfunktion demonstriert die Verwendung der Sequalized-Bibliothek:
Diese Klasse definiert ein Modell für die Datenbanktabelle:
Ich habe nicht den gesamten Prozess aufgeführt, das müssen Sie selbst herausfinden :)
Wenn Sie gerne zu meinem Projekt beitragen möchten, finden Sie hier den Link zum Repo:
https://github.com/rodevasia/sequelized
Das obige ist der detaillierte Inhalt vonAufbau einer PostgreSQL-Bibliothek in D. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!