Skip to content

Commit b58fb49

Browse files
committed
WIP: initial steps toward buggins#66
1 parent e63b3f4 commit b58fb49

File tree

12 files changed

+624
-78
lines changed

12 files changed

+624
-78
lines changed

.github/workflows/dub.yml

+27-4
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
# run: brew bundle
4242

4343
- name: build with SQLite config
44-
run: dub build --config=SQLite
44+
run: dub build --config=sqlite
4545

4646
build-examples:
4747
name: Test ${{ matrix.compiler }} on ${{ matrix.os }}
@@ -108,6 +108,20 @@ jobs:
108108
--health-timeout 3s
109109
--health-retries 3
110110
111+
mssql:
112+
#image: microsoft/mssql-server-linux:2017-latest
113+
image: mcr.microsoft.com/mssql/server:2019-latest
114+
ports: [1433]
115+
env:
116+
MSSQL_PID: Developer
117+
SA_PASSWORD: MSbbk4k77JKH88g54
118+
ACCEPT_EULA: Y
119+
# options: >-
120+
# --health-cmd "sqlcmd -S localhost -U sa -P MSbbk4k77JKH88g54 -Q 'SELECT 1' || exit 1"
121+
# --health-interval 10s
122+
# --health-timeout 3s
123+
# --health-retries 3
124+
111125
steps:
112126
- uses: actions/checkout@v3
113127

@@ -119,19 +133,28 @@ jobs:
119133
- name: HD Test (SQLite)
120134
working-directory: ./hdtest
121135
run: |
122-
dub build --config=SQLite && ./bin/hdtest
136+
dub build --config=sqlite && ./bin/hdtest
123137
124138
- name: HD Test (MySQL)
125139
working-directory: ./hdtest
126140
env:
127141
PORT: ${{ job.services.mysql.ports[3306] }}
128142
run: |
129-
dub build --config=MySQL && ./bin/hdtest --host=127.0.0.1 --port=$PORT --database=hdtest --user=testuser --password=passw0rd
143+
dub build --config=mysql && ./bin/hdtest --host=127.0.0.1 --port=$PORT --database=hdtest --user=testuser --password=passw0rd
130144
131145
- name: HD Test (Postgres)
132146
working-directory: ./hdtest
133147
env:
134148
PORT: ${{ job.services.postgres.ports[5432] }}
135149
run: |
136-
dub build --config=PGSQL && ./bin/hdtest --host=127.0.0.1 --port=$PORT --database=hdtest --user=testuser --password=passw0rd
150+
dub build --config=postgres && ./bin/hdtest --host=127.0.0.1 --port=$PORT --database=hdtest --user=testuser --password=passw0rd
151+
152+
- name: HD Test (SQL Server)
153+
working-directory: ./hdtest
154+
env:
155+
PORT: ${{ job.services.mssql.ports[1433] }}
156+
run: |
157+
sudo ACCEPT_EULA=Y apt-get install msodbcsql17 -y
158+
dub build --config=mssql
159+
./bin/hdtest --host=127.0.0.1 --port=$PORT --database=dbo --user=SA --password=MSbbk4k77JKH88g54 --driver="ODBC Driver 17 for SQL Server"
137160

dub.json

+31-4
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,29 @@
2020
"configurations": [
2121
{
2222
"name": "full",
23-
"versions": ["USE_MYSQL", "USE_SQLITE", "USE_PGSQL"],
23+
"versions": ["USE_MYSQL", "USE_SQLITE", "USE_PGSQL", "USE_PLSQL", "USE_TSQL"],
2424
"subConfigurations": {
2525
"ddbc": "full"
2626
}
2727
},
2828
{
29-
"name": "MySQL",
29+
"name": "test",
30+
"versions": ["USE_SQLITE"],
31+
"libs-posix": ["sqlite3"],
32+
"libs-windows": ["sqlite3"],
33+
"subConfigurations": {
34+
"ddbc": "SQLite"
35+
}
36+
},
37+
{
38+
"name": "mysql",
3039
"versions": ["USE_MYSQL"],
3140
"subConfigurations": {
3241
"ddbc": "MySQL"
3342
}
3443
},
3544
{
36-
"name": "SQLite",
45+
"name": "sqlite",
3746
"versions": ["USE_SQLITE"],
3847
"libs-posix": ["sqlite3"],
3948
"libs-windows": ["sqlite3"],
@@ -42,13 +51,31 @@
4251
}
4352
},
4453
{
45-
"name": "PGSQL",
54+
"name": "postgres",
4655
"versions": ["USE_PGSQL"],
4756
"libs-posix": ["pq"],
4857
"libs-windows": ["libpq"],
4958
"subConfigurations": {
5059
"ddbc": "PGSQL"
5160
}
61+
},
62+
{
63+
"name": "oracle",
64+
"versions": ["USE_PLSQL"],
65+
"libs-posix": ["odbc"],
66+
"libs-windows": ["odbc32"],
67+
"subConfigurations": {
68+
"ddbc": "ODBC"
69+
}
70+
},
71+
{
72+
"name": "mssql",
73+
"versions": ["USE_TSQL"],
74+
"libs-posix": ["odbc"],
75+
"libs-windows": ["odbc32"],
76+
"subConfigurations": {
77+
"ddbc": "ODBC"
78+
}
5279
}
5380
]
5481
}

hdtest/dub.json

+22-4
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,49 @@
1111
"configurations": [
1212
{
1313
"name": "full",
14-
"versions": ["USE_MYSQL", "USE_SQLITE", "USE_PGSQL"],
14+
"versions": ["USE_MYSQL", "USE_SQLITE", "USE_PGSQL", "USE_PLSQL", "USE_TSQL"],
1515
"subConfigurations": {
1616
"hibernated": "full"
1717
}
1818
},
1919
{
20-
"name": "MySQL",
20+
"name": "mysql",
2121
"versions": ["USE_MYSQL"],
2222
"subConfigurations": {
2323
"hibernated": "MySQL"
2424
}
2525
},
2626
{
27-
"name": "SQLite",
27+
"name": "sqlite",
2828
"versions": ["USE_SQLITE"],
2929
"subConfigurations": {
3030
"hibernated": "SQLite"
3131
}
3232
},
3333
{
34-
"name": "PGSQL",
34+
"name": "postgres",
3535
"versions": ["USE_PGSQL"],
3636
"subConfigurations": {
3737
"hibernated": "PGSQL"
3838
}
39+
},
40+
{
41+
"name": "oracle",
42+
"versions": ["USE_PLSQL"],
43+
"libs-posix": ["odbc"],
44+
"libs-windows": ["odbc32"],
45+
"subConfigurations": {
46+
"ddbc": "ODBC"
47+
}
48+
},
49+
{
50+
"name": "mssql",
51+
"versions": ["USE_TSQL"],
52+
"libs-posix": ["odbc"],
53+
"libs-windows": ["odbc32"],
54+
"subConfigurations": {
55+
"ddbc": "ODBC"
56+
}
3957
}
4058
]
4159
}

hdtest/source/htestmain.d

+27-4
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class MyGroup {
7070
}
7171
}
7272

73-
void testHibernate(immutable string host, immutable ushort port, immutable string dbName, immutable string dbUser, immutable string dbPass) {
73+
void testHibernate(immutable string host, immutable ushort port, immutable string dbName, immutable string dbUser, immutable string dbPass, immutable string driver) {
7474

7575
// setup DB connection
7676
version( USE_SQLITE )
@@ -98,7 +98,29 @@ void testHibernate(immutable string host, immutable ushort port, immutable strin
9898
params["ssl"] = "true";
9999

100100
DataSource ds = new ConnectionPoolDataSourceImpl(new PGSQLDriver(), url, params);
101-
Dialect dialect = new PGSQLDialect();
101+
Dialect dialect = new PGSQLDialect(); // should be called PostgreSQLDialect
102+
}
103+
else version( USE_TSQL )
104+
{
105+
// T-SQL is SQL Server
106+
import ddbc.drivers.odbcddbc;
107+
string[string] params = ODBCDriver.setUserAndPassword(par.user, par.password);
108+
params["driver"] = par.odbcdriver;
109+
immutable string url = ODBCDriver.generateUrl(par.host, par.port, params);
110+
111+
DataSource ds = new ConnectionPoolDataSourceImpl(new ODBCDriver(), url, params);
112+
Dialect dialect = new SQLServerDialect();
113+
}
114+
else version( USE_PLSQL )
115+
{
116+
// PL/SQL is Oracle
117+
import ddbc.drivers.odbcddbc;
118+
string[string] params = ODBCDriver.setUserAndPassword(par.user, par.password);
119+
params["driver"] = par.odbcdriver;
120+
immutable string url = ODBCDriver.generateUrl(par.host, par.port, params);
121+
122+
DataSource ds = new ConnectionPoolDataSourceImpl(new ODBCDriver(), url, params);
123+
Dialect dialect = new OracleDialect();
102124
}
103125

104126
// create metadata from annotations
@@ -255,6 +277,7 @@ struct ConnectionParams
255277
string database;
256278
string user;
257279
string pass;
280+
string driver;
258281
}
259282

260283
int main(string[] args)
@@ -264,14 +287,14 @@ int main(string[] args)
264287

265288
try
266289
{
267-
getopt(args, "host",&par.host, "port",&par.port, "database",&par.database, "user",&par.user, "password",&par.pass);
290+
getopt(args, "host",&par.host, "port",&par.port, "database",&par.database, "user",&par.user, "password",&par.pass, "driver",&par.driver);
268291
}
269292
catch (GetOptException)
270293
{
271294
stderr.writefln("Could not parse args");
272295
return 1;
273296
}
274-
testHibernate(par.host, par.port, par.database, par.user, par.pass);
297+
testHibernate(par.host, par.port, par.database, par.user, par.pass, par.driver);
275298

276299
return 0;
277300
}

source/hibernated/core.d

+11-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ module hibernated.core;
2626
//public import std.typetuple;
2727
//public import std.variant;
2828

29-
public import ddbc;
29+
public import ddbc; // pulls in core, common, and pods. Possibly better to only import core & common:
30+
//public import ddbc.core;
31+
//public import ddbc.common;
3032

3133
public import hibernated.annotations;
3234
public import hibernated.session;
@@ -47,3 +49,11 @@ version( USE_MYSQL )
4749
{
4850
public import hibernated.dialects.mysqldialect;
4951
}
52+
version( USE_PLSQL )
53+
{
54+
public import hibernated.dialects.oracledialect;
55+
}
56+
version( USE_TSQL )
57+
{
58+
public import hibernated.dialects.sqlserverdialect;
59+
}

source/hibernated/dialect.d

+54-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,61 @@
1414
*/
1515
module hibernated.dialect;
1616

17+
import std.algorithm.iteration : uniq;
18+
import std.array;
1719
import std.stdio;
1820
import std.string;
1921

2022
import hibernated.metadata;
2123

24+
/// Reserved words in the international SQL standard (ISO/IEC 9075) from 2016
25+
// See the SQL-2016 list on https://en.wikipedia.org/wiki/SQL_reserved_words
26+
const string[] SQL_RESERVED_WORDS = uniq([
27+
"ABS", "ACOS", "ALL", "ALLOCATE", "ALTER", "AND", "ANY", "ARE", "ARRAY", "ARRAY_AGG", "ARRAY_MAX_CARDINALITY",
28+
"AS", "ASENSITIVE", "ASIN", "ASYMMETRIC", "AT",
29+
"BEGIN", "BEGIN_FRAME", "BEGIN_PARTITION", "BETWEEN", "BIGINT", "BINARY", "BLOB", "BOOLEAN", "BOTH", "BY",
30+
"CALL", "CASE", "CHECK", "COLUMN",
31+
"CONSTRAINT", "CREATE",
32+
"DATABASE", "DEFAULT", "DELETE", "DESC", "DISTENCT", "DROP",
33+
"EXEC", "EXISTS",
34+
"FROM",
35+
"HAVING",
36+
"IN", "INDEX",
37+
"JOIN",
38+
"LIKE", "LIMIT",
39+
"NOT",
40+
"OR",
41+
"ROWNUM",
42+
"SELECT", "SET",
43+
"TABLE", "TOP",
44+
"UNION", "UNIQUE", "UPDATE",
45+
"VALUES", "VIEW",
46+
"WHERE"
47+
]).array;
48+
49+
unittest {
50+
import std.algorithm.searching : canFind;
51+
assert(canFind(SQL_RESERVED_WORDS, "AND"));
52+
assert(canFind(SQL_RESERVED_WORDS, "BIGINT"));
53+
assert(canFind(SQL_RESERVED_WORDS, "COLUMN"));
54+
assert(canFind(SQL_RESERVED_WORDS, "DATABASE"));
55+
assert(canFind(SQL_RESERVED_WORDS, "DELETE"));
56+
assert(canFind(SQL_RESERVED_WORDS, "INDEX"));
57+
assert(canFind(SQL_RESERVED_WORDS, "NOT"));
58+
assert(canFind(SQL_RESERVED_WORDS, "OR"));
59+
assert(canFind(SQL_RESERVED_WORDS, "JOIN"));
60+
assert(canFind(SQL_RESERVED_WORDS, "SELECT"));
61+
assert(canFind(SQL_RESERVED_WORDS, "UNION"));
62+
assert(canFind(SQL_RESERVED_WORDS, "WHERE"));
63+
64+
assert(!canFind(SQL_RESERVED_WORDS, "ABSOLUTE"));
65+
assert(!canFind(SQL_RESERVED_WORDS, "ADD")); // this in MySQL, Oracle, SQL Server
66+
assert(!canFind(SQL_RESERVED_WORDS, "ASC")); // this in MySQL, PostgreSQL, Oracle, SQL Server
67+
assert(!canFind(SQL_RESERVED_WORDS, "LONG"));
68+
assert(!canFind(SQL_RESERVED_WORDS, "PRIVILEGES")); // PRIVILEGES is an ODBC thing
69+
assert(!canFind(SQL_RESERVED_WORDS, "VARCHAR2"));
70+
}
71+
2272
/// Represents a dialect of SQL implemented by a particular RDBMS. -- generated from JavaDocs on org.hibernate.dialect.Dialect
2373
abstract class Dialect {
2474

@@ -56,7 +106,7 @@ abstract class Dialect {
56106

57107
protected int[string] keywordList;
58108

59-
protected void addKeywords(string[] keywords) {
109+
protected void addKeywords(const(string[]) keywords) {
60110
foreach(s; keywords) {
61111
keywordList[s] = 1;
62112
}
@@ -406,7 +456,9 @@ abstract class Dialect {
406456
version (USE_MYSQL) {
407457
} else version (USE_SQLITE) {
408458
} else version (USE_PGSQL) {
459+
} else version (USE_PLSQL) {
460+
} else version (USE_TSQL) {
409461
} else {
410-
pragma(msg, "No DB type version definition specified. Add one or more versions to command line: USE_MYSQL, USE_PGSQL, USE_SQLITE");
462+
pragma(msg, "No DB type version definition specified. Add one or more versions to command line: USE_SQLITE, USE_MYSQL, USE_PGSQL, USE_PLSQL, USE_TSQL");
411463
}
412464

source/hibernated/dialects/mysqldialect.d

+8-10
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,20 @@
1111
*/
1212
module hibernated.dialects.mysqldialect;
1313

14+
import std.algorithm.iteration : uniq;
15+
import std.array;
1416
import std.conv;
1517

1618
import hibernated.dialect;
1719
import hibernated.metadata;
1820
import hibernated.type;
1921
import ddbc.core;
2022

21-
string[] MYSQL_RESERVED_WORDS =
22-
[
23-
"ACCESSIBLE", "ADD", "ALL",
24-
"ALTER", "ANALYZE", "AND",
25-
"AS", "ASC", "ASENSITIVE",
26-
"BEFORE", "BETWEEN", "BIGINT",
27-
"BINARY", "BLOB", "BOTH",
28-
"BY", "CALL", "CASCADE",
29-
"CASE", "CHANGE", "CHAR",
23+
const string[] MYSQL_RESERVED_WORDS = uniq(SQL_RESERVED_WORDS ~
24+
[
25+
"ACCESSIBLE", "ADD", "ALTER", "ANALYZE", "AS", "ASC", "ASENSITIVE",
26+
"BEFORE", "BOTH", "BY",
27+
"CALL", "CASCADE", "CASE", "CHANGE", "CHAR",
3028
"CHARACTER", "CHECK", "COLLATE",
3129
"COLUMN", "CONDITION", "CONSTRAINT",
3230
"CONTINUE", "CONVERT", "CREATE",
@@ -100,7 +98,7 @@ string[] MYSQL_RESERVED_WORDS =
10098
"GET", "IO_AFTER_GTIDS", "IO_BEFORE_GTIDS",
10199
"MASTER_BIND", "ONE_SHOT", "PARTITION",
102100
"SQL_AFTER_GTIDS", "SQL_BEFORE_GTIDS",
103-
];
101+
]).array;
104102

105103
class MySQLDialect : Dialect {
106104
///The character specific to this dialect used to close a quoted identifier.

0 commit comments

Comments
 (0)