SqlSharpCli.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482
  1. //
  2. // SqlSharpCli.cs - main driver for SqlSharp
  3. //
  4. // Currently, only working on a command line interface for SqlSharp
  5. //
  6. // However, once GTK# and System.Windows.Forms are good-to-go,
  7. // I would like to create a SqlSharpGui using this.
  8. //
  9. // It would be nice if this is included as part of Mono
  10. // extra goodies under Mono.Data.SqlSharp.
  11. //
  12. // Also, this makes a good Test program for Mono System.Data.
  13. // For more information about Mono::,
  14. // visit http://www.go-mono.com/
  15. //
  16. // To build SqlSharpCli.cs:
  17. // $ mcs SqlSharpCli.cs -r System.Data.dll
  18. //
  19. // To run with mono:
  20. // $ mono SqlSharpCli.exe
  21. //
  22. // To run with mint:
  23. // $ mint SqlSharpCli.exe
  24. //
  25. // To run batch commands and get the output, do something like:
  26. // $ cat commands.txt | mono SqlSharpCli.exe > results.txt
  27. //
  28. // Author:
  29. // Daniel Morgan <[email protected]>
  30. //
  31. // (C)Copyright 2002 Daniel Morgan
  32. //
  33. using System;
  34. using System.Collections;
  35. using System.Data;
  36. using System.Data.Common;
  37. using System.Data.Odbc;
  38. using System.Data.OleDb;
  39. using System.Data.SqlClient;
  40. using System.IO;
  41. using System.Reflection;
  42. using System.Runtime.Remoting;
  43. using System.Text;
  44. namespace Mono.Data.SqlSharp {
  45. public enum FileFormat {
  46. Html,
  47. Xml,
  48. CommaSeparatedValues,
  49. TabSeparated,
  50. Normal
  51. }
  52. // SQL Sharp - Command Line Interface
  53. public class SqlSharpCli {
  54. // provider supports
  55. private bool UseParameters = true;
  56. private bool UseSimpleReader = false;
  57. private IDbConnection conn = null;
  58. private string provider = "POSTGRESQL"; // name of internal provider
  59. // {OleDb,SqlClient,MySql,Odbc,Oracle,PostgreSql,SqlLite} however, it
  60. // can be set to LOADEXTPROVIDER to load an external provider
  61. private string providerAssembly = ""; // filename of assembly
  62. // for example: "Mono.Data.MySql"
  63. private string providerConnectionClass = ""; // Connection class
  64. // in the provider assembly that implements the IDbConnection
  65. // interface. for example: "Mono.Data.MySql.MySqlConnection"
  66. private StringBuilder build = null; // SQL string to build
  67. private string buff = ""; // SQL string buffer
  68. private string connectionString =
  69. "host=localhost;dbname=test;user=postgres";
  70. private string inputFilename = "";
  71. private string outputFilename = "";
  72. private StreamReader inputFilestream = null;
  73. private StreamWriter outputFilestream = null;
  74. private FileFormat outputFileFormat = FileFormat.Html;
  75. private bool silent = false;
  76. private bool showHeader = true;
  77. private Hashtable internalVariables = new Hashtable();
  78. // DisplayResult - used to Read() display a result set
  79. // called by DisplayData()
  80. public void DisplayResult(IDataReader reader, DataTable schemaTable) {
  81. const string zero = "0";
  82. StringBuilder column = null;
  83. StringBuilder line = null;
  84. StringBuilder hdrUnderline = null;
  85. string outData = "";
  86. int hdrLen = 0;
  87. int spacing = 0;
  88. int columnSize = 0;
  89. int c;
  90. char spacingChar = ' '; // a space
  91. char underlineChar = '='; // an equal sign
  92. string dataType; // .NET Type
  93. Type theType;
  94. string dataTypeName; // native Database type
  95. DataRow row; // schema row
  96. line = new StringBuilder();
  97. hdrUnderline = new StringBuilder();
  98. OutputLine("Fields in Query Result: " +
  99. reader.FieldCount);
  100. OutputLine("");
  101. for(c = 0; c < schemaTable.Rows.Count; c++) {
  102. DataRow schemaRow = schemaTable.Rows[c];
  103. string columnHeader = (string) schemaRow["ColumnName"];
  104. if(columnHeader.Equals(""))
  105. columnHeader = "?column?";
  106. if(columnHeader.Length > 32)
  107. columnHeader = columnHeader.Substring(0,32);
  108. // spacing
  109. columnSize = (int) schemaRow["ColumnSize"];
  110. theType = (Type) schemaRow["DataType"];
  111. dataType = theType.ToString();
  112. dataTypeName = reader.GetDataTypeName(c);
  113. switch(dataType) {
  114. case "System.DateTime":
  115. columnSize = 19;
  116. break;
  117. case "System.Boolean":
  118. columnSize = 5;
  119. break;
  120. }
  121. if(provider.Equals("POSTGRESQL") ||
  122. provider.Equals("MYSQL"))
  123. if(dataTypeName.Equals("text"))
  124. columnSize = 32; // text will be truncated to 32
  125. hdrLen = (columnHeader.Length > columnSize) ?
  126. columnHeader.Length : columnSize;
  127. if(hdrLen < 0)
  128. hdrLen = 0;
  129. if(hdrLen > 32)
  130. hdrLen = 32;
  131. line.Append(columnHeader);
  132. if(columnHeader.Length < hdrLen) {
  133. spacing = hdrLen - columnHeader.Length;
  134. line.Append(spacingChar, spacing);
  135. }
  136. hdrUnderline.Append(underlineChar, hdrLen);
  137. line.Append(" ");
  138. hdrUnderline.Append(" ");
  139. }
  140. OutputHeader(line.ToString());
  141. line = null;
  142. OutputHeader(hdrUnderline.ToString());
  143. OutputHeader("");
  144. hdrUnderline = null;
  145. int rows = 0;
  146. // column data
  147. while(reader.Read()) {
  148. rows++;
  149. line = new StringBuilder();
  150. for(c = 0; c < reader.FieldCount; c++) {
  151. int dataLen = 0;
  152. string dataValue = "";
  153. column = new StringBuilder();
  154. outData = "";
  155. row = schemaTable.Rows[c];
  156. string colhdr = (string) row["ColumnName"];
  157. if(colhdr.Equals(""))
  158. colhdr = "?column?";
  159. if(colhdr.Length > 32)
  160. colhdr = colhdr.Substring(0, 32);
  161. columnSize = (int) row["ColumnSize"];
  162. theType = (Type) row["DataType"];
  163. dataType = theType.ToString();
  164. dataTypeName = reader.GetDataTypeName(c);
  165. switch(dataType) {
  166. case "System.DateTime":
  167. columnSize = 19;
  168. break;
  169. case "System.Boolean":
  170. columnSize = 5;
  171. break;
  172. }
  173. if(provider.Equals("POSTGRESQL") ||
  174. provider.Equals("MYSQL"))
  175. if(dataTypeName.Equals("text"))
  176. columnSize = 32; // text will be truncated to 32
  177. columnSize = (colhdr.Length > columnSize) ?
  178. colhdr.Length : columnSize;
  179. if(columnSize < 0)
  180. columnSize = 0;
  181. if(columnSize > 32)
  182. columnSize = 32;
  183. dataValue = "";
  184. if(reader.IsDBNull(c)) {
  185. dataValue = "";
  186. dataLen = 0;
  187. }
  188. else {
  189. StringBuilder sb;
  190. DateTime dt;
  191. if(dataType.Equals("System.DateTime")) {
  192. // display date in ISO format
  193. // "YYYY-MM-DD HH:MM:SS"
  194. dt = reader.GetDateTime(c);
  195. sb = new StringBuilder();
  196. // year
  197. if(dt.Year < 10)
  198. sb.Append("000" + dt.Year);
  199. else if(dt.Year < 100)
  200. sb.Append("00" + dt.Year);
  201. else if(dt.Year < 1000)
  202. sb.Append("0" + dt.Year);
  203. else
  204. sb.Append(dt.Year);
  205. sb.Append("-");
  206. // month
  207. if(dt.Month < 10)
  208. sb.Append(zero + dt.Month);
  209. else
  210. sb.Append(dt.Month);
  211. sb.Append("-");
  212. // day
  213. if(dt.Day < 10)
  214. sb.Append(zero + dt.Day);
  215. else
  216. sb.Append(dt.Day);
  217. sb.Append(" ");
  218. // hour
  219. if(dt.Hour < 10)
  220. sb.Append(zero + dt.Hour);
  221. else
  222. sb.Append(dt.Hour);
  223. sb.Append(":");
  224. // minute
  225. if(dt.Minute < 10)
  226. sb.Append(zero + dt.Minute);
  227. else
  228. sb.Append(dt.Minute);
  229. sb.Append(":");
  230. // second
  231. if(dt.Second < 10)
  232. sb.Append(zero + dt.Second);
  233. else
  234. sb.Append(dt.Second);
  235. dataValue = sb.ToString();
  236. }
  237. else {
  238. dataValue = reader.GetValue(c).ToString();
  239. }
  240. dataLen = dataValue.Length;
  241. if(dataLen < 0) {
  242. dataValue = "";
  243. dataLen = 0;
  244. }
  245. if(dataLen > 32) {
  246. dataValue = dataValue.Substring(0,32);
  247. dataLen = 32;
  248. }
  249. }
  250. columnSize = columnSize > dataLen ? columnSize : dataLen;
  251. // spacing
  252. spacingChar = ' ';
  253. if(columnSize < colhdr.Length) {
  254. spacing = colhdr.Length - columnSize;
  255. column.Append(spacingChar, spacing);
  256. }
  257. if(dataLen < columnSize) {
  258. spacing = columnSize - dataLen;
  259. column.Append(spacingChar, spacing);
  260. switch(dataType) {
  261. case "System.Int16":
  262. case "System.Int32":
  263. case "System.Int64":
  264. case "System.Single":
  265. case "System.Double":
  266. case "System.Decimal":
  267. outData = column.ToString() + dataValue;
  268. break;
  269. default:
  270. outData = dataValue + column.ToString();
  271. break;
  272. }
  273. }
  274. else
  275. outData = dataValue;
  276. line.Append(outData);
  277. line.Append(" ");
  278. }
  279. OutputData(line.ToString());
  280. line = null;
  281. }
  282. OutputLine("\nRows retrieved: " + rows.ToString());
  283. }
  284. public void OutputDataToHtmlFile(IDataReader rdr, DataTable dt) {
  285. StringBuilder strHtml = new StringBuilder();
  286. strHtml.Append("<html> \n <head> <title>");
  287. strHtml.Append("Results");
  288. strHtml.Append("</title> </head>");
  289. strHtml.Append("<body>");
  290. strHtml.Append("<h1> Results </h1>");
  291. strHtml.Append("<table border=1>");
  292. outputFilestream.WriteLine(strHtml.ToString());
  293. strHtml = null;
  294. strHtml = new StringBuilder();
  295. strHtml.Append("<tr>");
  296. foreach (DataRow schemaRow in dt.Rows) {
  297. strHtml.Append("<td> <b>");
  298. object dataObj = schemaRow["ColumnName"];
  299. string sColumnName = dataObj.ToString();
  300. strHtml.Append(sColumnName);
  301. strHtml.Append("</b> </td>");
  302. }
  303. strHtml.Append("</tr>");
  304. outputFilestream.WriteLine(strHtml.ToString());
  305. strHtml = null;
  306. int col = 0;
  307. string dataValue = "";
  308. while(rdr.Read()) {
  309. strHtml = new StringBuilder();
  310. strHtml.Append("<tr>");
  311. for(col = 0; col < rdr.FieldCount; col++) {
  312. // column data
  313. if(rdr.IsDBNull(col) == true)
  314. dataValue = "NULL";
  315. else {
  316. object obj = rdr.GetValue(col);
  317. dataValue = obj.ToString();
  318. }
  319. strHtml.Append("<td>");
  320. strHtml.Append(dataValue);
  321. strHtml.Append("</td>");
  322. }
  323. strHtml.Append("\t\t</tr>");
  324. outputFilestream.WriteLine(strHtml.ToString());
  325. strHtml = null;
  326. }
  327. outputFilestream.WriteLine(" </table> </body> \n </html>");
  328. strHtml = null;
  329. }
  330. // DisplayData - used to display any Result Sets
  331. // from execution of SQL SELECT Query or Queries
  332. // called by DisplayData.
  333. // ExecuteSql() only calls this function
  334. // for a Query, it does not get
  335. // for a Command.
  336. public void DisplayData(IDataReader reader) {
  337. DataTable schemaTable = null;
  338. int ResultSet = 0;
  339. OutputLine("Display any result sets...");
  340. do {
  341. // by Default, SqlDataReader has the
  342. // first Result set if any
  343. ResultSet++;
  344. OutputLine("Display the result set " + ResultSet);
  345. schemaTable = reader.GetSchemaTable();
  346. if(reader.FieldCount > 0) {
  347. // SQL Query (SELECT)
  348. // RecordsAffected -1 and DataTable has a reference
  349. OutputQueryResult(reader, schemaTable);
  350. }
  351. else if(reader.RecordsAffected >= 0) {
  352. // SQL Command (INSERT, UPDATE, or DELETE)
  353. // RecordsAffected >= 0
  354. Console.WriteLine("SQL Command Records Affected: " + reader.RecordsAffected);
  355. }
  356. else {
  357. // SQL Command (not INSERT, UPDATE, nor DELETE)
  358. // RecordsAffected -1 and DataTable has a null reference
  359. Console.WriteLine("SQL Command Executed.");
  360. }
  361. // get next result set (if anymore is left)
  362. } while(reader.NextResult());
  363. }
  364. // display the result in a simple way
  365. // new ADO.NET providers may have not certain
  366. // things implemented yet, such as, TableSchema
  367. // support
  368. public void DisplayDataSimple(IDataReader reader) {
  369. int row = 0;
  370. Console.WriteLine("Reading Data using simple reader...");
  371. while(reader.Read()){
  372. row++;
  373. Console.WriteLine("Row: " + row);
  374. for(int col = 0; col < reader.FieldCount; col++) {
  375. Console.WriteLine(" Field: " + col);
  376. //string dname = reader.GetName(col);
  377. //Console.WriteLine(" Name: " + dname);
  378. string dvalue = reader.GetValue(col).ToString();
  379. Console.WriteLine(" Value: " + dvalue);
  380. }
  381. }
  382. Console.WriteLine("\n" + row + " ROWS RETRIEVED\n");
  383. }
  384. public void OutputQueryResult(IDataReader dreader, DataTable dtable) {
  385. if(outputFilestream == null) {
  386. DisplayResult(dreader, dtable);
  387. }
  388. else {
  389. switch(outputFileFormat) {
  390. case FileFormat.Normal:
  391. DisplayResult(dreader, dtable);
  392. break;
  393. case FileFormat.Html:
  394. OutputDataToHtmlFile(dreader, dtable);
  395. break;
  396. default:
  397. Console.WriteLine("Error: Output data file format not supported.");
  398. break;
  399. }
  400. }
  401. }
  402. public void BuildParameters(IDbCommand cmd) {
  403. if(UseParameters == true) {
  404. ParametersBuilder parmsBuilder =
  405. new ParametersBuilder(cmd,
  406. BindVariableCharacter.Colon);
  407. Console.WriteLine("Get Parameters (if any)...");
  408. parmsBuilder.ParseParameters();
  409. IList parms = (IList) cmd.Parameters;
  410. Console.WriteLine("Print each parm...");
  411. for(int p = 0; p < parms.Count; p++) {
  412. string theParmName;
  413. IDataParameter prm = (IDataParameter) parms[p];
  414. theParmName = prm.ParameterName;
  415. string inValue = "";
  416. bool found;
  417. if(parmsBuilder.ParameterMarkerCharacter == '?') {
  418. Console.Write("Enter Parameter " +
  419. (p + 1).ToString() +
  420. ": ");
  421. inValue = Console.ReadLine();
  422. prm.Value = inValue;
  423. }
  424. else {
  425. found = GetInternalVariable(theParmName, out inValue);
  426. if(found == true) {
  427. prm.Value = inValue;
  428. }
  429. else {
  430. Console.Write("Enter Parameter " + (p + 1).ToString() +
  431. ": " + theParmName + ": ");
  432. inValue = Console.ReadLine();
  433. prm.Value = inValue;
  434. }
  435. }
  436. }
  437. parmsBuilder = null;
  438. }
  439. }
  440. // ExecuteSql - Execute the SQL Command(s) and/or Query(ies)
  441. public void ExecuteSql(string sql) {
  442. Console.WriteLine("Execute SQL: " + sql);
  443. IDbCommand cmd = null;
  444. IDataReader reader = null;
  445. cmd = conn.CreateCommand();
  446. // set command properties
  447. cmd.CommandType = CommandType.Text;
  448. cmd.CommandText = sql;
  449. cmd.Connection = conn;
  450. BuildParameters(cmd);
  451. try {
  452. reader = cmd.ExecuteReader();
  453. if(UseSimpleReader == false)
  454. DisplayData(reader);
  455. else
  456. DisplayDataSimple(reader);
  457. reader.Close();
  458. reader = null;
  459. }
  460. catch(Exception e) {
  461. Console.WriteLine("Exception Caught Executing SQL: " + e);
  462. //if(reader != null) {
  463. // if(reader.IsClosed == false)
  464. // reader.Close();
  465. reader = null;
  466. //}
  467. }
  468. finally {
  469. // cmd.Dispose();
  470. cmd = null;
  471. }
  472. }
  473. // ExecuteSql - Execute the SQL Commands (no SELECTs)
  474. public void ExecuteSqlNonQuery(string sql) {
  475. Console.WriteLine("Execute SQL Non Query: " + sql);
  476. IDbCommand cmd = null;
  477. int rowsAffected = -1;
  478. cmd = conn.CreateCommand();
  479. // set command properties
  480. cmd.CommandType = CommandType.Text;
  481. cmd.CommandText = sql;
  482. cmd.Connection = conn;
  483. BuildParameters(cmd);
  484. try {
  485. rowsAffected = cmd.ExecuteNonQuery();
  486. cmd = null;
  487. Console.WriteLine("Rows affected: " + rowsAffected);
  488. }
  489. catch(Exception e) {
  490. Console.WriteLine("Exception Caught Executing SQL: " + e);
  491. }
  492. finally {
  493. // cmd.Dispose();
  494. cmd = null;
  495. }
  496. }
  497. public void ExecuteSqlScalar(string sql) {
  498. Console.WriteLine("Execute SQL Scalar: " + sql);
  499. IDbCommand cmd = null;
  500. string retrievedValue = "";
  501. cmd = conn.CreateCommand();
  502. // set command properties
  503. cmd.CommandType = CommandType.Text;
  504. cmd.CommandText = sql;
  505. cmd.Connection = conn;
  506. BuildParameters(cmd);
  507. try {
  508. retrievedValue = (string) cmd.ExecuteScalar().ToString();
  509. Console.WriteLine("Retrieved value: " + retrievedValue);
  510. }
  511. catch(Exception e) {
  512. Console.WriteLine("Exception Caught Executing SQL: " + e);
  513. }
  514. finally {
  515. // cmd.Dispose();
  516. cmd = null;
  517. }
  518. }
  519. public void ExecuteSqlXml(string sql) {
  520. Console.WriteLine("Error: Not implemented yet.");
  521. }
  522. // like ShowHelp - but only show at the beginning
  523. // only the most important commands are shown
  524. // like help and quit
  525. public void StartupHelp() {
  526. Console.WriteLine(@"Type: \Q to quit");
  527. Console.WriteLine(@" \ConnectionString to set the ConnectionString");
  528. Console.WriteLine(@" \Provider to set the Provider:");
  529. Console.WriteLine(@" {OleDb,SqlClient,MySql,Odbc,");
  530. Console.WriteLine(@" Oracle,PostgreSql,Sqlite)");
  531. Console.WriteLine(@" \Open to open the connection");
  532. Console.WriteLine(@" \Close to close the connection");
  533. Console.WriteLine(@" \Execute to execute SQL command(s)/queries(s)");
  534. Console.WriteLine(@" \h to show this help.");
  535. Console.WriteLine(@" \defaults to show default variables.");
  536. Console.WriteLine();
  537. }
  538. // ShowHelp - show the help - command a user can enter
  539. public void ShowHelp() {
  540. Console.WriteLine("");
  541. Console.WriteLine(@"Type: \Q to quit");
  542. Console.WriteLine(@" \ConnectionString to set the ConnectionString");
  543. Console.WriteLine(@" \Provider to set the Provider:");
  544. Console.WriteLine(@" {OleDb,SqlClient,MySql,Odbc,");
  545. Console.WriteLine(@" Oracle,PostgreSql, Sqlite}");
  546. Console.WriteLine(@" \Open to open the connection");
  547. Console.WriteLine(@" \Close to close the connection");
  548. Console.WriteLine(@" \Execute to execute SQL command(s)/queries(s)");
  549. Console.WriteLine(@" \exenonquery execute an SQL non query (not a SELECT).");
  550. Console.WriteLine(@" \exescalar execute SQL to get a single row/single column result.");
  551. Console.WriteLine(@" \f FILENAME to read a batch of Sql# commands/queries from.");
  552. Console.WriteLine(@" \o FILENAME to write out the result of commands executed.");
  553. Console.WriteLine(@" \load FILENAME to load from file SQL commands into SQL buffer.");
  554. Console.WriteLine(@" \save FILENAME to save SQL commands from SQL buffer to file.");
  555. Console.WriteLine(@" \h to show this help.");
  556. Console.WriteLine(@" \defaults to show default variables, such as,");
  557. Console.WriteLine(@" Provider and ConnectionString.");
  558. Console.WriteLine(@" \s {TRUE, FALSE} to silent messages.");
  559. Console.WriteLine(@" \r reset (clear) the query buffer.");
  560. Console.WriteLine(@" \set NAME VALUE - set an internal variable.");
  561. WaitForEnterKey();
  562. Console.WriteLine(@" \unset NAME - remove an internal variable.");
  563. Console.WriteLine(@" \variable NAME - display the value of an internal variable.");
  564. Console.WriteLine(@" \loadprovider CLASS - load the provider");
  565. Console.WriteLine(@" use the complete name of its connection class.");
  566. Console.WriteLine(@" \loadextprovider ASSEMBLY CLASS - load the provider");
  567. Console.WriteLine(@" use the complete name of its assembly and");
  568. Console.WriteLine(@" its Connection class.");
  569. Console.WriteLine(@" \print - show what's in the SQL buffer now.");
  570. Console.WriteLine(@" \UseParameters (TRUE,FALSE) - use parameters when executing SQL.");
  571. Console.WriteLine(@" \UseSimpleReader (TRUE,FALSE) - use simple reader when displaying results.");
  572. Console.WriteLine();
  573. }
  574. public void WaitForEnterKey() {
  575. Console.Write("Waiting... Press Enter key to continue. ");
  576. string entry = Console.ReadLine();
  577. }
  578. // ShowDefaults - show defaults for connection variables
  579. public void ShowDefaults() {
  580. Console.WriteLine();
  581. Console.WriteLine("The default Provider is " + provider);
  582. if(provider.Equals("LOADEXTPROVIDER")) {
  583. Console.WriteLine(" Assembly: " +
  584. providerAssembly);
  585. Console.WriteLine(" Connection Class: " +
  586. providerConnectionClass);
  587. }
  588. Console.WriteLine();
  589. Console.WriteLine("The default ConnectionString is: ");
  590. Console.WriteLine(" \"" + connectionString + "\"");
  591. Console.WriteLine();
  592. }
  593. // OpenDataSource - open connection to the data source
  594. public void OpenDataSource() {
  595. Console.WriteLine("Attempt to open connection...");
  596. try {
  597. switch(provider) {
  598. case "ODBC":
  599. conn = new OdbcConnection();
  600. break;
  601. case "OLEDB":
  602. conn = new OleDbConnection();
  603. break;
  604. case "POSTGRESQL":
  605. // FIXME: System.Data.SqlClient should
  606. // be used for MS SQL Server 7/2000
  607. // and move the PostgreSQL provider
  608. // to Mono.Data.PostgreSQL
  609. // and use a connection class
  610. // PgSqlConnection
  611. conn = new SqlConnection();
  612. break;
  613. case "LOADEXTPROVIDER":
  614. if(LoadExternalProvider() == false)
  615. return;
  616. break;
  617. default:
  618. Console.WriteLine("Error: Bad argument or provider not supported.");
  619. return;
  620. }
  621. }
  622. catch(Exception e) {
  623. Console.WriteLine("Error: Unable to create Connection object. " + e);
  624. return;
  625. }
  626. conn.ConnectionString = connectionString;
  627. try {
  628. conn.Open();
  629. if(conn.State == ConnectionState.Open)
  630. Console.WriteLine("Open was successfull.");
  631. }
  632. catch(Exception e) {
  633. Console.WriteLine("Exception Caught Opening. " + e);
  634. conn = null;
  635. }
  636. }
  637. // CloseDataSource - close the connection to the data source
  638. public void CloseDataSource() {
  639. if(conn != null) {
  640. Console.WriteLine("Attempt to Close...");
  641. try {
  642. conn.Close();
  643. Console.WriteLine("Close was successfull.");
  644. }
  645. catch(Exception e) {
  646. Console.WriteLine("Exeception Caught Closing. " + e);
  647. }
  648. conn = null;
  649. }
  650. }
  651. // ChangeProvider - change the provider string variable
  652. public void ChangeProvider(string[] parms) {
  653. string[] extp;
  654. if(parms.Length == 2) {
  655. string parm = parms[1].ToUpper();
  656. switch(parm) {
  657. case "ORACLE":
  658. case "TDS":
  659. case "SYBASE":
  660. Console.WriteLine("Error: Provider not currently supported.");
  661. break;
  662. case "MYSQL":
  663. extp = new string[3] {
  664. "\\loadextprovider",
  665. "Mono.Data.MySql",
  666. "Mono.Data.MySql.MySqlConnection"};
  667. SetupExternalProvider(extp);
  668. UseParameters = false;
  669. UseSimpleReader = false;
  670. break;
  671. case "SQLITE":
  672. extp = new string[3] {
  673. "\\loadextprovider",
  674. "Mono.Data.SqliteClient",
  675. "Mono.Data.SqliteClient.SqliteConnection"};
  676. SetupExternalProvider(extp);
  677. UseParameters = false;
  678. UseSimpleReader = true;
  679. break;
  680. case "SQLCLIENT":
  681. provider = "POSTGRESQL";
  682. Console.WriteLine("Warning: Currently, the SqlClient provider is the PostgreSQL provider.");
  683. break;
  684. case "ODBC":
  685. UseParameters = false;
  686. UseSimpleReader = false;
  687. provider = parm;
  688. break;
  689. case "GDA":
  690. case "OLEDB":
  691. UseParameters = false;
  692. UseSimpleReader = true;
  693. provider = parm;
  694. break;
  695. case "POSTGRESQL":
  696. UseParameters = true;
  697. UseSimpleReader = false;
  698. provider = parm;
  699. break;
  700. default:
  701. Console.WriteLine("Error: " + "Bad argument or Provider not supported.");
  702. break;
  703. }
  704. Console.WriteLine("The default Provider is " + provider);
  705. if(provider.Equals("LOADEXTPROVIDER")) {
  706. Console.WriteLine(" Assembly: " +
  707. providerAssembly);
  708. Console.WriteLine(" Connection Class: " +
  709. providerConnectionClass);
  710. }
  711. }
  712. else
  713. Console.WriteLine("Error: provider only has one parameter.");
  714. }
  715. // ChangeConnectionString - change the connection string variable
  716. public void ChangeConnectionString(string entry) {
  717. if(entry.Length > 18)
  718. connectionString = entry.Substring(18, entry.Length - 18);
  719. else
  720. connectionString = "";
  721. }
  722. public void SetupOutputResultsFile(string[] parms) {
  723. if(parms.Length != 2) {
  724. Console.WriteLine("Error: wrong number of parameters");
  725. return;
  726. }
  727. try {
  728. outputFilestream = new StreamWriter(parms[1]);
  729. }
  730. catch(Exception e) {
  731. Console.WriteLine("Error: Unable to setup output results file. " + e);
  732. return;
  733. }
  734. }
  735. public void SetupInputCommandsFile(string[] parms) {
  736. if(parms.Length != 2) {
  737. Console.WriteLine("Error: wrong number of parameters");
  738. return;
  739. }
  740. try {
  741. inputFilestream = new StreamReader(parms[1]);
  742. }
  743. catch(Exception e) {
  744. Console.WriteLine("Error: Unable to setup input commmands file. " + e);
  745. return;
  746. }
  747. }
  748. public void LoadBufferFromFile(string[] parms) {
  749. if(parms.Length != 2) {
  750. Console.WriteLine("Error: wrong number of parameters");
  751. return;
  752. }
  753. string inFilename = parms[1];
  754. try {
  755. StreamReader sr = new StreamReader( inFilename);
  756. StringBuilder buffer = new StringBuilder();
  757. string NextLine;
  758. while((NextLine = sr.ReadLine()) != null) {
  759. buffer.Append(NextLine);
  760. buffer.Append("\n");
  761. }
  762. sr.Close();
  763. buff = buffer.ToString();
  764. build = null;
  765. build = new StringBuilder();
  766. build.Append(buff);
  767. }
  768. catch(Exception e) {
  769. Console.WriteLine("Error: Unable to read file into SQL Buffer. " + e);
  770. }
  771. }
  772. public void SaveBufferToFile(string[] parms) {
  773. if(parms.Length != 2) {
  774. Console.WriteLine("Error: wrong number of parameters");
  775. return;
  776. }
  777. string outFilename = parms[1];
  778. try {
  779. StreamWriter sw = new StreamWriter(outFilename);
  780. sw.WriteLine(buff);
  781. sw.Close();
  782. }
  783. catch(Exception e) {
  784. Console.WriteLine("Error: Could not save SQL Buffer to file." + e);
  785. }
  786. }
  787. public void SetUseParameters(string[] parms) {
  788. if(parms.Length != 2) {
  789. Console.WriteLine("Error: wrong number of parameters");
  790. return;
  791. }
  792. string parm = parms[1].ToUpper();
  793. if(parm.Equals("TRUE"))
  794. UseParameters = true;
  795. else if(parm.Equals("FALSE"))
  796. UseParameters = false;
  797. else
  798. Console.WriteLine("Error: invalid parameter.");
  799. }
  800. public void SetUseSimpleReader(string[] parms) {
  801. if(parms.Length != 2) {
  802. Console.WriteLine("Error: wrong number of parameters");
  803. return;
  804. }
  805. string parm = parms[1].ToUpper();
  806. if(parm.Equals("TRUE"))
  807. UseSimpleReader = true;
  808. else if(parm.Equals("FALSE"))
  809. UseSimpleReader = false;
  810. else
  811. Console.WriteLine("Error: invalid parameter.");
  812. }
  813. public void SetupSilentMode(string[] parms) {
  814. if(parms.Length != 2) {
  815. Console.WriteLine("Error: wrong number of parameters");
  816. return;
  817. }
  818. string parm = parms[1].ToUpper();
  819. if(parm.Equals("TRUE"))
  820. silent = true;
  821. else if(parm.Equals("FALSE"))
  822. silent = false;
  823. else
  824. Console.WriteLine("Error: invalid parameter.");
  825. }
  826. public void SetInternalVariable(string[] parms) {
  827. if(parms.Length < 2) {
  828. Console.WriteLine("Error: wrong number of parameters.");
  829. return;
  830. }
  831. string parm = parms[1];
  832. StringBuilder ps = new StringBuilder();
  833. for(int i = 2; i < parms.Length; i++)
  834. ps.Append(parms[i]);
  835. internalVariables[parm] = ps.ToString();
  836. }
  837. public void UnSetInternalVariable(string[] parms) {
  838. if(parms.Length != 2) {
  839. Console.WriteLine("Error: wrong number of parameters.");
  840. return;
  841. }
  842. string parm = parms[1];
  843. try {
  844. internalVariables.Remove(parm);
  845. }
  846. catch(Exception e) {
  847. Console.WriteLine("Error: internal variable does not exist.");
  848. }
  849. }
  850. public void ShowInternalVariable(string[] parms) {
  851. string internalVariableValue = "";
  852. if(parms.Length != 2) {
  853. Console.WriteLine("Error: wrong number of parameters.");
  854. return;
  855. }
  856. string parm = parms[1];
  857. if(GetInternalVariable(parm, out internalVariableValue) == true)
  858. Console.WriteLine("Internal Variable - Name: " +
  859. parm + " Value: " + internalVariableValue);
  860. }
  861. public bool GetInternalVariable(string name, out string sValue) {
  862. sValue = "";
  863. bool valueReturned = false;
  864. try {
  865. if(internalVariables.ContainsKey(name) == true) {
  866. sValue = (string) internalVariables[name];
  867. valueReturned = true;
  868. }
  869. else
  870. Console.WriteLine("Error: internal variable does not exist.");
  871. }
  872. catch(Exception e) {
  873. Console.WriteLine("Error: internal variable does not exist.");
  874. }
  875. return valueReturned;
  876. }
  877. // to be used for loading .NET Data Providers that exist in
  878. // the System.Data assembly, but are not explicitly handling
  879. // in SQL#
  880. public void LoadProvider(string[] parms) {
  881. Console.WriteLine("Error: not implemented yet.");
  882. }
  883. public void SetupExternalProvider(string[] parms) {
  884. if(parms.Length != 3) {
  885. Console.WriteLine("Error: Wrong number of parameters.");
  886. return;
  887. }
  888. provider = "LOADEXTPROVIDER";
  889. providerAssembly = parms[1];
  890. providerConnectionClass = parms[2];
  891. }
  892. public bool LoadExternalProvider() {
  893. bool success = false;
  894. // For example: for the MySQL provider in Mono.Data.MySql
  895. // \LoadExtProvider Mono.Data.MySql Mono.Data.MySql.MySqlConnection
  896. // \ConnectionString dbname=test
  897. // \open
  898. // insert into sometable (tid, tdesc, aint) values ('abc','def',12)
  899. // \exenonquery
  900. // \close
  901. // \quit
  902. try {
  903. Console.WriteLine("Loading external provider...");
  904. Console.Out.Flush();
  905. Assembly ps = Assembly.Load(providerAssembly);
  906. Type typ = ps.GetType(providerConnectionClass);
  907. conn = (IDbConnection) Activator.CreateInstance(typ);
  908. success = true;
  909. Console.WriteLine("External provider loaded.");
  910. Console.Out.Flush();
  911. }
  912. catch(FileNotFoundException f) {
  913. Console.WriteLine("Error: unable to load the assembly of the provider: " +
  914. providerAssembly);
  915. }
  916. return success;
  917. }
  918. // used for outputting message, but if silent is set,
  919. // don't display
  920. public void OutputLine(string line) {
  921. if(silent == false)
  922. OutputData(line);
  923. }
  924. // used for outputting the header columns of a result
  925. public void OutputHeader(string line) {
  926. if(showHeader == true)
  927. OutputData(line);
  928. }
  929. // OutputData() - used for outputting data
  930. // if an output filename is set, then the data will
  931. // go to a file; otherwise, it will go to the Console.
  932. public void OutputData(string line) {
  933. if(outputFilestream == null)
  934. Console.WriteLine(line);
  935. else
  936. outputFilestream.WriteLine(line);
  937. }
  938. // HandleCommand - handle SqlSharpCli commands entered
  939. public void HandleCommand(string entry) {
  940. string[] parms;
  941. parms = entry.Split(new char[1] {' '});
  942. string userCmd = parms[0].ToUpper();
  943. switch(userCmd) {
  944. case "\\PROVIDER":
  945. ChangeProvider(parms);
  946. break;
  947. case "\\CONNECTIONSTRING":
  948. ChangeConnectionString(entry);
  949. break;
  950. case "\\LOADPROVIDER":
  951. // TODO:
  952. //SetupProvider(parms);
  953. break;
  954. case "\\LOADEXTPROVIDER":
  955. SetupExternalProvider(parms);
  956. break;
  957. case "\\OPEN":
  958. OpenDataSource();
  959. break;
  960. case "\\CLOSE":
  961. CloseDataSource();
  962. break;
  963. case "\\S":
  964. SetupSilentMode(parms);
  965. break;
  966. case "\\E":
  967. case "\\EXECUTE":
  968. // Execute SQL Commands or Queries
  969. if(conn == null)
  970. Console.WriteLine("Error: connection is not Open.");
  971. else if(conn.State == ConnectionState.Closed)
  972. Console.WriteLine("Error: connection is not Open.");
  973. else {
  974. if(build == null)
  975. Console.WriteLine("Error: SQL Buffer is empty.");
  976. else {
  977. buff = build.ToString();
  978. ExecuteSql(buff);
  979. }
  980. build = null;
  981. }
  982. break;
  983. case "\\EXENONQUERY":
  984. if(conn == null)
  985. Console.WriteLine("Error: connection is not Open.");
  986. else if(conn.State == ConnectionState.Closed)
  987. Console.WriteLine("Error: connection is not Open.");
  988. else {
  989. if(build == null)
  990. Console.WriteLine("Error: SQL Buffer is empty.");
  991. else {
  992. buff = build.ToString();
  993. ExecuteSqlNonQuery(buff);
  994. }
  995. build = null;
  996. }
  997. break;
  998. case "\\EXESCALAR":
  999. if(conn == null)
  1000. Console.WriteLine("Error: connection is not Open.");
  1001. else if(conn.State == ConnectionState.Closed)
  1002. Console.WriteLine("Error: connection is not Open.");
  1003. else {
  1004. if(build == null)
  1005. Console.WriteLine("Error: SQL Buffer is empty.");
  1006. else {
  1007. buff = build.ToString();
  1008. ExecuteSqlScalar(buff);
  1009. }
  1010. build = null;
  1011. }
  1012. break;
  1013. case "\\F":
  1014. SetupInputCommandsFile(parms);
  1015. break;
  1016. case "\\O":
  1017. SetupOutputResultsFile(parms);
  1018. break;
  1019. case "\\LOAD":
  1020. // Load file into SQL buffer: \load FILENAME
  1021. LoadBufferFromFile(parms);
  1022. break;
  1023. case "\\SAVE":
  1024. // Save SQL buffer to file: \save FILENAME
  1025. SaveBufferToFile(parms);
  1026. break;
  1027. case "\\H":
  1028. case "\\HELP":
  1029. // Help
  1030. ShowHelp();
  1031. break;
  1032. case "\\DEFAULTS":
  1033. // show the defaults for provider and connection strings
  1034. ShowDefaults();
  1035. break;
  1036. case "\\Q":
  1037. case "\\QUIT":
  1038. // Quit
  1039. break;
  1040. case "\\R":
  1041. // reset (clear) the query buffer
  1042. build = null;
  1043. break;
  1044. case "\\SET":
  1045. // sets internal variable
  1046. // \set name value
  1047. SetInternalVariable(parms);
  1048. break;
  1049. case "\\UNSET":
  1050. // deletes internal variable
  1051. // \unset name
  1052. UnSetInternalVariable(parms);
  1053. break;
  1054. case "\\VARIABLE":
  1055. ShowInternalVariable(parms);
  1056. break;
  1057. case "\\PRINT":
  1058. if(build == null)
  1059. Console.WriteLine("SQL Buffer is empty.");
  1060. else
  1061. Console.WriteLine("SQL Bufer:\n" + buff);
  1062. break;
  1063. case "\\USEPARAMETERS":
  1064. SetUseParameters(parms);
  1065. break;
  1066. case "\\USESIMPLEREADER":
  1067. SetUseSimpleReader(parms);
  1068. break;
  1069. default:
  1070. // Error
  1071. Console.WriteLine("Error: Unknown user command.");
  1072. break;
  1073. }
  1074. }
  1075. public void DealWithArgs(string[] args) {
  1076. for(int a = 0; a < args.Length; a++) {
  1077. if(args[a].Substring(0,1).Equals("-")) {
  1078. string arg = args[a].ToUpper().Substring(1, args[a].Length - 1);
  1079. switch(arg) {
  1080. case "S":
  1081. silent = true;
  1082. break;
  1083. case "F":
  1084. if(a + 1 >= args.Length)
  1085. Console.WriteLine("Error: Missing FILENAME for -f switch");
  1086. else {
  1087. inputFilename = args[a + 1];
  1088. inputFilestream = new StreamReader(inputFilename);
  1089. }
  1090. break;
  1091. case "O":
  1092. if(a + 1 >= args.Length)
  1093. Console.WriteLine("Error: Missing FILENAME for -o switch");
  1094. else {
  1095. outputFilename = args[a + 1];
  1096. outputFilestream = new StreamWriter(outputFilename);
  1097. }
  1098. break;
  1099. default:
  1100. Console.WriteLine("Error: Unknow switch: " + args[a]);
  1101. break;
  1102. }
  1103. }
  1104. }
  1105. }
  1106. public string ReadSqlSharpCommand() {
  1107. string entry = "";
  1108. if(inputFilestream == null) {
  1109. Console.Write("\nSQL# ");
  1110. entry = Console.ReadLine();
  1111. }
  1112. else {
  1113. try {
  1114. entry = inputFilestream.ReadLine();
  1115. if(entry == null) {
  1116. Console.WriteLine("Executing SQL# Commands from file done.");
  1117. }
  1118. }
  1119. catch(Exception e) {
  1120. Console.WriteLine("Error: Reading command from file.");
  1121. }
  1122. Console.Write("\nSQL# ");
  1123. entry = Console.ReadLine();
  1124. }
  1125. return entry;
  1126. }
  1127. public void Run(string[] args) {
  1128. DealWithArgs(args);
  1129. string entry = "";
  1130. build = null;
  1131. if(silent == false) {
  1132. Console.WriteLine("Welcome to SQL#. The interactive SQL command-line client ");
  1133. Console.WriteLine("for Mono.Data. See http://www.go-mono.com/ for more details.\n");
  1134. StartupHelp();
  1135. ShowDefaults();
  1136. }
  1137. while(entry.ToUpper().Equals("\\Q") == false &&
  1138. entry.ToUpper().Equals("\\QUIT") == false) {
  1139. while((entry = ReadSqlSharpCommand()) == "") {}
  1140. if(entry.Substring(0,1).Equals("\\")) {
  1141. HandleCommand(entry);
  1142. }
  1143. else if(entry.IndexOf(";") >= 0) {
  1144. // most likely the end of SQL Command or Query found
  1145. // execute the SQL
  1146. if(conn == null)
  1147. Console.WriteLine("Error: connection is not Open.");
  1148. else if(conn.State == ConnectionState.Closed)
  1149. Console.WriteLine("Error: connection is not Open.");
  1150. else {
  1151. if(build == null) {
  1152. build = new StringBuilder();
  1153. }
  1154. build.Append(entry);
  1155. //build.Append("\n");
  1156. buff = build.ToString();
  1157. ExecuteSql(buff);
  1158. build = null;
  1159. }
  1160. }
  1161. else {
  1162. // most likely a part of a SQL Command or Query found
  1163. // append this part of the SQL
  1164. if(build == null) {
  1165. build = new StringBuilder();
  1166. }
  1167. build.Append(entry + "\n");
  1168. buff = build.ToString();
  1169. }
  1170. }
  1171. CloseDataSource();
  1172. if(outputFilestream != null)
  1173. outputFilestream.Close();
  1174. }
  1175. }
  1176. public enum BindVariableCharacter {
  1177. Colon, // ':' - named parameter - :name
  1178. At, // '@' - named parameter - @name
  1179. QuestionMark, // '?' - positioned parameter - ?
  1180. SquareBrackets // '[]' - delimited named parameter - [name]
  1181. }
  1182. public class ParametersBuilder {
  1183. private BindVariableCharacter bindCharSetting;
  1184. private char bindChar;
  1185. private IDataParameterCollection parms;
  1186. private string sql;
  1187. private IDbCommand cmd;
  1188. private void SetBindCharacter() {
  1189. switch(bindCharSetting) {
  1190. case BindVariableCharacter.Colon:
  1191. bindChar = ':';
  1192. break;
  1193. case BindVariableCharacter.At:
  1194. bindChar = '@';
  1195. break;
  1196. case BindVariableCharacter.SquareBrackets:
  1197. bindChar = '[';
  1198. break;
  1199. case BindVariableCharacter.QuestionMark:
  1200. bindChar = '?';
  1201. break;
  1202. }
  1203. }
  1204. public ParametersBuilder(IDbCommand command, BindVariableCharacter bindVarChar) {
  1205. cmd = command;
  1206. sql = cmd.CommandText;
  1207. parms = cmd.Parameters;
  1208. bindCharSetting = bindVarChar;
  1209. SetBindCharacter();
  1210. }
  1211. public char ParameterMarkerCharacter {
  1212. get {
  1213. return bindChar;
  1214. }
  1215. }
  1216. public int ParseParameters() {
  1217. int numParms = 0;
  1218. IDataParameterCollection parms = cmd.Parameters;
  1219. char[] chars = sql.ToCharArray();
  1220. bool bStringConstFound = false;
  1221. for(int i = 0; i < chars.Length; i++) {
  1222. if(chars[i] == '\'') {
  1223. if(bStringConstFound == true)
  1224. bStringConstFound = false;
  1225. else
  1226. bStringConstFound = true;
  1227. }
  1228. else if(chars[i] == bindChar &&
  1229. bStringConstFound == false) {
  1230. if(bindChar != '?') {
  1231. StringBuilder parm = new StringBuilder();
  1232. i++;
  1233. if(bindChar.Equals('[')) {
  1234. bool endingBracketFound = false;
  1235. while(i <= chars.Length) {
  1236. char ch;
  1237. if(i == chars.Length)
  1238. ch = ' '; // a space
  1239. else
  1240. ch = chars[i];
  1241. if(Char.IsLetterOrDigit(ch) || ch == ' ') {
  1242. parm.Append(ch);
  1243. }
  1244. else if (ch == ']') {
  1245. endingBracketFound = true;
  1246. string p = parm.ToString();
  1247. AddParameter(p);
  1248. numParms ++;
  1249. break;
  1250. }
  1251. else throw new Exception("SQL Parser Error: Invalid character in parameter name");
  1252. i++;
  1253. }
  1254. i--;
  1255. if(endingBracketFound == false)
  1256. throw new Exception("SQL Parser Error: Ending bracket not found for parameter");
  1257. }
  1258. else {
  1259. while(i <= chars.Length) {
  1260. char ch;
  1261. if(i == chars.Length)
  1262. ch = ' '; // a space
  1263. else
  1264. ch = chars[i];
  1265. if(Char.IsLetterOrDigit(ch)) {
  1266. parm.Append(ch);
  1267. }
  1268. else {
  1269. string p = parm.ToString();
  1270. AddParameter(p);
  1271. numParms ++;
  1272. break;
  1273. }
  1274. i++;
  1275. }
  1276. i--;
  1277. }
  1278. }
  1279. else {
  1280. // placeholder paramaeter for ?
  1281. string p = numParms.ToString();
  1282. AddParameter(p);
  1283. numParms ++;
  1284. }
  1285. }
  1286. }
  1287. return numParms;
  1288. }
  1289. public void AddParameter (string p) {
  1290. Console.WriteLine("Add Parameter: " + p);
  1291. if(parms.Contains(p) == false) {
  1292. IDataParameter prm = cmd.CreateParameter();
  1293. prm.ParameterName = p;
  1294. prm.Direction = ParameterDirection.Input;
  1295. prm.DbType = DbType.String; // default
  1296. prm.Value = ""; // default
  1297. cmd.Parameters.Add(prm);
  1298. }
  1299. }
  1300. }
  1301. public class SqlSharpDriver {
  1302. public static void Main(string[] args) {
  1303. SqlSharpCli sqlCommandLineEngine = new SqlSharpCli();
  1304. sqlCommandLineEngine.Run(args);
  1305. }
  1306. }
  1307. }