mirror of
https://github.com/mdbtools/mdbtools.git
synced 2025-06-28 10:27:52 +08:00
added man pages for utils.
lots of gmdb2 work. added statistics collection.
This commit is contained in:
parent
cc362c42e9
commit
320f03c401
35
HACKING
35
HACKING
@ -461,18 +461,43 @@ Indices
|
||||
|
||||
Indices are not completely understood but here is what we know.
|
||||
|
||||
+------+---------+-------------+------------------------------------------+
|
||||
| data | length | name | description |
|
||||
+------+---------+-------------+------------------------------------------+
|
||||
| 0x01 | 1 bytes | page_type | 0x03 indicate an index page |
|
||||
| 0x01 | 1 bytes | unknown | |
|
||||
| ???? | 2 bytes | free_space | The free space at the end this page |
|
||||
| ???? | 4 bytes | parent_page | The page number of the TDEF for this idx |
|
||||
| ???? | 4 bytes | prev_page | Previous page at this index level |
|
||||
| ???? | 4 bytes | next_page | Next page at this index level |
|
||||
| ???? | 4 bytes | leaf_page | Pointer to leaf page, purpose unknown |
|
||||
+-------------------------------------------------------------------------+
|
||||
|
||||
On the page pointed to by the table definition a series of records start at
|
||||
byte offset 0xf8.
|
||||
|
||||
The record generally begins with 0x7f or 0x80. 0x80 is the one's complement of 0x7f and all text data in the index would then need to be negated. The reason
|
||||
for this negation is unknown, although I suspect it has to do with descending
|
||||
order.
|
||||
If the page is an index page (type 0x03) then the value of each key column is
|
||||
stored (for integers it seems to be in msb-lsb order to help comparison) preceded
|
||||
by a flag field and followed by the data pointer to the index entries record, this
|
||||
is then followed by a pointer to a leaf index page.
|
||||
|
||||
Access stored an 'alphabetic sort order' version of the text key columns in the index. Basically this means that upper and lower case characters A-Z are merged and start at 0x60. Digits are 0x56 through 0x5f. Once converted into this
|
||||
The flag field is generally either 0x00, 0x7f, 0x80. 0x80 is the one's complement
|
||||
of 0x7f and all text data in the index would then need to be negated. The reason
|
||||
for this negation is unknown, although I suspect it has to do with descending
|
||||
order. The 0x00 flag indicates that the key column is null, and no data will follow,
|
||||
only the page pointer.
|
||||
|
||||
Access stores an 'alphabetic sort order' version of the text key columns in the index. Basically this means that upper and lower case characters A-Z are merged and start at 0x60. Digits are 0x56 through 0x5f. Once converted into this
|
||||
(non-ascii) character set, the text value is able to be sorted in 'alphabetic'
|
||||
order. A text column will end with a NULL (0x00 or 0xff if negated).
|
||||
|
||||
Beyond the key columns is stored a 3 byte page number and 1 byte row number.
|
||||
The leaf page entries store the key column and the 3 byte page and 1 byte row
|
||||
number.
|
||||
|
||||
The value of the index root page in the index definition may be an index page
|
||||
(type 0x03), an index leaf page (type 0x04) if there is only one index page,
|
||||
or (in the case of tables small enough to fit on one page) a data page
|
||||
(type 0x01).
|
||||
|
||||
So to search the index, you need to convert your value into the alphabetic
|
||||
character set, compare against each index entry, and on successful comparison
|
||||
|
@ -1,4 +1,4 @@
|
||||
SUBDIRS = src include
|
||||
SUBDIRS = src include doc
|
||||
|
||||
DEFDIR = $(prefix)
|
||||
|
||||
|
@ -110,4 +110,4 @@ LDFLAGS=$OLDLDFLAGS
|
||||
|
||||
AC_SUBST(READLINE_LIBS)
|
||||
|
||||
AC_OUTPUT(src/util/Makefile src/extras/Makefile Makefile include/Makefile src/Makefile src/libmdb/Makefile include/Makefile src/sql/Makefile src/odbc/Makefile src/gmdb2/Makefile)
|
||||
AC_OUTPUT(src/util/Makefile src/extras/Makefile Makefile include/Makefile src/Makefile src/libmdb/Makefile include/Makefile src/sql/Makefile src/odbc/Makefile src/gmdb2/Makefile doc/Makefile)
|
||||
|
25
doc/mdb-export.txt
Normal file
25
doc/mdb-export.txt
Normal file
@ -0,0 +1,25 @@
|
||||
NAME
|
||||
mdb-export - Export data in an MDB database table to CSV format.
|
||||
SYNOPSIS
|
||||
mdb-export [-H] [-Q] [-d <delimiter>] <database> <table>
|
||||
|
||||
DESCRIPTION
|
||||
mdb-export is a utility program distributed with MDB Tools.
|
||||
|
||||
It produces a CSV (comma separated value) output for the given table. Such output is suitable for importation into databases or spreadsheets.
|
||||
|
||||
OPTIONS
|
||||
-H Supress header row
|
||||
-Q Don't wrap text-like fields (text, memo, date) in quotes. If not specified text fiels will be surrounded by " (double quote) characters.
|
||||
-d Specify an alternative column delimiter If no delimiter is specified, table names will be delimited by a , (comma) character.
|
||||
|
||||
NOTES
|
||||
|
||||
HISTORY
|
||||
mdb-export first appeared in MDB Tools 0\.1
|
||||
|
||||
AUTHORS
|
||||
The mdb-export utility was written by Brian Bruns
|
||||
|
||||
BUGS
|
||||
Memo fields are allowed to contain a newline characters, the current program does nothing about this.
|
25
doc/mdb-schema.txt
Normal file
25
doc/mdb-schema.txt
Normal file
@ -0,0 +1,25 @@
|
||||
NAME
|
||||
mdb-schema - Generate schema creation DDL
|
||||
SYNOPSIS
|
||||
mdb-schema [-T <table>] <database> [<backend>]
|
||||
|
||||
DESCRIPTION
|
||||
mdb-schema is a utility program distributed with MDB Tools.
|
||||
|
||||
It produces DDL (data definition language) output for the given database. This can be passed to another database to create a replica of the original access table format.
|
||||
|
||||
OPTIONS
|
||||
-T Single table option. Create schema for this table only.
|
||||
backend Specifies target DDL dialect. Supported values are access, sybase, oracle, and postgres. If not specified the generated DDL will be in access format.
|
||||
|
||||
NOTES
|
||||
|
||||
HISTORY
|
||||
mdb-schema first appeared in MDB Tools 0\.1
|
||||
|
||||
AUTHORS
|
||||
The mdb-schema utility was written by Brian Bruns
|
||||
|
||||
BUGS
|
||||
Relationships and other features may not be supported by all databases.
|
||||
Access datatypes are mapped to their closest counterparts in the target backend. This may not always yield an exact fit.
|
67
doc/mdb-sql.txt
Normal file
67
doc/mdb-sql.txt
Normal file
@ -0,0 +1,67 @@
|
||||
NAME
|
||||
mdb-sql - SQL interface to MDB Tools
|
||||
|
||||
SYNOPSIS
|
||||
mdb-sql [-HFp] [-d <delimiter>] [-i <file>] [-o <file>] [<database>]
|
||||
|
||||
DESCRIPTION
|
||||
mdb-sql is a utility program distributed with MDB Tools.
|
||||
|
||||
mdb-sql allows querying of an MDB database using a limited SQL subset
|
||||
language.
|
||||
|
||||
OPTIONS
|
||||
-H Supress header row.
|
||||
-F Supress footer row.
|
||||
-p Turn off pretty printing. By default results are printed in an
|
||||
ascii table format which looks nice but is not condusive to manipulating the
|
||||
output with unix tools. This option prints output plainly in a tab separated
|
||||
format.
|
||||
-d Specify an alternative column delimiter. If no delimiter is
|
||||
specified, columns will be delimited by a tab character if pretty printing
|
||||
(-p) is turned off. If pretty printing is enabled this option is meaningless.
|
||||
-i Specify an input file. This option allows an input file containing the SQL to be passed to mdb-sql. See Notes.
|
||||
-o Specify an output file. This option allows the name of an output file to be used instead of stdout.
|
||||
|
||||
COMMANDS
|
||||
mdb-sql in interactive mode takes some special commands.
|
||||
|
||||
connect to <database> If no database was specified on the command line this command is necessary before any querys are issued. It also allows the switching of databases once in the tool.
|
||||
disconnect Will disconnect from the current database.
|
||||
go Each batch is sent to the parser using the 'go' command.
|
||||
|
||||
reset A batch can be cleared using the 'reset' command.
|
||||
|
||||
list tables The list tables command will display a list of available tables in this database, similar to the mdb-tables utility on the command line.
|
||||
describe table <table> Will display the column information for the specified table.
|
||||
quit Will exit the tool.
|
||||
|
||||
SQL LANGUAGE
|
||||
The currently implemented SQL subset is quite small, supporting only single table queries, no aggregates, and limited support for WHERE clauses. Here is a brief synopsis of the supported language.
|
||||
|
||||
select: SELECT [* | <column list>] FROM <table> WHERE <where clause>
|
||||
|
||||
column list: <column> [, <column list>]
|
||||
|
||||
where clause: <column> <operator> <literal> [AND <where clause>]
|
||||
|
||||
operator: =, =>, =<, <>, like, <, >
|
||||
|
||||
literal: integers, floating point numbers, or string literal in single quotes
|
||||
|
||||
NOTES
|
||||
When passing a file (-i) or piping output to mdb-sql the final 'go' is optional. This allow constructs like
|
||||
|
||||
echo "Select * from Table1" | mdb-sql mydb.mdb
|
||||
|
||||
to work correctly.
|
||||
|
||||
The -i command can be passed the string 'stdin' to test entering text as if using a pipe.
|
||||
|
||||
HISTORY
|
||||
mdb-sql first appeared in MDB Tools 0\.3
|
||||
|
||||
AUTHORS
|
||||
The mdb-sql utility was written by Brian Bruns
|
||||
|
||||
BUGS
|
27
doc/mdb-tables.txt
Normal file
27
doc/mdb-tables.txt
Normal file
@ -0,0 +1,27 @@
|
||||
NAME
|
||||
mdb-tables - Get listing of tables in an MDB database
|
||||
SYNOPSIS
|
||||
mdb-tables [-S] [-1 | -d<delimiter>] <database>
|
||||
|
||||
DESCRIPTION
|
||||
mdb-tables is a utility program distributed with MDB Tools.
|
||||
|
||||
It produces a list of tables contained within an MDB database in a format suitable for use in shell scripts.
|
||||
|
||||
OPTIONS
|
||||
-S Show system tables. System tables are generally those beginning with 'MSys'
|
||||
|
||||
-1 specifies that the tables should be listed 1 per line.
|
||||
|
||||
-d delimiter specifies an alternative delimiter. If no delimiter is specified, table names will be delimited by a tab character, or by newline if the -1 option was specified.
|
||||
|
||||
NOTES
|
||||
|
||||
HISTORY
|
||||
mdb-tables first appeared in MDB Tools 0\.3
|
||||
|
||||
AUTHORS
|
||||
The mdb-tables utility was written by Brian Bruns
|
||||
|
||||
BUGS
|
||||
Access allows for tables to have spaces embeded in the table name. You must specify a delimiter (-d) if you intend on piping the output of mdb-tables to a program such as awk or cut.
|
25
doc/mdb-ver.txt
Normal file
25
doc/mdb-ver.txt
Normal file
@ -0,0 +1,25 @@
|
||||
NAME
|
||||
mdb-ver - Return the format of a given MDB database.
|
||||
SYNOPSIS
|
||||
mdb-ver <database>
|
||||
|
||||
DESCRIPTION
|
||||
mdb-ver is a utility program distributed with MDB Tools.
|
||||
|
||||
It will return a single line of output with either 'JET3' for those files produced in Access 97 format or 'JET4' for those produced by Access 2000 and XP.
|
||||
|
||||
OPTIONS
|
||||
|
||||
NOTES
|
||||
Access changed its format between Jet 3 used in Access 97 and Jet 4 used for Access 2000 and XP. The nature of the changes included moving the page size from 2K to 4K and added support for unicode. MDB Tools actively supports both formats.
|
||||
|
||||
HISTORY
|
||||
mdb-ver first appeared in MDB Tools 0\.4
|
||||
|
||||
AUTHORS
|
||||
The mdb-ver utility was written by Brian Bruns
|
||||
|
||||
BUGS
|
||||
mdb-ver does minimal checking on the validity of a file. It is possbile for it to misidentify a non-MDB file.
|
||||
|
||||
mdb-ver does not recognize Access 2.0 (Jet 2) or the newer MSDE format files.
|
307
doc/txt2man
Executable file
307
doc/txt2man
Executable file
@ -0,0 +1,307 @@
|
||||
#!/bin/sh
|
||||
test "$HOME" = ~ || exec ksh $0 "$@" # try ksh if sh too old (not yet POSIX)
|
||||
|
||||
# Copyright (C) 2001, 2002 Marc Vertes
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
|
||||
# txt2man-1.4.5
|
||||
|
||||
usage()
|
||||
{
|
||||
cat << EOT
|
||||
NAME
|
||||
txt2man - convert flat ASCII text to man page format
|
||||
SYNOPSIS
|
||||
txt2man [-hpTX] [-t mytitle] [-P pname] [-r rel] [-s sect]
|
||||
[-v vol] [-I txt] [-B txt] [ifile]
|
||||
DESCRIPTION
|
||||
txt2man converts the input text into nroff/troff standard man(7)
|
||||
macros used to format Unix manual pages. Nice pages can be generated
|
||||
specially for commands (section 1 or 8) or for C functions reference
|
||||
(sections 2, 3), with the ability to recognize and format command and
|
||||
function names, flags, types and arguments.
|
||||
|
||||
txt2man is also able to recognize and format sections, paragraphs,
|
||||
lists (standard, numbered, description, nested), cross references and
|
||||
literal display blocks.
|
||||
|
||||
If input file ifile is omitted, standard input is used. Result is
|
||||
displayed on standard output.
|
||||
|
||||
Here is how text patterns are recognized and processed:
|
||||
Sections These headers are defined by a line in upper case, starting
|
||||
column 1. If there is one or more leading spaces, a
|
||||
sub-section will be generated instead.
|
||||
Paragraphs They must be separated by a blank line, and left aligned.
|
||||
Tag list The item definition is separated from the item description
|
||||
by at least 2 blank spaces, even before a new line, if
|
||||
definition is too long. Definition will be emphasized
|
||||
by default.
|
||||
Bullet list
|
||||
Bullet list items are defined by the first word being "-"
|
||||
or "*" or "o".
|
||||
Enumerated list
|
||||
The first word must be a number followed by a dot.
|
||||
Literal display blocks
|
||||
This paragraph type is used to display unmodified text,
|
||||
for example source code. It must be separated by a blank
|
||||
line, and be indented. It is primarily used to format
|
||||
unmodified source code. It will be printed using fixed font
|
||||
whenever possible (troff).
|
||||
Cross references
|
||||
A cross reference (another man page) is defined by a word
|
||||
followed by a number in parenthesis.
|
||||
|
||||
Special sections:
|
||||
NAME The function or command name and short description are set in
|
||||
this section.
|
||||
SYNOPSIS This section receives a special treatment to identify command
|
||||
name, flags and arguments, and propagate corresponding
|
||||
attributes later in the text. If a C like function is recognized
|
||||
(word immediately followed by an open parenthesis), txt2man will
|
||||
print function name in bold font, types in normal font, and
|
||||
variables in italic font. The whole section will be printed using
|
||||
a fixed font family (courier) whenever possible (troff).
|
||||
|
||||
It is a good practice to embed documentation into source code, by using
|
||||
comments or constant text variables. txt2man allows to do that, keeping
|
||||
the document source readable, usable even without further formatting
|
||||
(i.e. for online help) and easy to write. The result is high quality
|
||||
and standard complying document.
|
||||
OPTIONS
|
||||
-h The option -h displays help.
|
||||
-P pname Set pname as project name in header. Default to uname -s.
|
||||
-p Probe title, section name and volume.
|
||||
-t mytitle Set mytitle as title of generated man page.
|
||||
-r rel Set rel as project name and release.
|
||||
-s sect Set sect as section in heading, ususally a value from 1 to 8.
|
||||
-v vol Set vol as volume name, i.e. "Unix user 's manual".
|
||||
-I txt Italicize txt in output. Can be specified more than once.
|
||||
-B txt Emphasize (bold) txt in output. Can be specified more than once.
|
||||
-T Text result previewing using PAGER, usually more(1).
|
||||
-X X11 result previewing using gxditview(1).
|
||||
ENVIRONMENT
|
||||
PAGER name of paging command, usually more(1), or less(1). If not set
|
||||
falls back to more(1).
|
||||
EXAMPLE
|
||||
Try this command to format this text itself:
|
||||
|
||||
$ txt2man -h | txt2man -T
|
||||
HINTS
|
||||
To obtain an overall good formating of output document, keep paragraphs
|
||||
indented correctly. If you have unwanted bold sections, search for
|
||||
multiple spaces between words, which are used to identify a tag list
|
||||
(term followed by a description). Choose also carefully the name of
|
||||
command line or function parameters, as they will be emphasized each
|
||||
time they are encountered in the document.
|
||||
SEE ALSO
|
||||
man(1), mandoc(7), rman(1), groff(1), more(1), gxditview(1), troff(1).
|
||||
BUGS
|
||||
- Automatic probe (-p option) works only if input is a regular file (i.e.
|
||||
not stdin).
|
||||
AUTHOR
|
||||
mvertes@cimai.com (Marc Vertes)
|
||||
EOT
|
||||
}
|
||||
|
||||
sys=$(uname -s)
|
||||
rel=
|
||||
volume=
|
||||
section=
|
||||
title=untitled
|
||||
doprobe=
|
||||
itxt=
|
||||
btxt=
|
||||
post=cat
|
||||
while getopts :hpTXr:s:t:v:P:I:B: opt
|
||||
do
|
||||
case $opt in
|
||||
r) rel=$OPTARG;;
|
||||
t) title=$OPTARG;;
|
||||
s) section=$OPTARG;;
|
||||
v) volume=$OPTARG;;
|
||||
P) sys=$OPTARG;;
|
||||
p) doprobe=1;;
|
||||
I) itxt="$OPTARG§$itxt";;
|
||||
B) btxt=$OPTARG;;
|
||||
T) post="groff -mandoc -Tlatin1 | ${PAGER:-more}";;
|
||||
X) post="groff -mandoc -X";;
|
||||
*) usage; exit;;
|
||||
esac
|
||||
done
|
||||
shift $(($OPTIND - 1))
|
||||
|
||||
if test "$doprobe"
|
||||
then
|
||||
title=${1##*/}; title=${title%.txt}
|
||||
grep -q '#include ' $1 &&
|
||||
{ section=${section:-3};
|
||||
volume=${volume:-"$sys Programmer's Manual"}; } ||
|
||||
{ section=${section:-1};
|
||||
volume=${volume:-"$sys Reference Manual"}; }
|
||||
# get release from path
|
||||
rel=$(pwd | sed 's:/.*[^0-9]/::g
|
||||
s:/.*::g')
|
||||
fi
|
||||
|
||||
head=".TH $title $section \"$(date +'%B %d, %Y')\" \"$rel\" \"$volume\""
|
||||
|
||||
expand $* | # All tabs converted to spaces
|
||||
gawk -v head="$head" -v itxt="$itxt" -v btxt="$btxt" ' # gawk is needed because use of non standard regexp
|
||||
BEGIN {
|
||||
print ".\\\" Text automatically generated by txt2man-1.4.5"
|
||||
print head
|
||||
avar[1] = btxt; avar[2] = itxt
|
||||
for (k in avar) {
|
||||
mark = (k == 1 ? "\\fB" : "\\fI")
|
||||
split(avar[k], tt, "§")
|
||||
for (i in tt)
|
||||
if (tt[i] != "")
|
||||
subwords["\\<" tt[i] "\\>"] = mark tt[i] "\\fP"
|
||||
delete tt
|
||||
}
|
||||
delete avar
|
||||
}
|
||||
{ sub(/\.\.\./, "\\.\\.\\.") }
|
||||
/^[^[:lower:]]+$/ { # Section header
|
||||
if (in_bd == 1) {
|
||||
in_bd = 0
|
||||
print ".fam T\n.fi"
|
||||
}
|
||||
if (section == "SYNOPSIS") {
|
||||
print ".fam T\n.fi"
|
||||
type["SYNOPSIS"] = ""
|
||||
}
|
||||
if ($0 ~/^[^[:space:]]/) print ".SH " $0
|
||||
else print ".SS" $0
|
||||
sub(/^ +/, "")
|
||||
section = $0
|
||||
if (section == "SYNOPSIS") print ".nf\n.fam C"
|
||||
ls = 0 # line start index
|
||||
pls = 0 # previous line start index
|
||||
pnzls = 0 # previous non zero line start index
|
||||
ni = 0 # indent level
|
||||
ind[0] = 0 # indent offset table
|
||||
prevblankline = 0
|
||||
next
|
||||
}
|
||||
{ # compute line start index, handle start of example display block
|
||||
pls = ls
|
||||
if (ls != 0) pnzls = ls
|
||||
match($0, /[^ ]/)
|
||||
ls = RSTART
|
||||
if (pls == 0 && pnzls > 0 && ls > pnzls && $1 !~ /^[0-9\-\*\o]\.*$/) {
|
||||
# example display block
|
||||
if (prevblankline == 1) { print ".PP"; prevblankline = 0 }
|
||||
print ".nf\n.fam C"
|
||||
in_bd = 1
|
||||
eoff = ls
|
||||
}
|
||||
if (ls > 0 && ind[0] == 0) ind[0] = ls
|
||||
}
|
||||
in_bd == 1 { # In example display block
|
||||
if (ls != 0 && ls < eoff) { # End of litteral display block
|
||||
in_bd = 0
|
||||
print ".fam T\n.fi"
|
||||
} else { print; next }
|
||||
}
|
||||
section == "NAME" { $1 = "\\fB" $1; sub(/ \- /, " \\fP- ") }
|
||||
section == "SYNOPSIS" { # Identify arguments of fcts and cmds
|
||||
if (type["SYNOPSIS"] == "") {
|
||||
if (index($0, "(") == 0 && index($0, ")") == 0 &&
|
||||
index($0, "#include") == 0)
|
||||
type["SYNOPSIS"] = "cmd"
|
||||
else
|
||||
type["SYNOPSIS"] = "fct"
|
||||
}
|
||||
if (type["SYNOPSIS"] == "cmd") { # Line is a command line
|
||||
if ($1 !~ /^\[/) {
|
||||
b = $1
|
||||
sub(/^\*/, "", b)
|
||||
subwords["\\<" b "\\>"] = "\\fB" b "\\fP"
|
||||
}
|
||||
for (i = 2; i <= NF; i++) {
|
||||
a = $i
|
||||
gsub(/[\[\]\|]/, "", a)
|
||||
if (a ~ /^[^\-]/) subwords["\\<" a "\\>"] = "\\fI" a "\\fP"
|
||||
}
|
||||
} else { # Line is a C function definition
|
||||
for (i = 1; i <= NF; i++)
|
||||
if ($i ~ /[\,\)]/) {
|
||||
a = $i
|
||||
sub(/.*\(/, "", a)
|
||||
gsub(/\W/, "", a)
|
||||
subwords["\\<" a "\\>"] = "\\fI" a "\\fP"
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
for (i = 1; i <= NF; i++) { # identify func calls and cross refs
|
||||
while ($i ~ /\w\.\w/) sub(/\./, "_dOt_", $i) # protect dots inside words
|
||||
b = $i
|
||||
sub(/^\*/, "", b)
|
||||
if ((a = index(b, ")(")) > 0) {
|
||||
w = substr(b, 3, a - 3)
|
||||
subwords["\\<" w "\\>"] = "\\fI" w "\\fP"
|
||||
}
|
||||
if ((a = index(b, "(")) > 0) {
|
||||
w = substr(b, 1, a - 1)
|
||||
subwords["\\<" w "\\("] = "\\fB" w "\\fP("
|
||||
}
|
||||
}
|
||||
#for (i in subwords) gsub(i, subwords[i]) # word attributes
|
||||
gsub(/\B\-+\w+(\-\w+)*/, "\\fB&\\fP") # shell options
|
||||
gsub(/_dOt_/, ".") # unprotect dots inside words
|
||||
|
||||
if (match($0, /[^ ] +/) > 0) { # tag list item
|
||||
adjust_indent()
|
||||
tag = substr($0, 1, RSTART)
|
||||
sub(/^ */, "", tag)
|
||||
tail = substr($0, RSTART + RLENGTH)
|
||||
print ".TP\n.B"
|
||||
print tag
|
||||
$0 = tail
|
||||
prevblankline = 0
|
||||
if (NF == 0) next
|
||||
} else if ($1 == "-"||$1 == "o"||$1 == "*") { # bullet list item
|
||||
adjust_indent()
|
||||
print ".IP \\(bu 3"
|
||||
prevblankline = 0
|
||||
$1 = ""
|
||||
} else if ($1 ~ /^[0-9]+[\).]$/) { # enum list item
|
||||
adjust_indent()
|
||||
print ".IP " $1 " 4"
|
||||
prevblankline = 0
|
||||
$1 = ""
|
||||
} else if (pls == 0) { # new paragraph
|
||||
adjust_indent()
|
||||
} else if (NF == 0) { # blank line
|
||||
prevblankline = 1; next
|
||||
} else prevblankline = 0 # other
|
||||
if (prevblankline == 1) { # flush vertical space
|
||||
print ".PP"; prevblankline = 0
|
||||
}
|
||||
sub(/ */,"") # trim leading blank spaces
|
||||
print
|
||||
}
|
||||
function adjust_indent()
|
||||
{
|
||||
if (ls > ind[ni]) { ind[++ni] = ls; print ".RS" }
|
||||
else if (ls < ind[ni])
|
||||
while (ls < ind[ni]) { ni--; print ".RE" }
|
||||
}
|
||||
' | eval $post
|
@ -38,7 +38,7 @@
|
||||
#define MDB_MAX_IDX_COLS 10
|
||||
#define MDB_CATALOG_PG 18
|
||||
#define MDB_MEMO_OVERHEAD 12
|
||||
#define MDB_BIND_SIZE 65536
|
||||
#define MDB_BIND_SIZE 16384
|
||||
|
||||
enum {
|
||||
MDB_VER_JET3 = 0,
|
||||
@ -108,6 +108,11 @@ typedef struct {
|
||||
char **types_table;
|
||||
} MdbBackend;
|
||||
|
||||
typedef struct {
|
||||
gboolean collect;
|
||||
unsigned long pg_reads;
|
||||
} MdbStatistics;
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
gboolean writable;
|
||||
@ -115,9 +120,14 @@ typedef struct {
|
||||
guint32 jet_version;
|
||||
guint32 db_key;
|
||||
char db_passwd[14];
|
||||
MdbBackend *default_backend;
|
||||
char *backend_name;
|
||||
MdbStatistics *stats;
|
||||
/* free map */
|
||||
int map_sz;
|
||||
unsigned char *free_map;
|
||||
/* reference count */
|
||||
int refs;
|
||||
} MdbFile;
|
||||
|
||||
/* offset to row count on data pages...version dependant */
|
||||
@ -150,6 +160,7 @@ typedef struct {
|
||||
MdbBackend *default_backend;
|
||||
char *backend_name;
|
||||
MdbFormatConstants *fmt;
|
||||
MdbStatistics *stats;
|
||||
} MdbHandle;
|
||||
|
||||
typedef struct {
|
||||
|
@ -20,7 +20,7 @@
|
||||
extern GtkWidget *app;
|
||||
extern MdbHandle *mdb;
|
||||
|
||||
GladeXML *debugwin_xml;
|
||||
GList *debug_list = NULL;
|
||||
|
||||
#define LINESZ 77
|
||||
|
||||
@ -134,6 +134,88 @@ GtkWidget *textview;
|
||||
}
|
||||
}
|
||||
void
|
||||
gmdb_debug_jump_cb(GtkWidget *w, GladeXML *xml)
|
||||
{
|
||||
GtkTextView *textview;
|
||||
GtkTextMark *mark;
|
||||
GtkTextBuffer *txtbuffer;
|
||||
GtkTextIter start, end;
|
||||
GtkWidget *entry;
|
||||
gchar *text;
|
||||
gchar page[12];
|
||||
gchar digits[4][3];
|
||||
gchar *hex_digit;
|
||||
int i, num_digits = 0;
|
||||
|
||||
textview = (GtkTextView *) glade_xml_get_widget (xml, "debug_textview");
|
||||
txtbuffer = gtk_text_view_get_buffer(textview);
|
||||
if (!gtk_text_buffer_get_selection_bounds(txtbuffer, &start, &end)) {
|
||||
/* FIX ME -- replace with text in status bar */
|
||||
fprintf(stderr, "Nothing selected\n");
|
||||
return;
|
||||
}
|
||||
text = g_strdup(gtk_text_buffer_get_text(txtbuffer, &start, &end, FALSE));
|
||||
fprintf(stderr, "selected text = %s\n",text);
|
||||
hex_digit = strtok(text, " ");
|
||||
strcpy(page, "0x");
|
||||
do {
|
||||
if (strlen(hex_digit)>2) {
|
||||
fprintf(stderr, "Not a hex value\n");
|
||||
return;
|
||||
}
|
||||
strcpy(digits[num_digits++],hex_digit);
|
||||
} while (num_digits < 4 && (hex_digit = strtok(NULL," ")));
|
||||
for (i=num_digits-1;i>=0;i--) {
|
||||
strcat(page, digits[i]);
|
||||
}
|
||||
g_free(text);
|
||||
fprintf(stderr, "going to page %s\n",page);
|
||||
entry = glade_xml_get_widget (xml, "debug_entry");
|
||||
gtk_entry_set_text(GTK_ENTRY(entry),page);
|
||||
gmdb_debug_display_cb(w, xml);
|
||||
}
|
||||
void
|
||||
gmdb_debug_jump_msb_cb(GtkWidget *w, GladeXML *xml)
|
||||
{
|
||||
GtkTextView *textview;
|
||||
GtkTextMark *mark;
|
||||
GtkTextBuffer *txtbuffer;
|
||||
GtkTextIter start, end;
|
||||
GtkWidget *entry;
|
||||
gchar *text;
|
||||
gchar page[12];
|
||||
gchar digits[4][3];
|
||||
gchar *hex_digit;
|
||||
int i, num_digits = 0;
|
||||
|
||||
textview = (GtkTextView *) glade_xml_get_widget (xml, "debug_textview");
|
||||
txtbuffer = gtk_text_view_get_buffer(textview);
|
||||
if (!gtk_text_buffer_get_selection_bounds(txtbuffer, &start, &end)) {
|
||||
/* FIX ME -- replace with text in status bar */
|
||||
fprintf(stderr, "Nothing selected\n");
|
||||
return;
|
||||
}
|
||||
text = g_strdup(gtk_text_buffer_get_text(txtbuffer, &start, &end, FALSE));
|
||||
fprintf(stderr, "selected text = %s\n",text);
|
||||
hex_digit = strtok(text, " ");
|
||||
strcpy(page, "0x");
|
||||
do {
|
||||
if (strlen(hex_digit)>2) {
|
||||
fprintf(stderr, "Not a hex value\n");
|
||||
return;
|
||||
}
|
||||
strcpy(digits[num_digits++],hex_digit);
|
||||
} while (num_digits < 4 && (hex_digit = strtok(NULL," ")));
|
||||
for (i=0;i<num_digits;i++) {
|
||||
strcat(page, digits[i]);
|
||||
}
|
||||
g_free(text);
|
||||
fprintf(stderr, "going to page %s\n",page);
|
||||
entry = glade_xml_get_widget (xml, "debug_entry");
|
||||
gtk_entry_set_text(GTK_ENTRY(entry),page);
|
||||
gmdb_debug_display_cb(w, xml);
|
||||
}
|
||||
void
|
||||
gmdb_debug_display_cb(GtkWidget *w, GladeXML *xml)
|
||||
{
|
||||
int page;
|
||||
@ -309,6 +391,37 @@ GtkCTreeNode *node;
|
||||
gmdb_debug_add_item(store, parent, str, offset+4, offset+7);
|
||||
}
|
||||
void
|
||||
gmdb_debug_dissect_index2(GtkTreeStore *store, GtkTreeIter *parent, char *fbuf, int offset)
|
||||
{
|
||||
gchar str[100];
|
||||
GtkCTreeNode *node;
|
||||
int mod=0;
|
||||
unsigned char flags;
|
||||
gchar flagstr[100]; /* If adding flags increase this */
|
||||
|
||||
snprintf(str, 100, "Column mask");
|
||||
gmdb_debug_add_item(store, parent, str, offset, offset+29);
|
||||
snprintf(str, 100, "Unknown");
|
||||
gmdb_debug_add_item(store, parent, str, offset+30, offset+33);
|
||||
snprintf(str, 100, "Root index page");
|
||||
gmdb_debug_add_item(store, parent, str, offset+34, offset+37);
|
||||
flags = fbuf[offset+38];
|
||||
if (flags & MDB_IDX_UNIQUE) {
|
||||
strcat(flagstr, "Unique"); mod++;
|
||||
}
|
||||
if (flags & MDB_IDX_IGNORENULLS) {
|
||||
if (mod) strcat(flagstr, ",");
|
||||
strcat(flagstr, "Ignore Nulls"); mod++;
|
||||
}
|
||||
if (flags & MDB_IDX_REQUIRED) {
|
||||
if (mod) strcat(flagstr, ",");
|
||||
strcat(flagstr, "Required");
|
||||
}
|
||||
if (!mod) strcpy(flagstr, "None");
|
||||
snprintf(str, 100, "Index Flags (%s)", flagstr);
|
||||
gmdb_debug_add_item(store, parent, str, offset+38, offset+38);
|
||||
}
|
||||
void
|
||||
gmdb_debug_add_page_ptr(GtkTreeStore *store, GtkTreeIter *parent, char *fbuf, const char *label, int offset)
|
||||
{
|
||||
gchar str[100];
|
||||
@ -334,6 +447,7 @@ int i;
|
||||
snprintf(str, 100, "Num columns: %u", num_cols);
|
||||
gmdb_debug_add_item(store, parent, str, offset, offset);
|
||||
bitmask_sz = ((num_cols-1) / 8) + 1;
|
||||
printf("bitmask_sz %d\n", bitmask_sz);
|
||||
var_cols_loc = end - bitmask_sz;
|
||||
var_cols = fbuf[var_cols_loc];
|
||||
fixed_end = offset + fbuf[var_cols_loc - 1] - 1; /* work even if 0 b/c of EOD */
|
||||
@ -357,6 +471,20 @@ int i;
|
||||
snprintf(str, 100, "Null mask");
|
||||
gmdb_debug_add_item(store, parent, str, var_cols_loc + 1, end);
|
||||
}
|
||||
void
|
||||
gmdb_debug_dissect_index_pg(GtkTreeStore *store, char *fbuf, int offset, int len)
|
||||
{
|
||||
gchar str[100];
|
||||
guint32 tdef;
|
||||
|
||||
snprintf(str, 100, "Page free space: %u",
|
||||
get_uint16(&fbuf[offset+2]));
|
||||
gmdb_debug_add_item(store, NULL, str, offset+2, offset+3);
|
||||
tdef = get_uint32(&fbuf[offset+4]);
|
||||
snprintf(str, 100, "Parents TDEF page: 0x%06x (%lu)", tdef,tdef);
|
||||
gmdb_debug_add_item(store, NULL, str, offset+4, offset+7);
|
||||
}
|
||||
|
||||
void
|
||||
gmdb_debug_dissect_leaf_pg(GtkTreeStore *store, char *fbuf, int offset, int len)
|
||||
{
|
||||
@ -484,7 +612,7 @@ GtkTreeIter *node, *container;
|
||||
for (i=0;i<num_idx;i++) {
|
||||
snprintf(str, 100, "Index %d", i+1);
|
||||
node = gmdb_debug_add_item(store, container, str, newbase+(i*39), newbase+(i*39)+38);
|
||||
//gmdb_debug_dissect_index2(store, container, fbuf, newbase+(i*39));
|
||||
gmdb_debug_dissect_index2(store, node, fbuf, newbase+(i*39));
|
||||
}
|
||||
newbase += num_idx * 39;
|
||||
container = gmdb_debug_add_item(store, NULL, "Index definition 2", -1, -1);
|
||||
@ -528,7 +656,7 @@ gchar str[100];
|
||||
gmdb_debug_dissect_tabledef_pg(store, fbuf, 0, len);
|
||||
break;
|
||||
case 0x03:
|
||||
//gmdb_debug_dissect_dbpage(store, fbuf, 1, len);
|
||||
gmdb_debug_dissect_index_pg(store, fbuf, 0, len);
|
||||
break;
|
||||
case 0x04:
|
||||
gmdb_debug_dissect_leaf_pg(store, fbuf, 0, len);
|
||||
@ -623,9 +751,26 @@ void
|
||||
gmdb_debug_close_cb(GtkWidget *w, GladeXML *xml)
|
||||
{
|
||||
GtkWidget *win;
|
||||
|
||||
debug_list = g_list_remove(debug_list, xml);
|
||||
win = glade_xml_get_widget (xml, "debug_window");
|
||||
if (win) gtk_widget_destroy(win);
|
||||
return FALSE;
|
||||
}
|
||||
void
|
||||
gmdb_debug_close_all()
|
||||
{
|
||||
GladeXML *xml;
|
||||
GtkWidget *win;
|
||||
|
||||
while (xml = g_list_nth_data(debug_list, 0)) {
|
||||
printf("fetching %ld from list\n", xml);
|
||||
win = glade_xml_get_widget (xml, "debug_window");
|
||||
debug_list = g_list_remove(debug_list, xml);
|
||||
if (win) gtk_widget_destroy(win);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gmdb_debug_new_cb(GtkWidget *w, gpointer *data)
|
||||
{
|
||||
@ -633,12 +778,15 @@ GtkTextView *textview;
|
||||
guint32 page;
|
||||
GtkWidget *entry, *mi, *button, *debugwin;
|
||||
gchar text[20];
|
||||
GladeXML *debugwin_xml;
|
||||
|
||||
/* load the interface */
|
||||
debugwin_xml = glade_xml_new("gladefiles/gmdb-debug.glade", NULL, NULL);
|
||||
/* connect the signals in the interface */
|
||||
glade_xml_signal_autoconnect(debugwin_xml);
|
||||
|
||||
debug_list = g_list_append(debug_list, debugwin_xml);
|
||||
|
||||
/* set signals with user data, anyone know how to do this in glade? */
|
||||
entry = glade_xml_get_widget (debugwin_xml, "debug_entry");
|
||||
g_signal_connect (G_OBJECT (entry), "activate",
|
||||
@ -647,7 +795,22 @@ gchar text[20];
|
||||
mi = glade_xml_get_widget (debugwin_xml, "close_menu");
|
||||
g_signal_connect (G_OBJECT (mi), "activate",
|
||||
G_CALLBACK (gmdb_debug_close_cb), debugwin_xml);
|
||||
|
||||
button = glade_xml_get_widget (debugwin_xml, "close_button");
|
||||
g_signal_connect (G_OBJECT (button), "clicked",
|
||||
G_CALLBACK (gmdb_debug_close_cb), debugwin_xml);
|
||||
|
||||
mi = glade_xml_get_widget (debugwin_xml, "menu_page");
|
||||
g_signal_connect (G_OBJECT (mi), "activate",
|
||||
G_CALLBACK (gmdb_debug_jump_cb), debugwin_xml);
|
||||
mi = glade_xml_get_widget (debugwin_xml, "menu_page_msb");
|
||||
g_signal_connect (G_OBJECT (mi), "activate",
|
||||
G_CALLBACK (gmdb_debug_jump_msb_cb), debugwin_xml);
|
||||
|
||||
button = glade_xml_get_widget (debugwin_xml, "jump_button");
|
||||
g_signal_connect (G_OBJECT (button), "clicked",
|
||||
G_CALLBACK (gmdb_debug_jump_cb), debugwin_xml);
|
||||
|
||||
button = glade_xml_get_widget (debugwin_xml, "debug_button");
|
||||
g_signal_connect (G_OBJECT (button), "clicked",
|
||||
G_CALLBACK (gmdb_debug_display_cb), debugwin_xml);
|
||||
|
@ -156,4 +156,6 @@ void
|
||||
gmdb_file_close_cb(GtkWidget *button, gpointer data)
|
||||
{
|
||||
gmdb_reset_widgets();
|
||||
gmdb_debug_close_all();
|
||||
gmdb_sql_close_all();
|
||||
}
|
||||
|
@ -37,6 +37,22 @@
|
||||
<child>
|
||||
<widget class="GtkMenu" id="file1_menu">
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="new1">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock_item">GNOMEUIINFO_MENU_NEW_ITEM</property>
|
||||
<property name="label" translatable="yes">_New</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="gmdb_debug_new_cb" last_modification_time="Fri, 03 Jan 2003 13:11:43 GMT"/>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="separator1">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="close_menu">
|
||||
<property name="visible">True</property>
|
||||
@ -48,6 +64,58 @@
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="view1">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock_item">GNOMEUIINFO_MENU_VIEW_TREE</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenu" id="view1_menu">
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menu_back">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Back</property>
|
||||
<property name="use_underline">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="menu_forward">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock_item">GNOMEUIINFO_MENU_NEW_ITEM</property>
|
||||
<property name="label" translatable="yes">_Forward</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_menu_forward_activate" last_modification_time="Fri, 03 Jan 2003 15:27:51 GMT"/>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="separator2">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menu_page">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Selected Page</property>
|
||||
<property name="use_underline">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menu_page_msb">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Selected Page (_MSB)</property>
|
||||
<property name="use_underline">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="help1">
|
||||
<property name="visible">True</property>
|
||||
@ -60,7 +128,7 @@
|
||||
<widget class="GtkImageMenuItem" id="about1">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock_item">GNOMEUIINFO_MENU_ABOUT_ITEM</property>
|
||||
<signal name="activate" handler="gmdb_about_cb" last_modification_time="Sat, 21 Dec 2002 18:17:10 GMT"/>
|
||||
<signal name="activate" handler="gmdb_about_cb" last_modification_time="Fri, 03 Jan 2003 13:11:09 GMT"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
@ -79,6 +147,80 @@
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="BonoboDockItem" id="bonobodockitem2">
|
||||
<property name="visible">True</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkToolbar" id="toolbar1">
|
||||
<property name="border_width">1</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
|
||||
<property name="toolbar_style">GTK_TOOLBAR_ICONS</property>
|
||||
<property name="tooltips">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="button" id="button4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label">gtk-new</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="gmdb_debug_new_cb" last_modification_time="Fri, 03 Jan 2003 13:12:52 GMT"/>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="button" id="back_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">New File</property>
|
||||
<property name="label">gtk-go-back</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="new_group">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="button" id="forward_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Open File</property>
|
||||
<property name="label">gtk-go-forward</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="button" id="jump_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="label">gtk-jump-to</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="button" id="close_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Save File</property>
|
||||
<property name="label">gtk-close</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="new_group">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="placement">BONOBO_DOCK_TOP</property>
|
||||
<property name="band">1</property>
|
||||
<property name="position">0</property>
|
||||
<property name="offset">0</property>
|
||||
<property name="behavior">BONOBO_DOCK_ITEM_BEH_EXCLUSIVE</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
@ -87,20 +229,19 @@
|
||||
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame1">
|
||||
<property name="border_width">8</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="label_yalign">0.5</property>
|
||||
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox3">
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">12</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Page Number</property>
|
||||
<property name="use_underline">False</property>
|
||||
@ -185,10 +326,35 @@
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<widget class="GtkHPaned" id="hpaned1">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">0</property>
|
||||
<property name="can_focus">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
||||
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="debug_treeview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<property name="rules_hint">False</property>
|
||||
<property name="reorderable">False</property>
|
||||
<property name="enable_search">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="shrink">True</property>
|
||||
<property name="resize">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow2">
|
||||
@ -200,82 +366,26 @@
|
||||
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkViewport" id="viewport1">
|
||||
<widget class="GtkTextView" id="debug_textview">
|
||||
<property name="visible">True</property>
|
||||
<property name="shadow_type">GTK_SHADOW_IN</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHPaned" id="hpaned1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
||||
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="debug_treeview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<property name="rules_hint">False</property>
|
||||
<property name="reorderable">False</property>
|
||||
<property name="enable_search">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="shrink">True</property>
|
||||
<property name="resize">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
||||
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkTextView" id="debug_textview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">True</property>
|
||||
<property name="justification">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap_mode">GTK_WRAP_NONE</property>
|
||||
<property name="cursor_visible">True</property>
|
||||
<property name="pixels_above_lines">0</property>
|
||||
<property name="pixels_below_lines">0</property>
|
||||
<property name="pixels_inside_wrap">0</property>
|
||||
<property name="left_margin">0</property>
|
||||
<property name="right_margin">0</property>
|
||||
<property name="indent">0</property>
|
||||
<property name="text" translatable="yes"></property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="shrink">True</property>
|
||||
<property name="resize">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">True</property>
|
||||
<property name="justification">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap_mode">GTK_WRAP_NONE</property>
|
||||
<property name="cursor_visible">True</property>
|
||||
<property name="pixels_above_lines">0</property>
|
||||
<property name="pixels_below_lines">0</property>
|
||||
<property name="pixels_inside_wrap">0</property>
|
||||
<property name="left_margin">0</property>
|
||||
<property name="right_margin">0</property>
|
||||
<property name="indent">0</property>
|
||||
<property name="text" translatable="yes"></property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="shrink">True</property>
|
||||
<property name="resize">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
|
@ -30,8 +30,7 @@ typedef struct GMdbSQLWindow {
|
||||
GList *history;
|
||||
} GMdbSQLWindow;
|
||||
|
||||
GList *window_list;
|
||||
GladeXML *sqlwin_xml;
|
||||
GList *sql_list;
|
||||
|
||||
extern GtkWidget *app;
|
||||
extern MdbHandle *mdb;
|
||||
@ -39,20 +38,25 @@ extern MdbSQL *sql;
|
||||
|
||||
void gmdb_sql_tree_populate(MdbHandle *mdb, GladeXML *xml);
|
||||
|
||||
/* callbacks */
|
||||
#if 0
|
||||
gint
|
||||
gmdb_sql_close_cb(GtkList *list, GtkWidget *w, GMdbSQLWindow *sqlwin)
|
||||
void
|
||||
gmdb_sql_close_all()
|
||||
{
|
||||
window_list = g_list_remove(window_list, sql);
|
||||
g_free(sql);
|
||||
return FALSE;
|
||||
GladeXML *xml;
|
||||
GtkWidget *win;
|
||||
|
||||
while (xml = g_list_nth_data(sql_list, 0)) {
|
||||
win = glade_xml_get_widget (xml, "sql_window");
|
||||
sql_list = g_list_remove(sql_list, xml);
|
||||
if (win) gtk_widget_destroy(win);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* callbacks */
|
||||
void
|
||||
gmdb_sql_close_cb(GtkWidget *w, GladeXML *xml)
|
||||
{
|
||||
GtkWidget *win;
|
||||
sql_list = g_list_remove(sql_list, xml);
|
||||
win = glade_xml_get_widget (xml, "sql_window");
|
||||
if (win) gtk_widget_destroy(win);
|
||||
}
|
||||
@ -71,7 +75,7 @@ GtkTreeStore *store;
|
||||
GtkTreeView *tree;
|
||||
GtkTreeIter *iter, iter2;
|
||||
|
||||
tree = (GtkTreeView *) glade_xml_get_widget(sqlwin_xml, "sql_treeview");
|
||||
tree = (GtkTreeView *) glade_xml_get_widget(xml, "sql_treeview");
|
||||
select = gtk_tree_view_get_selection(GTK_TREE_VIEW (tree));
|
||||
store = (GtkTreeStore *) gtk_tree_view_get_model(tree);
|
||||
gtk_tree_selection_get_selected (select, NULL, &iter2);
|
||||
@ -221,12 +225,15 @@ gmdb_sql_new_cb(GtkWidget *w, gpointer data)
|
||||
{
|
||||
GtkTargetEntry src;
|
||||
GtkWidget *mi, *but;
|
||||
GladeXML *sqlwin_xml;
|
||||
|
||||
/* load the interface */
|
||||
sqlwin_xml = glade_xml_new("gladefiles/gmdb-sql.glade", NULL, NULL);
|
||||
/* connect the signals in the interface */
|
||||
glade_xml_signal_autoconnect(sqlwin_xml);
|
||||
|
||||
sql_list = g_list_append(sql_list, sqlwin_xml);
|
||||
|
||||
mi = glade_xml_get_widget (sqlwin_xml, "close_menu");
|
||||
g_signal_connect (G_OBJECT (mi), "activate",
|
||||
G_CALLBACK (gmdb_sql_close_cb), sqlwin_xml);
|
||||
@ -290,7 +297,7 @@ int i;
|
||||
MdbCatalogEntry *entry;
|
||||
GtkTreeIter *iter1, *iter2;
|
||||
|
||||
GtkWidget *tree = glade_xml_get_widget(sqlwin_xml, "sql_treeview");
|
||||
GtkWidget *tree = glade_xml_get_widget(xml, "sql_treeview");
|
||||
GtkTreeStore *store = (GtkTreeStore *) gtk_tree_view_get_model(GTK_TREE_VIEW(tree));
|
||||
|
||||
/* loop over each entry in the catalog */
|
||||
|
@ -1,4 +1,4 @@
|
||||
lib_LTLIBRARIES = libmdb.la
|
||||
libmdb_la_SOURCES= catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c write.c
|
||||
libmdb_la_SOURCES= catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c write.c stats.c
|
||||
INCLUDES = -I$(top_srcdir)/include $(GLIB_CFLAGS)
|
||||
LIBS = $(GLIB_LIBS)
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "time.h"
|
||||
#include "math.h"
|
||||
|
||||
#define MDB_DEBUG_OLE 1
|
||||
|
||||
char *mdb_money_to_string(MdbHandle *mdb, int start, char *s);
|
||||
static int _mdb_attempt_bind(MdbHandle *mdb,
|
||||
MdbColumn *col, unsigned char isnull, int offset, int len);
|
||||
@ -561,7 +563,7 @@ guint16 len, cur;
|
||||
ole_row = mdb->pg_buf[start+4];
|
||||
|
||||
lval_pg = mdb_get_int24(mdb, start+5);
|
||||
#if MDB_DEBUG
|
||||
#if MDB_DEBUG_OLE
|
||||
printf("Reading LVAL page %06x\n", lval_pg);
|
||||
#endif
|
||||
if(mdb_read_alt_pg(mdb, lval_pg) != mdb->fmt->pg_size) {
|
||||
@ -576,7 +578,7 @@ guint16 len, cur;
|
||||
row_stop = mdb->fmt->pg_size - 1;
|
||||
}
|
||||
row_start = mdb_get_int16(mdb, 10 + ole_row * 2);
|
||||
#if MDB_DEBUG
|
||||
#if MDB_DEBUG_OLE
|
||||
printf("row num %d row start %d row stop %d\n", ole_row, row_start, row_stop);
|
||||
#endif
|
||||
len = row_stop - row_start;
|
||||
@ -587,7 +589,7 @@ guint16 len, cur;
|
||||
} else if (ole_flags == 0x0000) {
|
||||
ole_row = mdb->pg_buf[start+4];
|
||||
lval_pg = mdb_get_int24(mdb, start+5);
|
||||
#if MDB_DEBUG
|
||||
#if MDB_DEBUG_OLE
|
||||
printf("Reading LVAL page %06x\n", lval_pg);
|
||||
#endif
|
||||
/* swap the alt and regular page buffers, so we can call get_int16 */
|
||||
@ -604,7 +606,7 @@ guint16 len, cur;
|
||||
row_stop = mdb->fmt->pg_size - 1;
|
||||
}
|
||||
row_start = mdb_get_int16(mdb, 10 + ole_row * 2);
|
||||
#if MDB_DEBUG
|
||||
#if MDB_DEBUG_OLE
|
||||
printf("row num %d row start %d row stop %d\n", ole_row, row_start, row_stop);
|
||||
#endif
|
||||
len = row_stop - row_start;
|
||||
|
@ -51,6 +51,7 @@ int j,pos;
|
||||
/* fprintf(stderr,"Couldn't open file %s\n",filename); */
|
||||
return NULL;
|
||||
}
|
||||
mdb->f->refs++;
|
||||
if (!mdb_read_pg(mdb, 0)) {
|
||||
fprintf(stderr,"Couldn't read first page.\n");
|
||||
return NULL;
|
||||
@ -87,9 +88,30 @@ MdbHandle *mdb_open(char *filename)
|
||||
void mdb_close(MdbHandle *mdb)
|
||||
{
|
||||
if (mdb->f) {
|
||||
mdb_free_file(mdb->f);
|
||||
mdb->f->refs--;
|
||||
if (mdb->f->refs<=0) mdb_free_file(mdb->f);
|
||||
}
|
||||
}
|
||||
MdbHandle *mdb_clone_handle(MdbHandle *mdb)
|
||||
{
|
||||
MdbHandle *newmdb;
|
||||
MdbCatalogEntry *entry;
|
||||
int i;
|
||||
|
||||
newmdb = mdb_alloc_handle();
|
||||
memcpy(newmdb, mdb, sizeof(MdbHandle));
|
||||
newmdb->stats = NULL;
|
||||
newmdb->catalog = g_array_new(FALSE,FALSE,sizeof(MdbCatalogEntry));
|
||||
for (i=0;i<mdb->num_catalog;i++) {
|
||||
entry = g_ptr_array_index(mdb->catalog,i);
|
||||
newmdb->catalog = g_array_append_val(newmdb->catalog, entry);
|
||||
}
|
||||
mdb->backend_name = NULL;
|
||||
if (mdb->f) {
|
||||
mdb->f->refs++;
|
||||
}
|
||||
return newmdb;
|
||||
}
|
||||
|
||||
/*
|
||||
** mdb_read a wrapper for read that bails if anything is wrong
|
||||
@ -121,6 +143,9 @@ off_t offset = pg * mdb->fmt->pg_size;
|
||||
fprintf(stderr,"offset %lu is beyond EOF\n",offset);
|
||||
return 0;
|
||||
}
|
||||
if (mdb->stats && mdb->stats->collect)
|
||||
mdb->stats->pg_reads++;
|
||||
|
||||
lseek(mdb->f->fd, offset, SEEK_SET);
|
||||
len = read(mdb->f->fd,pg_buf,mdb->fmt->pg_size);
|
||||
if (len==-1) {
|
||||
@ -166,6 +191,20 @@ int i;
|
||||
return i;
|
||||
|
||||
}
|
||||
gint32 mdb_get_int24_msb(MdbHandle *mdb, int offset)
|
||||
{
|
||||
gint32 l;
|
||||
unsigned char *c;
|
||||
|
||||
if (offset <0 || offset+3 > mdb->fmt->pg_size) return -1;
|
||||
c = &mdb->pg_buf[offset];
|
||||
l =c[0]; l<<=8;
|
||||
l+=c[1]; l<<=8;
|
||||
l+=c[2];
|
||||
|
||||
mdb->cur_pos+=3;
|
||||
return l;
|
||||
}
|
||||
gint32 mdb_get_int24(MdbHandle *mdb, int offset)
|
||||
{
|
||||
gint32 l;
|
||||
|
@ -126,7 +126,7 @@ int i;
|
||||
for (i=0;i<idx->num_keys;i++) {
|
||||
marker = mdb->pg_buf[cur_pos++];
|
||||
col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1);
|
||||
printf("column %d coltype %d col_size %d\n",i,col->col_type, mdb_col_fixed_size(col));
|
||||
printf("column %d coltype %d col_size %d (%d)\n",i,col->col_type, mdb_col_fixed_size(col), col->col_size);
|
||||
}
|
||||
}
|
||||
void mdb_index_dump(MdbTableDef *table, MdbIndex *idx)
|
||||
|
@ -30,6 +30,16 @@ void mdb_exit()
|
||||
g_hash_table_destroy(mdb_backends);
|
||||
}
|
||||
|
||||
MdbStatistics *mdb_alloc_stats(MdbHandle *mdb)
|
||||
{
|
||||
mdb->stats = g_malloc0(sizeof(MdbStatistics));
|
||||
return mdb->stats;
|
||||
}
|
||||
void mdb_free_stats(MdbHandle *mdb)
|
||||
{
|
||||
g_free(mdb->stats);
|
||||
mdb->stats = NULL;
|
||||
}
|
||||
MdbFile *mdb_alloc_file()
|
||||
{
|
||||
MdbHandle *f;
|
||||
@ -60,8 +70,9 @@ void mdb_free_handle(MdbHandle *mdb)
|
||||
{
|
||||
if (!mdb) return;
|
||||
|
||||
if (mdb->stats) mdb_free_stats(mdb);
|
||||
if (mdb->catalog) mdb_free_catalog(mdb);
|
||||
if (mdb->f) mdb_free_file(mdb->f);
|
||||
if (mdb->f && mdb->f->refs<=0) mdb_free_file(mdb->f);
|
||||
if (mdb->backend_name) free(mdb->backend_name);
|
||||
free(mdb);
|
||||
}
|
||||
|
43
src/libmdb/stats.c
Normal file
43
src/libmdb/stats.c
Normal file
@ -0,0 +1,43 @@
|
||||
/* MDB Tools - A library for reading MS Access database files
|
||||
* Copyright (C) 2000 Brian Bruns
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "mdbtools.h"
|
||||
|
||||
void
|
||||
mdb_stats_on(MdbHandle *mdb)
|
||||
{
|
||||
if (!mdb->stats)
|
||||
mdb_alloc_stats(mdb);
|
||||
|
||||
mdb->stats->collect = TRUE;
|
||||
}
|
||||
void
|
||||
mdb_stats_off(MdbHandle *mdb)
|
||||
{
|
||||
if (!mdb->stats) return;
|
||||
|
||||
mdb->stats->collect = FALSE;
|
||||
}
|
||||
void
|
||||
mdb_dump_stats(MdbHandle *mdb)
|
||||
{
|
||||
if (!mdb->stats) return;
|
||||
|
||||
fprintf(stdout, "Physical Page Reads: %lu\n", mdb->stats->pg_reads);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
bin_PROGRAMS = mdb-export mdb-array mdb-schema mdb-tables mdb-parsecsv mdb-header mdb-sql mdb-ver prtable prcat prdata prkkd prdump prole updrow
|
||||
bin_PROGRAMS = mdb-export mdb-array mdb-schema mdb-tables mdb-parsecsv mdb-header mdb-sql mdb-ver prtable prcat prdata prkkd prdump prole updrow prindex
|
||||
LIBS = $(GLIB_LIBS) $(READLINE_LIBS) @LEXLIB@
|
||||
INCLUDES = -I$(top_srcdir)/include $(GLIB_CFLAGS)
|
||||
LDADD = ../libmdb/libmdb.la
|
||||
|
@ -24,8 +24,16 @@
|
||||
#include <string.h>
|
||||
#include "mdbsql.h"
|
||||
|
||||
void dump_results(MdbSQL *sql);
|
||||
void dump_results_pp(MdbSQL *sql);
|
||||
|
||||
#if SQL
|
||||
|
||||
int headers = 1;
|
||||
int footers = 1;
|
||||
int pretty_print = 1;
|
||||
char *delimiter;
|
||||
|
||||
#ifndef HAVE_READLINE
|
||||
char *readline(char *prompt)
|
||||
{
|
||||
@ -65,6 +73,166 @@ int parse(MdbSQL *sql, char *buf)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
do_set_cmd(MdbSQL *sql, char *s)
|
||||
{
|
||||
char *level1, *level2;
|
||||
level1 = strtok(s, " \t\n");
|
||||
if (!strcmp(level1,"stats")) {
|
||||
level2 = strtok(NULL, " \t");
|
||||
if (!strcmp(level2,"on")) {
|
||||
mdb_stats_on(sql->mdb);
|
||||
} else if (!strcmp(level2,"off")) {
|
||||
mdb_stats_off(sql->mdb);
|
||||
mdb_dump_stats(sql->mdb);
|
||||
} else {
|
||||
printf("Unknown stats option %s\n", level2);
|
||||
}
|
||||
} else {
|
||||
printf("Unknown set command %s\n", level1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run_query(MdbSQL *sql, char *mybuf)
|
||||
{
|
||||
if (!parse(sql, mybuf) && sql->cur_table) {
|
||||
mdbsql_bind_all(sql);
|
||||
if (pretty_print)
|
||||
dump_results_pp(sql);
|
||||
else
|
||||
dump_results(sql);
|
||||
}
|
||||
}
|
||||
|
||||
void print_value(char *v, int sz, int first)
|
||||
{
|
||||
int i;
|
||||
int vlen;
|
||||
|
||||
if (first) {
|
||||
fprintf(stdout,"|");
|
||||
}
|
||||
vlen = strlen(v);
|
||||
for (i=0;i<sz;i++) {
|
||||
fprintf(stdout,"%c",i >= vlen ? ' ' : v[i]);
|
||||
}
|
||||
fprintf(stdout,"|");
|
||||
}
|
||||
static void print_break(int sz, int first)
|
||||
{
|
||||
int i;
|
||||
if (first) {
|
||||
fprintf(stdout,"+");
|
||||
}
|
||||
for (i=0;i<sz;i++) {
|
||||
fprintf(stdout,"-");
|
||||
}
|
||||
fprintf(stdout,"+");
|
||||
}
|
||||
void
|
||||
dump_results(MdbSQL *sql)
|
||||
{
|
||||
int j;
|
||||
MdbSQLColumn *sqlcol;
|
||||
unsigned long row_count = 0;
|
||||
|
||||
if (headers) {
|
||||
for (j=0;j<sql->num_columns-1;j++) {
|
||||
sqlcol = g_ptr_array_index(sql->columns,j);
|
||||
fprintf(stdout, "%s%s", sqlcol->name, delimiter);
|
||||
}
|
||||
sqlcol = g_ptr_array_index(sql->columns,sql->num_columns-1);
|
||||
fprintf(stdout, "%s", sqlcol->name);
|
||||
fprintf(stdout,"\n");
|
||||
}
|
||||
while(mdb_fetch_row(sql->cur_table)) {
|
||||
row_count++;
|
||||
for (j=0;j<sql->num_columns-1;j++) {
|
||||
sqlcol = g_ptr_array_index(sql->columns,j);
|
||||
fprintf(stdout, "%s%s", sql->bound_values[j], delimiter);
|
||||
}
|
||||
sqlcol = g_ptr_array_index(sql->columns,sql->num_columns-1);
|
||||
fprintf(stdout, "%s", sql->bound_values[sql->num_columns-1]);
|
||||
fprintf(stdout,"\n");
|
||||
}
|
||||
if (footers) {
|
||||
if (!row_count)
|
||||
fprintf(stdout, "No Rows retrieved\n");
|
||||
else if (row_count==1)
|
||||
fprintf(stdout, "1 Row retrieved\n");
|
||||
else
|
||||
fprintf(stdout, "%d Rows retrieved\n", row_count);
|
||||
}
|
||||
mdb_sql_reset(sql);
|
||||
}
|
||||
|
||||
void
|
||||
dump_results_pp(MdbSQL *sql)
|
||||
{
|
||||
int j;
|
||||
MdbSQLColumn *sqlcol;
|
||||
unsigned long row_count = 0;
|
||||
|
||||
/* print header */
|
||||
if (headers) {
|
||||
for (j=0;j<sql->num_columns;j++) {
|
||||
sqlcol = g_ptr_array_index(sql->columns,j);
|
||||
print_break(sqlcol->disp_size, !j);
|
||||
}
|
||||
fprintf(stdout,"\n");
|
||||
for (j=0;j<sql->num_columns;j++) {
|
||||
sqlcol = g_ptr_array_index(sql->columns,j);
|
||||
print_value(sqlcol->name,sqlcol->disp_size,!j);
|
||||
}
|
||||
fprintf(stdout,"\n");
|
||||
}
|
||||
|
||||
for (j=0;j<sql->num_columns;j++) {
|
||||
sqlcol = g_ptr_array_index(sql->columns,j);
|
||||
print_break(sqlcol->disp_size, !j);
|
||||
}
|
||||
fprintf(stdout,"\n");
|
||||
|
||||
/* print each row */
|
||||
while(mdb_fetch_row(sql->cur_table)) {
|
||||
row_count++;
|
||||
for (j=0;j<sql->num_columns;j++) {
|
||||
sqlcol = g_ptr_array_index(sql->columns,j);
|
||||
print_value(sql->bound_values[j],sqlcol->disp_size,!j);
|
||||
}
|
||||
fprintf(stdout,"\n");
|
||||
}
|
||||
|
||||
/* footer */
|
||||
for (j=0;j<sql->num_columns;j++) {
|
||||
sqlcol = g_ptr_array_index(sql->columns,j);
|
||||
print_break(sqlcol->disp_size, !j);
|
||||
}
|
||||
fprintf(stdout,"\n");
|
||||
if (footers) {
|
||||
if (!row_count)
|
||||
fprintf(stdout, "No Rows retrieved\n");
|
||||
else if (row_count==1)
|
||||
fprintf(stdout, "1 Row retrieved\n");
|
||||
else
|
||||
fprintf(stdout, "%d Rows retrieved\n", row_count);
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
for (j=0;j<sql->num_columns;j++) {
|
||||
if (sql->bound_values[j]) free(sql->bound_values[j]);
|
||||
}
|
||||
|
||||
/* the column and table names are no good now */
|
||||
mdb_sql_reset(sql);
|
||||
}
|
||||
|
||||
void myexit(int r)
|
||||
{
|
||||
free(delimiter);
|
||||
exit(r);
|
||||
}
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *s;
|
||||
@ -74,11 +242,54 @@ char *mybuf;
|
||||
int bufsz = 4096;
|
||||
int done = 0;
|
||||
MdbSQL *sql;
|
||||
int opt;
|
||||
FILE *in = NULL, *out = NULL;
|
||||
|
||||
|
||||
if (!isatty(fileno(stdin))) {
|
||||
in = stdin;
|
||||
}
|
||||
while ((opt=getopt(argc, argv, "hfpd:i:o:"))!=-1) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
delimiter = malloc(strlen(optarg)+1);
|
||||
strcpy(delimiter, optarg);
|
||||
break;
|
||||
case 'p':
|
||||
pretty_print=0;
|
||||
break;
|
||||
case 'H':
|
||||
headers=0;
|
||||
break;
|
||||
case 'F':
|
||||
footers=0;
|
||||
break;
|
||||
case 'i':
|
||||
if (!strcmp(optarg, "stdin"))
|
||||
in = stdin;
|
||||
else if (!(in = fopen(optarg, "r"))) {
|
||||
fprintf(stderr,"Unable to open file %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if (!(out = fopen(optarg, "w"))) {
|
||||
fprintf(stderr,"Unable to open file %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stdout,"Unknown option.\nUsage: %s [-HFp] [-d <delimiter>] [-i <file>] [-o <file>] [<database>]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (!delimiter) {
|
||||
delimiter = strdup("\t");
|
||||
}
|
||||
/* initialize the SQL engine */
|
||||
sql = mdb_sql_init();
|
||||
if (argc>1) {
|
||||
mdb_sql_open(sql, argv[1]);
|
||||
if (argc>optind) {
|
||||
mdb_sql_open(sql, argv[optind]);
|
||||
}
|
||||
|
||||
/* give the buffer an initial size */
|
||||
@ -86,15 +297,20 @@ MdbSQL *sql;
|
||||
mybuf = (char *) malloc(bufsz);
|
||||
mybuf[0]='\0';
|
||||
|
||||
sprintf(prompt,"1 => ");
|
||||
s=readline(prompt);
|
||||
if (in) {
|
||||
s=malloc(256);
|
||||
if (!fgets(s, 256, in)) myexit(0);
|
||||
} else {
|
||||
sprintf(prompt,"1 => ");
|
||||
s=readline(prompt);
|
||||
}
|
||||
while (!done) {
|
||||
if (!strcmp(s,"go")) {
|
||||
if (line==1 && !strncmp(s,"set ", 4)) {
|
||||
do_set_cmd(sql, &s[4]);
|
||||
line = 0;
|
||||
if (!parse(sql, mybuf) && sql->cur_table) {
|
||||
mdbsql_bind_all(sql);
|
||||
mdbsql_dump_results(sql);
|
||||
}
|
||||
} else if (!strcmp(s,"go")) {
|
||||
line = 0;
|
||||
run_query(sql, mybuf);
|
||||
mybuf[0]='\0';
|
||||
} else if (!strcmp(s,"reset")) {
|
||||
line = 0;
|
||||
@ -109,16 +325,27 @@ MdbSQL *sql;
|
||||
/* preserve line numbering for the parser */
|
||||
strcat(mybuf,"\n");
|
||||
}
|
||||
sprintf(prompt,"%d => ",++line);
|
||||
free(s);
|
||||
s=readline(prompt);
|
||||
if (in) {
|
||||
s=malloc(256);
|
||||
if (!fgets(s, 256, in)) {
|
||||
/* if we have something in the buffer, run it */
|
||||
if (strlen(mybuf))
|
||||
run_query(sql, mybuf);
|
||||
myexit(0);
|
||||
}
|
||||
if (s[strlen(s)-1]=='\n') s[strlen(s)-1]=0;
|
||||
} else {
|
||||
sprintf(prompt,"%d => ",++line);
|
||||
s=readline(prompt);
|
||||
}
|
||||
if (!strcmp(s,"exit") || !strcmp(s,"quit") || !strcmp(s,"bye")) {
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
mdb_sql_exit(sql);
|
||||
|
||||
exit(0);
|
||||
myexit(0);
|
||||
}
|
||||
#else
|
||||
int main(int argc, char **argv)
|
||||
|
@ -74,7 +74,7 @@ char *sargname = NULL;
|
||||
void dump_ole(MdbTableDef *table, char *colname, char *sargname)
|
||||
{
|
||||
int i, found = 0;
|
||||
char ole_data[12000];
|
||||
char ole_data[200000];
|
||||
int len;
|
||||
MdbColumn *col;
|
||||
MdbSarg sarg;
|
||||
|
Loading…
Reference in New Issue
Block a user