postgresql 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. * Status of the PostgreSQL ADO.NET Provider
  2. <p> Still exists in System.Data.SqlClient and needs to be moved to Mono.Data.PostgreSQL.
  3. <p>What follows below is Status information for the PostgreSQL ADO.NET provider.
  4. <p>We are able to do simple CREATE TABLE, DROP TABLE, UPDATE, INSERT, and
  5. DELETE SQL commands using the ExecuteNonQuery method in SqlCommand.
  6. <p>We can execute multiple queries and do a NextResult() in SqlDataReader()
  7. to get the next result set.
  8. <p>We are also able to do simple aggregate functions,
  9. ie, count(), sum(), min(), and max()
  10. in a simple SELECT SQL query using the ExecuteScalar() now.
  11. <p>We are also able to retrieve data with a simple SELECT SQL query
  12. using ExecuteReader() which returns a SqlDataReader. We are able to
  13. use GetSchemaTable() to get the meta data about the table columns.
  14. We are able to Read() to get each row from the result set.
  15. <p>Here is a sample of code that is based on PostgresTest.cs and
  16. TestSqlDataReader.cs tests:
  17. <pre>
  18. static void SelectData (IDbConnection cnc) {
  19. IDbCommand selectCommand = cnc.CreateCommand();
  20. IDataReader reader;
  21. selectCommand.CommandType = CommandType.Text;
  22. selectCommand.CommandText =
  23. "select * from pg_user;" +
  24. "select * from pg_tables;" +
  25. "select * from pg_database";
  26. reader = selectCommand.ExecuteReader ();
  27. do {
  28. // get the DataTable that holds
  29. // the schema
  30. DataTable dt = rdr.GetSchemaTable();
  31. if(rdr.RecordsAffected != -1) {
  32. // Results for
  33. // SQL INSERT, UPDATE, DELETE Commands
  34. // have RecordsAffected >= 0
  35. Console.WriteLine("Result is from a SQL Command (INSERT,UPDATE,DELETE). Records Affected: " + rdr.RecordsAffected);
  36. }
  37. else if (dt == null)
  38. Console.WriteLine("Result is from a SQL Command not (INSERT,UPDATE,DELETE). Records Affected: " + rdr.RecordsAffected);
  39. else {
  40. // Results for
  41. // SQL not INSERT, UPDATE, nor DELETE
  42. // have RecordsAffected = -1
  43. Console.WriteLine("Result is from a SQL SELECT Query. Records Affected: " + rdr.RecordsAffected);
  44. // Results for a SQL Command (CREATE TABLE, SET, etc)
  45. // will have a null reference returned from GetSchemaTable()
  46. //
  47. // Results for a SQL SELECT Query
  48. // will have a DataTable returned from GetSchemaTable()
  49. results++;
  50. Console.WriteLine("Result Set " + results + "...");
  51. // number of columns in the table
  52. Console.WriteLine(" Total Columns: " +
  53. dt.Columns.Count);
  54. // display the schema
  55. foreach (DataRow schemaRow in dt.Rows) {
  56. foreach (DataColumn schemaCol in dt.Columns)
  57. Console.WriteLine(schemaCol.ColumnName +
  58. " = " +
  59. schemaRow[schemaCol]);
  60. Console.WriteLine();
  61. }
  62. int nRows = 0;
  63. string output, metadataValue, dataValue;
  64. // Read and display the rows
  65. Console.WriteLine("Gonna do a Read() now...");
  66. while(rdr.Read()) {
  67. Console.WriteLine(" Row " + nRows + ": ");
  68. for(c = 0; c < rdr.FieldCount; c++) {
  69. // column meta data
  70. DataRow dr = dt.Rows[c];
  71. metadataValue =
  72. " Col " +
  73. c + ": " +
  74. dr["ColumnName"];
  75. // column data
  76. if(rdr.IsDBNull(c) == true)
  77. dataValue = " is NULL";
  78. else
  79. dataValue =
  80. ": " +
  81. rdr.GetValue(c);
  82. // display column meta data and data
  83. output = metadataValue + dataValue;
  84. Console.WriteLine(output);
  85. }
  86. nRows++;
  87. }
  88. Console.WriteLine(" Total Rows: " +
  89. nRows);
  90. }
  91. } while(rdr.NextResult());
  92. Console.WriteLine("Total Result sets: " + results);
  93. rdr.Close();
  94. }
  95. </pre>
  96. <p>We are able to get
  97. String data (char, character, text, varchar), Int16 (smallint),
  98. Int32 (integer), Int64 (bigint), DateTime (time, date, timestamp),
  99. Boolean (boolean), Single (float), and Double (double).
  100. More data types will come later. Note, the types that do work still
  101. need thorough testing.
  102. <p>Rows that are returned which contain columns that are NULL are handled now.
  103. The SqlDataReader method IsDBNull() needs to be called to determine
  104. if a field IS NULL before trying to read data from that field.
  105. <p>Calling PostgreSQL stored procedures works. It does not work perfectly. It may not
  106. even work to specification - yet. If you want to test it yourself, look at
  107. TestSqlDataReader.cs or PostgresTest.cs in
  108. mcs/class/System.Data/Test.
  109. <p>Below, I have some sample code you can
  110. use to call a PostgreSQL stored procedure named "version". This stored
  111. procedure returns a string containing the PostgreSQL server version. Notice
  112. the CommandType is StoredProcedure and the method ExecuteScalar() is called.
  113. <p>ExecuteScalar() is a lightweight method in class SqlCommand that only returns
  114. one row and one column as one object - even if there is more than row or column.
  115. <pre>
  116. static string GetDatabaseServerVersion (SqlConnection cnc)
  117. {
  118. SqlCommand cmd = cnc.CreateCommand ();
  119. string data;
  120. cmd.CommandType = CommandType.StoredProcedure;
  121. cmd.CommandText = "version";
  122. data = (string) cmd.ExecuteScalar ();
  123. return data;
  124. }
  125. </pre>
  126. <p>We have the beginnings of Parameters support PostgreSQL. Only
  127. Input Parameters are currently supported. Output, Input/Output,
  128. and Return parameters still need to be done.
  129. <p>A lot of functionality in System.Data is missing, but the
  130. infrastructure is starting to come together.
  131. <p>A lot of Exceptions need to be thrown for various exceptions. However,
  132. SqlException, SqlErrorCollection, and SqlError have been partially
  133. implemented.
  134. <p>Tim Coleman and Rodrigo Moya got the beginnings of the
  135. SqlDataAdapter/DataSet/DataTable/DataRow to work. Currently,
  136. the SqlDataAdapter can Fill() relational data into a DataTable in a DataSet.
  137. See the test mcs/class/System.Data/Test/TestSqlDataAdapter.cs to see it in action.
  138. Below, I show a snippets from the test:
  139. <pre>
  140. string connectionString;
  141. string sqlQuery;
  142. SqlDataAdapter adapter;
  143. DataSet dataSet = null;
  144. connectionString =
  145. "host=localhost;" +
  146. "dbname=test;" +
  147. "user=postgres";
  148. sqlQuery = "select * from pg_tables";
  149. adapter = new SqlDataAdapter (sqlQuery,
  150. connectionString);
  151. dataSet = new DataSet ();
  152. adapter.Fill (dataSet);
  153. if (dataSet != null) {
  154. foreach (DataRow row in dataSet.Tables["Table"].Rows)
  155. Console.WriteLine("tablename: " + row["tablename"]);
  156. }
  157. </pre>
  158. * Testing the PostgreSQL ADO.NET Provider
  159. <p>In order to test System.Data.SqlClient, you will need to have
  160. access to a remote PostgreSQL DBMS, or you will have to install
  161. one locally. PostgreSQL is the DBMS used for the initial
  162. implementation of System.Data.SqlClient.
  163. <p>Why? Because it is free software, has a client
  164. library that is easy to use, PostgreSQL is easy to install on
  165. Unix and Windows (using the Cygwin install program), not difficult to setup after
  166. installation, and it runs under: Linux,
  167. Windows (via cygwin and ipc-daemon), Unix, and
  168. others. This allowed us to create the
  169. System.Data functionality in Mono much quicker.
  170. <p>If you plan on using a remote PostgreSQL DBMS Server,
  171. than you will need to have the PostgreSQL client software on your
  172. local computer that includes libpq.so (pq.dll on Windows).
  173. <p>The System.Data tests use this connection string to connect
  174. to the PostgreSQL database named "test" at host "localhost" as
  175. user "postgres".
  176. <pre>
  177. "host=localhost;dbname=test;user=postgres"
  178. </pre>
  179. <p>Installation instructions for PostgreSQL DBMS:
  180. <b>On Unix</b>
  181. <ul>
  182. * Read the PostgreSQL Installation Instructions
  183. at \usr\doc\postgresql-x.x.x\html\installation.html
  184. * Depending on your Unix system,
  185. PostgreSQL maybe already installed, a database user 'postgres' created,
  186. a linux user 'postgres' created and initdb ran. Or maybe not.
  187. <pre>
  188. su
  189. adduser postgres
  190. mkdir /usr/local/pgsql/data
  191. chown postgres /usr/local/pgsql/data
  192. su - postgres
  193. initdb -D /usr/local/pgsql/data
  194. postmaster -i -D /usr/local/pgsql/data
  195. createdb test
  196. psql test
  197. </pre>
  198. * Make sure you have a database user named postgres. It is best to install
  199. the PostgreSQL DBMS under linux user postgres. When you run the postmaster,
  200. run it under the user postgres as well. If this was not done, then you
  201. will need to create a user named postgres for the System.Data tests.
  202. * If you already installed PostgeSQL and you do not have a database
  203. user named postgres, then you can create user postgres using psql:
  204. <pre>
  205. psql test
  206. create user postgres with password 'fun2db';
  207. </pre>
  208. * The postmaster must be run with -i option.
  209. * In the /usr/local/pgsql/data/pg_hba.conf file, you need
  210. to have the AUTH_TYPE set to md5. You can read more on this at
  211. /usr/doc/postgresql-7.2.1/html/client-authentication.html
  212. or wherever your
  213. PostgreSQL html docs are located. See the 2nd line below,
  214. host 127.0.0.1 has an AUTH_TYPE md5 in pg_hba.conf.
  215. <pre>
  216. # TYPE DATABASE IP_ADDRESS MASK AUTH_TYPE
  217. local all trust
  218. host all 127.0.0.1 255.255.255.255 md5
  219. </pre>
  220. * If you can not find your PostgreSQL documentation locally or you
  221. did not install it, then you
  222. can get it <a href="http://www.postgresql.org/idocs/">here</a>.
  223. </ul>
  224. <b>On Windows</b>
  225. <ul>
  226. * Use the <a href="http://www.cygwin.com/">Cygwin</a> installer to
  227. install the PostgreSQL DBMS. It is
  228. found in the database category.
  229. * <p>Read the file postgres-x.x.README at /usr/doc/Cygwin and read
  230. the requirements to install PostgreSQL. Those requirements
  231. are included with cygwin except cygipc. A default installtion
  232. of cygwin does not install everything you will need, so on the
  233. safe side, just include everything when installing cygwin.
  234. * <p>The -x.x in postgres-x.x is the version of your PostgreSQL DBMS.
  235. * <p>Once Cygwin has installed the PostgreSQL DBMS on your computer,
  236. read the file FAQ_MSWIN which is available
  237. in /usr/doc/postgres-x.x
  238. * <p>Important notes from this file are:
  239. <ul>
  240. <p><b>2.</b> - Install the latest <a href="http://www.neuro.gatech.edu/users/cwilson/cygutils/OBSOLETE/V1.1/cygipc/index.html">CygIPC</a> package.
  241. <p>The cygipc package contains the ipc-daemon you will need
  242. to run before you can
  243. run the PostgreSQL DBMS Server daemon (postmaster) or run
  244. initdb which initializes the PostgreSQL database.
  245. <p><b>3.</b> The Cygwin bin directory has to be placed in
  246. the path before the Windows program directories,
  247. for example, C:\cygwin\bin
  248. <p><b>My own note.</b> In the Windows control panel, I set
  249. the environment variables PATH to my cygwin /usr/local/bin,
  250. /usr/bin, and /bin. I also set my LD_LIBRARY_PATH to
  251. /usr/local/lib and /usr/lib. For example:
  252. <p>
  253. <pre>
  254. PATH=c:\cygwin\usr\local\bin;c:\cygwin\usr\bin;c:\cygwin\bin;
  255. LD_LIBRARY_PATH=c:\cygwin\usr\local\lib;c:\cygwin\usr\lib;
  256. </pre>
  257. <p><b>4.</b> Start the ipc-daemon that came with the cygipc
  258. package. There
  259. are two ways to do this: run it from the command line as:
  260. <p>
  261. <pre>
  262. ipc-daemon &
  263. </pre>
  264. <p>or you can set it up as a Windows service. See the
  265. file cygrunsrv.README at /usr/doc/Cygwin on how to do this
  266. for ipc-daemon and postmaster. Note the
  267. troubleshooting section at the end of
  268. the cygrunsrv.README file.
  269. <p>To install ipc-daemon as a service,
  270. you just have to run
  271. <p>
  272. <pre>
  273. ipc-daemon --install-as-service' (--remove-as-service)
  274. </pre>
  275. <p>and then run
  276. <pre>
  277. net start ipc-daemon
  278. </pre>
  279. </ul>
  280. <p>Read the installation.html file
  281. at /usr/doc/postgresql-x.x/html/installation.html
  282. <p>You will see in this file that you will need to
  283. run the following commands:
  284. <p>
  285. <pre>
  286. mkdir /usr/local/pgsql/data
  287. initdb -D /usr/local/pgsql/data
  288. postmaster -D /usr/local/pgsql/data
  289. createdb test
  290. psql test
  291. </pre>
  292. <p>When you need to connect to the database,
  293. you will need ipc-daemon and postmaster running. Start ipc-daemon
  294. before any of the command above. If you restart your computer, you
  295. need to start ipc-daemon and postmaster either manually or as a
  296. service.
  297. <p>psql is a command-line PostgreSQL client tool to
  298. enter and run SQL commands and queries.
  299. <p>If there is no database user named postgres, create a user named
  300. postgres with the following SQL command in the client tool psql:
  301. <p>
  302. <pre>
  303. psql test
  304. create user postgres with password 'fun2db';
  305. </pre>
  306. <p>The only reason I say this is so you can easily use the System.Data tests
  307. without having to change the database, userid, etc.
  308. </ul>
  309. <p>In the path mcs/class/System.Data/Test
  310. there is a PostgreSQL test program named
  311. PostgreTest.cs. Thanks goes to Gonzalo for creating the original
  312. PostgreSQL test.
  313. <p>To use it to test System.Data, you
  314. modify the file to your PostgreSQL database
  315. connection requirements:
  316. <p>
  317. <ul>
  318. <li><b>dbname</b> database, ie., test</li>
  319. <li><b>host</b> hostname of the PostgreSQL DBMS Server to connect to, ie., localhost</li>
  320. <li><b>user</b> username, ie., someuser</li>
  321. <li><b>password</b> password, ie., mypass1234</li>
  322. </ul>
  323. <p>The connection string is in OLE-DB connection string format. Internally,
  324. SqlConnection converts this to the PostgreSQL connection string format.
  325. <p>
  326. <pre>
  327. OLE-DB: "host=localhost;dbname=test;user=joe;password=smoe"
  328. PostgreSQL: "host=localhost dbname=test user=joe password=smoe"
  329. </pre>
  330. <p>
  331. Note that OLE-DB includes the semicolons while PostgreSQL's connection
  332. string does not.
  333. <p>
  334. To compile the PostgresTest.cs program, do:
  335. <p>
  336. <pre>
  337. mcs PostgresTest.cs -r System.Data.dll
  338. </pre>
  339. <p>
  340. To run using mint, do:
  341. <p>
  342. <pre>
  343. mint PostgresTest.exe
  344. </pre>
  345. <p>
  346. To run using mono, do:
  347. <pre>
  348. mono PostgresTest.exe
  349. </pre>
  350. <p>Below, I show how the output from PostgresTest. I have omitted a lot
  351. of the meta data for the columns except two columns. The classes
  352. used were from System.Data.SqlClient and were used to connect to a
  353. PostgreSQL database and retrieve data.
  354. <p>
  355. <pre>
  356. danmorg@DANPC ~/mono/mcs/class/System.Data/Test
  357. $ mcs PostgresTest.cs -r System.Data.dll
  358. danmorg@DANPC ~/mono/mcs/class/System.Data/Test
  359. $ mono PostgresTest.exe
  360. Postgres provider specific tests...
  361. Drop table:
  362. Error (don't worry about this one)SqlError:PGRES_FATAL_ERROR ERROR: table "mono
  363. _postgres_test" does not exist
  364. <Stack Trace>
  365. Create table with all supported types:
  366. OK
  367. Insert values for all known types:
  368. OK
  369. Update values:
  370. OK
  371. Insert values for all known types:
  372. OK
  373. Aggregate: count(*)
  374. Agg Result: 2
  375. Aggregate: min(text_value)
  376. Agg Result: This is a text
  377. Aggregate: max(int4_value)
  378. Agg Result: 1048000
  379. Aggregate: sum(int4_value)
  380. Agg Result: 1048003
  381. Select values from the database:
  382. Result is from a SELECT SQL Query. Records Affected: -1
  383. Result Set 1...
  384. Total Columns: 28
  385. ColumnName = boolean_value
  386. ColumnOrdinal = 1
  387. ColumnSize = 1
  388. NumericPrecision = 0
  389. NumericScale = 0
  390. IsUnique = False
  391. IsKey =
  392. BaseCatalogName =
  393. BaseColumnName = boolean_value
  394. BaseSchemaName =
  395. BaseTableName =
  396. DataType = System.Boolean
  397. AllowDBNull = False
  398. ProviderType = 16
  399. IsAliased = False
  400. IsExpression = False
  401. IsIdentity = False
  402. IsAutoIncrement = False
  403. IsRowVersion = False
  404. IsHidden = False
  405. IsLong = False
  406. IsReadOnly = False
  407. ...
  408. ColumnName = null_timestamp_value
  409. ColumnOrdinal = 28
  410. ColumnSize = 8
  411. NumericPrecision = 0
  412. NumericScale = 0
  413. IsUnique = False
  414. IsKey =
  415. BaseCatalogName =
  416. BaseColumnName = null_timestamp_value
  417. BaseSchemaName =
  418. BaseTableName =
  419. DataType = System.DateTime
  420. AllowDBNull = False
  421. ProviderType = 1184
  422. IsAliased = False
  423. IsExpression = False
  424. IsIdentity = False
  425. IsAutoIncrement = False
  426. IsRowVersion = False
  427. IsHidden = False
  428. IsLong = False
  429. IsReadOnly = False
  430. Gonna do a Read() now...
  431. Row 0:
  432. Col 0: boolean_value: False
  433. Col 1: int2_value: 5
  434. Col 2: int4_value: 3
  435. Col 3: bigint_value: 9
  436. Col 4: float_value: 3.141590
  437. Col 5: double_value: 3.14159
  438. Col 6: numeric_value: 123456789012.345
  439. Col 7: char_value: Mono.Data!
  440. Col 8: varchar_value: It was not me!
  441. Col 9: text_value: We got data!
  442. Col 10: point_value: (1,0)
  443. Col 11: time_value: 01/01/1 21:13:14
  444. Col 12: date_value: 02/29/2000 00:00:00
  445. Col 13: timestamp_value: 02/29/2004 14:00:11
  446. Col 14: null_boolean_value is NULL
  447. Col 15: null_int2_value is NULL
  448. Col 16: null_int4_value is NULL
  449. Col 17: null_bigint_value is NULL
  450. Col 18: null_float_value is NULL
  451. Col 19: null_double_value is NULL
  452. Col 20: null_numeric_value is NULL
  453. Col 21: null_char_value is NULL
  454. Col 22: null_varchar_value is NULL
  455. Col 23: null_text_value is NULL
  456. Col 24: null_point_value is NULL
  457. Col 25: null_time_value is NULL
  458. Col 26: null_date_value is NULL
  459. Col 27: null_timestamp_value is NULL
  460. Row 1:
  461. Col 0: boolean_value: True
  462. Col 1: int2_value: -22
  463. Col 2: int4_value: 1048000
  464. Col 3: bigint_value: 123456789012345
  465. Col 4: float_value: 3.141590
  466. Col 5: double_value: 3.14159
  467. Col 6: numeric_value: 123456789012.345
  468. Col 7: char_value: This is a char
  469. Col 8: varchar_value: This is a varchar
  470. Col 9: text_value: This is a text
  471. Col 10: point_value: (1,0)
  472. Col 11: time_value: 01/01/1 21:13:14
  473. Col 12: date_value: 02/29/2000 00:00:00
  474. Col 13: timestamp_value: 02/29/2004 14:00:11
  475. Col 14: null_boolean_value is NULL
  476. Col 15: null_int2_value is NULL
  477. Col 16: null_int4_value is NULL
  478. Col 17: null_bigint_value is NULL
  479. Col 18: null_float_value is NULL
  480. Col 19: null_double_value is NULL
  481. Col 20: null_numeric_value is NULL
  482. Col 21: null_char_value is NULL
  483. Col 22: null_varchar_value is NULL
  484. Col 23: null_text_value is NULL
  485. Col 24: null_point_value is NULL
  486. Col 25: null_time_value is NULL
  487. Col 26: null_date_value is NULL
  488. Col 27: null_timestamp_value is NULL
  489. Total Rows Retrieved: 2
  490. Total Result sets: 1
  491. Call ExecuteReader with a SQL Command. (Not INSERT,UPDATE,DELETE
  492. ).
  493. Result is from a SQL Command not (INSERT,UPDATE,DELETE). Records Affected: -1
  494. Total Result sets: 0
  495. Call ExecuteReader with a SQL Command. (Is INSERT,UPDATE,DELETE)
  496. .
  497. Result is from a SQL Command (INSERT,UPDATE,DELETE). Records Affected: 1
  498. Total Result sets: 0
  499. Calling stored procedure version()
  500. Result: PostgreSQL 7.2.1 on i686-pc-cygwin, compiled by GCC 2.95.3-5
  501. Database Server Version: PostgreSQL 7.2.1 on i686-pc-cygwin, compiled by GCC 2.9
  502. 5.3-5
  503. Clean up...
  504. Drop table...
  505. OK
  506. RESULT: 0
  507. </pre>