3 using System
.Data
.Common
;
4 using System
.Data
.Odbc
;
5 using System
.Data
.SqlTypes
;
6 using System
.Data
.SqlClient
;
7 using System
.Collections
.Generic
;
15 public abstract class WvDbi
: IDisposable
17 static WvIni settings
= new WvIni("wvodbc.ini");
18 protected static WvLog log
= new WvLog("WvDbi", WvLog
.L
.Debug1
);
20 // MSSQL freaks out if there are more than 100 connections open at a
21 // time. Give ourselves a safety margin.
22 static int num_active
= 0;
23 static int max_active
= 50;
25 public static WvDbi
create(string moniker
)
27 log
.print("Creating '{0}'\n", moniker
);
29 if (!moniker
.Contains(":") && settings
[moniker
].Count
> 0)
31 var sect
= settings
[moniker
];
33 if (sect
["driver"] == "SqlClient")
34 return create(wv
.fmt("mssql:"
35 + "server={0};database={1};"
36 + "User ID={2};Password={3};",
39 sect
["user"], sect
["password"]));
41 return create(wv
.fmt("ado:"
42 + "driver={0};server={1};database={2};"
44 sect
["driver"], sect
["server"],
46 sect
["user"], sect
["password"]));
49 if (moniker
.StartsWith("dsn=") || moniker
.StartsWith("driver="))
50 return create("ado:" + moniker
);
52 WvDbi dbi
= WvMoniker
<WvDbi
>.create(moniker
);
55 (wv
.fmt("No moniker found for '{0}'", moniker
));
61 wv
.assert(num_active
< max_active
,
62 "BUG: Too many open WvDbi connections");
68 wv
.assert(false, "A WvDbi object was not Dispose()d");
71 // Implement IDisposable.
72 public virtual void Dispose()
75 GC
.SuppressFinalize(this);
78 public abstract WvSqlRows
select(string sql
, params object[] args
);
79 public abstract int execute(string sql
, params object[] args
);
81 public WvSqlRow
select_onerow(string sql
, params object[] args
)
83 // only iterates a single row, if it exists
84 foreach (WvSqlRow r
in select(sql
, args
))
85 return r
; // only return the first one
89 public WvAutoCast
select_one(string sql
, params object[] args
)
91 var a
= select_onerow(sql
, args
);
92 if (a
!= null && a
.Length
> 0)
95 return WvAutoCast
._null
;
98 public int exec(string sql
, params object[] args
)
100 return execute(sql
, args
);
103 public int try_execute(string sql
, params object[] args
)
107 return execute(sql
, args
);
111 // well, I guess no rows were affected...
116 public int try_exec(string sql
, params object[] args
)
118 return try_execute(sql
, args
);
122 public class WvDbi_IDbConnection
: WvDbi
125 protected IDbConnection db
126 { get { return _db; }
}
128 public WvDbi_IDbConnection()
132 public override void Dispose()
140 protected void opendb(IDbConnection db
)
143 if ((db
.State
& System
.Data
.ConnectionState
.Open
) == 0)
147 public override WvSqlRows
select(string sql
, params object[] args
)
149 return new WvSqlRows_IDataReader(prepare(sql
, args
));
152 public override int execute(string sql
, params object[] args
)
154 return prepare(sql
, args
).ExecuteNonQuery();
157 protected virtual IDbCommand
prepare(string sql
, params object[] args
)
159 IDbCommand cmd
= db
.CreateCommand();
160 cmd
.CommandText
= sql
;
162 for (int i
= 0; i
< args
.Length
; i
++)
165 IDbDataParameter param
;
166 if (cmd
.Parameters
.Count
<= i
)
167 cmd
.Parameters
.Add(param
= cmd
.CreateParameter());
169 param
= (IDbDataParameter
)cmd
.Parameters
[i
];
172 param
.DbType
= DbType
.DateTime
;
177 param
.DbType
= DbType
.Int32
;
182 string s
= a
.ToString();
183 param
.DbType
= DbType
.String
; // I sure hope so...
185 param
.Size
= s
.Length
;
194 public class WvDbi_ODBC
: WvDbi_IDbConnection
196 public static void wvmoniker_register()
198 WvMoniker
<WvDbi
>.register("ado",
199 (string m
, object o
) => new WvDbi_ODBC(m
));
200 WvMoniker
<WvDbi
>.register("odbc",
201 (string m
, object o
) => new WvDbi_ODBC(m
));
202 WvMoniker
<WvDbi
>.register("mysql",
203 (string m
, object o
) => new WvDbi_ODBC("MySQL:" + m
));
206 public WvDbi_ODBC(string moniker
)
209 if (moniker
.StartsWith("dsn=") || moniker
.StartsWith("driver="))
213 // try to parse it as an URL
214 WvUrl url
= new WvUrl(moniker
);
215 if (url
.path
.StartsWith("/"))
216 url
.path
= url
.path
.Substring(1);
217 if (url
.method
== "file") // method not provided
218 real
= wv
.fmt("dsn={0};database={1};"
219 + "User ID={2};uid={2};Password={3};pwd={3}",
220 url
.host
, url
.path
, url
.user
, url
.password
);
222 real
= wv
.fmt("driver={0};server={1};database={2};"
223 + "User ID={3};uid={3};Password={4};pwd={4}",
224 url
.method
, url
.host
, url
.path
,
225 url
.user
, url
.password
);
228 log
.print("ODBC create: '{0}'\n", real
);
229 opendb(new OdbcConnection(real
));
235 public class WvDbi_MSSQL
: WvDbi_IDbConnection
237 public static void wvmoniker_register()
239 WvMoniker
<WvDbi
>.register("mssql",
240 (string m
, object o
) => new WvDbi_MSSQL(m
));
243 public WvDbi_MSSQL(string moniker
)
246 if (!moniker
.StartsWith("//"))
250 // try to parse it as an URL
251 WvUrl url
= new WvUrl(moniker
);
252 if (url
.path
.StartsWith("/"))
253 url
.path
= url
.path
.Substring(1);
254 real
= wv
.fmt("server={0};database={1};"
255 + "User ID={2};Password={3};",
256 url
.host
, url
.path
, url
.user
, url
.password
);
259 log
.print("MSSQL create: '{0}'\n", real
);
260 opendb(new SqlConnection(real
));
263 protected override IDbCommand
prepare(string sql
, params object[] args
)
265 SqlCommand cmd
= (SqlCommand
)db
.CreateCommand();
266 cmd
.CommandText
= sql
;
268 for (int i
= 0; i
< args
.Length
; i
++)
271 if (cmd
.Parameters
.Count
<= i
)
273 string name
= wv
.fmt("@col{0}", i
);
274 cmd
.Parameters
.Add(new SqlParameter(name
, a
));
276 cmd
.Parameters
[i
].Value
= a
;