pg 0.8.0-x86-mswin32-60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,42 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <sys/types.h>
4
+
5
+ #include "ruby.h"
6
+ #include "libpq-fe.h"
7
+ #include "libpq/libpq-fs.h" /* large-object interface */
8
+
9
+ #include "compat.h"
10
+
11
+ #if RUBY_VM != 1
12
+ #define RUBY_18_COMPAT
13
+ #endif
14
+
15
+ #ifndef RARRAY_LEN
16
+ #define RARRAY_LEN(x) RARRAY((x))->len
17
+ #endif /* RARRAY_LEN */
18
+
19
+ #ifndef RSTRING_LEN
20
+ #define RSTRING_LEN(x) RSTRING((x))->len
21
+ #endif /* RSTRING_LEN */
22
+
23
+ #ifndef RSTRING_PTR
24
+ #define RSTRING_PTR(x) RSTRING((x))->ptr
25
+ #endif /* RSTRING_PTR */
26
+
27
+ #ifndef StringValuePtr
28
+ #define StringValuePtr(x) STR2CSTR(x)
29
+ #endif /* StringValuePtr */
30
+
31
+ #ifdef RUBY_18_COMPAT
32
+ #define rb_io_stdio_file GetWriteFile
33
+ #include "rubyio.h"
34
+ #else
35
+ #include "ruby/io.h"
36
+ #endif
37
+
38
+ #if defined(_WIN32)
39
+ __declspec(dllexport)
40
+ #endif
41
+ void Init_pg(void);
42
+
@@ -0,0 +1,26 @@
1
+ 
2
+ Microsoft Visual Studio Solution File, Format Version 10.00
3
+ # Visual Studio 2008
4
+ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pg", "pg_18\pg.vcproj", "{9A8BF0C8-1D75-4DC0-8D84-BAEFD693795E}"
5
+ EndProject
6
+ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pg_19", "pg_19\pg_19.vcproj", "{2EE30C74-074F-4611-B39B-38D5F3C9B071}"
7
+ EndProject
8
+ Global
9
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
10
+ Debug|Win32 = Debug|Win32
11
+ Release|Win32 = Release|Win32
12
+ EndGlobalSection
13
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
14
+ {9A8BF0C8-1D75-4DC0-8D84-BAEFD693795E}.Debug|Win32.ActiveCfg = Debug|Win32
15
+ {9A8BF0C8-1D75-4DC0-8D84-BAEFD693795E}.Debug|Win32.Build.0 = Debug|Win32
16
+ {9A8BF0C8-1D75-4DC0-8D84-BAEFD693795E}.Release|Win32.ActiveCfg = Release|Win32
17
+ {9A8BF0C8-1D75-4DC0-8D84-BAEFD693795E}.Release|Win32.Build.0 = Release|Win32
18
+ {2EE30C74-074F-4611-B39B-38D5F3C9B071}.Debug|Win32.ActiveCfg = Debug|Win32
19
+ {2EE30C74-074F-4611-B39B-38D5F3C9B071}.Debug|Win32.Build.0 = Debug|Win32
20
+ {2EE30C74-074F-4611-B39B-38D5F3C9B071}.Release|Win32.ActiveCfg = Release|Win32
21
+ {2EE30C74-074F-4611-B39B-38D5F3C9B071}.Release|Win32.Build.0 = Release|Win32
22
+ EndGlobalSection
23
+ GlobalSection(SolutionProperties) = preSolution
24
+ HideSolutionNode = FALSE
25
+ EndGlobalSection
26
+ EndGlobal
@@ -0,0 +1,47 @@
1
+ require "pg"
2
+
3
+ def main
4
+ conn = PGconn.connect("localhost",5432,"","")
5
+ puts("dbname: " + conn.db + "\thost: " + conn.host + "\tuser: " + conn.user)
6
+
7
+ # Transaction
8
+ conn.exec("BEGIN")
9
+ lobj = conn.loimport("losample.rb")
10
+ lobjnum = lobj.oid
11
+ puts("loimport ok! oid=" + lobj.oid.to_s)
12
+ lobj.open
13
+ lobj.seek(0,PGlarge::SEEK_SET) # SEEK_SET or SEEK_CUR or SEEK_END
14
+ buff = lobj.read(18)
15
+ puts buff
16
+ if 'require "postgres"' == buff
17
+ puts "read ok!"
18
+ end
19
+ lobj.seek(0,PGlarge::SEEK_END)
20
+ buff = lobj.write("write test ok?\n")
21
+ puts lobj.tell
22
+ puts 'export test .file:lowrite.losample add "write test of?"...'
23
+ lobj.export("lowrite.txt")
24
+ lobj.close
25
+ conn.exec("COMMIT")
26
+ begin
27
+ lobj.read(1)
28
+ puts "boo!"
29
+ return
30
+ rescue
31
+ puts "ok! Large Object is closed"
32
+ end
33
+ conn.exec("BEGIN")
34
+ puts lobjnum.to_s
35
+ lobj = conn.loopen(lobjnum)
36
+ puts "large object reopen ok!"
37
+ lobj.seek(0,PGlarge::SEEK_SET) # SEEK_SET or SEEK_CUR or SEEK_END
38
+ buff = lobj.read(18)
39
+ puts buff
40
+ puts "reread ok!"
41
+ conn.exec("COMMIT")
42
+ lobj.unlink
43
+ puts "large object unlink"
44
+ end
45
+
46
+ main
47
+
@@ -0,0 +1,1181 @@
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 1.1.1.3 2002/04/24 05:46:44 noboru Exp $
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
+