pg 0.12.2 → 0.13.0.pre298

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.hoerc +2 -0
  3. data/.tm_properties +12 -0
  4. data/ChangeLog +86 -6
  5. data/Contributors.rdoc +7 -0
  6. data/History.rdoc +29 -0
  7. data/LICENSE +12 -14
  8. data/Manifest.txt +15 -14
  9. data/{BSD → POSTGRES} +0 -0
  10. data/{README.OS_X.rdoc → README-OS_X.rdoc} +0 -0
  11. data/{README.windows.rdoc → README-Windows.rdoc} +0 -0
  12. data/README.ja.rdoc +1 -1
  13. data/README.rdoc +39 -27
  14. data/Rakefile +1 -2
  15. data/ext/extconf.rb +9 -2
  16. data/ext/pg.c +232 -4297
  17. data/ext/pg.h +87 -23
  18. data/ext/pg_connection.c +3301 -0
  19. data/ext/pg_result.c +905 -0
  20. data/lib/pg.rb +26 -43
  21. data/lib/pg/connection.rb +58 -0
  22. data/lib/pg/constants.rb +11 -0
  23. data/lib/pg/exceptions.rb +11 -0
  24. data/lib/pg/result.rb +11 -0
  25. data/misc/openssl-pg-segfault.rb +1 -1
  26. data/sample/async_api.rb +16 -21
  27. data/sample/async_copyto.rb +1 -1
  28. data/sample/async_mixed.rb +56 -0
  29. data/sample/copyfrom.rb +1 -1
  30. data/sample/copyto.rb +1 -1
  31. data/sample/cursor.rb +1 -1
  32. data/sample/losample.rb +6 -6
  33. data/sample/notify_wait.rb +51 -22
  34. data/sample/test_binary_values.rb +4 -6
  35. data/spec/lib/helpers.rb +14 -10
  36. data/spec/{pgconn_spec.rb → pg/connection_spec.rb} +227 -60
  37. data/spec/{pgresult_spec.rb → pg/result_spec.rb} +31 -35
  38. data/spec/pg_spec.rb +22 -0
  39. metadata +44 -42
  40. metadata.gz.sig +0 -0
  41. data/GPL +0 -340
  42. data/ext/compat.c +0 -541
  43. data/ext/compat.h +0 -184
  44. data/sample/psql.rb +0 -1181
  45. data/sample/psqlHelp.rb +0 -158
  46. data/sample/test1.rb +0 -60
  47. data/sample/test2.rb +0 -44
  48. data/sample/test4.rb +0 -71
  49. data/spec/m17n_spec.rb +0 -170
@@ -1,184 +0,0 @@
1
-
2
- #ifndef __compat_h
3
- #define __compat_h
4
-
5
- #include <stdlib.h>
6
-
7
- #ifdef RUBY_EXTCONF_H
8
- #include RUBY_EXTCONF_H
9
- #endif
10
-
11
- #include "libpq-fe.h"
12
- #include "libpq/libpq-fs.h" /* large-object interface */
13
-
14
- #include "ruby.h"
15
-
16
- /* pg_config.h does not exist in older versions of
17
- * PostgreSQL, so I can't effectively use PG_VERSION_NUM
18
- * Instead, I create some #defines to help organization.
19
- */
20
- #ifndef HAVE_PQCONNECTIONUSEDPASSWORD
21
- #define PG_BEFORE_080300
22
- #endif
23
-
24
- #ifndef HAVE_PQISTHREADSAFE
25
- #define PG_BEFORE_080200
26
- #endif
27
-
28
- #ifndef HAVE_LO_CREATE
29
- #define PG_BEFORE_080100
30
- #endif
31
-
32
- #ifndef HAVE_PQPREPARE
33
- #define PG_BEFORE_080000
34
- #endif
35
-
36
- #ifndef HAVE_PQEXECPARAMS
37
- #define PG_BEFORE_070400
38
- #endif
39
-
40
- #ifndef HAVE_PQESCAPESTRINGCONN
41
- #define PG_BEFORE_070300
42
- #error PostgreSQL client version too old, requires 7.3 or later.
43
- #endif
44
-
45
- /* This is necessary because NAMEDATALEN is defined in
46
- * pg_config_manual.h in 8.3, and that include file doesn't
47
- * exist before 7.4
48
- */
49
- #ifndef PG_BEFORE_070400
50
- #include "pg_config_manual.h"
51
- #endif
52
-
53
- #ifndef PG_DIAG_INTERNAL_POSITION
54
- #define PG_DIAG_INTERNAL_POSITION 'p'
55
- #endif /* PG_DIAG_INTERNAL_POSITION */
56
-
57
- #ifndef PG_DIAG_INTERNAL_QUERY
58
- #define PG_DIAG_INTERNAL_QUERY 'q'
59
- #endif /* PG_DIAG_INTERNAL_QUERY */
60
-
61
- #ifdef PG_BEFORE_080300
62
-
63
- #ifndef HAVE_PG_ENCODING_TO_CHAR
64
- #define pg_encoding_to_char(x) "SQL_ASCII"
65
- #else
66
- /* Some versions ofPostgreSQL prior to 8.3 define pg_encoding_to_char
67
- * but do not declare it in a header file, so this declaration will
68
- * eliminate an unecessary warning
69
- */
70
- extern char* pg_encoding_to_char(int);
71
- #endif /* HAVE_PG_ENCODING_TO_CHAR */
72
-
73
- int PQconnectionNeedsPassword(PGconn *conn);
74
- int PQconnectionUsedPassword(PGconn *conn);
75
- int lo_truncate(PGconn *conn, int fd, size_t len);
76
-
77
- #endif /* PG_BEFORE_080300 */
78
-
79
- #ifdef PG_BEFORE_080200
80
- int PQisthreadsafe(void);
81
- int PQnparams(const PGresult *res);
82
- Oid PQparamtype(const PGresult *res, int param_number);
83
- PGresult * PQdescribePrepared(PGconn *conn, const char *stmtName);
84
- PGresult * PQdescribePortal(PGconn *conn, const char *portalName);
85
- int PQsendDescribePrepared(PGconn *conn, const char *stmtName);
86
- int PQsendDescribePortal(PGconn *conn, const char *portalName);
87
- char *PQencryptPassword(const char *passwd, const char *user);
88
- #endif /* PG_BEFORE_080200 */
89
-
90
- #ifdef PG_BEFORE_080100
91
- Oid lo_create(PGconn *conn, Oid lobjId);
92
- #endif /* PG_BEFORE_080100 */
93
-
94
- #ifdef PG_BEFORE_080000
95
- PGresult *PQprepare(PGconn *conn, const char *stmtName, const char *query,
96
- int nParams, const Oid *paramTypes);
97
- int PQsendPrepare(PGconn *conn, const char *stmtName, const char *query,
98
- int nParams, const Oid *paramTypes);
99
- int PQserverVersion(const PGconn* conn);
100
- #endif /* PG_BEFORE_080000 */
101
-
102
- #ifdef PG_BEFORE_070400
103
-
104
- #define PG_DIAG_SEVERITY 'S'
105
- #define PG_DIAG_SQLSTATE 'C'
106
- #define PG_DIAG_MESSAGE_PRIMARY 'M'
107
- #define PG_DIAG_MESSAGE_DETAIL 'D'
108
- #define PG_DIAG_MESSAGE_HINT 'H'
109
- #define PG_DIAG_STATEMENT_POSITION 'P'
110
- #define PG_DIAG_CONTEXT 'W'
111
- #define PG_DIAG_SOURCE_FILE 'F'
112
- #define PG_DIAG_SOURCE_LINE 'L'
113
- #define PG_DIAG_SOURCE_FUNCTION 'R'
114
-
115
- #define PQfreemem(ptr) free(ptr)
116
- #define PGNOTIFY_EXTRA(notify) ""
117
-
118
- /* CONNECTION_SSL_STARTUP was added to an enum type
119
- * after 7.3. For 7.3 in order to compile, we just need
120
- * it to evaluate to something that is not present in that
121
- * enum.
122
- */
123
- #define CONNECTION_SSL_STARTUP 1000000
124
-
125
- typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res);
126
-
127
- typedef enum
128
- {
129
- PQERRORS_TERSE, /* single-line error messages */
130
- PQERRORS_DEFAULT, /* recommended style */
131
- PQERRORS_VERBOSE /* all the facts, ma'am */
132
- } PGVerbosity;
133
-
134
- typedef enum
135
- {
136
- PQTRANS_IDLE, /* connection idle */
137
- PQTRANS_ACTIVE, /* command in progress */
138
- PQTRANS_INTRANS, /* idle, within transaction block */
139
- PQTRANS_INERROR, /* idle, within failed transaction */
140
- PQTRANS_UNKNOWN /* cannot determine status */
141
- } PGTransactionStatusType;
142
-
143
- PGresult *PQexecParams(PGconn *conn, const char *command, int nParams,
144
- const Oid *paramTypes, const char * const * paramValues, const int *paramLengths,
145
- const int *paramFormats, int resultFormat);
146
- PGTransactionStatusType PQtransactionStatus(const PGconn *conn);
147
- char *PQparameterStatus(const PGconn *conn, const char *paramName);
148
- int PQprotocolVersion(const PGconn *conn);
149
- PGresult *PQexecPrepared(PGconn *conn, const char *stmtName, int nParams,
150
- const char * const *ParamValues, const int *paramLengths, const int *paramFormats,
151
- int resultFormat);
152
- int PQsendQueryParams(PGconn *conn, const char *command, int nParams,
153
- const Oid *paramTypes, const char * const * paramValues, const int *paramLengths,
154
- const int *paramFormats, int resultFormat);
155
- int PQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams,
156
- const char * const *ParamValues, const int *paramLengths, const int *paramFormats,
157
- int resultFormat);
158
- int PQputCopyData(PGconn *conn, const char *buffer, int nbytes);
159
- int PQputCopyEnd(PGconn *conn, const char *errormsg);
160
- int PQgetCopyData(PGconn *conn, char **buffer, int async);
161
- PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity);
162
- Oid PQftable(const PGresult *res, int column_number);
163
- int PQftablecol(const PGresult *res, int column_number);
164
- int PQfformat(const PGresult *res, int column_number);
165
- char *PQresultErrorField(const PGresult *res, int fieldcode);
166
- PQnoticeReceiver PQsetNoticeReceiver(PGconn *conn, PQnoticeReceiver proc, void *arg);
167
-
168
- #else
169
- #define PGNOTIFY_EXTRA(notify) ((notify)->extra)
170
- #endif /* PG_BEFORE_070400 */
171
-
172
- #ifdef PG_BEFORE_070300
173
- #error unsupported postgresql version, requires 7.3 or later.
174
- int PQsetClientEncoding(PGconn *conn, const char *encoding)
175
- size_t PQescapeString(char *to, const char *from, size_t length);
176
- unsigned char * PQescapeBytea(const unsigned char *bintext, size_t binlen, size_t *bytealen);
177
- unsigned char * PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen);
178
- size_t PQescapeStringConn(PGconn *conn, char *to, const char *from,
179
- size_t length, int *error);
180
- unsigned char *PQescapeByteaConn(PGconn *conn, const unsigned char *from,
181
- size_t from_length, size_t *to_length);
182
- #endif /* PG_BEFORE_070300 */
183
-
184
- #endif /* __compat_h */
@@ -1,1181 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # an interactive front-end to postgreSQL
4
- #
5
- # Original source code is written by C.
6
- # Copyright (c) 1996, Regents of the University of California
7
- #
8
- # ruby version is written by ematsu
9
- # Copyright (c) 1997 Eiji-usagi-MATSUmoto <ematsu@pfu.co.jp>
10
- #
11
- # Changes:
12
- #
13
- # Fri 12 Dec 19:56:34 JST 1997
14
- # * replace puts -> print
15
- #
16
- # $Id: psql.rb,v a3434e641f6a 2009/12/10 18:22:46 mahlon $
17
- #
18
-
19
- require "pg"
20
- require "parsearg"
21
- require "psqlHelp"
22
-
23
- PROMPT = "=> "
24
- MAX_QUERY_BUFFER = 20000
25
- DEFAULT_SHELL = "/bin/sh"
26
- DEFAULT_EDITOR = "vi"
27
- DEFAULT_FIELD_SEP= "|"
28
-
29
- PsqlSettings = Struct.new("PsqlSettings", :db, :queryFout, :opt, :prompt,
30
- :gfname, :notty,:pipe, :echoQuery,:quiet,
31
- :singleStep, :singleLineMode, :useReadline)
32
-
33
- PrintOpt = Struct.new("PrintOpt", :header, :align, :standard, :html3,
34
- :expanded, :pager, :fieldSep, :tableOpt,
35
- :caption, :fieldName)
36
-
37
- $readline_ok = TRUE
38
-
39
- def usage()
40
- printf("Usage: psql.rb [options] [dbname]\n")
41
- printf("\t -a authsvc set authentication service\n")
42
- printf("\t -A turn off alignment when printing out attributes\n")
43
- printf("\t -c query run single query (slash commands too)\n")
44
- printf("\t -d dbName specify database name\n")
45
- printf("\t -e echo the query sent to the backend\n")
46
- printf("\t -f filename use file as a source of queries\n")
47
- printf("\t -F sep set the field separator (default is \" \")\n")
48
- printf("\t -h host set database server host\n")
49
- printf("\t -H turn on html3.0 table output\n")
50
- printf("\t -l list available databases\n")
51
- printf("\t -n don't use readline library\n")
52
- printf("\t -o filename send output to filename or (|pipe)\n")
53
- printf("\t -p port set port number\n")
54
- printf("\t -q run quietly (no messages, no prompts)\n")
55
- printf("\t -s single step mode (prompts for each query)\n")
56
- printf("\t -S single line mode (i.e. query terminated by newline)\n")
57
- printf("\t -t turn off printing of headings and row count\n")
58
- printf("\t -T html set html3.0 table command options (cf. -H)\n")
59
- printf("\t -x turn on expanded output (field names on left)\n")
60
- exit(1)
61
- end
62
- $USAGE = 'usage'
63
-
64
- def slashUsage(ps)
65
- printf(" \\? -- help\n")
66
- printf(" \\a -- toggle field-alignment (currenty %s)\n", on(ps.opt.align))
67
- printf(" \\C [<captn>] -- set html3 caption (currently '%s')\n", ps.opt.caption );
68
- printf(" \\connect <dbname> -- connect to new database (currently '%s')\n", ps.db.db)
69
- printf(" \\copy {<table> to <file> | <file> from <table>}\n")
70
- printf(" \\d [<table>] -- list tables in database or columns in <table>, * for all\n")
71
- printf(" \\da -- list aggregates\n")
72
- printf(" \\di -- list only indices\n")
73
- printf(" \\ds -- list only sequences\n")
74
- printf(" \\dS -- list system tables and indexes\n")
75
- printf(" \\dt -- list only tables\n")
76
- printf(" \\dT -- list types\n")
77
- printf(" \\e [<fname>] -- edit the current query buffer or <fname>\n")
78
- printf(" \\E [<fname>] -- edit the current query buffer or <fname>, and execute\n")
79
- printf(" \\f [<sep>] -- change field separater (currently '%s')\n", ps.opt.fieldSep)
80
- printf(" \\g [<fname>] [|<cmd>] -- send query to backend [and results in <fname> or pipe]\n")
81
- printf(" \\h [<cmd>] -- help on syntax of sql commands, * for all commands\n")
82
- printf(" \\H -- toggle html3 output (currently %s)\n", on(ps.opt.html3))
83
- printf(" \\i <fname> -- read and execute queries from filename\n")
84
- printf(" \\l -- list all databases\n")
85
- printf(" \\m -- toggle monitor-like table display (currently %s)\n", on(ps.opt.standard))
86
- printf(" \\o [<fname>] [|<cmd>] -- send all query results to stdout, <fname>, or pipe\n")
87
- printf(" \\p -- print the current query buffer\n")
88
- printf(" \\q -- quit\n")
89
- printf(" \\r -- reset(clear) the query buffer\n")
90
- printf(" \\s [<fname>] -- print history or save it in <fname>\n")
91
- printf(" \\t -- toggle table headings and row count (currently %s)\n", on(ps.opt.header))
92
- printf(" \\T [<html>] -- set html3.0 <table ...> options (currently '%s')\n", ps.opt.tableOpt)
93
- printf(" \\x -- toggle expanded output (currently %s)\n", on(ps.opt.expanded))
94
- printf(" \\! [<cmd>] -- shell escape or command\n")
95
- end
96
-
97
- def on(f)
98
- if f
99
- return "on"
100
- else
101
- return "off"
102
- end
103
- end
104
-
105
- def toggle(settings, sw, msg)
106
- sw = !sw
107
- if !settings.quiet
108
- printf(STDERR, "turned %s %s\n", on(sw), msg)
109
- end
110
- return sw
111
- end
112
-
113
- def gets(prompt, source)
114
- if source == STDIN
115
- if ($readline_ok)
116
- line = Readline.readline(prompt,source)
117
- else
118
- STDOUT.print(prompt)
119
- STDOUT.flush()
120
- line = source.gets
121
- end
122
- end
123
-
124
- if line == nil
125
- return nil
126
- else
127
- if line.length > MAX_QUERY_BUFFER
128
- printf(STDERR, "line read exceeds maximum length. Truncating at %d\n",
129
- MAX_QUERY_BUFFER)
130
- return line[0..MAX_QUERY_BUFFER-1]
131
- else
132
- return line
133
- end
134
- end
135
- end
136
-
137
- def PSQLexec(ps, query)
138
- res = ps.db.exec(query)
139
-
140
- if res == nil
141
- printf(STDERR, "%s\n", ps.db.error())
142
-
143
- else
144
- if (res.status() == PGresult::COMMAND_OK ||
145
- res.status() == PGresult::TUPLES_OK)
146
- return res
147
- end
148
-
149
- if !ps.quiet
150
- printf(STDERR, "%s\n", ps.db.error())
151
- end
152
-
153
- res.clear()
154
- end
155
-
156
- end
157
-
158
- def listAllDbs(ps)
159
- query = "select * from pg_database;"
160
-
161
- if (results = PSQLexec(ps, query)) == nil
162
- return 1
163
-
164
- else
165
- results.print(ps.queryFout, ps.opt)
166
- results.clear()
167
- return 0
168
- end
169
- end
170
-
171
- def tableList(ps, deep_tablelist, info_type, system_tables)
172
- listbuf = "SELECT usename, relname, relkind, relhasrules"
173
- listbuf += " FROM pg_class, pg_user "
174
- listbuf += "WHERE usesysid = relowner "
175
- case info_type
176
- when 't'
177
- listbuf += "and ( relkind = 'r') "
178
- when 'i'
179
- listbuf += "and ( relkind = 'i') "
180
- haveIndexes = true
181
- when 'S'
182
- listbuf += "and ( relkind = 'S') "
183
- else
184
- listbuf += "and ( relkind = 'r' OR relkind = 'i' OR relkind='S') "
185
- haveIndexes = true
186
- end
187
- if (!system_tables)
188
- listbuf += "and relname !~ '^pg_' "
189
- else
190
- listbuf += "and relname ~ '^pg_' "
191
- end
192
- if (haveIndexes)
193
- listbuf += "and (relkind != 'i' OR relname !~'^xinx')"
194
- end
195
- listbuf += " ORDER BY relname "
196
-
197
- res = PSQLexec(ps, listbuf)
198
- if res == nil
199
- return
200
- end
201
-
202
- # first, print out the attribute names
203
- nColumns = res.num_tuples
204
- if nColumns > 0
205
- if deep_tablelist
206
- table = res.result
207
- res.clear
208
- for i in 0..nColumns-1
209
- tableDesc(ps, table[i][1])
210
- end
211
- else
212
- # Display the information
213
-
214
- printf("\nDatabase = %s\n", ps.db.db)
215
- printf(" +------------------+----------------------------------+----------+\n")
216
- printf(" | Owner | Relation | Type |\n")
217
- printf(" +------------------+----------------------------------+----------+\n")
218
-
219
- # next, print out the instances
220
- for i in 0..res.num_tuples-1
221
- printf(" | %-16.16s", res.getvalue(i, 0))
222
- printf(" | %-32.32s | ", res.getvalue(i, 1))
223
- rk = res.getvalue(i, 2)
224
- rr = res.getvalue(i, 3)
225
- if (rk.eql?("r"))
226
- printf("%-8.8s |", if (rr[0] == 't') then "view?" else "table" end)
227
- else
228
- printf("%-8.8s |", "index")
229
- end
230
- printf("\n")
231
- end
232
- printf(" +------------------+----------------------------------+----------+\n")
233
- res.clear()
234
- end
235
- else
236
- printf(STDERR, "Couldn't find any tables!\n")
237
- end
238
- end
239
-
240
- def tableDesc(ps, table)
241
- descbuf = "SELECT a.attnum, a.attname, t.typname, a.attlen"
242
- descbuf += " FROM pg_class c, pg_attribute a, pg_type t "
243
- descbuf += " WHERE c.relname = '"
244
- descbuf += table
245
- descbuf += "'"
246
- descbuf += " and a.attnum > 0 "
247
- descbuf += " and a.attrelid = c.oid "
248
- descbuf += " and a.atttypid = t.oid "
249
- descbuf += " ORDER BY attnum "
250
-
251
- res = PSQLexec(ps, descbuf)
252
- if res == nil
253
- return
254
- end
255
-
256
- # first, print out the attribute names
257
- nColumns = res.num_tuples()
258
- if nColumns > 0
259
- #
260
- # Display the information
261
- #
262
-
263
- printf("\nTable = %s\n", table)
264
- printf("+----------------------------------+----------------------------------+-------+\n")
265
- printf("| Field | Type | Length|\n")
266
- printf("+----------------------------------+----------------------------------+-------+\n")
267
-
268
- # next, print out the instances
269
- for i in 0..res.num_tuples-1
270
-
271
- printf("| %-32.32s | ", res.getvalue(i, 1))
272
- rtype = res.getvalue(i, 2);
273
- rsize = res.getvalue(i, 3).to_i
274
-
275
- if (rtype.eql?("text"))
276
- printf("%-32.32s |", rtype)
277
- printf("%6s |", "var")
278
- elsif (rtype.eql?("bpchar"))
279
- printf("%-32.32s |", "(bp)char")
280
- printf("%6i |", if (rsize > 0) then rsize - 4 else 0 end)
281
- elsif (rtype.eql?("varchar"))
282
- printf("%-32.32s |", rtype)
283
- printf("%6d |", if (rsize > 0) then rsize - 4 else 0 end)
284
- else
285
- # array types start with an underscore
286
- if (rtype[0, 1] != '_')
287
- printf("%-32.32s |", rtype)
288
- else
289
- newname = rtype + "[]"
290
- printf("%-32.32s |", newname)
291
- end
292
- if (rsize > 0)
293
- printf("%6d |", rsize)
294
- else
295
- printf("%6s |", "var")
296
- end
297
- end
298
- printf("\n")
299
- end
300
- printf("+----------------------------------+----------------------------------+-------+\n")
301
-
302
- res.clear()
303
-
304
- else
305
- printf(STDERR, "Couldn't find table %s!\n", table)
306
- end
307
- end
308
-
309
- def unescape(source)
310
- dest = source.gsub(/(\\n|\\r|\\t|\\f|\\\\)/) {
311
- |c|
312
- case c
313
- when "\\n"
314
- "\n"
315
- when "\\r"
316
- "\r"
317
- when "\\t"
318
- "\t"
319
- when "\\f"
320
- "\f"
321
- when "\\\\"
322
- "\\"
323
- end
324
- }
325
- return dest
326
- end
327
-
328
- def do_shell(command)
329
- if !command
330
- command = ENV["SHELL"]
331
- if shellName == nil
332
- command = DEFAULT_SHELL
333
- end
334
- end
335
- system(command);
336
- end
337
-
338
- def do_help(topic)
339
- if !topic
340
- printf("type \\h <cmd> where <cmd> is one of the following:\n")
341
-
342
- left_center_right = 'L' # Start with left column
343
- for i in 0..QL_HELP.length-1
344
- case left_center_right
345
- when 'L'
346
- printf(" %-25s", QL_HELP[i][0])
347
- left_center_right = 'C'
348
-
349
- when 'C'
350
- printf("%-25s", QL_HELP[i][0])
351
- left_center_right = 'R'
352
-
353
- when 'R'
354
- printf("%-25s\n", QL_HELP[i][0])
355
- left_center_right = 'L'
356
-
357
- end
358
- end
359
- if (left_center_right != 'L')
360
- STDOUT.print("\n")
361
- end
362
- printf("type \\h * for a complete description of all commands\n")
363
- else
364
- help_found = FALSE
365
- for i in 0..QL_HELP.length-1
366
- if QL_HELP[i][0] == topic || topic == "*"
367
- help_found = TRUE
368
- printf("Command: %s\n", QL_HELP[i][0])
369
- printf("Description: %s\n", QL_HELP[i][1])
370
- printf("Syntax:\n")
371
- printf("%s\n", QL_HELP[i][2])
372
- printf("\n")
373
- end
374
- end
375
- if !help_found
376
- printf("command not found, ")
377
- printf("try \\h with no arguments to see available help\n")
378
- end
379
- end
380
- end
381
-
382
- def do_edit(filename_arg, query)
383
- if filename_arg
384
- fname = filename_arg
385
- error = FALSE
386
- else
387
- fname = sprintf("/tmp/psql.rb.%d", $$)
388
- p fname
389
- if test(?e, fname)
390
- File.unlink(fname)
391
- end
392
-
393
- if query
394
- begin
395
- fd = File.new(fname, "w")
396
- if query[query.length-1, 1] != "\n"
397
- query += "\n"
398
- end
399
- if fd.print(query) != query.length
400
- fd.close
401
- File.unlink(fname)
402
- error = TRUE
403
- else
404
- error = FALSE
405
- end
406
- fd.close
407
- rescue
408
- error = TRUE
409
- end
410
- else
411
- error = FALSE
412
- end
413
- end
414
-
415
- if error
416
- status = 1
417
- else
418
- editFile(fname)
419
- begin
420
- fd = File.new(fname, "r")
421
- query = fd.read
422
- fd.close
423
- if query == nil
424
- status = 1
425
- else
426
- query.sub!(/[ \t\f\r\n]*$/, "")
427
- if query.length != 0
428
- status = 3
429
- else
430
- query = nil
431
- status = 1
432
- end
433
- end
434
- rescue
435
- status = 1
436
- ensure
437
- if !filename_arg
438
- if test(?e, fname)
439
- File.unlink(fname)
440
- end
441
- end
442
- end
443
- end
444
- return status, query
445
- end
446
-
447
- def editFile(fname)
448
- editorName = ENV["EDITOR"]
449
- if editorName == nil
450
- editorName = DEFAULT_EDITOR
451
- end
452
- system(editorName + " " + fname)
453
- end
454
-
455
- def do_connect(settings, new_dbname)
456
- dbname = settings.db.db
457
-
458
- if !new_dbname
459
- printf(STDERR, "\\connect must be followed by a database name\n");
460
- else
461
- olddb = settings.db
462
-
463
- begin
464
- printf("closing connection to database: %s\n", dbname);
465
- settings.db = PGconn.connect(olddb.host, olddb.port, "", "", new_dbname)
466
- printf("connecting to new database: %s\n", new_dbname)
467
- olddb.finish()
468
- rescue
469
- printf(STDERR, "%s\n", $!)
470
- printf("reconnecting to %s\n", dbname)
471
- settings.db = PGconn.connect(olddb.host, olddb.port,"", "", dbname)
472
- ensure
473
- settings.prompt = settings.db.db + PROMPT
474
- end
475
- end
476
- end
477
-
478
- def do_copy(settings, table, from_p, file)
479
- if (table == nil || from_p == nil || file == nil)
480
- printf("Syntax error, reffer \\copy help with \\? \n")
481
- return
482
- end
483
-
484
- if from_p.upcase! == "FROM"
485
- from = TRUE
486
- else
487
- from = FALSE
488
- end
489
-
490
- query = "COPY "
491
- query += table
492
-
493
- if from
494
- query += " FROM stdin"
495
- copystream = File.new(file, "r")
496
- else
497
- query += " TO stdout"
498
- copystream = File.new(file, "w")
499
- end
500
-
501
- begin
502
- success = SendQuery(settings, query, from, !from, copystream);
503
- copystream.close
504
- if !settings.quiet
505
- if success
506
- printf("Successfully copied.\n");
507
- else
508
- printf("Copy failed.\n");
509
- end
510
- end
511
- rescue
512
- printf(STDERR, "Unable to open file %s which to copy.",
513
- if from then "from" else "to" end)
514
- end
515
- end
516
-
517
- def handleCopyOut(settings, copystream)
518
- copydone = FALSE
519
-
520
- while !copydone
521
- copybuf = settings.db.getline
522
-
523
- if !copybuf
524
- copydone = TRUE
525
- else
526
- if copybuf == "\\."
527
- copydone = TRUE
528
- else
529
- copystream.print(copybuf + "\n")
530
- end
531
- end
532
- end
533
- copystream.flush
534
- settings.db.endcopy
535
- end
536
-
537
- def handleCopyIn(settings, mustprompt, copystream)
538
- copydone = FALSE
539
-
540
- if mustprompt
541
- STDOUT.print("Enter info followed by a newline\n")
542
- STDOUT.print("End with a backslash and a ")
543
- STDOUT.print("period on a line by itself.\n")
544
- end
545
-
546
- while !copydone
547
- if mustprompt
548
- STDOUT.print(">> ")
549
- STDOUT.flush
550
- end
551
-
552
- copybuf = copystream.gets
553
- if copybuf == nil
554
- settings.db.putline("\\.\n")
555
- copydone = TRUE
556
- break
557
- end
558
- settings.db.putline(copybuf)
559
- if copybuf == "\\.\n"
560
- copydone = TRUE
561
- end
562
- end
563
- settings.db.endcopy
564
- end
565
-
566
- def setFout(ps, fname)
567
- if (ps.queryFout && ps.queryFout != STDOUT)
568
- ps.queryFout.close
569
- end
570
-
571
- if !fname
572
- ps.queryFout = STDOUT
573
- else
574
- begin
575
- if fname[0, 1] == "|"
576
- dumy, ps.queryFout = pipe(fname)
577
- ps.pipe = TRUE
578
- else
579
- ps.queryFout = File.new(fname, "w+")
580
- ps.pipe = FALSE
581
- end
582
- rescue
583
- ps.queryFout = STDOUT
584
- ps.pipe = FALSE
585
- end
586
- end
587
- end
588
-
589
- def HandleSlashCmds(settings, line, query)
590
- status = 1
591
- cmd = unescape(line[1, line.length])
592
- args = cmd.split
593
-
594
- case args[0]
595
- when 'a' # toggles to align fields on output
596
- settings.opt.align =
597
- toggle(settings, settings.opt.align, "field alignment")
598
-
599
- when 'C' # define new caption
600
- if !args[1]
601
- settings.opt.caption = ""
602
- else
603
- settings.opt.caption = args[1]
604
- end
605
-
606
- when 'c', 'connect' # connect new database
607
- do_connect(settings, args[1])
608
-
609
- when 'copy' # copy from file
610
- do_copy(settings, args[1], args[2], args[3])
611
-
612
- when 'd' # \d describe tables or columns in a table
613
- if !args[1]
614
- tableList(settings, FALSE, 'b', FALSE)
615
- elsif args[1] == "*"
616
- tableList(settings, FALSE, 'b', FALSE)
617
- tableList(settings, TRUE, 'b', FALSE)
618
- else
619
- tableDesc(settings, args[1])
620
- end
621
-
622
- when 'da'
623
- descbuf = "SELECT a.aggname AS aggname, t.typname AS type, "
624
- descbuf += "obj_description (a.oid) as description "
625
- descbuf += "FROM pg_aggregate a, pg_type t "
626
- descbuf += "WHERE a.aggbasetype = t.oid "
627
- if (args[1])
628
- descbuf += "AND a.aggname ~ '^"
629
- descbuf += args[1]
630
- descbuf += "' "
631
- end
632
- descbuf += "UNION SELECT a.aggname AS aggname, "
633
- descbuf += "'all types' as type, obj_description (a.oid) "
634
- descbuf += "as description FROM pg_aggregate a "
635
- descbuf += "WHERE a.aggbasetype = 0"
636
- if (args[1])
637
- descbuf += "AND a.aggname ~ '^"
638
- descbuf += args[1]
639
- descbuf += "' "
640
- end
641
- descbuf += "ORDER BY aggname, type;"
642
- res = SendQuery(settings, descbuf, FALSE, FALSE, 0)
643
-
644
- when 'di'
645
- tableList(settings, FALSE, 'i', FALSE)
646
-
647
- when 'ds'
648
- tableList(settings, FALSE, 'S', FALSE)
649
-
650
- when 'dS'
651
- tableList(settings, FALSE, 'b', TRUE)
652
-
653
- when 'dt'
654
- tableList(settings, FALSE, 't', FALSE)
655
-
656
- when 'e' # edit
657
- status, query = do_edit(args[1], query)
658
-
659
- when 'E'
660
- if args[1]
661
- begin
662
- lastfile = args[1]
663
- File.file?(lastfile) && (mt = File.mtime(lastfile))
664
- editFile(lastfile)
665
- File.file?(lastfile) && (mt2 = File.mtime(lastfile))
666
- fd = File.new(lastfile, "r")
667
- if mt != mt2
668
- MainLoop(settings, fd)
669
- fd.close()
670
- else
671
- if !settings.quiet
672
- printf(STDERR, "warning: %s not modified. query not executed\n", lastfile)
673
- end
674
- fd.close()
675
- end
676
- rescue
677
- #
678
- end
679
- else
680
- printf(STDERR, "\\r must be followed by a file name initially\n");
681
- end
682
- when 'f'
683
- if args[1]
684
- settings.opt.fieldSep = args[1]
685
- if !settings.quiet
686
- printf(STDERR, "field separater changed to '%s'\n", settings.opt.fieldSep)
687
- end
688
- end
689
-
690
- when 'g' # \g means send query
691
- if !args[1]
692
- settings.gfname = nil
693
- else
694
- settings.gfname = args[1]
695
- end
696
- status = 0
697
-
698
- when 'h' # help
699
- if args[2]
700
- args[1] += " " + args[2]
701
- end
702
- do_help(args[1])
703
-
704
- when 'i' # \i is include file
705
- if args[1]
706
- begin
707
- fd = File.open(args[1], "r")
708
- MainLoop(settings, fd)
709
- fd.close()
710
- rescue Errno::ENOENT
711
- printf(STDERR, "file named %s could not be opened\n", args[1])
712
- end
713
- else
714
- printf(STDERR, "\\i must be followed by a file name\n")
715
- end
716
- when 'l' # \l is list database
717
- listAllDbs(settings)
718
-
719
- when 'H'
720
- settings.opt.html3 =
721
- toggle(settings, settings.opt.html3, "HTML3.0 tabular output")
722
-
723
- if settings.opt.html3
724
- settings.opt.standard = FALSE
725
- end
726
-
727
- when 'o'
728
- setFout(settings, args[1])
729
-
730
- when 'p'
731
- if query
732
- File.print(query)
733
- File.print("\n")
734
- end
735
-
736
- when 'q' # \q is quit
737
- status = 2
738
-
739
- when 'r' # reset(clear) the buffer
740
- query = nil
741
- if !settings.quiet
742
- printf(STDERR, "buffer reset(cleared)\n")
743
- end
744
-
745
- when 's' # \s is save history to a file
746
- begin
747
- if (args[1])
748
- fd = File.open(args[1], "w")
749
- else
750
- fd = STDOUT
751
- end
752
- Readline::HISTORY.each do |his|
753
- fd.write (his + "\n")
754
- end
755
- if !fd.tty?
756
- begin
757
- fd.close
758
- end
759
- end
760
- rescue
761
- printf(STDERR, "cannot write history \n");
762
- end
763
-
764
- when 'm' # monitor like type-setting
765
- settings.opt.standard =
766
- toggle(settings, settings.opt.standard, "standard SQL separaters and padding")
767
- if settings.opt.standard
768
- settings.opt.html3 = FALSE
769
- settings.opt.expanded = FALSE
770
- settings.opt.align = TRUE
771
- settings.opt.header = TRUE
772
- if settings.opt.fieldSep
773
- settings.opt.fieldSep = ""
774
- end
775
- settings.opt.fieldSep = "|"
776
- if !settings.quiet
777
- printf(STDERR, "field separater changed to '%s'\n", settings.opt.fieldSep)
778
- end
779
- else
780
- if settings.opt.fieldSep
781
- settings.opt.fieldSep = ""
782
- end
783
- settings.opt.fieldSep = DEFAULT_FIELD_SEP
784
- if !settings.quiet
785
- printf(STDERR, "field separater changed to '%s'\n", settings.opt.fieldSep)
786
- end
787
- end
788
-
789
- when 't' # toggle headers
790
- settings.opt.header =
791
- toggle(settings, settings.opt.header, "output headings and row count")
792
-
793
- when 'T' # define html <table ...> option
794
- if !args[1]
795
- settings.opt.tableOpt = nil
796
- else
797
- settings.opt.tableOpt = args[1]
798
- end
799
-
800
- when 'x'
801
- settings.opt.expanded =
802
- toggle(settings, settings.opt.expanded, "expanded table representation")
803
-
804
- when '!'
805
- do_shell(args[1])
806
-
807
- when '?' # \? is help
808
- slashUsage(settings)
809
- end
810
-
811
- return status, query
812
- end
813
-
814
- def SendQuery(settings, query, copy_in, copy_out, copystream)
815
- if settings.singleStep
816
- printf("\n**************************************")
817
- printf("*****************************************\n")
818
- end
819
-
820
- if (settings.echoQuery || settings.singleStep)
821
- printf(STDERR, "QUERY: %s\n", query);
822
- end
823
-
824
- if settings.singleStep
825
- printf("\n**************************************");
826
- printf("*****************************************\n")
827
- STDOUT.flush
828
- printf("\npress return to continue ..\n");
829
- gets("", STDIN);
830
- end
831
-
832
- begin
833
- results = settings.db.exec(query)
834
- case results.status
835
- when PGresult::TUPLES_OK
836
- success = TRUE
837
- if settings.gfname
838
- setFout(settings, settings.gfname)
839
- settings.gfname = nil
840
- results.print(settings.queryFout, settings.opt)
841
- settings.queryFout.flush
842
- if settings.queryFout != STDOUT
843
- settings.queryFout.close
844
- settings.queryFout = STDOUT
845
- end
846
- else
847
- results.print(settings.queryFout, settings.opt)
848
- settings.queryFout.flush
849
- end
850
- results.clear
851
-
852
- when PGresult::EMPTY_QUERY
853
- success = TRUE
854
-
855
- when PGresult::COMMAND_OK
856
- success = TRUE
857
- if !settings.quiet
858
- printf("%s\n", results.cmdstatus)
859
- end
860
-
861
- when PGresult::COPY_OUT
862
- success = TRUE
863
- if copy_out
864
- handleCopyOut(settings, copystream)
865
- else
866
- if !settings.quiet
867
- printf("Copy command returns...\n")
868
- end
869
-
870
- handleCopyOut(settings, STDOUT)
871
- end
872
-
873
- when PGresult::COPY_IN
874
- success = TRUE
875
- if copy_in
876
- handleCopyIn(settings, FALSE, copystream)
877
- else
878
- handleCopyIn(settings, !settings.quiet, STDIN)
879
- end
880
- end
881
-
882
- if (settings.db.status == PGconn::CONNECTION_BAD)
883
- printf(STDERR, "We have lost the connection to the backend, so ")
884
- printf(STDERR, "further processing is impossible. ")
885
- printf(STDERR, "Terminating.\n")
886
- exit(2)
887
- end
888
-
889
- # check for asynchronous returns
890
- # notify = settings.db.notifies()
891
- # if notify
892
- # printf(STDERR,"ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
893
- # notify.relname, notify.be_pid)
894
- # end
895
-
896
- rescue
897
- printf(STDERR, "%s", $!)
898
- success = FALSE
899
- end
900
-
901
- return success
902
- end
903
-
904
- def MainLoop(settings, source)
905
-
906
- success = TRUE
907
- interactive = TRUE
908
- insideQuote = FALSE
909
- querySent = FALSE
910
- done = FALSE
911
-
912
- query = nil
913
- queryWaiting = nil
914
- slashCmdStatus = -1
915
- interactive = (source == STDIN && !settings.notty)
916
-
917
- if settings.quiet
918
- settings.prompt = nil
919
- else
920
- settings.prompt = settings.db.db + PROMPT
921
- end
922
-
923
- while !done
924
- if slashCmdStatus == 3
925
- line = query
926
- query = nil
927
- else
928
- if interactive && !settings.quiet
929
- if insideQuote
930
- settings.prompt[settings.prompt.length-3,1] = "\'"
931
- elsif (queryWaiting != nil && !querySent)
932
- settings.prompt[settings.prompt.length-3,1] = "-"
933
- else
934
- settings.prompt[settings.prompt.length-3,1] = "="
935
- end
936
- end
937
- line = gets(settings.prompt, source)
938
- end
939
-
940
- if line == nil
941
- printf("EOF\n")
942
- done = TRUE
943
- else
944
-
945
- ### debbegging information ###
946
- if !interactive && !settings.singleStep && !settings.quiet
947
- printf(STDERR, "%s\n", line)
948
- end
949
-
950
- ### ommit comment ###
951
- begin_comment = line.index("--")
952
- if begin_comment
953
- line = line[0, begin_comment]
954
- end
955
-
956
- ### erase unnecessary characters ###
957
- line.gsub!(/[ \t\f\n\r]+\z/, "")
958
- if line.length == 0
959
- next
960
- end
961
- ### begin slash command handling ###
962
- if line[0, 1] == "\\"
963
- query = line
964
- slashCmdStatus, query = HandleSlashCmds(settings, line, nil)
965
- if slashCmdStatus == 0 && query != nil
966
- success = SendQuery(settings, query, FALSE, FALSE, 0) && success
967
- querySent = TRUE
968
- elsif slashCmdStatus == 1
969
- query = nil
970
- elsif slashCmdStatus == 2
971
- break
972
- end
973
- line = nil
974
- next
975
- end
976
-
977
- ### begin query command handling ###
978
- slashCmdStatus = -1
979
- if settings.singleLineMode
980
- success = SendQuery(settings, line, FALSE, FALSE, 0) && success
981
- querySent = TRUE
982
- else
983
-
984
- if queryWaiting
985
- queryWaiting += " " + line
986
- else
987
- queryWaiting = line
988
- end
989
-
990
- for i in 0..line.length-1
991
- if line[i, 1] == "\'"
992
- insideQuote = !insideQuote
993
- end
994
- end
995
-
996
- if !insideQuote
997
- if line[line.length-1, 1] == ";"
998
- query = queryWaiting
999
- queryWaiting = nil
1000
-
1001
- success = SendQuery(settings, query, FALSE, FALSE, 0) && success
1002
- querySent = TRUE
1003
- else
1004
- querySent = FALSE
1005
- end
1006
- else
1007
- querySent = FALSE
1008
- end
1009
- end
1010
- end
1011
- end # while
1012
- return success
1013
- end
1014
-
1015
- def main
1016
- dbname = nil
1017
- host = "localhost"
1018
- port = 5432
1019
- qfilename = nil
1020
-
1021
- singleQuery = nil
1022
- settings = PsqlSettings.new(nil, nil, nil, nil, nil, FALSE, FALSE,
1023
- FALSE, FALSE, FALSE, FALSE, FALSE)
1024
- settings.opt = PrintOpt.new(FALSE, FALSE, FALSE, FALSE, FALSE,
1025
- FALSE, nil, nil, nil, nil)
1026
-
1027
- listDatabases = FALSE
1028
- successResult = TRUE
1029
- singleSlashCmd = FALSE
1030
-
1031
- settings.opt.align = TRUE
1032
- settings.opt.header = TRUE
1033
- settings.queryFout = STDOUT
1034
- settings.opt.fieldSep = DEFAULT_FIELD_SEP.dup
1035
- settings.opt.pager = TRUE
1036
- settings.quiet = FALSE
1037
- settings.notty = FALSE
1038
- settings.useReadline = TRUE
1039
-
1040
- parsed = parseArgs(0, nil, "AelHnsqStx", "a:", "c:", "d:", "f:", "F:",
1041
- "h:", "o:", "p:", "T:")
1042
-
1043
- if $OPT_A
1044
- settings.opt.align = FALSE
1045
- end
1046
-
1047
- if $OPT_a
1048
- #fe_setauthsvc(optarg, errbuf);
1049
- printf("not implemented, sorry.\n")
1050
- exit(1)
1051
- end
1052
-
1053
- if $OPT_c
1054
- singleQuery = $OPT_c
1055
- if singleQuery[0, 1] == "\\"
1056
- singleSlashCmd = TRUE
1057
- end
1058
- end
1059
-
1060
- if $OPT_d
1061
- dbname = $OPT_d
1062
- end
1063
-
1064
- if $OPT_e
1065
- settings.echoQuery = TRUE
1066
- end
1067
-
1068
- if $OPT_f
1069
- qfilename = $OPT_f
1070
- end
1071
-
1072
- if $OPT_F
1073
- settings.opt.fieldSep = $OPT_F
1074
- end
1075
-
1076
- if $OPT_l
1077
- listDatabases = TRUE
1078
- end
1079
-
1080
- if $OPT_h
1081
- host = $OPT_h
1082
- end
1083
-
1084
- if $OPT_H
1085
- settings.opt.html3 = TRUE
1086
- end
1087
-
1088
- if $OPT_n
1089
- settings.useReadline = FALSE
1090
- end
1091
-
1092
- if $OPT_o
1093
- setFout(settings, $OPT_o)
1094
- end
1095
-
1096
- if $OPT_p
1097
- port = $OPT_p.to_i
1098
- end
1099
-
1100
- if $OPT_q
1101
- settings.quiet = TRUE
1102
- end
1103
-
1104
- if $OPT_s
1105
- settings.singleStep = TRUE
1106
- end
1107
-
1108
- if $OPT_S
1109
- settings.singleLineMode = TRUE
1110
- end
1111
-
1112
- if $OPT_t
1113
- settings.opt.header = FALSE
1114
- end
1115
-
1116
- if $OPT_T
1117
- settings.opt.tableOpt = $OPT_T
1118
- end
1119
-
1120
- if $OPT_x
1121
- settings.opt.expanded = TRUE
1122
- end
1123
-
1124
- if ARGV.length == 1
1125
- dbname = ARGV[0]
1126
- end
1127
-
1128
- if listDatabases
1129
- dbname = "template1"
1130
- end
1131
-
1132
- settings.db = PGconn.connect(host, port, "", "", dbname);
1133
- dbname = settings.db.db
1134
-
1135
- if settings.db.status() == PGconn::CONNECTION_BAD
1136
- printf(STDERR, "Connection to database '%s' failed.\n", dbname)
1137
- printf(STDERR, "%s", settings.db.error)
1138
- exit(1)
1139
- end
1140
- if listDatabases
1141
- exit(listAllDbs(settings))
1142
- end
1143
- if (!settings.quiet && !singleQuery && !qfilename)
1144
- printf("Welcome to the POSTGRESQL interactive sql monitor:\n")
1145
- printf(" Please read the file COPYRIGHT for copyright terms of POSTGRESQL\n\n")
1146
- printf(" type \\? for help on slash commands\n")
1147
- printf(" type \\q to quit\n")
1148
- printf(" type \\g or terminate with semicolon to execute query\n")
1149
- printf(" You are currently connected to the database: %s\n\n", dbname)
1150
- end
1151
- if (qfilename || singleSlashCmd)
1152
- if singleSlashCmd
1153
- line = singleQuery
1154
- else
1155
- line = sprintf("\\i %s", qfilename)
1156
- end
1157
- HandleSlashCmds(settings, line, "")
1158
- else
1159
- if settings.useReadline
1160
- begin
1161
- require "readline"
1162
- $readline_ok = TRUE
1163
- rescue
1164
- $readline_ok = FALSE
1165
- end
1166
- else
1167
- $readline_ok = FALSE
1168
- end
1169
- if singleQuery
1170
- success = SendQuery(settings, singleQuery, false, false, 0)
1171
- successResult = success
1172
- else
1173
- successResult = MainLoop(settings, STDIN)
1174
- end
1175
- end
1176
- settings.db.finish()
1177
- return !successResult
1178
- end
1179
-
1180
- main
1181
-