Browse Source

init - vibe-d postgresql driver with pool and toml config - example 1

221V 1 month ago
parent
commit
7e012ae985
5 changed files with 134 additions and 21 deletions
  1. 9 0
      README.md
  2. 7 2
      vtest/dub.json
  3. 0 18
      vtest/dub.selections.json
  4. 11 0
      vtest/settings.toml
  5. 107 1
      vtest/source/app.d

+ 9 - 0
README.md

@@ -20,6 +20,15 @@
 "mustache-d": "~>0.1.5"
 
 
+because gssapi_krb5 not supports static linking - use dynamics linking for it
+ls /usr/lib/x86_64-linux-gnu/libgssapi_krb5*
+/usr/lib/x86_64-linux-gnu/libgssapi_krb5.so@  /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2@  /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2
+
+so delete -static
+"dflags": ["-w", "-O", "-static"],
+
+sudo apt update
+sudo apt-get install libpq-dev libpq5 libldap2-dev libssl-dev libkrb5-dev
 
 sudo apt-get install libevent-dev
 sudo apt-get install libmemcached-dev

+ 7 - 2
vtest/dub.json

@@ -3,7 +3,7 @@
   "description": "A simple vibe.d server application.",
   
   "targetName": "vtest",
-  "dflags": ["-w", "-O", "-static"],
+  "dflags": ["-w", "-O"],
   "targetType": "executable",
   "dependencies": {
     "vibe-inet:crypto": "~>1.1.2",
@@ -12,8 +12,13 @@
     "vibe-stream": "~>1.1.1",
     "vibe-inet:textfilter": "~>1.1.2",
     
-    "mustache-d": "~>0.1.5"
+    "mustache-d": "~>0.1.5",
+    
+    "vibe-d-postgresql": "~>3.1.3",
+    "toml": "~>2.0.1"
   },
+  "libs": ["pq", "ssl", "crypto", "ldap", "gssapi_krb5"],
+  "lflags": [],
   
   "license": "proprietary",
   "copyright": "Copyright © 2025, 221V",

+ 0 - 18
vtest/dub.selections.json

@@ -1,18 +0,0 @@
-{
-	"fileVersion": 1,
-	"versions": {
-		"eventcore": "0.9.35",
-		"mir-linux-kernel": "1.2.1",
-		"mustache-d": "0.1.5",
-		"openssl": "3.3.4",
-		"openssl-static": "1.0.5+3.0.8",
-		"stdx-allocator": "2.77.5",
-		"taggedalgebraic": "0.11.23",
-		"vibe-container": "1.6.2",
-		"vibe-core": "2.11.0",
-		"vibe-http": "1.2.2",
-		"vibe-inet": "1.1.2",
-		"vibe-serialization": "1.1.1",
-		"vibe-stream": "1.1.1"
-	}
-}

+ 11 - 0
vtest/settings.toml

@@ -0,0 +1,11 @@
+# settings
+
+[database]
+host = "localhost" # localhost or ip string
+port = "5432" # string
+dbname = "mydb"
+user = "username"
+pass = "password"
+connect_timeout = "5" # seconds
+connections_number = 10 # integer
+

+ 107 - 1
vtest/source/app.d

@@ -25,6 +25,19 @@ import mustache;
 alias MustacheEngine!(string) Mustache;
 
 
+import vibe.db.postgresql;
+import vibe.data.bson;
+//import vibe.data.json;
+// https://github.com/vibe-d/vibe.d/blob/master/source/vibe/vibe.d
+
+PostgresClient client;
+
+
+import std.file : read;
+import toml;
+
+TOMLDocument toml_s;
+
 
 /* test unproper arguments order */
 /* do not */
@@ -124,6 +137,83 @@ void hello(HTTPServerRequest req, HTTPServerResponse res){
 */
 
 
+string s_toml_db              = "database";
+string s_toml_db_host         = "host";
+string s_toml_db_port         = "port";
+string s_toml_db_name         = "dbname";
+string s_toml_db_user         = "user";
+string s_toml_db_pass         = "pass";
+string s_toml_db_conn_timeout = "connect_timeout";
+string s_toml_db_conn_num     = "connections_number";
+
+bool are_valid_config_values(ref TOMLDocument toml_s){
+  string invalid_settings = "invalid settings: ";
+  string grumpy = " :(";
+  string invalid_group = " group ";
+  string invalid_key = " key" ~ grumpy;
+  
+  bool invalid_toml_group(string group){
+    writeln(invalid_settings ~ group ~ invalid_group ~ grumpy); return false;
+  }
+  
+  bool invalid_toml_value(string group, string key){
+    writeln(invalid_settings ~ group ~ invalid_group ~ key ~ invalid_key ~ grumpy); return false;
+  }
+  
+  if((s_toml_db in toml_s) != null){
+      auto toml_db = toml_s[s_toml_db];
+      
+      if((s_toml_db_host in toml_db) != null){
+        if(toml_db[s_toml_db_host].type == TOMLType.STRING){}else{ return invalid_toml_value(s_toml_db, s_toml_db_host); }
+      }else{ return invalid_toml_value(s_toml_db, s_toml_db_host); }
+      
+      if((s_toml_db_port in toml_db) != null){
+        if(toml_db[s_toml_db_port].type == TOMLType.STRING){}else{ return invalid_toml_value(s_toml_db, s_toml_db_port); }
+      }else{ return invalid_toml_value(s_toml_db, s_toml_db_port); }
+      
+      if((s_toml_db_name in toml_db) != null){
+        if(toml_db[s_toml_db_name].type == TOMLType.STRING){}else{ return invalid_toml_value(s_toml_db, s_toml_db_name); }
+      }else{ return invalid_toml_value(s_toml_db, s_toml_db_name); }
+      
+      if((s_toml_db_user in toml_db) != null){
+        if(toml_db[s_toml_db_user].type == TOMLType.STRING){}else{ return invalid_toml_value(s_toml_db, s_toml_db_user); }
+      }else{ return invalid_toml_value(s_toml_db, s_toml_db_user); }
+      
+      if((s_toml_db_pass in toml_db) != null){
+        if(toml_db[s_toml_db_pass].type == TOMLType.STRING){}else{ return invalid_toml_value(s_toml_db, s_toml_db_pass); }
+      }else{ return invalid_toml_value(s_toml_db, s_toml_db_pass); }
+      
+      if((s_toml_db_conn_timeout in toml_db) != null){
+        if(toml_db[s_toml_db_conn_timeout].type == TOMLType.STRING){}else{ return invalid_toml_value(s_toml_db, s_toml_db_conn_timeout); }
+      }else{ return invalid_toml_value(s_toml_db, s_toml_db_conn_timeout); }
+      
+      if((s_toml_db_conn_num in toml_db) != null){
+        if(toml_db[s_toml_db_conn_num].type == TOMLType.INTEGER){}else{ return invalid_toml_value(s_toml_db, s_toml_db_conn_num); }
+      }else{ return invalid_toml_value(s_toml_db, s_toml_db_conn_num); }
+      
+  }else{ return invalid_toml_group(s_toml_db); }
+  return true;
+}
+
+void test_pg_conn_driver(){
+  client.pickConnection( (scope conn){
+    immutable result = conn.execStatement(
+      "SELECT 123 as first_num, 567 as second_num, 'abc'::text as third_text " ~
+      "UNION ALL " ~
+      "SELECT 890, 233, 'fgh'::text as third_text",
+      ValueFormat.BINARY
+    );
+    
+    assert(result[0]["second_num"].as!PGinteger == 567);
+    assert(result[1]["third_text"].as!PGtext == "fgh");
+    
+    foreach (val; rangify(result[0])){
+      writeln("Found entry: ", val.as!Bson.toJson);
+    }
+  } );
+}
+
+
 void test(HTTPServerRequest req, HTTPServerResponse res){
   auto cache = memcachedConnect("127.0.0.1:11211");
   
@@ -192,6 +282,20 @@ void test(HTTPServerRequest req, HTTPServerResponse res){
   writeln(cache.del("test1"));
   
   
+  toml_s = parseTOML(cast(string)read("settings.toml"));
+  if( are_valid_config_values(toml_s) ){}else{ return; }
+  // https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING
+  // https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS
+  //client = new PostgresClient("host=localhost port=5432 dbname=mydb user=username password=pass connect_timeout=5", 100);
+  client = new PostgresClient( "host=" ~ toml_s[s_toml_db][s_toml_db_host].str() ~
+    " port=" ~ toml_s[s_toml_db][s_toml_db_port].str() ~
+    " dbname=" ~ toml_s[s_toml_db][s_toml_db_name].str() ~
+    " user=" ~ toml_s[s_toml_db][s_toml_db_user].str() ~
+    " password=" ~ toml_s[s_toml_db][s_toml_db_pass].str() ~
+    " connect_timeout=" ~ toml_s[s_toml_db][s_toml_db_conn_timeout].str(),
+    cast(uint) toml_s[s_toml_db][s_toml_db_conn_num].integer() );
+  test_pg_conn_driver();
+  
   
   Mustache mustache2;
   auto context2 = new Mustache.Context;
@@ -208,6 +312,9 @@ void test(HTTPServerRequest req, HTTPServerResponse res){
   //context.useSection("boolean");
   //assert(mustache.renderString(" {{#boolean}}YES{{/boolean}}\n {{#boolean}}GOOD{{/boolean}}\n", context) == " YES\n GOOD\n");
   
+  //{{escaped_html_tags}}
+  //{{{not_escaped_html_tags}}}
+  
   //{{#repo}}<b>{{name}}</b>{{/repo}}
   //{{^repo}}No repos :({{/repo}}
   //  to
@@ -226,4 +333,3 @@ void test(HTTPServerRequest req, HTTPServerResponse res){
   res.writeBody( mustache.render("main", context) );
 }
 
-