pg 0.8.0 → 0.9.0.pre156
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.
- data/ChangeLog +440 -230
- data/Contributors +2 -0
- data/README +41 -98
- data/README.OS_X +19 -0
- data/README.ja +183 -0
- data/README.windows +72 -0
- data/Rakefile.local +239 -0
- data/ext/extconf.rb +101 -62
- data/ext/pg.c +823 -142
- data/ext/pg.h +9 -2
- data/lib/pg.rb +11 -0
- data/rake/191_compat.rb +26 -0
- data/rake/dependencies.rb +76 -0
- data/rake/helpers.rb +435 -0
- data/rake/hg.rb +273 -0
- data/rake/manual.rb +782 -0
- data/rake/packaging.rb +123 -0
- data/rake/publishing.rb +274 -0
- data/rake/rdoc.rb +30 -0
- data/rake/style.rb +62 -0
- data/rake/svn.rb +668 -0
- data/rake/testing.rb +187 -0
- data/rake/verifytask.rb +64 -0
- data/spec/lib/helpers.rb +216 -0
- data/spec/m17n_spec.rb +139 -0
- data/spec/pgconn_spec.rb +199 -38
- data/spec/pgresult_spec.rb +157 -51
- metadata +71 -48
- data/COPYING.txt +0 -340
- data/Rakefile +0 -103
- data/doc/postgres.html +0 -278
- data/doc/postgres.jp.html +0 -256
- data/ext/mingw/Rakefile +0 -24
- data/ext/mingw/build.rake +0 -40
- data/ext/mkrf_config.rb +0 -138
- data/ext/vc/pg.sln +0 -26
- data/sample/losample.rb +0 -47
- data/sample/psql.rb +0 -1181
- data/sample/psqlHelp.rb +0 -158
- data/sample/test1.rb +0 -63
- data/sample/test2.rb +0 -44
- data/sample/test4.rb +0 -71
- data/spec/data/expected_trace.out +0 -26
- data/spec/data/random_binary_data +0 -0
data/ext/mingw/Rakefile
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
# We can't use Ruby's standard build procedures
|
2
|
-
# on Windows because the Ruby executable is
|
3
|
-
# built with VC++ while here we want to build
|
4
|
-
# with MingW. So just roll our own...
|
5
|
-
|
6
|
-
require 'fileutils'
|
7
|
-
require 'rbconfig'
|
8
|
-
|
9
|
-
EXTENSION_NAME = "pg.#{Config::CONFIG["DLEXT"]}"
|
10
|
-
|
11
|
-
# This is called when the Windows GEM is installed!
|
12
|
-
task :install do
|
13
|
-
# Gems will pass these two environment variables:
|
14
|
-
# RUBYARCHDIR=#{dest_path}
|
15
|
-
# RUBYLIBDIR=#{dest_path}
|
16
|
-
|
17
|
-
dest_path = ENV['RUBYLIBDIR']
|
18
|
-
mkdir_p(dest_path)
|
19
|
-
|
20
|
-
# Copy the extension
|
21
|
-
cp(EXTENSION_NAME, dest_path)
|
22
|
-
end
|
23
|
-
|
24
|
-
task :default => :install
|
data/ext/mingw/build.rake
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# We can't use Ruby's standard build procedures
|
2
|
-
# on Windows because the Ruby executable is
|
3
|
-
# built with VC++ while here we want to build
|
4
|
-
# with MingW. So just roll our own...
|
5
|
-
|
6
|
-
require 'rake/clean'
|
7
|
-
require 'rbconfig'
|
8
|
-
|
9
|
-
RUBY_INCLUDE_DIR = Config::CONFIG["archdir"]
|
10
|
-
RUBY_BIN_DIR = Config::CONFIG["bindir"]
|
11
|
-
RUBY_LIB_DIR = Config::CONFIG["libdir"]
|
12
|
-
RUBY_SHARED_LIB = Config::CONFIG["LIBRUBY"]
|
13
|
-
RUBY_SHARED_DLL = RUBY_SHARED_LIB.gsub(/lib$/, 'dll')
|
14
|
-
|
15
|
-
EXTENSION_NAME = "pg.#{Config::CONFIG["DLEXT"]}"
|
16
|
-
|
17
|
-
CLEAN.include('*.o')
|
18
|
-
CLOBBER.include(EXTENSION_NAME)
|
19
|
-
|
20
|
-
task :default => "pg"
|
21
|
-
|
22
|
-
DEFINES = "-DHAVE_LIBPQ_FE_H -DHAVE_LIBPQ_LIBPQ_FS_H -DHAVE_PQCONNECTIONUSEDPASSWORD -DHAVE_PQISTHREADSAFE -DHAVE_LO_CREATE -DHAVE_PQPREPARE -DHAVE_PQEXECPARAMS -DHAVE_PQESCAPESTRING -DHAVE_PQESCAPESTRINGCONN -DHAVE_PG_ENCODING_TO_CHAR -DHAVE_PQSETCLIENTENCODING"
|
23
|
-
LIBS = "-lpq -lm"
|
24
|
-
SRC = FileList['../*.c']
|
25
|
-
OBJ = SRC.collect do |file_name|
|
26
|
-
File.basename(file_name).ext('o')
|
27
|
-
end
|
28
|
-
|
29
|
-
SRC.each do |srcfile|
|
30
|
-
objfile = File.basename(srcfile).ext('o')
|
31
|
-
file objfile => srcfile do
|
32
|
-
command = "gcc -c -O2 -Wall #{DEFINES} -o #{objfile} -I/usr/local/include #{srcfile} -I#{RUBY_INCLUDE_DIR}"
|
33
|
-
sh "sh -c '#{command}'"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
file "pg" => OBJ do
|
38
|
-
command = "gcc -shared -o #{EXTENSION_NAME} #{OBJ} -L/usr/local/lib #{LIBS} #{RUBY_BIN_DIR}/#{RUBY_SHARED_DLL}"
|
39
|
-
sh "sh -c '#{command}'"
|
40
|
-
end
|
data/ext/mkrf_config.rb
DELETED
@@ -1,138 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'mkrf'
|
3
|
-
|
4
|
-
pg_config_command =
|
5
|
-
if RUBY_PLATFORM.match(/win32/)
|
6
|
-
"pg_config --bindir > nul"
|
7
|
-
else
|
8
|
-
"pg_config --bindir > /dev/null"
|
9
|
-
end
|
10
|
-
|
11
|
-
unless system(pg_config_command)
|
12
|
-
$stderr.write("ERROR: can't find pg_config.\n")
|
13
|
-
$stderr.write("HINT: Make sure pg_config is in your PATH\n")
|
14
|
-
exit 1
|
15
|
-
end
|
16
|
-
|
17
|
-
$functions = %w[
|
18
|
-
lo_create
|
19
|
-
PQconnectionUsedPassword
|
20
|
-
PQisthreadsafe
|
21
|
-
PQprepare
|
22
|
-
PQexecParams
|
23
|
-
PQescapeString
|
24
|
-
PQescapeStringConn
|
25
|
-
lo_create
|
26
|
-
pg_encoding_to_char
|
27
|
-
PQsetClientEncoding
|
28
|
-
]
|
29
|
-
|
30
|
-
# OS X compatibility
|
31
|
-
if(PLATFORM =~ /darwin/) then
|
32
|
-
# test if postgresql is probably universal
|
33
|
-
bindir = escape_path(IO.popen("pg_config --bindir").readline.chomp)
|
34
|
-
Open3.popen3('file',"#{bindir}/pg_config") do |the_in, the_out, the_err|
|
35
|
-
filetype = the_out.readline.chomp
|
36
|
-
end
|
37
|
-
# if it's not universal, ARCHFLAGS should be set
|
38
|
-
if((filetype !~ /universal binary/) && ENV['ARCHFLAGS'].nil?) then
|
39
|
-
arch_tmp = (IO.popen("uname -p").readline.chomp rescue nil)
|
40
|
-
if(arch_tmp == 'powerpc')
|
41
|
-
arch = 'ppc'
|
42
|
-
else
|
43
|
-
arch = 'i386'
|
44
|
-
end
|
45
|
-
$stderr.write %{
|
46
|
-
=========== WARNING ===========
|
47
|
-
|
48
|
-
You are building this extension on OS X without setting the
|
49
|
-
ARCHFLAGS environment variable, and PostgreSQL does not appear
|
50
|
-
to have been built as a universal binary. If you are seeing this
|
51
|
-
message, that means that the build will probably fail.
|
52
|
-
|
53
|
-
Try setting the environment variable ARCHFLAGS
|
54
|
-
to '-arch #{arch}' before building.
|
55
|
-
|
56
|
-
For example:
|
57
|
-
(in bash) $ export ARCHFLAGS='-arch #{arch}'
|
58
|
-
(in tcsh) % setenv ARCHFLAGS '-arch #{arch}'
|
59
|
-
|
60
|
-
Then try building again.
|
61
|
-
|
62
|
-
===================================
|
63
|
-
}
|
64
|
-
# We don't exit here. Who knows? It might build.
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
if RUBY_VERSION < '1.8'
|
69
|
-
puts 'This library is for ruby-1.8 or higher.'
|
70
|
-
exit 1
|
71
|
-
end
|
72
|
-
|
73
|
-
def escape_path(path)
|
74
|
-
if(PLATFORM =~ /mswin|mingw/) then
|
75
|
-
'"' + path + '"'
|
76
|
-
else
|
77
|
-
path.gsub(%r{([^a-zA-Z0-9/._-])}, "\\\\\\1")
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def pg_config(type)
|
82
|
-
IO.popen("pg_config --#{type}dir").readline.chomp
|
83
|
-
end
|
84
|
-
|
85
|
-
def config_value(type)
|
86
|
-
escape_path(ENV["POSTGRES_#{type.upcase}"] || pg_config(type))
|
87
|
-
end
|
88
|
-
|
89
|
-
Mkrf::Generator.new('pg', '*.c',
|
90
|
-
{
|
91
|
-
:includes => [config_value('include'), Config::CONFIG['includedir'],
|
92
|
-
Config::CONFIG["archdir"], Config::CONFIG['sitelibdir'], "."],
|
93
|
-
:library_paths => [config_value('lib')],
|
94
|
-
# must set loaded_libs to work around a mkrf bug on some platforms
|
95
|
-
:loaded_libs => []
|
96
|
-
}
|
97
|
-
) do |g|
|
98
|
-
|
99
|
-
$stdout.write("checking for libpq-fe.h... ")
|
100
|
-
if g.include_header('libpq-fe.h') &&
|
101
|
-
g.include_header('libpq/libpq-fs.h')
|
102
|
-
then
|
103
|
-
puts 'yes'
|
104
|
-
else
|
105
|
-
puts 'no'
|
106
|
-
puts 'Could not find PostgreSQL headers: ' +
|
107
|
-
'Rakefile not created'
|
108
|
-
exit 1
|
109
|
-
end
|
110
|
-
|
111
|
-
$stdout.write("checking for libpq... ")
|
112
|
-
# we have to check a few possible names to account
|
113
|
-
# for building on windows
|
114
|
-
if g.include_library('pq') ||
|
115
|
-
g.include_library('libpq') ||
|
116
|
-
g.include_library('ms/libpq')
|
117
|
-
then
|
118
|
-
puts 'yes'
|
119
|
-
else
|
120
|
-
puts 'no'
|
121
|
-
puts 'Could not find PostgreSQL client library: ' +
|
122
|
-
'Rakefile not created'
|
123
|
-
exit 1
|
124
|
-
end
|
125
|
-
|
126
|
-
$functions.each do |func|
|
127
|
-
$stdout.write("checking for #{func}()... ")
|
128
|
-
if(g.has_function?(func)) then
|
129
|
-
g.add_define("HAVE_#{func.upcase}")
|
130
|
-
puts 'yes'
|
131
|
-
else
|
132
|
-
puts 'no'
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
puts "creating Rakefile"
|
137
|
-
end
|
138
|
-
|
data/ext/vc/pg.sln
DELETED
@@ -1,26 +0,0 @@
|
|
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
|
data/sample/losample.rb
DELETED
@@ -1,47 +0,0 @@
|
|
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
|
-
|
data/sample/psql.rb
DELETED
@@ -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 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
|
-
|