Initial import.

This commit is contained in:
Gregory Burd 2007-03-10 20:04:07 +01:00
commit a04d39bc52
297 changed files with 138798 additions and 0 deletions

339
LICENSE Normal file
View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 of the License, 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

109
LICENSE_EXCEPTIONS Normal file
View file

@ -0,0 +1,109 @@
FLOSS License Exception v1.0
The DBSQL Exception for Free/Libre and Open Source Software-only Applications
Using DBSQL Libraries (the "FLOSS Exception").
Version 1.0, 4 February 2007
Exception Intent
We want specified Free/Libre and Open Source Software ("FLOSS") applications
to be able to use specified GPL-licensed MySQL client libraries (the "Program")
despite the fact that not all FLOSS licenses are compatible with version 2 of
the GNU General Public License (the "GPL").
Legal Terms and Conditions
As a special exception to the terms and conditions of version 2.0 or later of
the GPL:
You are free to distribute a Derivative Work that is formed entirely from the
Program and one or more works (each, a "FLOSS Work") licensed under one or
more of the licenses listed below in section 1, as long as:
1. You obey the GPL in all respects for the Program and the Derivative
Work, except for identifiable sections of the Derivative Work which
are not derived from the Program, and which can reasonably be considered
independent and separate works in themselves,
2. all identifiable sections of the Derivative Work which are not derived
from the Program, and which can reasonably be considered independent and
separate works in themselves,
1. are distributed subject to one of the FLOSS licenses listed below,
and
2. the object code or executable form of those sections are
accompanied by the complete corresponding machine-readable source
code for those sections on the same medium and under the same
FLOSS license as the corresponding object code or executable forms
of those sections, and
3. any works which are aggregated with the Program or with a
Derivative Work on a volume of a storage or distribution medium in
accordance with the GPL, can reasonably be considered independent
and separate works in themselves which are not derivatives of
either the Program, a Derivative Work or a FLOSS Work.
If the above conditions are not met, then the Program may only be copied,
modified, distributed or used under the terms and conditions of the GPL or
another valid licensing option from The DBSQL Group, Inc.
1. FLOSS License List
License name Version(s)/Copyright Date
-----------------------------------------------------|-------------------------
Academic Free License | 2.0
Apache Software License | 1.0/1.1/2.0
Apple Public Source License | 2.0
Artistic license | From Perl 5.8.0
BSD license | "July 22 1999"
Common Development and Distribution License (CDDL) | 1.0
Common Public License | 1.0
GNU Library or "Lesser" General Public License (LGPL)| 2.0/2.1
Jabber Open Source License | 1.0
MIT License (As listed in file MIT-License.txt) | -
Mozilla Public License (MPL) | 1.0/1.1
Open Software License | 2.0
OpenSSL license (with original SSLeay license) | "2003" ("1998")
PHP License | 3.0
Python license (CNRI Python License) | -
Python Software Foundation License | 2.1.1
Sleepycat License | "1999"
University of Illinois/NCSA Open Source License | -
W3C License | "2001"
X11 License | "2001"
Zlib/libpng License | -
Zope Public License | 2.0
Due to the many variants of some of the above licenses, we require that any
version follow the 2003 version of the Free Software Foundation's Free
Software Definition (http://www.gnu.org/philosophy/free-sw.html) or version
1.9 of the Open Source Definition by the Open Source Initiative
(http://www.opensource.org/docs/definition.php).
2. Definitions
1. Terms used, but not defined, herein shall have the meaning
provided in the GPL.
2. Derivative Work means a derivative work under copyright law.
3. Applicability
This FLOSS Exception applies to all Programs that contain a notice placed by
The DBSQL Group, Inc. saying that the Program may be distributed under the
terms of this FLOSS Exception. If you create or distribute a work which is a
Derivative Work of both the Program and any other work licensed under the GPL,
then this FLOSS Exception is not available for that work; thus, you must
remove the FLOSS Exception notice from that work and comply with the GPL in
all respects, including by retaining all GPL notices. You may choose to
redistribute a copy of the Program exclusively under the terms of the GPL by
removing the FLOSS Exception notice from that copy of the Program, provided
that the copy has never been modified by you or any third party.
Appendix A. Qualified Libraries and
The following is a a non-exhaustive list of libraries and packages which are
covered by the FLOSS License Exception. Please note that appendix is merely
provided as an additional service to specific FLOSS projects who wish to
simplify licensing information for their users. Compliance with one of the
licenses noted under the "FLOSS license list" section remains a prerequisite.
Package name | Qualifying License | Version
------------------------------|--------------------------|---------------------
Apache Portable Runtime (APR) | Apache Software License | 2.0

46
README Normal file
View file

@ -0,0 +1,46 @@
DBSQL 0.2.2: (March 10, 2007)
This is version 0.2.2 of DBSQL.
To view the release and installation documentation, load the distribution
file docs/index.html into your web browser.
This work started from the SQLite project (found on the web at
http://www.sqlite.org/). SQLite and all contributions to the SQLite
project have been placed in the public domain by its author, Dr. Richard Hipp.
There was no assertion of copyright at all on the code I used as a starting
point for my work. In fact there are statements that explicitly disclaim
copyright. I am asserting copyright on this work, DBSQL. I believe
that if you examine the extent to which I've changed, updated, and
modified the SQLite code you'll respect my copyright assertion. This
is a new product, heavily inspired by another.
The goal for DBSQL is to provide a small SQL92 relational database layer
on top of the Berkeley DB database. Berkeley DB is copyright Oracle
Corporation (formerly Sleepycat Software, acquired in Feb 2006) and
licensed under the Sleepycat Public License. That license is compatible
with the GPL for open source use. Recognize that you, as someone using
DBSQL, will need to review the Sleepycat License and the GPL before you
use and redistribute your incorporating work. It is your responsibility
to comply with those licenses as I am in my work on DBSQL itself. My
motivation on a personal level is quite simple, I am in product management
these days and not in the code itself. I believe that product managers
should be engineers at heart with an ability to understand business,
politics, and software sales and support. This is my playground to keep
my engineering skills sharp enough to speak fluent geek. As a former
engineer at Sleepycat I understand and value the Berkeley DB programming
infrasture, design, and methodologies and I have liberally copied and
reused them in this project to improve SQLite in ways that I hope will
be of value to open source users out there. I did this because I see the
value of SQLite to its userbase, it is a perfect example of the 80/20
rule and the KISS method and I admire those qualities in software. My
hope is that the Berkeley DB database engine will provide some significant
features that SQLite cannot such as replication for high availability
while remaining small enough to live comfortably inside applications,
services, and devices.
Information and resources pertaining to DBSQL can be found at dbsql.org.
Commercial licenses without the restrictions found in the GPL can be
purchased for this product. See http://dbsql.org/wiki/CommercialUse

486
dist/Makefile.in vendored Normal file
View file

@ -0,0 +1,486 @@
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# $Id: Makefile.in 7 2007-02-03 13:34:17Z gburd $
srcdir= @srcdir@/../src
tstdir= @srcdir@/../test
distdir= @srcdir@/../dist
builddir=.
##################################################
# Installation directories and permissions.
##################################################
prefix= @prefix@
exec_prefix= @exec_prefix@
bindir= @bindir@
includedir= @includedir@
libdir= @libdir@
docdir= $(prefix)/docs
dmode= 755
emode= 555
fmode= 444
transform=@program_transform_name@
##################################################
# Paths for standard user-level commands.
##################################################
SHELL= @db_cv_path_sh@
ar= @db_cv_path_ar@
awk= @db_cv_path_awk@
chmod= @db_cv_path_chmod@
cp= @db_cv_path_cp@
depend= @db_cv_path_makedepend@
grep= @db_cv_path_grep@
ln= @db_cv_path_ln@
mkdir= @db_cv_path_mkdir@
ranlib= @db_cv_path_ranlib@
rm= @db_cv_path_rm@
rpm= @db_cv_path_rpm@
sed= @db_cv_path_sed@
perl= @db_cv_path_perl@
splint= @db_cv_path_splint@
strip= @db_cv_path_strip@
##################################################
# General library information.
##################################################
DEF_LIB= @DEFAULT_LIB@
DEF_LIB_CXX= @DEFAULT_LIB_CXX@
INSTALLER= @INSTALLER@
LIBTOOL= @LIBTOOL@
POSTLINK= @POSTLINK@
SOLINK= @MAKEFILE_SOLINK@
SOFLAGS= @SOFLAGS@
LIBMAJOR= @DBSQL_VERSION_MAJOR@
LIBVERSION= @DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@
CPPFLAGS= -I$(builddir) -I$(srcdir) @CPPFLAGS@
##################################################
# Lemon parser generator information.
##################################################
LEMON= ./lemon
LEMON_FLAGS=
##################################################
# C API.
##################################################
CFLAGS= -c $(CPPFLAGS) @CFLAGS@
CC= @MAKEFILE_CC@
CCLINK= @MAKEFILE_CCLINK@
LDFLAGS= @LDFLAGS@
LIBS= @LIBS@
LIBSO_LIBS= @LIBSO_LIBS@
libdbsql_base= libdbsql
libdbsql= $(libdbsql_base).a
libdbsql_version= $(libdbsql_base)-$(LIBVERSION).a
libso= $(libdbsql_base)-$(LIBVERSION)@SOSUFFIX@
libso_target= $(libdbsql_base)-$(LIBVERSION).la
libso_default= $(libdbsql_base)@SOSUFFIX@
libso_major= $(libdbsql_base)-$(LIBMAJOR)@SOSUFFIX@
##################################################
# Python Language Bindings
#
# Python support is optional and requires shared libraries.
##################################################
##################################################
# NOTHING BELOW THIS LINE SHOULD EVER NEED TO BE MODIFIED.
##################################################
##################################################
# Source file lists.
##################################################
C_FILES=\
$(srcdir)/api.c $(srcdir)/api_table.c $(srcdir)/cg_attach.c \
$(srcdir)/cg_auth.c $(srcdir)/cg_build.c $(srcdir)/cg_copy.c \
$(srcdir)/cg_date.c $(srcdir)/cg_delete.c $(srcdir)/cg_expr.c \
$(srcdir)/cg_insert.c $(srcdir)/cg_pragma.c $(srcdir)/cg_select.c \
$(srcdir)/cg_trigger.c $(srcdir)/cg_update.c $(srcdir)/cg_where.c \
$(srcdir)/clib/xvprintf.c $(srcdir)/dbsql/dbsql.c \
$(srcdir)/sm.c $(srcdir)/common/hash.c $(srcdir)/lemon/lemon.c \
$(srcdir)/lemon/lempar.c $(srcdir)/os/os.c $(srcdir)/clib/random.c \
$(srcdir)/sql_fns.c $(srcdir)/sql_tokenize.c \
$(srcdir)/cg_vacuum.c $(srcdir)/vdbe.c $(srcdir)/vdbe_method.c \
$(srcdir)/common/dbsql_err.c $(srcdir)/clib/snprintf.c \
$(srcdir)/os/os_jtime.c $(srcdir)/clib/memcmp.c \
$(srcdir)/clib/strcasecmp.c $(srcdir)/os/dbsql_alloc.c \
$(srcdir)/common/str.c $(srcdir)/common/dbsql_atoi.c \
$(srcdir)/common/dbsql_atof.c $(srcdir)/safety.c \
$(srcdir)/clib/strdup.c
##################################################
# Object and utility lists.
##################################################
C_OBJS= @ADDITIONAL_OBJS@ @REPLACEMENT_OBJS@ \
cg_attach@o@ cg_insert@o@ sql_tokenize@o@ cg_auth@o@ \
cg_copy@o@ api_table@o@ cg_date@o@ api@o@ xvprintf@o@ \
cg_pragma@o@ cg_where@o@ cg_trigger@o@ cg_build@o@ \
sql_fns@o@ random@o@ cg_update@o@ cg_delete@o@ hash@o@ \
cg_expr@o@ opcodes@o@ sql_parser@o@ cg_vacuum@o@ \
vdbe@o@ vdbe_method@o@ sm@o@ snprintf@o@ dbsql_err@o@ cg_select@o@ \
os_jtime@o@ memcmp@o@ dbsql_atof@o@ safety@o@ \
strcasecmp@o@ strdup@o@ dbsql_alloc@o@ str@o@ dbsql_atoi@o@
LEMON_OBJS=\
lemon@o@
UTIL_PROGS=\
@ADDITIONAL_PROGS@ \
dbsql
##################################################
# List of files installed into the library directory.
##################################################
LIB_INSTALL_FILE_LIST=\
$(libdbsql) \
$(libso) \
$(libso_default) \
$(libso_major) \
$(libdbsql_version) \
$(libso_target) \
$(libtso) \
$(libtso_default) \
$(libtso_major) \
$(libtso_static) \
$(libtso_target)
##################################################
# We're building a standard library or a RPM file hierarchy.
# Note: "all" must be the first target in the Makefile.
##################################################
all: @BUILD_TARGET@
install-strip install: all @INSTALL_TARGET@
##################################################
# Library and standard utilities build.
##################################################
library_build: @INSTALL_LIBS@ @ADDITIONAL_LANG@ $(UTIL_PROGS)
# Static C library named libdbsql.a.
$(libdbsql): $(DEF_LIB)
$(rm) -f $@
test ! -f .libs/$(libdbsql_version) || \
$(ln) -s .libs/$(libdbsql_version) $@
test -f .libs/$(libdbsql_version) || \
(test -f $(libdbsql_version) &&
$(ln) -s $(libdbsql_version) $@)
# Real static C library.
$(libdbsql_version): dbsql_int.h sql_parser.h opcodes.h $(C_OBJS)
$(ar) cr $@ $(C_OBJS)
test ! -f $(ranlib) || $(ranlib) $@
# Shared C library.
$(libso_target): dbsql_int.h sql_parser.h opcodes.h $(C_OBJS)
$(SOLINK) $(SOFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) $(LIBSO_LIBS)
##################################################
# Utilities
##################################################
lemon: $(LEMON_OBJS)
$(CCLINK) -o $@ $(LDFLAGS) \
$(LEMON_OBJS) $(LIBS)
$(POSTLINK) $@
$(cp) $(srcdir)/lemon/lempar.c .
dbsql: $(DEF_LIB) dbsql@o@
$(CCLINK) -o $@ $(LDFLAGS) \
dbsql@o@ $(DEF_LIB) $(LIBS)
$(POSTLINK) $@
##################################################
# Testing.
##################################################
test: $(tstdir)/scr050/dbsql_tclsh
$(tstdir)/scr050/dbsql_tclsh $(tstdir)/quick.test
##################################################
# Library and standard utilities install.
##################################################
library_install: install_setup
library_install: install_include install_lib install_utilities install_docs
uninstall: uninstall_include uninstall_lib uninstall_utilities uninstall_docs
install_setup:
@test -d $(DESTDIR)$(prefix) || \
($(mkdir) -p $(DESTDIR)$(prefix) && \
$(chmod) $(dmode) $(DESTDIR)$(prefix))
INCDOT= dbsql.h @ADDITIONAL_INCS@
install_include:
@echo "Installing DBSQL include files: $(DESTDIR)$(includedir) ..."
@test -d $(DESTDIR)$(includedir) || \
($(mkdir) -p $(DESTDIR)$(includedir) && \
$(chmod) $(dmode) $(DESTDIR)$(includedir))
@cd $(DESTDIR)$(includedir) && $(rm) -f $(INCDOT)
@$(cp) -p $(INCDOT) $(DESTDIR)$(includedir)
@cd $(DESTDIR)$(includedir) && $(chmod) $(fmode) $(INCDOT)
uninstall_include:
@cd $(DESTDIR)$(includedir) && $(rm) -f $(INCDOT)
install_lib:
@echo "Installing DBSQL library: $(DESTDIR)$(libdir) ..."
@test -d $(DESTDIR)$(libdir) || \
($(mkdir) -p $(DESTDIR)$(libdir) && \
$(chmod) $(dmode) $(DESTDIR)$(libdir))
@cd $(DESTDIR)$(libdir) && $(rm) -f $(LIB_INSTALL_FILE_LIST)
@$(INSTALLER) @INSTALL_LIBS@ $(DESTDIR)$(libdir)
@(cd $(DESTDIR)$(libdir) && \
test -f $(libso) && $(ln) -s $(libso) $(libso_default); \
test -f $(libso) && $(ln) -s $(libso) $(libso_major); \
test -f $(libtso) && $(ln) -s $(libtso) $(libtso_default); \
test -f $(libtso) && $(ln) -s $(libtso) $(libtso_major);
uninstall_lib:
@cd $(DESTDIR)$(libdir) && $(rm) -f $(LIB_INSTALL_FILE_LIST)
install_utilities:
@echo "Installing DBSQL utilities: $(DESTDIR)$(bindir) ..."
@test -d $(DESTDIR)$(bindir) || \
($(mkdir) -p $(DESTDIR)$(bindir) && \
$(chmod) $(dmode) $(DESTDIR)$(bindir))
@for i in $(UTIL_PROGS); do \
$(rm) -f $(DESTDIR)$(bindir)/$$i $(DESTDIR)$(bindir)/$$i.exe; \
test -f $$i.exe && i=$$i.exe || true; \
$(INSTALLER) $$i $(DESTDIR)$(bindir)/$$i; \
test -f $(strip) && $(strip) $(DESTDIR)$(bindir)/$$i || true; \
$(chmod) $(emode) $(DESTDIR)$(bindir)/$$i; \
done
uninstall_utilities:
@(cd $(DESTDIR)$(bindir); for i in $(UTIL_PROGS); do \
$(rm) -f $$i $$i.exe; \
done)
##################################################
# RPM, build and install.
##################################################
rpm_build:
@test -f @db_cv_path_rpm_archive@ || \
(echo "@db_cv_path_rpm_archive@: archive file not found" && false)
@$(rm) -rf BUILD RPMS SOURCES SPECS SRPMS RPM_INSTALL
@$(mkdir) -p BUILD && $(chmod) $(dmode) BUILD
@$(mkdir) -p RPMS/i386 && $(chmod) $(dmode) RPMS RPMS/i386
@$(mkdir) -p SOURCES && $(chmod) $(dmode) SOURCES
@$(mkdir) -p SPECS && $(chmod) $(dmode) SPECS
@$(mkdir) -p SRPMS && $(chmod) $(dmode) SRPMS
$(cp) @db_cv_path_rpm_archive@ SOURCES/
$(cp) dbsql.spec SPECS/dbsql.spec
@RPM_BUILD@ --define="`cat rpm-macro-defines`" -ba SPECS/dbsql.spec
rpm_install:
RPM_SRPMS=dbsql-@DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@.@DBSQL_VERSION_PATCH@-1.src.rpm
##################################################
# Remaining standard Makefile targets.
##################################################
CLEAN_LIST=\
lemon
mostly-clean clean:
$(rm) -rf $(C_OBJS)
$(rm) -rf $(UTIL_PROGS) *.exe $(CLEAN_LIST)
$(rm) -rf $(JAVA_CLASSTOP) $(JAVA_EXCLASSTOP)
$(rm) -rf tags *@o@ *~ *.o *.o.lock *.lo core *.core *.loT
$(rm) -rf .libs $(LIB_INSTALL_FILE_LIST)
$(rm) -rf sql_parser.c sql_parser.h sql_parser.out
$(rm) -rf opcodes.c opcodes.h
$(rm) -rf lempar.c
$(rm) -rf test.db test?.db test.db-journal test1.bt data?.txt
$(rm) -f log.*
REALCLEAN_LIST=\
Makefile config.cache config.log config.status \
configure.lineno dbsql.h dbsql.spec dbsql_config.h \
db_int.h dbsql_int.h db_int_def.h rpm-macro-defines win_dbsql.h
distclean maintainer-clean realclean: clean
$(rm) -rf $(REALCLEAN_LIST)
$(rm) -rf libtool
check dvi info obj TAGS:
@echo "$@: make target not supported" && true
dist:
@echo "$@: make target not supported" && false
##################################################
# TODO Example programs for C.
##################################################
##################################################
# Opcodes are generated from the vdbe.[ch] files.
##################################################
opcodes.c: $(srcdir)/vdbe.c
@echo '/* Automatically generated file. Do not edit */' >opcodes.c
@echo 'char *__opcode_names[] = { "???", ' >>opcodes.c
@$(grep) '^case OP_' $(srcdir)/vdbe.c | \
$(sed) -e 's/^.*OP_/ "/' -e 's/:.*$$/", /' >>opcodes.c
@echo '};' >>opcodes.c
opcodes.h: $(srcdir)/vdbe.c
@echo '/* Automatically generated file. Do not edit */' >opcodes.h
@$(grep) '^case OP_' $(srcdir)/vdbe.c | \
$(sed) -e 's/://' | \
$(awk) '{printf "#define %-30s %3d\n", $$2, ++cnt}' >>opcodes.h
##################################################
# C API build rules.
##################################################
api@o@: $(srcdir)/api.c
$(CC) $(CFLAGS) $?
api_table@o@: $(srcdir)/api_table.c
$(CC) $(CFLAGS) $?
cg_attach@o@: $(srcdir)/cg_attach.c
$(CC) $(CFLAGS) $?
cg_auth@o@: $(srcdir)/cg_auth.c
$(CC) $(CFLAGS) $?
cg_build@o@: $(srcdir)/cg_build.c
$(CC) $(CFLAGS) $?
cg_copy@o@: $(srcdir)/cg_copy.c
$(CC) $(CFLAGS) $?
cg_date@o@: $(srcdir)/cg_date.c
$(CC) $(CFLAGS) $?
cg_delete@o@: $(srcdir)/cg_delete.c
$(CC) $(CFLAGS) $?
cg_expr@o@: $(srcdir)/cg_expr.c
$(CC) $(CFLAGS) $?
cg_insert@o@: $(srcdir)/cg_insert.c
$(CC) $(CFLAGS) $?
cg_pragma@o@: $(srcdir)/cg_pragma.c
$(CC) $(CFLAGS) $?
cg_select@o@: $(srcdir)/cg_select.c
$(CC) $(CFLAGS) $?
cg_trigger@o@: $(srcdir)/cg_trigger.c
$(CC) $(CFLAGS) $?
cg_update@o@: $(srcdir)/cg_update.c
$(CC) $(CFLAGS) $?
cg_where@o@: $(srcdir)/cg_where.c
$(CC) $(CFLAGS) $?
cg_vacuum@o@: $(srcdir)/cg_vacuum.c
$(CC) $(CFLAGS) $?
db_int.h: $(srcdir)/inc/db_int.h
@$(sed) -e 's/__DB_UNIQUE_NAME__/@DB_UNIQUE_NAME@/g' \
$(srcdir)/inc/db_int.h > db_int.h
dbsql_atof@o@: $(srcdir)/common/dbsql_atof.c
$(CC) $(CFLAGS) $?
dbsql_atoi@o@: $(srcdir)/common/dbsql_atoi.c
$(CC) $(CFLAGS) $?
dbsql_err@o@: $(srcdir)/common/dbsql_err.c
$(CC) $(CFLAGS) $?
str@o@: $(srcdir)/common/str.c
$(CC) $(CFLAGS) $?
hash@o@: $(srcdir)/common/hash.c
$(CC) $(CFLAGS) $?
opcodes.c: opcodes.h
opcodes@o@: opcodes.c
$(CC) $(CFLAGS) $?
dbsql_alloc@o@: $(srcdir)/common/dbsql_alloc.c
$(CC) $(CFLAGS) $?
os_jtime@o@: $(srcdir)/os/os_jtime.c
$(CC) $(CFLAGS) $?
lemon@o@: $(srcdir)/lemon/lemon.c
$(CC) $(CFLAGS) $?
memcmp@o@: $(srcdir)/clib/memcmp.c
$(CC) $(CFLAGS) $?
xvprintf@o@: $(srcdir)/clib/xvprintf.c
$(CC) $(CFLAGS) $?
random@o@: $(srcdir)/clib/random.c
$(CC) $(CFLAGS) $?
safety@o@: $(srcdir)/safety.c
$(CC) $(CFLAGS) $?
sm@o@: $(srcdir)/sm.c
$(CC) $(CFLAGS) $?
snprintf@o@: $(srcdir)/clib/snprintf.c
$(CC) $(CFLAGS) $?
sql_fns@o@: $(srcdir)/sql_fns.c
$(CC) $(CFLAGS) $?
sql_parser.c: $(srcdir)/sql_parser.y lemon
@$(cp) $(srcdir)/sql_parser.y .
@$(LEMON) $(LEMON_FLAGS) sql_parser.y
@$(cp) ./sql_parser.c ./_sql_parser.c
@$(sed) -e 's/dbsql_parserAlloc/__sql_parser_alloc/g' \
-e 's/dbsql_parserFree/__sql_parser_free/g' \
-e 's/dbsql_parserTrace/__sql_parser_trace/g' \
-e 's/dbsql_parser(/__sql_parser(/g' \
-e 's/__set_stringn/__str_nappend/g' \
-e 's/__set_string/__str_append/g' \
./_sql_parser.c > ./sql_parser.c
@$(rm) -f ./_sql_parser.c
@$(rm) -f ./sql_parser.y
sql_parser.h: sql_parser.c
sql_parser@o@: sql_parser.c
$(CC) $(CFLAGS) $?
sql_tokenize@o@: $(srcdir)/sql_tokenize.c
$(CC) $(CFLAGS) $?
strcasecmp@o@: $(srcdir)/clib/strcasecmp.c
$(CC) $(CFLAGS) $?
strdup@o@: $(srcdir)/clib/strdup.c
$(CC) $(CFLAGS) $?
vdbe@o@: $(srcdir)/vdbe.c
$(CC) $(CFLAGS) $?
vdbe_method@o@: $(srcdir)/vdbe_method.c
$(CC) $(CFLAGS) $?
dbsql.h: $(srcdir)/dbsql.in
@echo dbsql.h is out of date, re-configure to regenerate it.
##################################################
# Utility build rules.
##################################################
dbsql@o@: $(srcdir)/dbsql/dbsql.c
$(CC) $(CFLAGS) $?
##################################################
# Lint.
##################################################
splint:
$(splint) -nof -f $(distdir)/splint.rc -strict \
$(CPPFLAGS) @CFLAGS@ -I. $(C_FILES)
lint: splint
##################################################
# Dependencies
##################################################
#depend:
# @$(depend) -o @o@ $(CPPFLAGS) @CFLAGS@ $(C_FILES)
# @$(perl) -p -i -e 's#^@srcdir@/../src/common/##g' Makefile
# @$(perl) -p -i -e 's#^@srcdir@/../src/os/##g' Makefile
# @$(perl) -p -i -e 's#^@srcdir@/../src/clib/##g' Makefile
# @$(perl) -p -i -e 's#^@srcdir@/../src/lemon/##g' Makefile
# @$(perl) -p -i -e 's#^@srcdir@/../src/##g' Makefile
# DO NOT DELETE THIS LINE -- make depend depends on it.

31
dist/RELEASE vendored Normal file
View file

@ -0,0 +1,31 @@
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# $Id: RELEASE 7 2007-02-03 13:34:17Z gburd $
DBSQL_VERSION_MAJOR=0
DBSQL_VERSION_MINOR=2
DBSQL_VERSION_PATCH=2
DBSQL_VERSION="$DBSQL_VERSION_MAJOR.$DBSQL_VERSION_MINOR.$DBSQL_VERSION_PATCH"
DBSQL_VERSION_UNIQUE_NAME=`printf "_%d%03d" $DBSQL_VERSION_MAJOR $DBSQL_VERSION_MINOR`
DBSQL_RELEASE_DATE=`date "+%B %e, %Y"`
DBSQL_VERSION_STRING="DBSQL $DBSQL_VERSION: ($DBSQL_RELEASE_DATE)"

26
dist/aclocal/config.ac vendored Normal file
View file

@ -0,0 +1,26 @@
# Features we don't test for, but want the #defines to exist for
# other ports.
AH_TEMPLATE(DBSQL_WIN32,
[We use DBSQL_WIN32 much as one would use _WIN32 -- to specify that
we're using an operating system environment that supports Win32
calls and semantics. We don't use _WIN32 because Cygwin/GCC also
defines _WIN32, even though Cygwin/GCC closely emulates the Unix
environment.])
AH_TEMPLATE(HAVE_FILESYSTEM_NOTZERO,
[Define to 1 if allocated filesystem blocks are not zeroed.])
AH_TEMPLATE(HAVE_UNLINK_WITH_OPEN_FAILURE,
[Define to 1 if unlink of file with open file descriptors will fail.])
AH_BOTTOM([/*
* Exit success/failure macros.
*/
#ifndef HAVE_EXIT_SUCCESS
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
#endif
#ifdef DBSQL_WIN32
#include "win_dbsql.h"
#endif])

17
dist/aclocal/cxx.ac vendored Normal file
View file

@ -0,0 +1,17 @@
# C++ checks to determine what style of headers to use and
# whether to use "using" clauses.
AC_DEFUN(AC_CXX_HAVE_STDHEADERS, [
AC_SUBST(cxx_have_stdheaders)
AC_CACHE_CHECK([whether C++ supports the ISO C++ standard includes],
db_cv_cxx_have_stdheaders,
[AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_COMPILE([#include <iostream>
],[std::ostream *o; return 0;],
db_cv_cxx_have_stdheaders=yes, db_cv_cxx_have_stdheaders=no)
AC_LANG_RESTORE
])
if test "$db_cv_cxx_have_stdheaders" = yes; then
cxx_have_stdheaders="#define HAVE_CXX_STDHEADERS 1"
fi])

36
dist/aclocal/gcc.ac vendored Normal file
View file

@ -0,0 +1,36 @@
# Version 2.96 of gcc (shipped with RedHat Linux 7.[01] and Mandrake) had
# serious problems.
AC_DEFUN(AC_GCC_CONFIG1, [
AC_CACHE_CHECK([whether we are using gcc version 2.96],
db_cv_gcc_2_96, [
db_cv_gcc_2_96=no
if test "$GCC" = "yes"; then
GCC_VERSION=`${MAKEFILE_CC} --version`
case ${GCC_VERSION} in
2.96*)
db_cv_gcc_2_96=yes;;
esac
fi])
if test "$db_cv_gcc_2_96" = "yes"; then
CFLAGS=`echo "$CFLAGS" | sed 's/-O2/-O/'`
CXXFLAGS=`echo "$CXXFLAGS" | sed 's/-O2/-O/'`
AC_MSG_WARN([INSTALLED GCC COMPILER HAS SERIOUS BUGS; PLEASE UPGRADE.])
AC_MSG_WARN([GCC OPTIMIZATION LEVEL SET TO -O.])
fi])
# Versions of g++ up to 2.8.0 required -fhandle-exceptions, but it is
# renamed as -fexceptions and is the default in versions 2.8.0 and after.
AC_DEFUN(AC_GCC_CONFIG2, [
AC_CACHE_CHECK([whether g++ requires -fhandle-exceptions],
db_cv_gxx_except, [
db_cv_gxx_except=no;
if test "$GXX" = "yes"; then
GXX_VERSION=`${MAKEFILE_CXX} --version`
case ${GXX_VERSION} in
1.*|2.[[01234567]].*|*-1.*|*-2.[[01234567]].*)
db_cv_gxx_except=yes;;
esac
fi])
if test "$db_cv_gxx_except" = "yes"; then
CXXFLAGS="$CXXFLAGS -fhandle-exceptions"
fi])

5867
dist/aclocal/libtool.ac vendored Normal file

File diff suppressed because it is too large Load diff

255
dist/aclocal/options.ac vendored Normal file
View file

@ -0,0 +1,255 @@
# $Id: options.ac 7 2007-02-03 13:34:17Z gburd $
# Process user-specified options.
AC_DEFUN(AM_OPTIONS_SET, [
AC_MSG_CHECKING(if --enable-utf8-encoding option specified)
AC_ARG_ENABLE(utf8-encoding,
AC_HELP_STRING([--enable-utf8-encoding],
[Encode strings as UTF-8 or ISO-8859.]),, enableval="yes")
db_cv_utf8_strings="$enableval"
case "$enableval" in
no) AC_MSG_RESULT(yes);;
yes) AC_MSG_RESULT(no);;
esac
if test "$cv_utf8_strings" = "yes"; then
ENCODING=UTF8
AC_DEFINE(DBSQL_UTF8_ENCODING)
else
ENCODING=ISO8859
AC_DEFINE(DBSQL_ISO8859_ENCODING)
fi
AH_TEMPLATE(DBSQL_ISO8859_ENCODING,
[Define to use ISO8859 string encoding.])
AH_TEMPLATE(DBSQL_UTF8_ENCODING,
[Define use UTF8 string encoding.])
AC_MSG_CHECKING(if --enable-incore-databases option specified)
AC_ARG_ENABLE(incore-databases,
AC_HELP_STRING([--enable-incore-databases],
[Enable incore databases for ATTACH and OPEN.]),, enableval="yes")
db_cv_incore_databases="$enableval"
case "$enableval" in
no) AC_MSG_RESULT(yes);;
yes) AC_MSG_RESULT(no);;
esac
if test "$db_cv_incore_databases" = "no"; then
INMEMORYDB=0
else
INMEMORYDB=1
fi
AC_DEFINE(INMEMORYDB)
AH_TEMPLATE(INMEMORYDB,
[Define to 1 to enable incore databases for ATTACH and OPEN.])
AC_MSG_CHECKING(if --enable-authentication option specified)
AC_ARG_ENABLE(authentication,
AC_HELP_STRING([--enable-authentication],
[Include authorization validation code.]),, enableval="yes")
db_cv_auth="$enableval"
case "$enableval" in
no) AC_MSG_RESULT(no);;
yes) AC_MSG_RESULT(yes);;
esac
if test "$db_cv_auth" = "no"; then
AC_DEFINE(DBSQL_OMIT_AUTHORIZATION)
fi
AH_TEMPLATE(DBSQL_OMIT_AUTHORIZATION,
[Define to 1 to omit authorization code from the build.])
AC_MSG_CHECKING(if --enable-vacuum option specified)
AC_ARG_ENABLE(vacuum,
AC_HELP_STRING([--enable-vacuum],
[Include the VACUUM command.]),, enableval="yes")
db_cv_auth="$enableval"
case "$enableval" in
no) AC_MSG_RESULT(no);;
yes) AC_MSG_RESULT(yes);;
esac
if test "$db_cv_auth" = "no"; then
AC_DEFINE(DBSQL_OMIT_VACUUM)
fi
AH_TEMPLATE(DBSQL_OMIT_VACUUM,
[Define to 1 to omit the code for the VACCUM command from the build.])
AC_MSG_CHECKING(if --enable-datetime option specified)
AC_ARG_ENABLE(enable-datetime,
AC_HELP_STRING([--enable-datetime],
[Include datetime functions.]),, enableval="yes")
db_cv_datetime="$enableval"
case "$enableval" in
no) AC_MSG_RESULT(no);;
yes) AC_MSG_RESULT(yes);;
esac
if test "$db_cv_datetime" = "no"; then
AC_DEFINE(DBSQL_OMIT_DATETIME_FUNCS)
fi
AH_TEMPLATE(DBSQL_OMIT_DATETIME_FUNCS,
[Define to 1 to omit support for datetime functions from the build.])
AC_MSG_CHECKING([if --with-berkeleydb=DIR option specified])
AC_ARG_WITH(berkeleydb,
[AC_HELP_STRING([--with-berkeleydb=DIR],
[Path of Berkeley DB. [DIR="/usr/local/BerkeleyDB.4.5"]])],
[with_berkeleydb="$withval"], [with_berkeleydb="no"])
AC_MSG_RESULT($with_berkeleydb)
# If --with-berkeleydb isn't specified, assume it's here | wc -l` -gt 0
if test "$with_berkeleydb" = "no"; then
with_berkeleydb="/usr/local/BerkeleyDB.4.5"
fi
DB_PATH="$with_berkeleydb"
if test `ls "$with_berkeleydb"/lib/libdb-*.la 2>/dev/null | wc -l` -gt 0 ; then
AC_MSG_CHECKING([for Berkeley DB version from install tree])
db_version=`ls "$with_berkeleydb"/lib/libdb-*.la | sed 's/.*db-\(.*\).la/\1/'`
AC_MSG_RESULT([$db_version])
echo "$CPPFLAGS" | grep "$with_berkeleydb/include" >/dev/null 2>&1 || CPPFLAGS="$CPPFLAGS -I$with_berkeleydb/include"
if test `ls "$with_berkeleydb"/lib/libdb-$db_version.* 2>/dev/null | wc -l` -gt 0 ; then
LIBSO_LIBS="$LIBS -L$with_berkeleydb/lib -ldb-$db_version"
else
LIBS="$LIBS -l$with_berkeleydb/lib/libdb-$db_version.a"
fi
elif test `ls /usr/local/lib/db?? 2>/dev/null | wc -l` -gt 0 ; then
AC_MSG_CHECKING([if Berkeley DB was installed using BSD ports])
db_num=`ls /usr/local/lib | grep db | grep -v lib | sed -e 's/db//' | sort -n | head -1`
db_version=`echo $db_num | sed 's/\(.\)\(.\)/\1.\2/'`
AC_MSG_RESULT([yes, $db_version])
echo "$CPPFLAGS" | grep /usr/local/include/db$db_num >/dev/null 2>&1 || CPPFLAGS="$CPPFLAGS -I/usr/local/include/db$db_num"
if test `ls /usr/local/lib/libdb-$db_version.* 2>/dev/null | wc -l` -gt 0 ; then
LIBSO_LIBS="$LIBS -L/usr/local/lib -ldb-$db_version"
else
LIBS="$LIBS -l/usr/local/lib/libdb-$db_version.a"
fi
else
AC_MSG_ERROR([$with_berkeleydb not a valid Berkeley DB install tree.])
fi
AC_MSG_CHECKING([if --with-db-uniquename=NAME option specified])
AC_ARG_WITH(db-uniquename,
[AC_HELP_STRING([--with-db-uniquename=NAME],
[Unique name used when building DB library.])],
[with_db_uniquename="$withval"], [with_db_uniquename="no"])
if test "$with_db_uniquename" = "no"; then
db_cv_uniquename="no"
DB_UNIQUE_NAME=""
AC_MSG_RESULT($with_db_uniquename)
else
db_cv_uniquename="yes"
if test "$with_db_uniquename" = "yes"; then
DB_UNIQUE_NAME="__EDIT_DB_VERSION_UNIQUE_NAME__"
else
DB_UNIQUE_NAME="$with_db_uniquename"
fi
AC_MSG_RESULT($DB_UNIQUE_NAME)
fi
AC_MSG_CHECKING(if --enable-incore-temp-databases option specified)
AC_ARG_ENABLE(incore-temp-databases,
AC_HELP_STRING([--enable-incore-temp-databases],
[Enable incore databases for temporary tables.]),, enableval="no")
db_cv_incore_temp_databases="$enableval"
case "$db_cv_incore_temp_databases" in
never)
TEMP_STORE=0
AC_MSG_RESULT([never])
;;
no)
INMEMORYDB=1
TEMP_STORE=1
AC_MSG_RESULT([no])
;;
always)
INMEMORYDB=1
TEMP_STORE=3
AC_MSG_RESULT([always])
;;
*)
INMEMORYDB=1
TEMP_STORE=2
AC_MSG_RESULT([yes])
;;
esac
AC_DEFINE(INMEMORYDB)
AH_TEMPLATE(INMEMORYDB,
[Define to 1 to enable memory resident databases.])
AC_DEFINE(TEMP_STORE)
AH_TEMPLATE(TEMP_STORE,
[Determines where TEMP databases can be stored, see table in source code.])
AC_MSG_CHECKING(if --disable-statistics option specified)
AC_ARG_ENABLE(statistics,
AC_HELP_STRING([--disable-statistics],
[Do not build statistics support.]),, enableval="yes")
db_cv_build_statistics="$enableval"
case "$enableval" in
no) AC_MSG_RESULT(yes);;
yes) AC_MSG_RESULT(no);;
esac
AC_MSG_CHECKING(if --enable-sqlite-compat option specified)
AC_ARG_ENABLE(sqlite-compat,
[AC_HELP_STRING([--enable-sqlite-compat],
[Build SQLite compatibility API.])],
[db_cv_sqlite_compat="$enable_sqlite_compat"],
[db_cv_sqlite_compat="no"])
AC_MSG_RESULT($db_cv_sqlite_compat)
AC_MSG_CHECKING(if --enable-soundex-sqlfn option specified)
AC_ARG_ENABLE(soundex-sqlfn,
[AC_HELP_STRING([--enable-soundex-sqlfn],
[Include soundex() sql function support.])],
[db_cv_sqlite_compat="$enable_soundex_sqlfn"],
[db_cv_sqlite_compat="no"])
AC_MSG_RESULT($db_cv_soundex_sqlfn)
AC_MSG_CHECKING(if --enable-posixmutexes option specified)
AC_ARG_ENABLE(posixmutexes,
[AC_HELP_STRING([--enable-posixmutexes],
[Force use of POSIX standard mutexes.])],
[db_cv_posixmutexes="$enable_posixmutexes"], [db_cv_posixmutexes="no"])
AC_MSG_RESULT($db_cv_posixmutexes)
AC_MSG_CHECKING(if --enable-debug option specified)
AC_ARG_ENABLE(debug,
[AC_HELP_STRING([--enable-debug],
[Build a debugging version.])],
[db_cv_debug="$enable_debug"], [db_cv_debug="no"])
AC_MSG_RESULT($db_cv_debug)
AC_MSG_CHECKING(if --enable-diagnostic option specified)
AC_ARG_ENABLE(diagnostic,
[AC_HELP_STRING([--enable-diagnostic],
[Build a version with run-time diagnostics.])],
[db_cv_diagnostic="$enable_diagnostic"], [db_cv_diagnostic="no"])
AC_MSG_RESULT($db_cv_diagnostic)
AC_MSG_CHECKING(if --enable-tcl option specified)
AC_ARG_ENABLE(tcl,
[AC_HELP_STRING([--enable-tcl],
[Build Tcl API.])],
[db_cv_tcl="$enable_tcl"], [db_cv_tcl="no"])
AC_MSG_RESULT($db_cv_tcl)
AC_MSG_CHECKING([if --with-tcl=DIR option specified])
AC_ARG_WITH(tcl,
[AC_HELP_STRING([--with-tcl=DIR],
[Directory location of tclConfig.sh.])],
[with_tclconfig="$withval"], [with_tclconfig="no"])
AC_MSG_RESULT($with_tclconfig)
AC_MSG_CHECKING(if --enable-test option specified)
AC_ARG_ENABLE(test,
[AC_HELP_STRING([--enable-test],
[Configure to run the test suite.])],
[db_cv_test="$enable_test"], [db_cv_test="no"])
AC_MSG_RESULT($db_cv_test)
# Test requires Tcl
if test "$db_cv_test" = "yes"; then
if test "$db_cv_tcl" = "no"; then
AC_MSG_ERROR([--enable-test requires --enable-tcl])
fi
fi])

118
dist/aclocal/programs.ac vendored Normal file
View file

@ -0,0 +1,118 @@
# $Id: programs.ac 7 2007-02-03 13:34:17Z gburd $
# Check for programs used in building/installation.
AC_DEFUN(AM_PROGRAMS_SET, [
AC_CHECK_TOOL(db_cv_path_ar, ar, missing_ar)
if test "$db_cv_path_ar" = missing_ar; then
AC_MSG_ERROR([No ar utility found.])
fi
AC_CHECK_TOOL(db_cv_path_chmod, chmod, missing_chmod)
if test "$db_cv_path_chmod" = missing_chmod; then
AC_MSG_ERROR([No chmod utility found.])
fi
AC_CHECK_TOOL(db_cv_path_sed, sed, missing_sed)
if test "$db_cv_path_sed" = missing_sed; then
AC_MSG_ERROR([No sed utility found.])
fi
AC_CHECK_TOOL(db_cv_path_perl, perl, missing_perl)
if test "$db_cv_path_perl" = missing_perl; then
AC_MSG_ERROR([No perl utility found.])
fi
AC_CHECK_TOOL(db_cv_path_makedepend, makedepend, missing_makedepend)
if test "$db_cv_path_makedepend" = missing_makedepend; then
AC_MSG_RESULT([no])
db_cv_path_makedepend=echo
fi
AC_CHECK_TOOL(db_cv_path_splint, splint, missing_splint)
if test "$db_cv_path_splint" = missing_splint; then
AC_MSG_RESULT([no])
db_cv_path_splint=echo
fi
AC_CHECK_TOOL(db_cv_path_python, python, missing_python)
if test "$db_cv_path_python" = missing_python; then
AC_MSG_RESULT([no])
db_cv_path_python=echo
fi
AC_CHECK_TOOL(db_cv_path_grep, grep, missing_grep)
if test "$db_cv_path_grep" = missing_grep; then
AC_MSG_ERROR([No grep utility found.])
fi
AC_CHECK_TOOL(db_cv_path_awk, awk, missing_awk)
if test "$db_cv_path_awk" = missing_awk; then
AC_MSG_ERROR([No awk utility found.])
fi
AC_CHECK_TOOL(db_cv_path_cp, cp, missing_cp)
if test "$db_cv_path_cp" = missing_cp; then
AC_MSG_ERROR([No cp utility found.])
fi
if test "$db_cv_rpm" = "yes"; then
AC_CHECK_TOOL(path_ldconfig, ldconfig, missing_ldconfig)
AC_PATH_PROG(db_cv_path_ldconfig, $path_ldconfig, missing_ldconfig)
if test "$db_cv_path_ldconfig" != missing_ldconfig; then
RPM_POST_INSTALL="%post -p $db_cv_path_ldconfig"
RPM_POST_UNINSTALL="%postun -p $db_cv_path_ldconfig"
fi
fi
AC_CHECK_TOOL(db_cv_path_ln, ln, missing_ln)
if test "$db_cv_path_ln" = missing_ln; then
AC_MSG_ERROR([No ln utility found.])
fi
AC_CHECK_TOOL(db_cv_path_mkdir, mkdir, missing_mkdir)
if test "$db_cv_path_mkdir" = missing_mkdir; then
AC_MSG_ERROR([No mkdir utility found.])
fi
# We need a complete path for ranlib, because it doesn't exist on some
# architectures because the ar utility packages the library itself.
AC_CHECK_TOOL(path_ranlib, ranlib, missing_ranlib)
AC_PATH_PROG(db_cv_path_ranlib, $path_ranlib, missing_ranlib)
AC_CHECK_TOOL(db_cv_path_rm, rm, missing_rm)
if test "$db_cv_path_rm" = missing_rm; then
AC_MSG_ERROR([No rm utility found.])
fi
if test "$db_cv_rpm" = "yes"; then
AC_CHECK_TOOL(db_cv_path_rpm, rpm, missing_rpm)
if test "$db_cv_path_rpm" = missing_rpm; then
AC_MSG_ERROR([No rpm utility found.])
fi
fi
# We need a complete path for sh, because some implementations of make
# get upset if SHELL is set to just the command name.
AC_CHECK_TOOL(path_sh, sh, missing_sh)
AC_PATH_PROG(db_cv_path_sh, $path_sh, missing_sh)
if test "$db_cv_path_sh" = missing_sh; then
AC_MSG_ERROR([No sh utility found.])
fi
# Don't strip the binaries if --enable-debug was specified.
if test "$db_cv_debug" = yes; then
db_cv_path_strip=debug_build_no_strip
else
AC_CHECK_TOOL(path_strip, strip, missing_strip)
AC_PATH_PROG(db_cv_path_strip, $path_strip, missing_strip)
fi
if test "$db_cv_test" = "yes"; then
AC_CHECK_TOOL(db_cv_path_kill, kill, missing_kill)
if test "$db_cv_path_kill" = missing_kill; then
AC_MSG_ERROR([No kill utility found.])
fi
fi
])

47
dist/aclocal/readline.ac vendored Normal file
View file

@ -0,0 +1,47 @@
# $Id: readline.ac 7 2007-02-03 13:34:17Z gburd $
# Find a readline compatible library.
AC_DEFUN([VL_LIB_READLINE], [
AC_CACHE_CHECK([for a readline compatible library],
vl_cv_lib_readline, [
ORIG_LIBS="$LIBS"
for readline_lib in readline edit editline; do
for termcap_lib in "" termcap curses ncurses; do
if test -z "$termcap_lib"; then
TRY_LIB="-l$readline_lib"
else
TRY_LIB="-l$readline_lib -l$termcap_lib"
fi
LIBS="$ORIG_LIBS $TRY_LIB"
AC_TRY_LINK_FUNC(readline, vl_cv_lib_readline="$TRY_LIB")
if test -n "$vl_cv_lib_readline"; then
break
fi
done
if test -n "$vl_cv_lib_readline"; then
break
fi
done
if test -z "$vl_cv_lib_readline"; then
vl_cv_lib_readline="no"
LIBS="$ORIG_LIBS"
fi
])
if test "$vl_cv_lib_readline" != "no"; then
AC_DEFINE(HAVE_LIBREADLINE, 1,
[Define if you have a readline compatible library])
AC_CHECK_HEADERS(readline.h readline/readline.h)
AC_CACHE_CHECK([whether readline supports history],
vl_cv_lib_readline_history, [
vl_cv_lib_readline_history="no"
AC_TRY_LINK_FUNC(add_history, vl_cv_lib_readline_history="yes")
])
if test "$vl_cv_lib_readline_history" = "yes"; then
AC_DEFINE(HAVE_READLINE_HISTORY, 1,
[Define if your readline library has \`add_history'])
AC_CHECK_HEADERS(history.h readline/history.h)
fi
fi
])dnl

76
dist/aclocal/sosuffix.ac vendored Normal file
View file

@ -0,0 +1,76 @@
# $Id: sosuffix.ac 7 2007-02-03 13:34:17Z gburd $
# Determine shared object suffixes.
#
# Our method is to use the libtool variable $library_names_spec,
# set by using AC_PROG_LIBTOOL. This variable is a snippet of shell
# defined in terms of $versuffix, $release, $libname and $module
# We want to eval it and grab the suffix used for shared objects.
# By setting $module to yes/no, we obtain the suffixes
# used to create dlloadable, or java loadable modules.
# On many (*nix) systems, these all evaluate to .so, but there
# are some notable exceptions.
# Before calling this macro, $LIBTOOL_PROG must be set to
# the correct method of invoking libtool (e.g. $SHELL ./libtool)
# This macro is used internally to discover the suffix for the current
# settings of $module. The result is stored in $_SOSUFFIX.
AC_DEFUN(_SOSUFFIX_INTERNAL, [
versuffix=""
release=""
libname=libfoo
eval _SOSUFFIX=\"$shrext\"
if test "X$_SOSUFFIX" = "" ; then
_SOSUFFIX=".so"
if test `$LIBTOOL_PROG --config | grep build_libtool_libs | grep no` 2>/dev/null; then
if test "X$_SOSUFFIX_MESSAGE" = "X"; then
_SOSUFFIX_MESSAGE=yes
AC_MSG_WARN([libtool may not know about this architecture.])
AC_MSG_WARN([assuming $_SUFFIX suffix for dynamic libraries.])
fi
fi
fi
])
# SOSUFFIX_CONFIG will set the variable SOSUFFIX to be the
# shared library extension used for general linking, not dlopen.
AC_DEFUN(SOSUFFIX_CONFIG, [
AC_MSG_CHECKING([SOSUFFIX from libtool])
module=no
_SOSUFFIX_INTERNAL
SOSUFFIX=$_SOSUFFIX
AC_MSG_RESULT($SOSUFFIX)
AC_SUBST(SOSUFFIX)
])
# MODSUFFIX_CONFIG will set the variable MODSUFFIX to be the
# shared library extension used for dlopen'ed modules.
# To discover this, we set $module, simulating libtool's -module option.
AC_DEFUN(MODSUFFIX_CONFIG, [
AC_MSG_CHECKING([MODSUFFIX from libtool])
module=yes
_SOSUFFIX_INTERNAL
MODSUFFIX=$_SOSUFFIX
AC_MSG_RESULT($MODSUFFIX)
AC_SUBST(MODSUFFIX)
])
# JMODSUFFIX_CONFIG will set the variable JMODSUFFIX to be the
# shared library extension used JNI modules opened by Java.
# To discover this, we set $jnimodule, simulating libtool's -shrext option.
##########################################################################
# Robert Boehne: Not much point in this macro any more because apparently
# Darwin is the only OS that wants or needs the .jnilib extension.
##########################################################################
AC_DEFUN(JMODSUFFIX_CONFIG, [
AC_MSG_CHECKING([JMODSUFFIX from libtool])
module=yes
_SOSUFFIX_INTERNAL
if test `uname` = "Darwin"; then
JMODSUFFIX=".jnilib"
else
JMODSUFFIX=$_SOSUFFIX
fi
AC_MSG_RESULT($JMODSUFFIX)
AC_SUBST(JMODSUFFIX)
])

128
dist/aclocal/tcl.ac vendored Normal file
View file

@ -0,0 +1,128 @@
# $Id: tcl.ac 7 2007-02-03 13:34:17Z gburd $
# The SC_* macros in this file are from the unix/tcl.m4 files in the Tcl
# 8.3.0 distribution, with some minor changes. For this reason, license
# terms for the Berkeley DB distribution dist/aclocal/tcl.m4 file are as
# follows (copied from the license.terms file in the Tcl 8.3 distribution):
#
# This software is copyrighted by the Regents of the University of
# California, Sun Microsystems, Inc., Scriptics Corporation,
# and other parties. The following terms apply to all files associated
# with the software unless explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
# and license this software and its documentation for any purpose, provided
# that existing copyright notices are retained in all copies and that this
# notice is included verbatim in any distributions. No written agreement,
# license, or royalty fee is required for any of the authorized uses.
# Modifications to this software may be copyrighted by their authors
# and need not follow the licensing terms described here, provided that
# the new terms are clearly indicated on the first page of each file where
# they apply.
#
# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
# MODIFICATIONS.
#
# GOVERNMENT USE: If you are acquiring this software on behalf of the
# U.S. government, the Government shall have only "Restricted Rights"
# in the software and related documentation as defined in the Federal
# Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
# are acquiring the software on behalf of the Department of Defense, the
# software shall be classified as "Commercial Computer Software" and the
# Government shall have only "Restricted Rights" as defined in Clause
# 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
# authors grant the U.S. Government and others acting in its behalf
# permission to use and distribute the software in accordance with the
# terms specified in this license.
AC_DEFUN(SC_PATH_TCLCONFIG, [
AC_CACHE_VAL(ac_cv_c_tclconfig,[
# First check to see if --with-tclconfig was specified.
if test x"${with_tclconfig}" != x; then
if test -f "${with_tclconfig}/tclConfig.sh" ; then
ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
else
AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
fi
fi
# check in a few common install locations
if test x"${ac_cv_c_tclconfig}" = x ; then
for i in `ls -d /usr/local/lib 2>/dev/null` ; do
if test -f "$i/tclConfig.sh" ; then
ac_cv_c_tclconfig=`(cd $i; pwd)`
break
fi
done
fi
])
if test x"${ac_cv_c_tclconfig}" = x ; then
TCL_BIN_DIR="# no Tcl configs found"
AC_MSG_ERROR(can't find Tcl configuration definitions)
else
TCL_BIN_DIR=${ac_cv_c_tclconfig}
fi
AC_SUBST(TCL_BIN_DIR)
])
AC_DEFUN(SC_LOAD_TCLCONFIG, [
AC_MSG_CHECKING([for existence of $TCL_BIN_DIR/tclConfig.sh])
if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
AC_MSG_RESULT([loading])
. $TCL_BIN_DIR/tclConfig.sh
else
AC_MSG_RESULT([file not found])
fi
# DBSQL requires at least version 8.4.
if test ${TCL_MAJOR_VERSION} -lt 8 \
-o ${TCL_MAJOR_VERSION} -eq 8 -a ${TCL_MINOR_VERSION} -lt 4; then
AC_MSG_ERROR([Berkeley DB requires Tcl version 8.4 or better.])
fi
if test x"$TCL_INCLUDE_SPEC" != x; then
TCL_CFLAGS="$TCL_INCLUDE_SPEC"
fi
AC_SUBST(TCL_LD_FLAGS)
AC_SUBST(TCL_LIBS)
AC_SUBST(TCL_LIB_SPEC)
])
# Optional Tcl API.
AC_DEFUN(AM_TCL_LOAD, [
if test "$db_cv_tcl" = "yes"; then
if test `$LIBTOOL_PROG --config | grep build_libtool_libs | grep no` 2>/dev/null; then
AC_MSG_ERROR([Tcl requires shared libraries])
fi
SC_PATH_TCLCONFIG
SC_LOAD_TCLCONFIG
if test x"$TCL_INCLUDE_SPEC" != x && test -f "$TCL_INCLUDE_SPEC/tcl.h"; then
TCL_CFLAGS="${TCL_CFLAGS} -I$TCL_INCLUDE_SPEC"
fi
INSTALL_LIBS="${INSTALL_LIBS} \$(libtso_target)"
TCL_TCLSH="${TCL_PREFIX}/bin/tclsh${TCL_VERSION}"
AC_SUBST(TCL_SRC_DIR)
AC_SUBST(TCL_LIB_FILE)
AC_SUBST(TCL_CFLAGS)
AC_SUBST(TCL_TCLSH)
fi])

130
dist/aclocal/types.ac vendored Normal file
View file

@ -0,0 +1,130 @@
# $Id: types.ac 7 2007-02-03 13:34:17Z gburd $
# Check the sizes we know about, and see if any of them match what's needed.
#
# Prefer ints to anything else, because read, write and others historically
# returned an int.
AC_DEFUN(AM_SEARCH_USIZES, [
case "$3" in
"$ac_cv_sizeof_unsigned_int")
$1="typedef unsigned int $2;";;
"$ac_cv_sizeof_unsigned_char")
$1="typedef unsigned char $2;";;
"$ac_cv_sizeof_unsigned_short")
$1="typedef unsigned short $2;";;
"$ac_cv_sizeof_unsigned_long")
$1="typedef unsigned long $2;";;
*)
AC_MSG_ERROR([No unsigned $3-byte integral type]);;
esac])
AC_DEFUN(AM_SEARCH_SSIZES, [
case "$3" in
"$ac_cv_sizeof_int")
$1="typedef int $2;";;
"$ac_cv_sizeof_char")
$1="typedef char $2;";;
"$ac_cv_sizeof_short")
$1="typedef short $2;";;
"$ac_cv_sizeof_long")
$1="typedef long $2;";;
*)
AC_MSG_ERROR([No signed $3-byte integral type]);;
esac])
# Check for the standard system types.
AC_DEFUN(AM_TYPES, [
# db.h includes <sys/types.h> and <stdio.h>, not the other default includes
# autoconf usually includes. For that reason, we specify a set of includes
# for all type checking tests. [#5060]
#
# IBM's OS/390 and z/OS releases have types in <inttypes.h> not also found
# in <sys/types.h>. Include <inttypes.h> as well, if it exists.
AC_SUBST(inttypes_decl)
db_includes="#include <sys/types.h>"
AC_CHECK_HEADER(inttypes.h, [
inttypes_decl="#include <inttypes.h>"
db_includes="$db_includes
#include <inttypes.h>"])
db_includes="$db_includes
#include <stdio.h>"
# We need to know the sizes of various objects on this system.
# We don't use the SIZEOF_XXX values created by autoconf.
AC_CHECK_SIZEOF(char,, $db_includes)
AC_CHECK_SIZEOF(unsigned char,, $db_includes)
AC_CHECK_SIZEOF(short,, $db_includes)
AC_CHECK_SIZEOF(unsigned short,, $db_includes)
AC_CHECK_SIZEOF(int,, $db_includes)
AC_CHECK_SIZEOF(unsigned int,, $db_includes)
AC_CHECK_SIZEOF(long,, $db_includes)
AC_CHECK_SIZEOF(unsigned long,, $db_includes)
AC_CHECK_SIZEOF(size_t,, $db_includes)
AC_CHECK_SIZEOF(char *,, $db_includes)
AC_CHECK_SIZEOF(long double,, $db_includes)
# We require off_t and size_t, and we don't try to substitute our own
# if we can't find them.
AC_CHECK_TYPE(off_t,, AC_MSG_ERROR([No off_t type.]), $db_includes)
AC_CHECK_TYPE(size_t,, AC_MSG_ERROR([No size_t type.]), $db_includes)
# We look for u_char, u_short, u_int, u_long -- if we can't find them,
# we create our own.
AC_SUBST(u_char_decl)
AC_CHECK_TYPE(u_char,,
[u_char_decl="typedef unsigned char u_char;"], $db_includes)
AC_SUBST(u_short_decl)
AC_CHECK_TYPE(u_short,,
[u_short_decl="typedef unsigned short u_short;"], $db_includes)
AC_SUBST(u_int_decl)
AC_CHECK_TYPE(u_int,,
[u_int_decl="typedef unsigned int u_int;"], $db_includes)
AC_SUBST(u_long_decl)
AC_CHECK_TYPE(u_long,,
[u_long_decl="typedef unsigned long u_long;"], $db_includes)
AC_SUBST(u_int8_decl)
AC_CHECK_TYPE(u_int8_t,,
[AM_SEARCH_USIZES(u_int8_decl, u_int8_t, 1)], $db_includes)
AC_SUBST(u_int16_decl)
AC_CHECK_TYPE(u_int16_t,,
[AM_SEARCH_USIZES(u_int16_decl, u_int16_t, 2)], $db_includes)
AC_SUBST(int16_decl)
AC_CHECK_TYPE(int16_t,,
[AM_SEARCH_SSIZES(int16_decl, int16_t, 2)], $db_includes)
AC_SUBST(u_int32_decl)
AC_CHECK_TYPE(u_int32_t,,
[AM_SEARCH_USIZES(u_int32_decl, u_int32_t, 4)], $db_includes)
AC_SUBST(int32_decl)
AC_CHECK_TYPE(int32_t,,
[AM_SEARCH_SSIZES(int32_decl, int32_t, 4)], $db_includes)
AC_SUBST(long_double_decl)
AC_CHECK_TYPE(long double,
[long_double_decl="typedef long double long_double_t;"],
[long_double_decl="typedef long double long_double_t;"], $db_includes)
# Check for ssize_t -- if none exists, find a signed integral type that's
# the same size as a size_t.
AC_SUBST(ssize_t_decl)
AC_CHECK_TYPE(ssize_t,,
[AM_SEARCH_SSIZES(ssize_t_decl, ssize_t, $ac_cv_sizeof_size_t)],
$db_includes)
# Find the largest integral type.
AC_SUBST(db_align_t_decl)
AC_CHECK_TYPE(unsigned long long,
[db_align_t_decl="typedef unsigned long long db_align_t;"],
[db_align_t_decl="typedef unsigned long db_align_t;"], $db_includes)
# Find an integral type which is the same size as a pointer.
AC_SUBST(db_alignp_t_decl)
AM_SEARCH_USIZES(db_alignp_t_decl, db_alignp_t, $ac_cv_sizeof_char_p)
])

138
dist/buildrel vendored Normal file
View file

@ -0,0 +1,138 @@
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# $Id: buildrel 7 2007-02-03 13:34:17Z gburd $
#
# Build the distribution package.
#
# A set of commands intended to be cut and pasted into a csh window.
# Development tree, release home.
setenv D `pwd`
# Update the release number.
cd $D/dist
cvs -q update RELEASE
vi RELEASE
setenv VERSION `sh -c '. RELEASE; echo $DB_VERSION'`
echo "Version: $VERSION"
# Make sure the source tree is up-to-date
cd $D && cvs -q update
# Build the documentation.
cd db.docs && cvs -q update
cd db.docs && sh build ../db.rel clean && sh build ../db.rel |& sed '/.html$/d'
cd db.docs && sh build ../db.rel javadoc
# Generate new support files, commit anything that's changed.
cd $D/dist && sh s_all
cd $D && cvs -q commit
# Copy a development tree into a release tree.
setenv R /var/tmp/db-$VERSION
rm -rf $R && mkdir -p $R
cd $D && cvs -q status | \
grep "Repository revision" | \
sed -e 's;.*CVSROOT/db/;;' \
-e 's;.*CVSROOT/;;' \
-e 's;,v$;;' | pax -rw $R/
# Copy the already-built documentation into place
rm -rf $R/docs && cp -r $D/docs $R/docs
# Remove source directories we don't distribute.
cd $R && rm -rf docs_src docs/api_java
cd $R && rm -rf test/TODO test/upgrade test_perf test_purify
cd $R && rm -rf test_server test_thread test_vxworks test_xa
cd $R && rm -rf java/src/com/sleepycat/xa
# Fix symbolic links and permissions.
cd $R/dist && sh s_perm
cd $R/dist && sh s_symlink
# Build a version.
cd $R && rm -rf build_run && mkdir build_run
cd $R/build_run && ~bostic/bin/dbconf && make >& mklog
# Smoke test.
cd $R/build_run && ./ex_access
# Check the install
cd $R/build_run && make prefix=`pwd`/BDB install
# Build a small-footprint version.
cd $R && rm -rf build_run && mkdir build_run
cd $R/build_run && ../dist/configure --enable-smallbuild && make >& mklog
# Remove the build directory
cd $R && rm -rf build_run
# ACQUIRE ROOT PRIVILEGES
cd $R && find . -type d | xargs chmod 775
cd $R && find . -type f | xargs chmod 444
cd $R && chmod 664 build_win32/*.dsp
cd $R/dist && sh s_perm
chown -R 100 $R
chgrp -R 100 $R
# DISCARD ROOT PRIVILEGES
# Create the crypto tar archive release.
setenv T "$R/../db-$VERSION.tar.gz"
cd $R/.. && tar cf - db-$VERSION | gzip --best > $T
chmod 444 $T
# Create the non-crypto tree.
setenv RNC "$R/../db-$VERSION.NC"
rm -rf $RNC $R/../__TMP && mkdir $R/../__TMP
cd $R/../__TMP && gzcat $T | tar xpf - && mv -i db-$VERSION $RNC
cd $R && rm -rf $R/../__TMP
cd $RNC/dist && sh s_crypto
# ACQUIRE ROOT PRIVILEGES
cd $RNC && find . -type d | xargs chmod 775
cd $RNC && find . -type f | xargs chmod 444
cd $RNC && chmod 664 build_win32/*.dsp
cd $RNC/dist && sh s_perm
chown -R 100 $RNC
chgrp -R 100 $RNC
# DISCARD ROOT PRIVILEGES
# Create the non-crypto tar archive release.
setenv T "$R/../db-$VERSION.NC.tar.gz"
cd $RNC/.. && tar cf - db-$VERSION.NC | gzip --best > $T
chmod 444 $T
# Remove tags files. They're large and we don't want to store symbolic links
# in the zip archive for portability reasons.
# ACQUIRE ROOT PRIVILEGES
cd $R && rm -f `find . -name 'tags'`
cd $RNC && rm -f `find . -name 'tags'`
# DISCARD ROOT PRIVILEGES
# Create the crypto zip archive release.
setenv T "$R/../db-$VERSION.zip"
cd $R/.. && zip -r - db-$VERSION > $T
chmod 444 $T
# Create the non-crypto zip archive release.
setenv T "$R/../db-$VERSION.NC.zip"
cd $RNC/.. && zip -r - db-$VERSION.NC > $T
chmod 444 $T

1410
dist/config.guess vendored Normal file

File diff suppressed because it is too large Load diff

223
dist/config.hin vendored Normal file
View file

@ -0,0 +1,223 @@
/* config.hin. Generated from configure.ac by autoheader. */
/* Define to 1 if you want a TCL API with test support. */
#undef CONFIG_TEST
/* Define to use ISO8859 string encoding. */
#undef DBSQL_ISO8859_ENCODING
/* Define to 1 to omit authorization code from the build. */
#undef DBSQL_OMIT_AUTHORIZATION
/* Define to 1 to omit support for datetime functions from the build. */
#undef DBSQL_OMIT_DATETIME_FUNCS
/* Define to 1 to omit the code for the VACCUM command from the build. */
#undef DBSQL_OMIT_VACUUM
/* Define use UTF8 string encoding. */
#undef DBSQL_UTF8_ENCODING
/* We use DBSQL_WIN32 much as one would use _WIN32 -- to specify that we're
using an operating system environment that supports Win32 calls and
semantics. We don't use _WIN32 because Cygwin/GCC also defines _WIN32, even
though Cygwin/GCC closely emulates the Unix environment. */
#undef DBSQL_WIN32
/* Define to 1 if you want a debugging version. */
#undef DEBUG
/* Define to 1 if you want a version with run-time diagnostic checking. */
#undef DIAGNOSTIC
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/
#undef HAVE_DIRENT_H
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have EXIT_SUCCESS/EXIT_FAILURE #defines. */
#undef HAVE_EXIT_SUCCESS
/* Define to 1 if allocated filesystem blocks are not zeroed. */
#undef HAVE_FILESYSTEM_NOTZERO
/* Define to 1 if you have the `getopt' function. */
#undef HAVE_GETOPT
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R
/* Define to 1 if you have the `lrand48_r' function. */
#undef HAVE_LRAND48_R
/* Define to 1 if you have the `memcmp' function. */
#undef HAVE_MEMCMP
/* Define to 1 if you have the `memcpy' function. */
#undef HAVE_MEMCPY
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#undef HAVE_NDIR_H
/* Define to 1 if building on QNX. */
#undef HAVE_QNX
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Define to 1 if you have the `srand48_r' function. */
#undef HAVE_SRAND48_R
/* Define to 1 if building statistics support. */
#undef HAVE_STATISTICS
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strncasecmp' function. */
#undef HAVE_STRNCASECMP
/* Define to 1 if you have the `strndup' function. */
#undef HAVE_STRNDUP
/* Define to 1 if `st_blksize' is member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
*/
#undef HAVE_SYS_DIR_H
/* Define to 1 if you have the <sys/fcntl.h> header file. */
#undef HAVE_SYS_FCNTL_H
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
*/
#undef HAVE_SYS_NDIR_H
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if unlink of file with open file descriptors will fail. */
#undef HAVE_UNLINK_WITH_OPEN_FAILURE
/* Define to 1 if you have the `usleep' function. */
#undef HAVE_USLEEP
/* Define to 1 to enable memory resident databases. */
#undef INMEMORYDB
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* The size of `char', as computed by sizeof. */
#undef SIZEOF_CHAR
/* The size of `char *', as computed by sizeof. */
#undef SIZEOF_CHAR_P
/* The size of `int', as computed by sizeof. */
#undef SIZEOF_INT
/* The size of `long', as computed by sizeof. */
#undef SIZEOF_LONG
/* The size of `long double', as computed by sizeof. */
#undef SIZEOF_LONG_DOUBLE
/* The size of `short', as computed by sizeof. */
#undef SIZEOF_SHORT
/* The size of `size_t', as computed by sizeof. */
#undef SIZEOF_SIZE_T
/* The size of `unsigned char', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_CHAR
/* The size of `unsigned int', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_INT
/* The size of `unsigned long', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_LONG
/* The size of `unsigned short', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_SHORT
/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
#undef STAT_MACROS_BROKEN
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Determines where TEMP databases can be stored, see table in source code. */
#undef TEMP_STORE
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/*
* Exit success/failure macros.
*/
#ifndef HAVE_EXIT_SUCCESS
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
#endif
#ifdef DBSQL_WIN32
#include "win_dbsql.h"
#endif

1508
dist/config.sub vendored Normal file

File diff suppressed because it is too large Load diff

33132
dist/configure vendored Normal file

File diff suppressed because it is too large Load diff

530
dist/configure.ac vendored Normal file
View file

@ -0,0 +1,530 @@
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# $Id: configure.ac 7 2007-02-03 13:34:17Z gburd $
# Process this file with autoconf to produce a configure script.
PACKAGE=dbsql
AC_INIT(DBSQL,
__EDIT_DBSQL_VERSION__,
support@dbsql.org,
dbsql-__EDIT_DBSQL_VERSION__)
AC_CONFIG_SRCDIR([../src/clib/memcmp.c])
AC_CONFIG_HEADERS([dbsql_config.h:config.hin])
# Configure setup.
AC_CANONICAL_HOST()
AC_ARG_PROGRAM()
# Don't build in the top-level or dist directories.
AC_MSG_CHECKING(if building in the top-level or dist directories)
if [ test -d build_unix -o -d aclocal ] ; then
AC_MSG_RESULT(yes)
AC_MSG_ERROR(
[DBSQL should not be built in the top-level or dist directories.])
fi
AC_MSG_RESULT(no)
# Substitution variables.
AC_SUBST(ADDITIONAL_INCS)
AC_SUBST(ADDITIONAL_LANG)
AC_SUBST(ADDITIONAL_OBJS)
AC_SUBST(ADDITIONAL_PROGS)
AC_SUBST(BUILD_TARGET)
AC_SUBST(CFLAGS)
AC_SUBST(CONFIGURATION_ARGS)
AC_SUBST(CONFIGURATION_PATH)
AC_SUBST(CPPFLAGS)
AC_SUBST(CXX)
AC_SUBST(CXXFLAGS)
AC_SUBST(DB_PATH)
AC_SUBST(DB_UNIQUE_NAME)
AC_SUBST(DEFAULT_LIB)
AC_SUBST(DEFAULT_LIB_CXX)
AC_SUBST(ENCODING)
AC_SUBST(INSTALLER)
AC_SUBST(INSTALL_LIBS)
AC_SUBST(INSTALL_TARGET)
AC_SUBST(LDFLAGS)
AC_SUBST(LIBS)
AC_SUBST(LIBSO_LIBS)
AC_SUBST(LIBTOOL)
AC_SUBST(LIBTSO_LIBS)
AC_SUBST(LIBTSO_MODSUFFIX)
AC_SUBST(LIBTSO_MODULE)
AC_SUBST(LIBXSO_LIBS)
AC_SUBST(LOAD_LIBS)
AC_SUBST(MAKEFILE_CC)
AC_SUBST(MAKEFILE_CCLINK)
AC_SUBST(MAKEFILE_CXX)
AC_SUBST(MAKEFILE_CXXLINK)
AC_SUBST(MAKEFILE_SOLINK)
AC_SUBST(MAKEFILE_XSOLINK)
AC_SUBST(OSDIR)
AC_SUBST(PATH_SEPARATOR)
AC_SUBST(POSTLINK)
AC_SUBST(REPLACEMENT_OBJS)
AC_SUBST(RPC_CLIENT_OBJS)
AC_SUBST(RPM_BUILD)
AC_SUBST(RPM_POST_INSTALL)
AC_SUBST(RPM_POST_UNINSTALL)
AC_SUBST(SOFLAGS)
AC_SUBST(o)
# RPM needs the current absolute path.
# RPM needs the list of original arguments, but we don't include the RPM
# option itself.
CONFIGURATION_PATH=${PWD-`pwd`}
CONFIGURATION_ARGS=`echo "$*" | sed -e 's/--with-rpm[[^ ]]*//'`
# Set the default installation location.
AC_PREFIX_DEFAULT(/usr/local/DBSQL.__EDIT_DBSQL_VERSION_MAJOR__.__EDIT_DBSQL_VERSION_MINOR__)
# Configure the version information.
AC_SUBST(DBSQL_VERSION_MAJOR)
DBSQL_VERSION_MAJOR="__EDIT_DBSQL_VERSION_MAJOR__"
AC_SUBST(DBSQL_VERSION_MINOR)
DBSQL_VERSION_MINOR="__EDIT_DBSQL_VERSION_MINOR__"
AC_SUBST(DBSQL_VERSION_PATCH)
DBSQL_VERSION_PATCH="__EDIT_DBSQL_VERSION_PATCH__"
AC_SUBST(DBSQL_VERSION_STRING)
DBSQL_VERSION_STRING='"__EDIT_DBSQL_VERSION_STRING__"'
AC_SUBST(DBSQL_VERSION_UNIQUE_NAME)
# Process all options before using them.
AM_OPTIONS_SET
# Set some #defines based on configuration options.
if test "$db_cv_diagnostic" = "yes"; then
AC_DEFINE(DIAGNOSTIC)
AH_TEMPLATE(DIAGNOSTIC,
[Define to 1 if you want a version with run-time diagnostic checking.])
fi
if test "$db_cv_test" = "yes"; then
AC_DEFINE(CONFIG_TEST)
AH_TEMPLATE(CONFIG_TEST,
[Define to 1 if you want to build a version for running the test suite.])
fi
# Check for programs used in building and installation.
AM_PROGRAMS_SET
AC_PROG_INSTALL
# RPM support: change the standard make and install targets
if test "$db_cv_rpm" = "yes"; then
BUILD_TARGET="rpm_build"
# Check if we are running RPM version 3 or 4.
case "`rpm --version`" in
*version\ 4*)
RPM_BUILD="rpmbuild"
echo "_topdir $CONFIGURATION_PATH" > rpm-macro-defines;;
*version\ 3*)
RPM_BUILD="rpm"
echo "topdir: $CONFIGURATION_PATH" > rpm-macro-defines;;
esac
INSTALL_TARGET="rpm_install"
else
BUILD_TARGET="library_build"
INSTALL_TARGET="library_install"
fi
# This is where we handle stuff that autoconf can't handle: compiler,
# preprocessor and load flags, libraries that the standard tests don't
# look for. The default optimization is -O. We would like to set the
# default optimization for systems using gcc to -O2, but we can't. By
# the time we know we're using gcc, it's too late to set optimization
# flags.
#
# There are additional libraries we need for some compiler/architecture
# combinations.
#
# Some architectures require DB to be compiled with special flags and/or
# libraries for threaded applications
#
# The makefile CC may be different than the CC used in config testing,
# because the makefile CC may be set to use $(LIBTOOL).
#
# XXX
# Don't override anything if it's already set from the environment.
optimize_def="-O"
case "$host_os" in
aix4.3.*|aix5*)
optimize_def="-O2"
CC=${CC-"xlc_r"}
CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE"
LDFLAGS="$LDFLAGS -Wl,-brtl";;
bsdi3*) optimize_def="-O2"
CC=${CC-"shlicc2"}
LIBS="$LIBS -lipc";;
bsdi*) optimize_def="-O2";;
cygwin*)
optimize_def="-O2"
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_REENTRANT";;
freebsd*)
optimize_def="-O2"
CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE"
LDFLAGS="$LDFLAGS -pthread";;
gnu*|k*bsd*-gnu|linux*)
optimize_def="-O2"
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_REENTRANT";;
hpux*) CPPFLAGS="$CPPFLAGS -D_REENTRANT";;
irix*) optimize_def="-O2"
CPPFLAGS="$CPPFLAGS -D_SGI_MP_SOURCE";;
mpeix*) CPPFLAGS="$CPPFLAGS -D_POSIX_SOURCE -D_SOCKET_SOURCE"
LIBS="$LIBS -lsocket -lsvipc";;
osf*) CPPFLAGS="$CPPFLAGS -pthread";;
*qnx*) AC_DEFINE(HAVE_QNX)
AH_TEMPLATE(HAVE_QNX, [Define to 1 if building on QNX.]);;
solaris*)
CPPFLAGS="$CPPFLAGS -D_REENTRANT";;
esac
# Set CFLAGS/CXXFLAGS. We MUST set the flags before we call autoconf
# compiler configuration macros, because if we don't, they set CFLAGS
# to no optimization and -g, which isn't what we want.
if test "$db_cv_debug" = "no"; then
CFLAGS=${CFLAGS-$optimize_def}
fi
CXXFLAGS=${CXXFLAGS-"$CFLAGS"}
# If the user wants a TCL library interface setup for testing, add
# -DCONFIG_TEST to the CFLAGS value.
if test "$db_cv_test" = "yes"; then
AC_DEFINE(CONFIG_TEST)
AH_TEMPLATE(CONFIG_TEST,
[Define to 1 if you want a TCL API with test support.])
CFLAGS="$CFLAGS -DCONFIG_TEST"
CXXFLAGS="$CXXFLAGS -DCONFIG_TEST"
db_cv_build_tcl_test_objs=TCL_TEST_OBJS
else
db_cv_build_tcl_test_objs=
fi
AC_SUBST(db_cv_build_tcl_test_objs)
# If the user wants a debugging environment, add -g to the CFLAGS value.
#
# XXX
# Some compilers can't mix optimizing and debug flags. The only way to
# handle this is to specify CFLAGS in the environment before configuring.
if test "$db_cv_debug" = "yes"; then
AC_DEFINE(DEBUG)
AH_TEMPLATE(DEBUG, [Define to 1 if you want a debugging version.])
CFLAGS="$CFLAGS -g"
CXXFLAGS="$CXXFLAGS -g"
db_cv_build_type=debug
else
db_cv_build_type=release
fi
AC_SUBST(db_cv_build_type)
# The default compiler is cc (NOT gcc), the default CFLAGS is as specified
# above, NOT what is set by AC_PROG_CC, as it won't set optimization flags
# for any compiler other than gcc.
AC_PROG_CC(cc gcc)
# Checks for compiler characteristics.
AC_SUBST(DB_PROTO1)
AC_SUBST(DB_PROTO2)
DB_PROTO1="#undef __P"
# AC_PROG_CC_STDC only sets ac_cv_prog_cc_stdc if the test fails, so
# check for "no", not "yes".
if test "$ac_cv_prog_cc_stdc" = "no"; then
DB_PROTO2="#define __P(protos) ()"
else
DB_PROTO2="#define __P(protos) protos"
fi
AC_C_CONST
AC_SUBST(DB_CONST)
if test "$ac_cv_c_const" != "yes"; then
DB_CONST="#define const"
fi
# Because of shared library building, the ${CC} used for config tests
# may be different than the ${CC} we want to put in the Makefile.
# The latter is known as ${MAKEFILE_CC} in this script.
MAKEFILE_CC="${CC}"
MAKEFILE_CCLINK="${CC}"
MAKEFILE_CXX="nocxx"
MAKEFILE_CXXLINK="nocxx"
# See if we need the C++ compiler at all. If so, we'd like to find one that
# interoperates with the C compiler we chose. Since we prefered cc over gcc,
# we'll also prefer the vendor's compiler over g++/gcc. If we're wrong, the
# user can set CC and CXX in their environment before running configure.
#
# AC_PROG_CXX sets CXX, but it uses $CXX and $CCC (in that order) as its
# first choices.
if test "$db_cv_cxx" = "yes"; then
if test "$GCC" != "yes"; then
case "$host_os" in
aix*) AC_CHECK_TOOL(CCC, xlC_r)
LIBXSO_LIBS="-lC_r $LIBXSO_LIBS"
LIBS="-lC_r $LIBS";;
hpux*) AC_CHECK_TOOL(CCC, aCC);;
irix*) AC_CHECK_TOOL(CCC, CC);;
osf*) AC_CHECK_TOOL(CCC, cxx);;
solaris*) AC_CHECK_TOOL(CCC, CC);;
esac
fi
AC_PROG_CXX
###### WORKAROUND: SEE SR #7938
AC_PROG_CXXCPP
###############################
AC_CXX_HAVE_STDHEADERS
MAKEFILE_CXX="${CXX}"
MAKEFILE_CXXLINK="${CXX}"
fi
# Do some gcc specific configuration.
AC_GCC_CONFIG1
AC_GCC_CONFIG2
# We need the -Kthread/-pthread flag when compiling on SCO/Caldera's UnixWare
# and OpenUNIX releases. We can't make the test until we know which compiler
# we're using.
case "$host_os" in
sysv5UnixWare*|sysv5OpenUNIX8*)
if test "$GCC" == "yes"; then
CPPFLAGS="$CPPFLAGS -pthread"
LDFLAGS="$LDFLAGS -pthread"
else
CPPFLAGS="$CPPFLAGS -Kthread"
LDFLAGS="$LDFLAGS -Kthread"
fi;;
esac
# Export our compiler preferences for the libtool configuration.
export CC CCC
CCC=CXX
# Libtool configuration.
AC_PROG_LIBTOOL
SOFLAGS="-rpath \$(libdir)"
LIBTOOL_PROG="${SHELL} ./libtool"
# Set SOSUFFIX and friends
SOSUFFIX_CONFIG
MODSUFFIX_CONFIG
INSTALLER="\$(LIBTOOL) --mode=install cp -p"
MAKEFILE_CC="\$(LIBTOOL) --mode=compile ${MAKEFILE_CC}"
MAKEFILE_SOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK} -avoid-version"
MAKEFILE_CCLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK}"
MAKEFILE_CXX="\$(LIBTOOL) --mode=compile ${MAKEFILE_CXX}"
MAKEFILE_XSOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK} -avoid-version"
MAKEFILE_CXXLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK}"
LIBTOOL="\$(SHELL) ./libtool"
case "$host_os" in
cygwin*)
MAKEFILE_SOLINK="$MAKEFILE_SOLINK -no-undefined"
MAKEFILE_XSOLINK="$MAKEFILE_XSOLINK -no-undefined";;
esac
# Configure for shared libraries, static libraries, or both. If both are
# configured, build the utilities and example programs with shared versions.
#
# $o is set to ".o" or ".lo", and is the file suffix used in the Makefile
# instead of .o
if test `$LIBTOOL_PROG --config |
grep build_libtool_libs | grep no` 2>/dev/null; then
enable_shared="no"
else
enable_shared="yes"
fi
if test `$LIBTOOL_PROG --config |
grep build_old_libs | grep no` 2>/dev/null; then
enable_static="no"
else
enable_static="yes"
fi
# C API.
if test "$enable_shared" = "no"; then
DEFAULT_LIB="\$(libdb_version)"
POSTLINK=": "
o=".o"
else
DEFAULT_LIB="\$(libso_target)"
POSTLINK="\$(LIBTOOL) --mode=execute true"
o=".lo"
fi
INSTALL_LIBS="$DEFAULT_LIB"
if test "$enable_static" = "yes"; then
INSTALL_LIBS="$INSTALL_LIBS \$(libdb)"
fi
# Optional C++ API.
if test "$db_cv_cxx" = "yes"; then
if test "$enable_shared" = "no"; then
DEFAULT_LIB_CXX="\$(libcxx_version)"
fi
if test "$enable_shared" = "yes"; then
DEFAULT_LIB_CXX="\$(libxso_target)"
fi
INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_CXX"
if test "$enable_static" = "yes"; then
INSTALL_LIBS="$INSTALL_LIBS \$(libcxx)"
fi
fi
dnl # Optional Java API. TODO
# MinGW support.
if test "$db_cv_mingw" = "yes"; then
OSDIR=os_win32
PATH_SEPARATOR="\\\\/:"
AC_DEFINE(DBSQL_WIN32)
AC_DEFINE(STDC_HEADERS)
else
OSDIR=os
PATH_SEPARATOR="/"
fi
# Apple's Mac OS/X had to rename shared libraries, so much for standards.
case "$host_os" in
darwin*)
LIBTSO_MODULE=""
LIBTSO_MODSUFFIX=".dylib"
;;
*)
LIBTSO_MODULE="-module"
LIBTSO_MODSUFFIX=@MODSUFFIX@
;;
esac
AM_TCL_LOAD
# You can disable pieces of functionality to save space.
# The stat code.
if test "$db_cv_build_statistics" = "yes"; then
AC_DEFINE(HAVE_STATISTICS)
AH_TEMPLATE(HAVE_STATISTICS,
[Define to 1 if building statistics support.])
fi
# Checks for include files, structures, C types.
AC_HEADER_STAT
AC_HEADER_TIME
AC_HEADER_DIRENT
AC_CHECK_HEADERS(sys/select.h sys/time.h sys/fcntl.h)
AC_CHECK_MEMBERS([struct stat.st_blksize])
AM_TYPES
AC_CACHE_CHECK([for ANSI C exit success/failure values], db_cv_exit_defines, [
AC_TRY_COMPILE([#include <stdlib.h>], return (EXIT_SUCCESS);,
[db_cv_exit_defines=yes], [db_cv_exit_defines=no])])
if test "$db_cv_exit_defines" = "yes"; then
AC_DEFINE(HAVE_EXIT_SUCCESS)
AH_TEMPLATE(HAVE_EXIT_SUCCESS,
[Define to 1 if you have EXIT_SUCCESS/EXIT_FAILURE #defines.])
fi
# Test for various functions/libraries that the test and example programs use:
# sched_yield function
# pthreads, socket and math libraries
AC_CHECK_FUNC(sched_yield,,
AC_SEARCH_LIBS(sched_yield, rt, LOAD_LIBS="$LOAD_LIBS -lrt"))
# XXX
# We can't check for pthreads in the same way we did the test for sched_yield
# because the Solaris C library includes pthread interfaces which are not
# thread-safe. For that reason we always add -lpthread if we find a pthread
# library. Also we can't depend on any specific call existing (pthread_create,
# for example), as it may be #defined in an include file -- OSF/1 (Tru64) has
# this problem.
AC_HAVE_LIBRARY(pthread, LOAD_LIBS="$LOAD_LIBS -lpthread")
# We use sqrt() so we need the math library -lm
AC_HAVE_LIBRARY(m, LIBS="$LIBS -lm")
# Checks for system functions for which we have replacements.
AC_REPLACE_FUNCS(getopt memcmp memcpy memmove strdup strndup strerror)
AC_REPLACE_FUNCS(snprintf localtime_r strcasecmp strncasecmp)
AC_REPLACE_FUNCS(srand48_r lrand48_r)
# Check for system functions we use.
AC_CHECK_FUNCS(usleep)
# A/UX has a broken getopt(3).
case "$host_os" in
aux*) AC_LIBOBJ([getopt]);;
esac
# Apple's Mac OS/X complains about long doubles, make it stop.
case "$host_os" in
darwin*)
CFLAGS="$CFLAGS -Wno-long-double -no-cpp-precomp"
;;
esac
# We need to add the additional object files into the Makefile with the correct
# suffix. We can't use $LTLIBOBJS itself, because that variable has $U encoded
# in it for automake, and that's not what we want. See SR #7227 for additional
# information.
#
# XXX: I'm not sure this is correct.
REPLACEMENT_OBJS=`echo "$LIB@&t@OBJS" |
sed "s,\.[[^.]]* ,$o ,g;s,\.[[^.]]*$,$o,"`
# This is necessary so that .o files in LIBOBJS are also built via
# the ANSI2KNR-filtering rules.
LIB@&t@OBJS=`echo "$LIB@&t@OBJS" |
sed 's,\.[[^.]]* ,$U&,g;s,\.[[^.]]*$,$U&,'`
LTLIBOBJS=`echo "$LIB@&t@OBJS" |
sed 's,\.[[^.]]* ,.lo ,g;s,\.[[^.]]*$,.lo,'`
AC_SUBST(LTLIBOBJS)
# Initial output file list.
CREATE_LIST="Makefile
dbsql_int.h:$srcdir/../src/inc/dbsql_int.in
$srcdir/../src/py/setup.py:$srcdir/../src/py/setup.py.in
$srcdir/../test/scr050/Makefile:$srcdir/../test/scr050/Makefile.in"
# MinGW needs win_db.h.
if test "$db_cv_mingw" = "yes"; then
CREATE_LIST="$CREATE_LIST
win_db.h:$srcdir/win_dbsql.in"
fi
# Create the dbsql.h file from a source file and a list of global function
# prototypes.
CREATE_LIST="$CREATE_LIST
dbsql.h:$srcdir/../src/dbsql.in"
if test "$db_cv_rpm" = "yes"; then
CREATE_LIST="$CREATE_LIST db.spec:../dist/dbsql.spec.in"
fi
AC_CONFIG_FILES($CREATE_LIST)
AC_OUTPUT

33
dist/dbsql.pc.in vendored Normal file
View file

@ -0,0 +1,33 @@
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# Package Information for pkg-config
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: dbsql
Description: A SQL database engine.
Version: @VERSION@
Libs: -L${libdir} -ldbsql -ldb
Cflags: -I${includedir}

55
dist/dbsql.spec.in vendored Normal file
View file

@ -0,0 +1,55 @@
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# DBSQL @DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@.@DBSQL_VERSION_PATCH@
Summary: DBSQL - A SQL database library.
Name: dbsql
Version: @DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@.@DBSQL_VERSION_PATCH@
Release: 1
Copyright: GPL - Freely redistributable, see LICENSE for details.
Source: http://www.dbsql.org/update/@DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@.@DBSQL_VERSION_PATCH@/dbsql-@DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@.@DBSQL_VERSION_PATCH@.tar.gz
URL: http://www.dbsql.org
Group: System Environment/Libraries
BuildRoot: @CONFIGURATION_PATH@/RPM_INSTALL
%define _unpackaged_files_terminate_build 0
%description
DBSQL is a programmatic toolkit that provides fast, scalable and
reliable SQL implementation.
%prep
%setup
%build
cd build_unix
CFLAGS="$RPM_OPT_FLAGS" ../dist/configure @CONFIGURATION_ARGS@
make library_build
%install
cd build_unix
make prefix=@CONFIGURATION_PATH@/RPM_INSTALL install
@RPM_POST_INSTALL@
@RPM_POST_UNINSTALL@
%changelog

39
dist/dot-gdbinit vendored Normal file
View file

@ -0,0 +1,39 @@
break __db_loadme
break __db_err
define dd
print __db_dump(dbp, "a", "/tmp/o")
end
define dc
print __db_dump(dbc->dbp, "a", "/tmp/o")
end
break __sm_create
break __sm_create_table
break __sm_create_index
break __sm_close_db
break __sm_checkpoint
break __sm_get_database_name
break __sm_begin_txn
break __sm_commit_txn
break __sm_abort_txn
break __sm_cursor
break __sm_close_cursor
break __sm_moveto
break __sm_next
break __sm_prev
break __sm_key_size
break __sm_data_size
break __sm_key_compare
break __sm_key
break __sm_data
break __sm_first
break __sm_last
break __sm_insert
break __sm_delete
break __sm_drop_table
break __sm_clear_table
break __sm_set_format_version
break __sm_get_format_version
break __sm_set_schema_sig
break __sm_get_schema_sig
break process_input
break __process_sql

67
dist/gen_inc.awk vendored Normal file
View file

@ -0,0 +1,67 @@
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
# This awk script parses C input files looking for lines marked "PUBLIC:"
# and "EXTERN:". (PUBLIC lines are DB internal function prototypes and
# #defines, EXTERN are DB external function prototypes and #defines.)
#
# PUBLIC lines are put into two versions of per-directory include files:
# one file that contains the prototypes, and one file that contains a
# #define for the name to be processed during configuration when creating
# unique names for every global symbol in the DB library.
#
# The EXTERN lines are put into two files: one of which contains prototypes
# which are always appended to the db.h file, and one of which contains a
# #define list for use when creating unique symbol names.
#
# Four arguments:
# e_dfile list of EXTERN #defines
# e_pfile include file that contains EXTERN prototypes
# i_dfile list of internal (PUBLIC) #defines
# i_pfile include file that contains internal (PUBLIC) prototypes
/PUBLIC:/ {
sub("^.*PUBLIC:[ ][ ]*", "")
if ($0 ~ "^#if|^#ifdef|^#ifndef|^#else|^#endif") {
print $0 >> i_pfile
print $0 >> i_dfile
next
}
pline = sprintf("%s %s", pline, $0)
if (pline ~ "\\)\\);") {
sub("^[ ]*", "", pline)
print pline >> i_pfile
pline = ""
}
}
/EXTERN:/ {
sub("^.*EXTERN:[ ][ ]*", "")
if ($0 ~ "^#if|^#ifdef|^#ifndef|^#else|^#endif") {
print $0 >> e_pfile
print $0 >> e_dfile
next
}
eline = sprintf("%s %s", eline, $0)
if (eline ~ "\\)\\);") {
sub("^[ ]*", "", eline)
print eline >> e_pfile
eline = ""
}
}

251
dist/install-sh vendored Normal file
View file

@ -0,0 +1,251 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
chmodcmd=""
else
instcmd=$mkdirprog
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

6290
dist/ltmain.sh vendored Normal file

File diff suppressed because it is too large Load diff

33
dist/s_all vendored Normal file
View file

@ -0,0 +1,33 @@
#!/bin/sh -
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# $Id: s_all 7 2007-02-03 13:34:17Z gburd $
sh s_perm # permissions.
sh s_symlink # symbolic links.
sh s_readme # distribution README file.
#
# The following order is important, s_include must run last.
#
sh s_config # autoconf.
sh s_include # standard include files.
sh s_tags # Tags files.

54
dist/s_config vendored Normal file
View file

@ -0,0 +1,54 @@
#!/bin/sh -x
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# $Id: s_config 7 2007-02-03 13:34:17Z gburd $
#
# Build the autoconfiguration files.
trap 'rm -f aclocal.m4 ; exit 0' 0 1 2 3 13 15
. ./RELEASE
echo "autoconf: building aclocal.m4..."
cat aclocal/*.ac > aclocal.m4
echo "autoconf: running autoheader to build config.hin..."
rm -f config.hin
autoheader
chmod 444 config.hin
echo "autoconf: running autoconf to build configure"
rm -f configure
autoconf
# Edit version information we couldn't pre-compute.
(echo "1,\$s/__EDIT_DBSQL_VERSION_MAJOR__/$DBSQL_VERSION_MAJOR/g" &&
echo "1,\$s/__EDIT_DBSQL_VERSION_MINOR__/$DBSQL_VERSION_MINOR/g" &&
echo "1,\$s/__EDIT_DBSQL_VERSION_PATCH__/$DBSQL_VERSION_PATCH/g" &&
echo "1,\$s/__EDIT_DBSQL_VERSION_STRING__/$DBSQL_VERSION_STRING/g" &&
echo "1,\$s/__EDIT_DBSQL_VERSION__/$DBSQL_VERSION/g" &&
echo "w" &&
echo "q") | ed -s configure
rm -rf autom4te.cache
chmod 555 configure
chmod 555 config.guess config.sub install-sh

109
dist/s_include vendored Normal file
View file

@ -0,0 +1,109 @@
#!/bin/sh -
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# $Id: s_include 7 2007-02-03 13:34:17Z gburd $
#
# Build the automatically generated function prototype files.
msgc="/* DO NOT EDIT: automatically built by dist/s_include. */"
head()
{
defonly=0
while :
do case "$1" in
space)
echo ""; shift;;
defonly)
defonly=1; shift;;
*)
name="$1"; break;;
esac
done
echo "$msgc"
echo "#ifndef $name"
echo "#define $name"
echo ""
if [ $defonly -eq 0 ]; then
echo "#if defined(__cplusplus)"
echo "extern \"C\" {"
echo "#endif"
echo ""
fi
}
tail()
{
defonly=0
while :
do case "$1" in
defonly)
defonly=1; shift;;
*)
name="$1"; break;;
esac
done
echo ""
if [ $defonly -eq 0 ]; then
echo "#if defined(__cplusplus)"
echo "}"
echo "#endif"
fi
echo "#endif /* !$name */"
}
# We are building several files:
# 1 external #define file
# 1 external prototype file
# 1 internal #define file
# N internal prototype files
e_dfile=/tmp/__db_c.$$
e_pfile=/tmp/__db_a.$$
i_dfile=/tmp/__db_d.$$
i_pfile=/tmp/__db_b.$$
trap 'rm -f $e_dfile $e_pfile $i_dfile $i_pfile; exit 0' 0 1 2 3 13 15
head defonly space _DBSQL_EXT_DEF_IN_ > $e_dfile
head space _DBSQL_EXT_PROT_IN_ > $e_pfile
head defonly _DBSQL_INT_DEF_IN_ > $i_dfile
# Process the standard directories, creating per-directory prototype
# files and adding to the external prototype and #define files.
for i in dbsql os clib common ; do
head "_${i}_ext_h_" > $i_pfile
f="../src/$i/*.c"
[ "$f" = "../src/dbsql/*.c" ] && f="../src/*.c"
awk -f gen_inc.awk \
-v e_dfile=$e_dfile \
-v e_pfile=$e_pfile \
-v i_dfile=$i_dfile \
-v i_pfile=$i_pfile $f
tail "_${i}_ext_h_" >> $i_pfile
f="../src/inc/${i}_ext.h"
cmp $i_pfile $f > /dev/null 2>&1 ||
(echo "Building $f" && rm -f $f && cp $i_pfile $f && chmod 444 $f)
done

49
dist/s_perm vendored Normal file
View file

@ -0,0 +1,49 @@
#!/bin/sh -
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# $Id: s_perm 7 2007-02-03 13:34:17Z gburd $
d=..
echo 'Updating DBSQL source tree permissions...'
run()
{
#echo " $1 ($2)"
if [ -f "$d/$1" ]; then
chmod "$2" "$d/$1"
else
echo "$d/$1: no such file or directory"
exit 1
fi
}
run dist/config.guess 555
run dist/config.sub 555
run dist/configure 555
run dist/install-sh 555
run dist/s_all 555
run dist/s_config 555
run dist/s_include 555
run dist/s_perm 555
run dist/s_readme 555
run dist/s_symlink 555
run dist/s_tags 555
run dist/s_test 555

86
dist/s_readme vendored Normal file
View file

@ -0,0 +1,86 @@
#!/bin/sh -
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# $Id: s_readme 7 2007-02-03 13:34:17Z gburd $
#
# Build the README.
echo 'Updating DBSQL README file...'
d=..
t=/tmp/__t
trap 'rm -f $t; exit 0' 0 1 2 3 13 15
. ./RELEASE
cat << END_OF_README>$t
$DBSQL_VERSION_STRING
This is version $DBSQL_VERSION_MAJOR.$DBSQL_VERSION_MINOR.$DBSQL_VERSION_PATCH of DBSQL.
To view the release and installation documentation, load the distribution
file docs/index.html into your web browser.
This work started from the SQLite project (found on the web at
http://www.sqlite.org/). SQLite and all contributions to the SQLite
project have been placed in the public domain by its author, Dr. Richard Hipp.
There was no assertion of copyright at all on the code I used as a starting
point for my work. In fact there are statements that explicitly disclaim
copyright. I am asserting copyright on this work, DBSQL. I believe
that if you examine the extent to which I've changed, updated, and
modified the SQLite code you'll respect my copyright assertion. This
is a new product, heavily inspired by another.
The goal for DBSQL is to provide a small SQL92 relational database layer
on top of the Berkeley DB database. Berkeley DB is copyright Oracle
Corporation (formerly Sleepycat Software, acquired in Feb 2006) and
licensed under the Sleepycat Public License. That license is compatible
with the GPL for open source use. Recognize that you, as someone using
DBSQL, will need to review the Sleepycat License and the GPL before you
use and redistribute your incorporating work. It is your responsibility
to comply with those licenses as I am in my work on DBSQL itself. My
motivation on a personal level is quite simple, I am in product management
these days and not in the code itself. I believe that product managers
should be engineers at heart with an ability to understand business,
politics, and software sales and support. This is my playground to keep
my engineering skills sharp enough to speak fluent geek. As a former
engineer at Sleepycat I understand and value the Berkeley DB programming
infrasture, design, and methodologies and I have liberally copied and
reused them in this project to improve SQLite in ways that I hope will
be of value to open source users out there. I did this because I see the
value of SQLite to its userbase, it is a perfect example of the 80/20
rule and the KISS method and I admire those qualities in software. My
hope is that the Berkeley DB database engine will provide some significant
features that SQLite cannot such as replication for high availability
while remaining small enough to live comfortably inside applications,
services, and devices.
Information and resources pertaining to DBSQL can be found at dbsql.org.
Commercial licenses without the restrictions found in the GPL can be
purchased for this product. See http://dbsql.org/wiki/CommercialUse
END_OF_README
f=../README
cmp $t $f > /dev/null 2>&1 ||
(echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)

44
dist/s_symlink vendored Normal file
View file

@ -0,0 +1,44 @@
#!/bin/sh -
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# $Id: s_symlink 7 2007-02-03 13:34:17Z gburd $
echo 'Creating DBSQL source tree symbolic links...'
build()
{
#echo " $1 -> $2"
(cd ../`dirname $1` && rm -f `basename $1` && ln -s $2 `basename $1`)
}
build src/tags ../dist/tags
build src/os/tags ../../dist/tags
build src/clib/tags ../../dist/tags
build src/py/tags ../../dist/tags
build test/scr050/tags ../../dist/tags
build build_unix/tags ../dist/tags
build src/TAGS ../dist/TAGS
build src/os/TAGS ../../dist/TAGS
build src/clib/TAGS ../../dist/TAGS
build src/py/TAGS ../../dist/TAGS
build test/scr050/TAGS ../../dist/tags
build build_unix/TAGS ../dist/TAGS

52
dist/s_tags vendored Normal file
View file

@ -0,0 +1,52 @@
#!/bin/sh -
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# $Id: s_tags 7 2007-02-03 13:34:17Z gburd $
#
# Build tags files.
files=`echo ../src/*.[ch] \
../src/inc/*.h \
../src/os/*.[ch] \
../src/py/*.[ch] \
../test/scr050/*.[ch]`
f=tags
echo "Building $f"
rm -f $f
# Figure out what flags this ctags accepts.
flags=""
if ctags -d ../src/api.c 2>/dev/null; then
flags="-d $flags"
fi
if ctags -t ../src/api.c 2>/dev/null; then
flags="-t $flags"
fi
if ctags -w ../src/api.c 2>/dev/null; then
flags="-w $flags"
fi
ctags $flags $files 2>/dev/null
chmod 444 $f
etags $files -o TAGS 2>/dev/null
chmod 444 $f

104
dist/s_test vendored Normal file
View file

@ -0,0 +1,104 @@
#!/bin/sh -
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# $Id: s_test 7 2007-02-03 13:34:17Z gburd $
#
# Build the Tcl test files.
msg1="# Automatically built by dist/s_test; may require local editing."
msg2="# Automatically built by dist/s_test; may require local editing."
t=/tmp/__t
trap 'rm -f $t; exit 0' 0 1 2 3 13 15
. RELEASE
(echo "$msg1" && \
echo "" && \
echo "set tclsh_path @TCL_TCLSH@" && \
echo "set tcllib .libs/libdbsql_tcl-@DBSQL_VERSION_MAJOR@.@DBSQL_VERSION_MINOR@@LIBTSO_MODSUFFIX@" && \
echo "" && \
echo "set src_root @srcdir@/.." && \
echo "set test_path @srcdir@/../test" && \
echo "" && \
echo "global testdir" && \
echo "set testdir ./TESTDIR" && \
echo "" && \
echo "global dict" && \
echo "global util_path" && \
echo "" && \
echo "global is_hp_test" && \
echo "global is_qnx_test" && \
echo "global is_windows_test" && \
echo "" && \
echo "set KILL \"@db_cv_path_kill@\"") > $t
f=../test/include.tcl
cmp $t $f > /dev/null 2>&1 ||
(echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
(echo "$msg1" && \
echo "" && \
echo "set tclsh_path SET_YOUR_TCLSH_PATH" && \
echo "set tcllib ./Debug/libdbsql_tcl${DBSQL_VERSION_MAJOR}${DBSQL_VERSION_MINOR}d.dll" && \
echo "" && \
echo "set src_root .." && \
echo "set test_path ../test" && \
echo "" && \
echo "global testdir" && \
echo "set testdir ./TESTDIR" && \
echo "" && \
echo "global dict" && \
echo "global util_path" && \
echo "" && \
echo "global is_hp_test" && \
echo "global is_qnx_test" && \
echo "global is_windows_test" && \
echo "" && \
echo "set KILL ./dbkill.exe") > $t
f=../build_win32/include.tcl
cmp $t $f > /dev/null 2>&1 ||
(echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)
# Build the test directory TESTS file.
(echo $msg2;
cat `egrep -l '^#[ ][ ]*TEST' ../test/*.tcl` |
sed -e '/^#[ ][ ]*TEST/!{' \
-e 's/.*//' \
-e '}' |
cat -s |
sed -e '/TEST/{' \
-e 's/^#[ ][ ]*TEST[ ]*//' \
-e 's/^ //' \
-e 'H' \
-e 'd' \
-e '}' \
-e 's/.*//' \
-e x \
-e 's/\n/__LINEBREAK__/g' |
sort |
sed -e 's/__LINEBREAK__/\
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\
/' \
-e 's/__LINEBREAK__/\
/g' |
sed -e 's/^[ ][ ]*$//') > $t
f=../test/TESTS
cmp $t $f > /dev/null 2>&1 ||
(echo "Building $f" && rm -f $f && cp $t $f && chmod 444 $f)

5
dist/splint.rc vendored Normal file
View file

@ -0,0 +1,5 @@
-namechecks
+posixstrictlib
+showallconjs
+showscan
+stats

61
dist/sqlconf vendored Normal file
View file

@ -0,0 +1,61 @@
#!/bin/sh -
#
# This is how I normally configure DBSQL when I'm doing daily work.
#
# Note that I'm usually using the latest copy of Mac OS/X for
# devlelopment work, so some of this may be specific to that.
#
[ -d build_unix ] && {
echo 'You cannot build in the top-level directory.'
exit 1
}
[ -d aclocal ] && {
echo 'You cannot build in the dist directory.'
exit 1
}
args=""
#args="--disable-shared $args"
#args="--disable-static $args"
args="--enable-vacuum $args"
args="--enable-datetime $args"
args="--enable-authentication $args"
args="--enable-incore-databases $args"
args="--enable-incore-temp-databases $args"
args="--enable-debug $args"
args="--enable-diagnostic $args"
args="--enable-test $args"
args="--enable-tcl $args"
#args="--enable-sqlite-compat $args"
args="--enable-soundex-sqlfn $args"
args="--enable-posix-mutexes $args"
args="--with-tcl=/usr/lib/tcl8.4 $args"
args="--with-berkeleydb=/usr/local/db $args"
#args="--with-db-uniquename=FOO $args"
#args="LD_TWOLEVEL_NAMESPACE=1 LIBTSO_LIBS=-ltcl8.4 $args" # Mac OS/X
echo "env $cppflags $ldflags $libs ../dist/configure $args"
env $cppflags $ldflags $libs sh ../dist/configure -C $args
# (echo "break __db_loadme" &&
# echo "break __db_err" &&
# echo "define dd" &&
# echo 'print __db_dump(dbp, "a", "/tmp/o")' &&
# echo "end" &&
# echo "define dc" &&
# echo 'print __db_dump(dbc->dbp, "a", "/tmp/o")' &&
# echo "end") > .gdbinit
(echo "set environment LD_LIBRARY_PATH=.:.libs" &&
echo "dir ../src" &&
echo "dir ../src/dbsql" &&
echo "dir /usr/local/db/src" &&
echo "path /usr/local/db/lib" &&
echo "path .") > .gdbinit
rm -f tags
ln -s ../dist/tags tags
mkdir .libs && /bin/true
ln -s .gdbinit .libs/.gdbinit
ln -s ./.libs/dbsql dbsql-bin && /bin/true

86
dist/srcfiles.in vendored Normal file
View file

@ -0,0 +1,86 @@
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
# $Id: srcfiles.in 7 2007-02-03 13:34:17Z gburd $
# This is an input file for the s_win32_dsp. It lists the source files in
# the DBSQL tree and notes which are used to build the Win/32 library.
#
# Please keep this list sorted alphabetically!
#
# Each non-blank, non-comment line is of the form
# filename module [ module ...]
#
# The possible modules, including the name of the project (.dsp) file:
#
# app=NAME Linked into application NAME.exe (db_NAME.dsp)
# dynamic File is in the Windows DLL (db_dll.dsp)
# static File is in the Windows static library (db_static.dsp)
# java File is in the Windows Java DLL (db_java.dsp)
# tcl File is in the Windows tcl DLL (db_tcl.dsp)
# testutil File is used for Windows testing (db_test.dsp)
build_unix/lempar.c dynamic static
build_unix/opcodes.c dynamic static
build_unix/sql_parser.c dynamic static
build_win32/dbkill.cpp testutil
dist/splint.rc
examples/binary_codec.c
src/api.c dynamic static
src/api_table.c dynamic static
src/cg_attach.c dynamic static
src/cg_auth.c dynamic static
src/cg_build.c dynamic static
src/cg_copy.c dynamic static
src/cg_date.c dynamic static
src/cg_delete.c dynamic static
src/cg_expr.c dynamic static
src/cg_insert.c dynamic static
src/cg_pragma.c dynamic static
src/cg_select.c dynamic static
src/cg_trigger.c dynamic static
src/cg_update.c dynamic static
src/cg_vacuum.c dynamic static
src/cg_where.c dynamic static
src/clib/getopt.c app=dbsql
src/clib/memcmp.c dynamic static
src/clib/random.c dynamic static
src/clib/snprintf.c dynamic static
src/clib/strcasecmp.c dynamic static
src/clib/strdup.c dynamic static
src/clib/xvprintf.c dynamic static
src/common/dbsql_alloc.c dynamic static
src/common/dbsql_atof.c dynamic static
src/common/dbsql_atoi.c dynamic static
src/common/dbsql_err.c dynamic static
src/common/hash.c dynamic static
src/common/str.c dynamic static
src/dbsql/dbsql.c app=dbsql
src/dbsql_tclsh.c app=dbsql_tclsh
src/lemon/lemon.c app=lemon
src/lemon/lempar.c app=lemon
src/os/os_jtime.c dynamic static
src/safety.c dynamic static
src/sm.c dynamic static
src/sql_fns.c dynamic static
src/sql_tokenize.c dynamic static
src/vdbe.c dynamic static
src/vdbe_method.c dynamic static

418
dist/win_config.in vendored Normal file
View file

@ -0,0 +1,418 @@
/* Define to 1 if you want to build a version for running the test suite. */
/* #undef CONFIG_TEST */
/* We use DBSQL_WIN32 much as one would use _WIN32 -- to specify that we're using
an operating system environment that supports Win32 calls and semantics. We
don't use _WIN32 because Cygwin/GCC also defines _WIN32, even though
Cygwin/GCC closely emulates the Unix environment. */
#define DBSQL_WIN32 1
/* Define to 1 if you want a debugging version. */
/* #undef DEBUG */
#if defined(_DEBUG)
#if !defined(DEBUG)
#define DEBUG 1
#endif
#endif
/* Define to 1 if you want a version that logs read operations. */
/* #undef DEBUG_ROP */
/* Define to 1 if you want a version that logs write operations. */
/* #undef DEBUG_WOP */
/* Define to 1 if you want a version with run-time diagnostic checking. */
/* #undef DIAGNOSTIC */
/* Define to 1 if you have the `clock_gettime' function. */
/* #undef HAVE_CLOCK_GETTIME */
/* Define to 1 if Berkeley DB release includes strong cryptography. */
#ifndef HAVE_SMALLBUILD
#define HAVE_CRYPTO 1
#endif
/* Define to 1 if you have the `directio' function. */
/* #undef HAVE_DIRECTIO */
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/
/* #undef HAVE_DIRENT_H */
/* Define to 1 if you have the <dlfcn.h> header file. */
/* #undef HAVE_DLFCN_H */
/* Define to 1 if you have EXIT_SUCCESS/EXIT_FAILURE #defines. */
#define HAVE_EXIT_SUCCESS 1
/* Define to 1 if fcntl/F_SETFD denies child access to file descriptors. */
/* #undef HAVE_FCNTL_F_SETFD */
/* Define to 1 if allocated filesystem blocks are not zeroed. */
#define HAVE_FILESYSTEM_NOTZERO 1
/* Define to 1 if you have the `getcwd' function. */
#define HAVE_GETCWD 1
/* Define to 1 if you have the `getopt' function. */
/* #undef HAVE_GETOPT */
/* Define to 1 if you have the `getrusage' function. */
/* #undef HAVE_GETRUSAGE */
/* Define to 1 if you have the `gettimeofday' function. */
/* #undef HAVE_GETTIMEOFDAY */
/* Define to 1 if you have the `getuid' function. */
/* #undef HAVE_GETUID */
/* Define to 1 if building Hash access method. */
#ifndef HAVE_SMALLBUILD
#define HAVE_HASH 1
#endif
/* Define to 1 if you have the <inttypes.h> header file. */
/* #undef HAVE_INTTYPES_H */
/* Define to 1 if you have the `nsl' library (-lnsl). */
/* #undef HAVE_LIBNSL */
/* Define to 1 if you have the `memcmp' function. */
#define HAVE_MEMCMP 1
/* Define to 1 if you have the `memcpy' function. */
#define HAVE_MEMCPY 1
/* Define to 1 if you have the `memmove' function. */
#define HAVE_MEMMOVE 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `mlock' function. */
/* #undef HAVE_MLOCK */
/* Define to 1 if you have the `mmap' function. */
/* #undef HAVE_MMAP */
/* Define to 1 if you have the `munlock' function. */
/* #undef HAVE_MUNLOCK */
/* Define to 1 if you have the `munmap' function. */
/* #undef HAVE_MUNMAP */
/* Define to 1 to use the GCC compiler and 68K assembly language mutexes. */
/* #undef HAVE_MUTEX_68K_GCC_ASSEMBLY */
/* Define to 1 to use the AIX _check_lock mutexes. */
/* #undef HAVE_MUTEX_AIX_CHECK_LOCK */
/* Define to 1 to use the GCC compiler and Alpha assembly language mutexes. */
/* #undef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY */
/* Define to 1 to use the GCC compiler and ARM assembly language mutexes. */
/* #undef HAVE_MUTEX_ARM_GCC_ASSEMBLY */
/* Define to 1 to use the Apple/Darwin _spin_lock_try mutexes. */
/* #undef HAVE_MUTEX_DARWIN_SPIN_LOCK_TRY */
/* Define to 1 to use the UNIX fcntl system call mutexes. */
/* #undef HAVE_MUTEX_FCNTL */
/* Define to 1 to use the GCC compiler and PaRisc assembly language mutexes.
*/
/* #undef HAVE_MUTEX_HPPA_GCC_ASSEMBLY */
/* Define to 1 to use the msem_XXX mutexes on HP-UX. */
/* #undef HAVE_MUTEX_HPPA_MSEM_INIT */
/* Define to 1 to use the GCC compiler and IA64 assembly language mutexes. */
/* #undef HAVE_MUTEX_IA64_GCC_ASSEMBLY */
/* Define to 1 to use the msem_XXX mutexes on systems other than HP-UX. */
/* #undef HAVE_MUTEX_MSEM_INIT */
/* Define to 1 to use the GCC compiler and PowerPC assembly language mutexes.
*/
/* #undef HAVE_MUTEX_PPC_GCC_ASSEMBLY */
/* Define to 1 to use POSIX 1003.1 pthread_XXX mutexes. */
/* #undef HAVE_MUTEX_PTHREADS */
/* Define to 1 to use Reliant UNIX initspin mutexes. */
/* #undef HAVE_MUTEX_RELIANTUNIX_INITSPIN */
/* Define to 1 to use the IBM C compiler and S/390 assembly language mutexes.
*/
/* #undef HAVE_MUTEX_S390_CC_ASSEMBLY */
/* Define to 1 to use the GCC compiler and S/390 assembly language mutexes. */
/* #undef HAVE_MUTEX_S390_GCC_ASSEMBLY */
/* Define to 1 to use the SCO compiler and x86 assembly language mutexes. */
/* #undef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY */
/* Define to 1 to use the obsolete POSIX 1003.1 sema_XXX mutexes. */
/* #undef HAVE_MUTEX_SEMA_INIT */
/* Define to 1 to use the SGI XXX_lock mutexes. */
/* #undef HAVE_MUTEX_SGI_INIT_LOCK */
/* Define to 1 to use the Solaris _lock_XXX mutexes. */
/* #undef HAVE_MUTEX_SOLARIS_LOCK_TRY */
/* Define to 1 to use the Solaris lwp threads mutexes. */
/* #undef HAVE_MUTEX_SOLARIS_LWP */
/* Define to 1 to use the GCC compiler and Sparc assembly language mutexes. */
/* #undef HAVE_MUTEX_SPARC_GCC_ASSEMBLY */
/* Define to 1 if mutexes hold system resources. */
/* #undef HAVE_MUTEX_SYSTEM_RESOURCES */
/* Define to 1 if fast mutexes are available. */
#define HAVE_MUTEX_THREADS 1
/* Define to 1 to configure mutexes intra-process only. */
/* #undef HAVE_MUTEX_THREAD_ONLY */
/* Define to 1 to use the CC compiler and Tru64 assembly language mutexes. */
/* #undef HAVE_MUTEX_TRU64_CC_ASSEMBLY */
/* Define to 1 to use the UNIX International mutexes. */
/* #undef HAVE_MUTEX_UI_THREADS */
/* Define to 1 to use the UTS compiler and assembly language mutexes. */
/* #undef HAVE_MUTEX_UTS_CC_ASSEMBLY */
/* Define to 1 to use VMS mutexes. */
/* #undef HAVE_MUTEX_VMS */
/* Define to 1 to use VxWorks mutexes. */
/* #undef HAVE_MUTEX_VXWORKS */
/* Define to 1 to use the MSVC compiler and Windows mutexes. */
#define HAVE_MUTEX_WIN32 1
/* Define to 1 to use the GCC compiler and Windows mutexes. */
/* #undef HAVE_MUTEX_WIN32_GCC */
/* Define to 1 to use the GCC compiler and x86 assembly language mutexes. */
/* #undef HAVE_MUTEX_X86_GCC_ASSEMBLY */
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
/* #undef HAVE_NDIR_H */
/* Define to 1 if you have the O_DIRECT flag. */
/* #undef HAVE_O_DIRECT */
/* Define to 1 if you have the `pread' function. */
/* #undef HAVE_PREAD */
/* Define to 1 if you have the `pstat_getdynamic' function. */
/* #undef HAVE_PSTAT_GETDYNAMIC */
/* Define to 1 if you have the `pwrite' function. */
/* #undef HAVE_PWRITE */
/* Define to 1 if building on QNX. */
/* #undef HAVE_QNX */
/* Define to 1 if building Queue access method. */
#ifndef HAVE_SMALLBUILD
#define HAVE_QUEUE 1
#endif
/* Define to 1 if you have the `raise' function. */
#define HAVE_RAISE 1
/* Define to 1 if building replication support. */
#ifndef HAVE_SMALLBUILD
#define HAVE_REPLICATION 1
#endif
/* Define to 1 if building RPC client/server. */
/* #undef HAVE_RPC */
/* Define to 1 if you have the `sched_yield' function. */
/* #undef HAVE_SCHED_YIELD */
/* Define to 1 if you have the `select' function. */
/* #undef HAVE_SELECT */
/* Define to 1 if you have the `shmget' function. */
/* #undef HAVE_SHMGET */
/* Define to 1 if you have the `snprintf' function. */
#define HAVE_SNPRINTF 1
/* Define to 1 if building statistics support. */
#define HAVE_STATISTICS 1
/* Define to 1 if you have the <stdint.h> header file. */
/* #undef HAVE_STDINT_H */
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcasecmp' function. */
/* #undef HAVE_STRCASECMP */
/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strtoul' function. */
#define HAVE_STRTOUL 1
/* Define to 1 if `st_blksize' is member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_BLKSIZE */
/* Define to 1 if you have the `sysconf' function. */
/* #undef HAVE_SYSCONF */
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
*/
/* #undef HAVE_SYS_DIR_H */
/* Define to 1 if you have the <sys/fcntl.h> header file. */
#define HAVE_SYS_FCNTL_H 1
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
*/
/* #undef HAVE_SYS_NDIR_H */
/* Define to 1 if you have the <sys/select.h> header file. */
/* #undef HAVE_SYS_SELECT_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
/* #undef HAVE_SYS_TIME_H */
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
/* #undef HAVE_UNISTD_H */
/* Define to 1 if unlink of file with open file descriptors will fail. */
/* #undef HAVE_UNLINK_WITH_OPEN_FAILURE */
/* Define to 1 if building access method verification support. */
#ifndef HAVE_SMALLBUILD
#define HAVE_VERIFY 1
#endif
/* Define to 1 if you have the `vsnprintf' function. */
#define HAVE_VSNPRINTF 1
/* Define to 1 if building VxWorks. */
/* #undef HAVE_VXWORKS */
/* Define to 1 if you have the `yield' function. */
/* #undef HAVE_YIELD */
/* Define to 1 if you have the `_fstati64' function. */
#define HAVE__FSTATI64 1
/* Define to a value if using non-standard mutex alignment. */
/* #undef MUTEX_ALIGN */
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "support@dbsql.org"
/* Define to the full name of this package. */
#define PACKAGE_NAME "DBSQL"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "DBSQL __EDIT_DBSQL_VERSION__"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "db-__EDIT_DBSQL_VERSION__"
/* Define to the version of this package. */
#define PACKAGE_VERSION "__EDIT_DBSQL_VERSION__"
/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
/* #undef STAT_MACROS_BROKEN */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
/* #undef TIME_WITH_SYS_TIME */
/* Define to 1 to mask harmless unitialized memory read/writes. */
/* #undef UMRW */
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/*
* Exit success/failure macros.
*/
#ifndef HAVE_EXIT_SUCCESS
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
#endif
/*
* Don't step on the namespace. Other libraries may have their own
* implementations of these functions, we don't want to use their
* implementations or force them to use ours based on the load order.
*/
#ifndef HAVE_GETCWD
#define getcwd __db_Cgetcwd
#endif
#ifndef HAVE_MEMCMP
#define memcmp __db_Cmemcmp
#endif
#ifndef HAVE_MEMCPY
#define memcpy __db_Cmemcpy
#endif
#ifndef HAVE_MEMMOVE
#define memmove __db_Cmemmove
#endif
#ifndef HAVE_RAISE
#define raise __db_Craise
#endif
#ifndef HAVE_SNPRINTF
#define snprintf __db_Csnprintf
#endif
#ifndef HAVE_STRCASECMP
#define strcasecmp __db_Cstrcasecmp
#define strncasecmp __db_Cstrncasecmp
#endif
#ifndef HAVE_STRERROR
#define strerror __db_Cstrerror
#endif
#ifndef HAVE_VSNPRINTF
#define vsnprintf __db_Cvsnprintf
#endif
#include "win_db.h"
/*
* Microsoft's compiler _doesn't_ define __STDC__ unless you invoke it with
* arguments turning OFF all vendor extensions. Even more unfortunately, if
* we do that, it fails to parse windows.h!!!!! So, we define __STDC__ here,
* after windows.h comes in. Note: the compiler knows we've defined it, and
* starts enforcing strict ANSI compilance from this point on.
*/
#define __STDC__ 1

60
dist/win_dbsql.in vendored Normal file
View file

@ -0,0 +1,60 @@
/*-
* $Id: win_dbsql.in 7 2007-02-03 13:34:17Z gburd $
*
* The following provides the information necessary to build Berkeley
* DB on native Windows, and other Windows environments such as MinGW.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <direct.h>
#include <fcntl.h>
#include <io.h>
#include <limits.h>
#include <memory.h>
#include <process.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <time.h>
#include <errno.h>
/*
* To build Tcl interface libraries, the include path must be configured to
* use the directory containing <tcl.h>, usually the include directory in
* the Tcl distribution.
*/
#ifdef DB_TCL_SUPPORT
#include <tcl.h>
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
/*
* All of the necessary includes have been included, ignore the #includes
* in the Berkeley DB source files.
*/
#define NO_SYSTEM_INCLUDES
/*
* Win32 has getcwd, snprintf and vsnprintf, but under different names.
*/
#define getcwd(buf, size) _getcwd(buf, size)
#define snprintf _snprintf
#define vsnprintf _vsnprintf
/*
* Win32 does not define getopt and friends in any header file, so we must.
*/
#if defined(__cplusplus)
extern "C" {
#endif
extern int optind;
extern char *optarg;
extern int getopt(int, char * const *, const char *);
#if defined(__cplusplus)
}
#endif

136
dist/win_exports.in vendored Normal file
View file

@ -0,0 +1,136 @@
# $Id: win_exports.in 7 2007-02-03 13:34:17Z gburd $
# Standard interfaces.
db_create
db_env_create
db_strerror
db_version
db_xa_switch
log_compare
# Library configuration interfaces.
db_env_set_func_close
db_env_set_func_dirfree
db_env_set_func_dirlist
db_env_set_func_exists
db_env_set_func_free
db_env_set_func_fsync
db_env_set_func_ioinfo
db_env_set_func_malloc
db_env_set_func_map
db_env_set_func_open
db_env_set_func_pread
db_env_set_func_pwrite
db_env_set_func_read
db_env_set_func_realloc
db_env_set_func_rename
db_env_set_func_seek
db_env_set_func_sleep
db_env_set_func_unlink
db_env_set_func_unmap
db_env_set_func_write
db_env_set_func_yield
# Needed for application-specific logging and recovery routines.
__db_add_recovery
# These are needed to link the tcl library.
__db_dbm_close
__db_dbm_delete
__db_dbm_fetch
__db_dbm_firstkey
__db_dbm_init
__db_dbm_nextkey
__db_dbm_store
__db_hcreate
__db_hdestroy
__db_hsearch
__db_loadme
__db_ndbm_clearerr
__db_ndbm_close
__db_ndbm_delete
__db_ndbm_dirfno
__db_ndbm_error
__db_ndbm_fetch
__db_ndbm_firstkey
__db_ndbm_nextkey
__db_ndbm_open
__db_ndbm_pagfno
__db_ndbm_rdonly
__db_ndbm_store
__db_panic
__db_r_attach
__db_r_detach
__db_win32_mutex_init
__db_win32_mutex_lock
__db_win32_mutex_unlock
__ham_func2
__ham_func3
__ham_func4
__ham_func5
__ham_test
__lock_id_set
__os_calloc
__os_closehandle
__os_free
__os_ioinfo
__os_malloc
__os_open
__os_openhandle
__os_read
__os_realloc
__os_strdup
__os_umalloc
__os_write
__txn_id_set
#These are needed for linking tools or java.
__bam_init_print
__bam_pgin
__bam_pgout
__crdel_init_print
__db_dispatch
__db_dump
__db_err
__db_getlong
__db_getulong
__db_global_values
__db_init_print
__db_inmemdbflags
__db_isbigendian
__db_omode
__db_overwrite
__db_pgin
__db_pgout
__db_pr_callback
__db_prdbt
__db_prfooter
__db_prheader
__db_rpath
__db_stat_pp
__db_stat_print_pp
__db_util_cache
__db_util_interrupted
__db_util_logset
__db_util_siginit
__db_util_sigresend
__db_verify_internal
__dbreg_init_print
__fop_init_print
__ham_get_meta
__ham_init_print
__ham_pgin
__ham_pgout
__ham_release_meta
__log_stat_pp
__os_clock
__os_get_errno
__os_id
__os_set_errno
__os_sleep
__os_ufree
__os_yield
__qam_init_print
__qam_pgin_out
__rep_stat_print
__txn_init_print

203
docs_src/dbsql.1 Normal file
View file

@ -0,0 +1,203 @@
.\" Hey, EMACS: -*- nroff -*-
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH DBSQL 1 "Mon Apr 15 23:49:17 2002"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
.\" .nh disable hyphenation
.\" .hy enable hyphenation
.\" .ad l left justify
.\" .ad b justify to both left and right margins
.\" .nf disable filling
.\" .fi enable filling
.\" .br insert line break
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
dbsql \- A command line interface for DBSQL
.SH SYNOPSIS
.B dbsql
.RI [ options ] " filename " [ SQL ]
.SS SUMMARY
.PP
dbsql is a terminal-based front-end to the DBSQL library. It enables
you to type in queries interactively, issue them to DBSQL and see the
results. Alternatively, you can specify SQL code on the command-line. In
addition it provides a number of meta-commands.
.SH DESCRIPTION
This manual page documents briefly the
.B dbsql
command.
This manual page was written for the Debian GNU/Linux distribution
because the original program does not have a manual page.
.SS GETTING STARTED
.PP
To start the dbsql program, just type "dbsql" followed by the name
the file that holds the DBSQL database. If the file does not exist, a
new one is created automatically. The dbsql program will then prompt
you to enter SQL. Type in SQL statements (terminated by a semicolon),
press "Enter" and the SQL will be executed.
For example, to create a new DBSQL database named "ex1" with a single
table named "tbl1", you might do this:
.sp
.nf
$ dbsql ex1
DBSQL version 2.0.0
Enter ".help" for instructions
dbsql> create table tbl1(one varchar(10), two smallint);
dbsql> insert into tbl1 values('hello!',10);
dbsql> insert into tbl1 values('goodbye', 20);
dbsql> select * from tbl1;
hello!|10
goodbye|20
dbsql>
.sp
.fi
.SS DBSQL META-COMMANDS
.PP
Most of the time, dbsql just reads lines of input and passes them on
to the DBSQL library for execution. But if an input line begins with
a dot ("."), then that line is intercepted and interpreted by the
dbsql program itself. These "dot commands" are typically used to
change the output format of queries, or to execute certain prepackaged
query statements.
For a listing of the available dot commands, you can enter ".help" at
any time. For example:
.sp
.nf
.cc |
dbsql> .help
.dump ?TABLE? ... Dump the database in an text format
.echo ON|OFF Turn command echo on or off
.exit Exit this program
.explain ON|OFF Turn output mode suitable for EXPLAIN on or off.
"off" will revert to the output mode that was
previously in effect
.header(s) ON|OFF Turn display of headers on or off
.help Show this message
.indices TABLE Show names of all indices on TABLE
.mode MODE Set mode to one of "line(s)", "column(s)",
"insert", "list", or "html"
.mode insert TABLE Generate SQL insert statements for TABLE
.nullvalue STRING Print STRING instead of nothing for NULL data
.output FILENAME Send output to FILENAME
.output stdout Send output to the screen
.prompt MAIN CONTINUE Replace the standard prompts
"dbsql > " and " ...> "
with the strings MAIN and CONTINUE
CONTINUE is optional.
.quit Exit this program
.read FILENAME Execute SQL in FILENAME
.reindex ?TABLE? Rebuild indices
.schema ?TABLE? Show the CREATE statements
.separator STRING Change separator string for "list" mode
.show Show the current values for the following:
.echo
.explain
.mode
.nullvalue
.output
.separator
.width
.tables ?PATTERN? List names of tables matching a pattern
.timeout MS Try opening locked tables for MS milliseconds
.width NUM NUM ... Set column widths for "column" mode
dbsql>
|cc .
.sp
.fi
.SH OPTIONS
The program has the following options:
.TP
.BI \-init\ file
Read in and process 'file', which contains "dot commands".
You can use this file to initialize display settings.
.TP
.B \-html
Set output mode to HTML.
.TP
.B \-list
Set output mode to 'list'.
.TP
.B \-line
Set output mode to 'line'.
.TP
.B \-column
Set output mode to 'column'.
.TP
.BI \-separator\ separator
Specify which output field separator for 'list' mode to use.
Default is '|'.
.TP
.BI \-nullvalue\ string
When a null is encountered, print 'string'. Default is no string.
.TP
.B \-[no]header
Turn headers on or off. Default is off.
.TP
.B \-echo
Print commands before execution.
.SH OUTPUT MODE
The DBSQL program has different output modes, which define the way
the output (from queries) is formatted.
In 'list' mode, which is the default, one record per line is output,
each field separated by the separator specified with the
\fB-separator\fP option or \fB.separator\fP command.
In 'line' mode, each column is output on its own line, records are
separated by blank lines.
In HTML mode, an XHTML table is generated.
In 'column' mode, one record per line is output, aligned neatly in colums.
.SH INIT FILE
dbsql can be initialized using resource files. These can be combined with
command line arguments to set up dbsql exactly the way you want it.
Initialization proceeds as follows:
o The defaults of
.sp
.nf
.cc |
mode = LIST
separator = "|"
main prompt = "dbsql> "
continue prompt = " ...> "
|cc .
.sp
.fi
are established.
o If a file .dbsqlrc can be found in the user's home directory, it is
read and processed. It should only contain "dot commands". If the
file is not found or cannot be read, processing continues without
notification.
o If a file is specified on the command line with the -init option, it
is processed in the same manner as .dbsqlrc
o All other command line options are processed
o The database is opened and you are now ready to begin.
.SH SEE ALSO
http://dbsql.org/
.br
The dbsql-doc package
.SH AUTHOR
This manual page was originally written by Andreas Rottmann
<rotty@debian.org>, for the Debian GNU/Linux system (but may be used
by others).

892
docs_src/lemon.html Normal file
View file

@ -0,0 +1,892 @@
<html>
<head>
<title>The Lemon Parser Generator</title>
</head>
<body bgcolor=white>
<h1 align=center>The Lemon Parser Generator</h1>
<p>Lemon is an LALR(1) parser generator for C or C++.
It does the same job as ``bison'' and ``yacc''.
But lemon is not another bison or yacc clone. It
uses a different grammar syntax which is designed to
reduce the number of coding errors. Lemon also uses a more
sophisticated parsing engine that is faster than yacc and
bison and which is both reentrant and thread-safe.
Furthermore, Lemon implements features that can be used
to eliminate resource leaks, making is suitable for use
in long-running programs such as graphical user interfaces
or embedded controllers.</p>
<p>This document is an introduction to the Lemon
parser generator.</p>
<h2>Theory of Operation</h2>
<p>The main goal of Lemon is to translate a context free grammar (CFG)
for a particular language into C code that implements a parser for
that language.
The program has two inputs:
<ul>
<li>The grammar specification.
<li>A parser template file.
</ul>
Typically, only the grammar specification is supplied by the programmer.
Lemon comes with a default parser template which works fine for most
applications. But the user is free to substitute a different parser
template if desired.</p>
<p>Depending on command-line options, Lemon will generate between
one and three files of outputs.
<ul>
<li>C code to implement the parser.
<li>A header file defining an integer ID for each terminal symbol.
<li>An information file that describes the states of the generated parser
automaton.
</ul>
By default, all three of these output files are generated.
The header file is suppressed if the ``-m'' command-line option is
used and the report file is omitted when ``-q'' is selected.</p>
<p>The grammar specification file uses a ``.y'' suffix, by convention.
In the examples used in this document, we'll assume the name of the
grammar file is ``gram.y''. A typical use of Lemon would be the
following command:
<pre>
lemon gram.y
</pre>
This command will generate three output files named ``gram.c'',
``gram.h'' and ``gram.out''.
The first is C code to implement the parser. The second
is the header file that defines numerical values for all
terminal symbols, and the last is the report that explains
the states used by the parser automaton.</p>
<h3>Command Line Options</h3>
<p>The behavior of Lemon can be modified using command-line options.
You can obtain a list of the available command-line options together
with a brief explanation of what each does by typing
<pre>
lemon -?
</pre>
As of this writing, the following command-line options are supported:
<ul>
<li><tt>-b</tt>
<li><tt>-c</tt>
<li><tt>-g</tt>
<li><tt>-m</tt>
<li><tt>-q</tt>
<li><tt>-s</tt>
<li><tt>-x</tt>
</ul>
The ``-b'' option reduces the amount of text in the report file by
printing only the basis of each parser state, rather than the full
configuration.
The ``-c'' option suppresses action table compression. Using -c
will make the parser a little larger and slower but it will detect
syntax errors sooner.
The ``-g'' option causes no output files to be generated at all.
Instead, the input grammar file is printed on standard output but
with all comments, actions and other extraneous text deleted. This
is a useful way to get a quick summary of a grammar.
The ``-m'' option causes the output C source file to be compatible
with the ``makeheaders'' program.
Makeheaders is a program that automatically generates header files
from C source code. When the ``-m'' option is used, the header
file is not output since the makeheaders program will take care
of generated all header files automatically.
The ``-q'' option suppresses the report file.
Using ``-s'' causes a brief summary of parser statistics to be
printed. Like this:
<pre>
Parser statistics: 74 terminals, 70 nonterminals, 179 rules
340 states, 2026 parser table entries, 0 conflicts
</pre>
Finally, the ``-x'' option causes Lemon to print its version number
and then stops without attempting to read the grammar or generate a parser.</p>
<h3>The Parser Interface</h3>
<p>Lemon doesn't generate a complete, working program. It only generates
a few subroutines that implement a parser. This section describes
the interface to those subroutines. It is up to the programmer to
call these subroutines in an appropriate way in order to produce a
complete system.</p>
<p>Before a program begins using a Lemon-generated parser, the program
must first create the parser.
A new parser is created as follows:
<pre>
void *pParser = ParseAlloc( malloc );
</pre>
The ParseAlloc() routine allocates and initializes a new parser and
returns a pointer to it.
The actual data structure used to represent a parser is opaque --
its internal structure is not visible or usable by the calling routine.
For this reason, the ParseAlloc() routine returns a pointer to void
rather than a pointer to some particular structure.
The sole argument to the ParseAlloc() routine is a pointer to the
subroutine used to allocate memory. Typically this means ``malloc()''.</p>
<p>After a program is finished using a parser, it can reclaim all
memory allocated by that parser by calling
<pre>
ParseFree(pParser, free);
</pre>
The first argument is the same pointer returned by ParseAlloc(). The
second argument is a pointer to the function used to release bulk
memory back to the system.</p>
<p>After a parser has been allocated using ParseAlloc(), the programmer
must supply the parser with a sequence of tokens (terminal symbols) to
be parsed. This is accomplished by calling the following function
once for each token:
<pre>
Parse(pParser, hTokenID, sTokenData, pArg);
</pre>
The first argument to the Parse() routine is the pointer returned by
ParseAlloc().
The second argument is a small positive integer that tells the parse the
type of the next token in the data stream.
There is one token type for each terminal symbol in the grammar.
The gram.h file generated by Lemon contains #define statements that
map symbolic terminal symbol names into appropriate integer values.
(A value of 0 for the second argument is a special flag to the
parser to indicate that the end of input has been reached.)
The third argument is the value of the given token. By default,
the type of the third argument is integer, but the grammar will
usually redefine this type to be some kind of structure.
Typically the second argument will be a broad category of tokens
such as ``identifier'' or ``number'' and the third argument will
be the name of the identifier or the value of the number.</p>
<p>The Parse() function may have either three or four arguments,
depending on the grammar. If the grammar specification file request
it, the Parse() function will have a fourth parameter that can be
of any type chosen by the programmer. The parser doesn't do anything
with this argument except to pass it through to action routines.
This is a convenient mechanism for passing state information down
to the action routines without having to use global variables.</p>
<p>A typical use of a Lemon parser might look something like the
following:
<pre>
01 ParseTree *ParseFile(const char *zFilename){
02 Tokenizer *pTokenizer;
03 void *pParser;
04 Token sToken;
05 int hTokenId;
06 ParserState sState;
07
08 pTokenizer = TokenizerCreate(zFilename);
09 pParser = ParseAlloc( malloc );
10 InitParserState(&sState);
11 while( GetNextToken(pTokenizer, &hTokenId, &sToken) ){
12 Parse(pParser, hTokenId, sToken, &sState);
13 }
14 Parse(pParser, 0, sToken, &sState);
15 ParseFree(pParser, free );
16 TokenizerFree(pTokenizer);
17 return sState.treeRoot;
18 }
</pre>
This example shows a user-written routine that parses a file of
text and returns a pointer to the parse tree.
(We've omitted all error-handling from this example to keep it
simple.)
We assume the existence of some kind of tokenizer which is created
using TokenizerCreate() on line 8 and deleted by TokenizerFree()
on line 16. The GetNextToken() function on line 11 retrieves the
next token from the input file and puts its type in the
integer variable hTokenId. The sToken variable is assumed to be
some kind of structure that contains details about each token,
such as its complete text, what line it occurs on, etc. </p>
<p>This example also assumes the existence of structure of type
ParserState that holds state information about a particular parse.
An instance of such a structure is created on line 6 and initialized
on line 10. A pointer to this structure is passed into the Parse()
routine as the optional 4th argument.
The action routine specified by the grammar for the parser can use
the ParserState structure to hold whatever information is useful and
appropriate. In the example, we note that the treeRoot field of
the ParserState structure is left pointing to the root of the parse
tree.</p>
<p>The core of this example as it relates to Lemon is as follows:
<pre>
ParseFile(){
pParser = ParseAlloc( malloc );
while( GetNextToken(pTokenizer,&hTokenId, &sToken) ){
Parse(pParser, hTokenId, sToken);
}
Parse(pParser, 0, sToken);
ParseFree(pParser, free );
}
</pre>
Basically, what a program has to do to use a Lemon-generated parser
is first create the parser, then send it lots of tokens obtained by
tokenizing an input source. When the end of input is reached, the
Parse() routine should be called one last time with a token type
of 0. This step is necessary to inform the parser that the end of
input has been reached. Finally, we reclaim memory used by the
parser by calling ParseFree().</p>
<p>There is one other interface routine that should be mentioned
before we move on.
The ParseTrace() function can be used to generate debugging output
from the parser. A prototype for this routine is as follows:
<pre>
ParseTrace(FILE *stream, char *zPrefix);
</pre>
After this routine is called, a short (one-line) message is written
to the designated output stream every time the parser changes states
or calls an action routine. Each such message is prefaced using
the text given by zPrefix. This debugging output can be turned off
by calling ParseTrace() again with a first argument of NULL (0).</p>
<h3>Differences With YACC and BISON</h3>
<p>Programmers who have previously used the yacc or bison parser
generator will notice several important differences between yacc and/or
bison and Lemon.
<ul>
<li>In yacc and bison, the parser calls the tokenizer. In Lemon,
the tokenizer calls the parser.
<li>Lemon uses no global variables. Yacc and bison use global variables
to pass information between the tokenizer and parser.
<li>Lemon allows multiple parsers to be running simultaneously. Yacc
and bison do not.
</ul>
These differences may cause some initial confusion for programmers
with prior yacc and bison experience.
But after years of experience using Lemon, I firmly
believe that the Lemon way of doing things is better.</p>
<h2>Input File Syntax</h2>
<p>The main purpose of the grammar specification file for Lemon is
to define the grammar for the parser. But the input file also
specifies additional information Lemon requires to do its job.
Most of the work in using Lemon is in writing an appropriate
grammar file.</p>
<p>The grammar file for lemon is, for the most part, free format.
It does not have sections or divisions like yacc or bison. Any
declaration can occur at any point in the file.
Lemon ignores whitespace (except where it is needed to separate
tokens) and it honors the same commenting conventions as C and C++.</p>
<h3>Terminals and Nonterminals</h3>
<p>A terminal symbol (token) is any string of alphanumeric
and underscore characters
that begins with an upper case letter.
A terminal can contain lower class letters after the first character,
but the usual convention is to make terminals all upper case.
A nonterminal, on the other hand, is any string of alphanumeric
and underscore characters than begins with a lower case letter.
Again, the usual convention is to make nonterminals use all lower
case letters.</p>
<p>In Lemon, terminal and nonterminal symbols do not need to
be declared or identified in a separate section of the grammar file.
Lemon is able to generate a list of all terminals and nonterminals
by examining the grammar rules, and it can always distinguish a
terminal from a nonterminal by checking the case of the first
character of the name.</p>
<p>Yacc and bison allow terminal symbols to have either alphanumeric
names or to be individual characters included in single quotes, like
this: ')' or '$'. Lemon does not allow this alternative form for
terminal symbols. With Lemon, all symbols, terminals and nonterminals,
must have alphanumeric names.</p>
<h3>Grammar Rules</h3>
<p>The main component of a Lemon grammar file is a sequence of grammar
rules.
Each grammar rule consists of a nonterminal symbol followed by
the special symbol ``::='' and then a list of terminals and/or nonterminals.
The rule is terminated by a period.
The list of terminals and nonterminals on the right-hand side of the
rule can be empty.
Rules can occur in any order, except that the left-hand side of the
first rule is assumed to be the start symbol for the grammar (unless
specified otherwise using the <tt>%start</tt> directive described below.)
A typical sequence of grammar rules might look something like this:
<pre>
expr ::= expr PLUS expr.
expr ::= expr TIMES expr.
expr ::= LPAREN expr RPAREN.
expr ::= VALUE.
</pre>
</p>
<p>There is one non-terminal in this example, ``expr'', and five
terminal symbols or tokens: ``PLUS'', ``TIMES'', ``LPAREN'',
``RPAREN'' and ``VALUE''.</p>
<p>Like yacc and bison, Lemon allows the grammar to specify a block
of C code that will be executed whenever a grammar rule is reduced
by the parser.
In Lemon, this action is specified by putting the C code (contained
within curly braces <tt>{...}</tt>) immediately after the
period that closes the rule.
For example:
<pre>
expr ::= expr PLUS expr. { printf("Doing an addition...\n"); }
</pre>
</p>
<p>In order to be useful, grammar actions must normally be linked to
their associated grammar rules.
In yacc and bison, this is accomplished by embedding a ``$$'' in the
action to stand for the value of the left-hand side of the rule and
symbols ``$1'', ``$2'', and so forth to stand for the value of
the terminal or nonterminal at position 1, 2 and so forth on the
right-hand side of the rule.
This idea is very powerful, but it is also very error-prone. The
single most common source of errors in a yacc or bison grammar is
to miscount the number of symbols on the right-hand side of a grammar
rule and say ``$7'' when you really mean ``$8''.</p>
<p>Lemon avoids the need to count grammar symbols by assigning symbolic
names to each symbol in a grammar rule and then using those symbolic
names in the action.
In yacc or bison, one would write this:
<pre>
expr -> expr PLUS expr { $$ = $1 + $3; };
</pre>
But in Lemon, the same rule becomes the following:
<pre>
expr(A) ::= expr(B) PLUS expr(C). { A = B+C; }
</pre>
In the Lemon rule, any symbol in parentheses after a grammar rule
symbol becomes a place holder for that symbol in the grammar rule.
This place holder can then be used in the associated C action to
stand for the value of that symbol.<p>
<p>The Lemon notation for linking a grammar rule with its reduce
action is superior to yacc/bison on several counts.
First, as mentioned above, the Lemon method avoids the need to
count grammar symbols.
Secondly, if a terminal or nonterminal in a Lemon grammar rule
includes a linking symbol in parentheses but that linking symbol
is not actually used in the reduce action, then an error message
is generated.
For example, the rule
<pre>
expr(A) ::= expr(B) PLUS expr(C). { A = B; }
</pre>
will generate an error because the linking symbol ``C'' is used
in the grammar rule but not in the reduce action.</p>
<p>The Lemon notation for linking grammar rules to reduce actions
also facilitates the use of destructors for reclaiming memory
allocated by the values of terminals and nonterminals on the
right-hand side of a rule.</p>
<h3>Precedence Rules</h3>
<p>Lemon resolves parsing ambiguities in exactly the same way as
yacc and bison. A shift-reduce conflict is resolved in favor
of the shift, and a reduce-reduce conflict is resolved by reducing
whichever rule comes first in the grammar file.</p>
<p>Just like in
yacc and bison, Lemon allows a measure of control
over the resolution of paring conflicts using precedence rules.
A precedence value can be assigned to any terminal symbol
using the %left, %right or %nonassoc directives. Terminal symbols
mentioned in earlier directives have a lower precedence that
terminal symbols mentioned in later directives. For example:</p>
<p><pre>
%left AND.
%left OR.
%nonassoc EQ NE GT GE LT LE.
%left PLUS MINUS.
%left TIMES DIVIDE MOD.
%right EXP NOT.
</pre></p>
<p>In the preceding sequence of directives, the AND operator is
defined to have the lowest precedence. The OR operator is one
precedence level higher. And so forth. Hence, the grammar would
attempt to group the ambiguous expression
<pre>
a AND b OR c
</pre>
like this
<pre>
a AND (b OR c).
</pre>
The associativity (left, right or nonassoc) is used to determine
the grouping when the precedence is the same. AND is left-associative
in our example, so
<pre>
a AND b AND c
</pre>
is parsed like this
<pre>
(a AND b) AND c.
</pre>
The EXP operator is right-associative, though, so
<pre>
a EXP b EXP c
</pre>
is parsed like this
<pre>
a EXP (b EXP c).
</pre>
The nonassoc precedence is used for non-associative operators.
So
<pre>
a EQ b EQ c
</pre>
is an error.</p>
<p>The precedence of non-terminals is transferred to rules as follows:
The precedence of a grammar rule is equal to the precedence of the
left-most terminal symbol in the rule for which a precedence is
defined. This is normally what you want, but in those cases where
you want to precedence of a grammar rule to be something different,
you can specify an alternative precedence symbol by putting the
symbol in square braces after the period at the end of the rule and
before any C-code. For example:</p>
<p><pre>
expr = MINUS expr. [NOT]
</pre></p>
<p>This rule has a precedence equal to that of the NOT symbol, not the
MINUS symbol as would have been the case by default.</p>
<p>With the knowledge of how precedence is assigned to terminal
symbols and individual
grammar rules, we can now explain precisely how parsing conflicts
are resolved in Lemon. Shift-reduce conflicts are resolved
as follows:
<ul>
<li> If either the token to be shifted or the rule to be reduced
lacks precedence information, then resolve in favor of the
shift, but report a parsing conflict.
<li> If the precedence of the token to be shifted is greater than
the precedence of the rule to reduce, then resolve in favor
of the shift. No parsing conflict is reported.
<li> If the precedence of the token it be shifted is less than the
precedence of the rule to reduce, then resolve in favor of the
reduce action. No parsing conflict is reported.
<li> If the precedences are the same and the shift token is
right-associative, then resolve in favor of the shift.
No parsing conflict is reported.
<li> If the precedences are the same the the shift token is
left-associative, then resolve in favor of the reduce.
No parsing conflict is reported.
<li> Otherwise, resolve the conflict by doing the shift and
report the parsing conflict.
</ul>
Reduce-reduce conflicts are resolved this way:
<ul>
<li> If either reduce rule
lacks precedence information, then resolve in favor of the
rule that appears first in the grammar and report a parsing
conflict.
<li> If both rules have precedence and the precedence is different
then resolve the dispute in favor of the rule with the highest
precedence and do not report a conflict.
<li> Otherwise, resolve the conflict by reducing by the rule that
appears first in the grammar and report a parsing conflict.
</ul>
<h3>Special Directives</h3>
<p>The input grammar to Lemon consists of grammar rules and special
directives. We've described all the grammar rules, so now we'll
talk about the special directives.</p>
<p>Directives in lemon can occur in any order. You can put them before
the grammar rules, or after the grammar rules, or in the mist of the
grammar rules. It doesn't matter. The relative order of
directives used to assign precedence to terminals is important, but
other than that, the order of directives in Lemon is arbitrary.</p>
<p>Lemon supports the following special directives:
<ul>
<li><tt>%code</tt>
<li><tt>%default_destructor</tt>
<li><tt>%default_type</tt>
<li><tt>%destructor</tt>
<li><tt>%extra_argument</tt>
<li><tt>%include</tt>
<li><tt>%left</tt>
<li><tt>%name</tt>
<li><tt>%nonassoc</tt>
<li><tt>%parse_accept</tt>
<li><tt>%parse_failure </tt>
<li><tt>%right</tt>
<li><tt>%stack_overflow</tt>
<li><tt>%stack_size</tt>
<li><tt>%start_symbol</tt>
<li><tt>%syntax_error</tt>
<li><tt>%token_destructor</tt>
<li><tt>%token_prefix</tt>
<li><tt>%token_type</tt>
<li><tt>%type</tt>
</ul>
Each of these directives will be described separately in the
following sections:</p>
<h4>The <tt>%code</tt> directive</h4>
<p>The %code directive is used to specify addition C/C++ code that
is added to the end of the main output file. This is similar to
the %include directive except that %include is inserted at the
beginning of the main output file.</p>
<p>%code is typically used to include some action routines or perhaps
a tokenizer as part of the output file.</p>
<h4>The <tt>%default_destructor</tt> directive</h4>
<p>The %default_destructor directive specifies a destructor to
use for non-terminals that do not have their own destructor
specified by a separate %destructor directive. See the documentation
on the %destructor directive below for additional information.</p>
<p>In some grammers, many different non-terminal symbols have the
same datatype and hence the same destructor. This directive is
a convenience way to specify the same destructor for all those
non-terminals using a single statement.</p>
<h4>The <tt>%default_type</tt> directive</h4>
<p>The %default_type directive specifies the datatype of non-terminal
symbols that do no have their own datatype defined using a separate
%type directive. See the documentation on %type below for addition
information.</p>
<h4>The <tt>%destructor</tt> directive</h4>
<p>The %destructor directive is used to specify a destructor for
a non-terminal symbol.
(See also the %token_destructor directive which is used to
specify a destructor for terminal symbols.)</p>
<p>A non-terminal's destructor is called to dispose of the
non-terminal's value whenever the non-terminal is popped from
the stack. This includes all of the following circumstances:
<ul>
<li> When a rule reduces and the value of a non-terminal on
the right-hand side is not linked to C code.
<li> When the stack is popped during error processing.
<li> When the ParseFree() function runs.
</ul>
The destructor can do whatever it wants with the value of
the non-terminal, but its design is to deallocate memory
or other resources held by that non-terminal.</p>
<p>Consider an example:
<pre>
%type nt {void*}
%destructor nt { free($$); }
nt(A) ::= ID NUM. { A = malloc( 100 ); }
</pre>
This example is a bit contrived but it serves to illustrate how
destructors work. The example shows a non-terminal named
``nt'' that holds values of type ``void*''. When the rule for
an ``nt'' reduces, it sets the value of the non-terminal to
space obtained from malloc(). Later, when the nt non-terminal
is popped from the stack, the destructor will fire and call
free() on this malloced space, thus avoiding a memory leak.
(Note that the symbol ``$$'' in the destructor code is replaced
by the value of the non-terminal.)</p>
<p>It is important to note that the value of a non-terminal is passed
to the destructor whenever the non-terminal is removed from the
stack, unless the non-terminal is used in a C-code action. If
the non-terminal is used by C-code, then it is assumed that the
C-code will take care of destroying it if it should really
be destroyed. More commonly, the value is used to build some
larger structure and we don't want to destroy it, which is why
the destructor is not called in this circumstance.</p>
<p>By appropriate use of destructors, it is possible to
build a parser using Lemon that can be used within a long-running
program, such as a GUI, that will not leak memory or other resources.
To do the same using yacc or bison is much more difficult.</p>
<h4>The <tt>%extra_argument</tt> directive</h4>
The %extra_argument directive instructs Lemon to add a 4th parameter
to the parameter list of the Parse() function it generates. Lemon
doesn't do anything itself with this extra argument, but it does
make the argument available to C-code action routines, destructors,
and so forth. For example, if the grammar file contains:</p>
<p><pre>
%extra_argument { MyStruct *pAbc }
</pre></p>
<p>Then the Parse() function generated will have an 4th parameter
of type ``MyStruct*'' and all action routines will have access to
a variable named ``pAbc'' that is the value of the 4th parameter
in the most recent call to Parse().</p>
<h4>The <tt>%include</tt> directive</h4>
<p>The %include directive specifies C code that is included at the
top of the generated parser. You can include any text you want --
the Lemon parser generator copies it blindly. If you have multiple
%include directives in your grammar file the value of the last
%include directive overwrites all the others.</p.
<p>The %include directive is very handy for getting some extra #include
preprocessor statements at the beginning of the generated parser.
For example:</p>
<p><pre>
%include {#include &lt;unistd.h&gt;}
</pre></p>
<p>This might be needed, for example, if some of the C actions in the
grammar call functions that are prototyed in unistd.h.</p>
<h4>The <tt>%left</tt> directive</h4>
The %left directive is used (along with the %right and
%nonassoc directives) to declare precedences of terminal
symbols. Every terminal symbol whose name appears after
a %left directive but before the next period (``.'') is
given the same left-associative precedence value. Subsequent
%left directives have higher precedence. For example:</p>
<p><pre>
%left AND.
%left OR.
%nonassoc EQ NE GT GE LT LE.
%left PLUS MINUS.
%left TIMES DIVIDE MOD.
%right EXP NOT.
</pre></p>
<p>Note the period that terminates each %left, %right or %nonassoc
directive.</p>
<p>LALR(1) grammars can get into a situation where they require
a large amount of stack space if you make heavy use or right-associative
operators. For this reason, it is recommended that you use %left
rather than %right whenever possible.</p>
<h4>The <tt>%name</tt> directive</h4>
<p>By default, the functions generated by Lemon all begin with the
five-character string ``Parse''. You can change this string to something
different using the %name directive. For instance:</p>
<p><pre>
%name Abcde
</pre></p>
<p>Putting this directive in the grammar file will cause Lemon to generate
functions named
<ul>
<li> AbcdeAlloc(),
<li> AbcdeFree(),
<li> AbcdeTrace(), and
<li> Abcde().
</ul>
The %name directive allows you to generator two or more different
parsers and link them all into the same executable.
</p>
<h4>The <tt>%nonassoc</tt> directive</h4>
<p>This directive is used to assign non-associative precedence to
one or more terminal symbols. See the section on precedence rules
or on the %left directive for additional information.</p>
<h4>The <tt>%parse_accept</tt> directive</h4>
<p>The %parse_accept directive specifies a block of C code that is
executed whenever the parser accepts its input string. To ``accept''
an input string means that the parser was able to process all tokens
without error.</p>
<p>For example:</p>
<p><pre>
%parse_accept {
printf("parsing complete!\n");
}
</pre></p>
<h4>The <tt>%parse_failure</tt> directive</h4>
<p>The %parse_failure directive specifies a block of C code that
is executed whenever the parser fails complete. This code is not
executed until the parser has tried and failed to resolve an input
error using is usual error recovery strategy. The routine is
only invoked when parsing is unable to continue.</p>
<p><pre>
%parse_failure {
fprintf(stderr,"Giving up. Parser is hopelessly lost...\n");
}
</pre></p>
<h4>The <tt>%right</tt> directive</h4>
<p>This directive is used to assign right-associative precedence to
one or more terminal symbols. See the section on precedence rules
or on the %left directive for additional information.</p>
<h4>The <tt>%stack_overflow</tt> directive</h4>
<p>The %stack_overflow directive specifies a block of C code that
is executed if the parser's internal stack ever overflows. Typically
this just prints an error message. After a stack overflow, the parser
will be unable to continue and must be reset.</p>
<p><pre>
%stack_overflow {
fprintf(stderr,"Giving up. Parser stack overflow\n");
}
</pre></p>
<p>You can help prevent parser stack overflows by avoiding the use
of right recursion and right-precedence operators in your grammar.
Use left recursion and and left-precedence operators instead, to
encourage rules to reduce sooner and keep the stack size down.
For example, do rules like this:
<pre>
list ::= list element. // left-recursion. Good!
list ::= .
</pre>
Not like this:
<pre>
list ::= element list. // right-recursion. Bad!
list ::= .
</pre>
<h4>The <tt>%stack_size</tt> directive</h4>
<p>If stack overflow is a problem and you can't resolve the trouble
by using left-recursion, then you might want to increase the size
of the parser's stack using this directive. Put an positive integer
after the %stack_size directive and Lemon will generate a parse
with a stack of the requested size. The default value is 100.</p>
<p><pre>
%stack_size 2000
</pre></p>
<h4>The <tt>%start_symbol</tt> directive</h4>
<p>By default, the start-symbol for the grammar that Lemon generates
is the first non-terminal that appears in the grammar file. But you
can choose a different start-symbol using the %start_symbol directive.</p>
<p><pre>
%start_symbol prog
</pre></p>
<h4>The <tt>%token_destructor</tt> directive</h4>
<p>The %destructor directive assigns a destructor to a non-terminal
symbol. (See the description of the %destructor directive above.)
This directive does the same thing for all terminal symbols.</p>
<p>Unlike non-terminal symbols which may each have a different data type
for their values, terminals all use the same data type (defined by
the %token_type directive) and so they use a common destructor. Other
than that, the token destructor works just like the non-terminal
destructors.</p>
<h4>The <tt>%token_prefix</tt> directive</h4>
<p>Lemon generates #defines that assign small integer constants
to each terminal symbol in the grammar. If desired, Lemon will
add a prefix specified by this directive
to each of the #defines it generates.
So if the default output of Lemon looked like this:
<pre>
#define AND 1
#define MINUS 2
#define OR 3
#define PLUS 4
</pre>
You can insert a statement into the grammar like this:
<pre>
%token_prefix TOKEN_
</pre>
to cause Lemon to produce these symbols instead:
<pre>
#define TOKEN_AND 1
#define TOKEN_MINUS 2
#define TOKEN_OR 3
#define TOKEN_PLUS 4
</pre>
<h4>The <tt>%token_type</tt> and <tt>%type</tt> directives</h4>
<p>These directives are used to specify the data types for values
on the parser's stack associated with terminal and non-terminal
symbols. The values of all terminal symbols must be of the same
type. This turns out to be the same data type as the 3rd parameter
to the Parse() function generated by Lemon. Typically, you will
make the value of a terminal symbol by a pointer to some kind of
token structure. Like this:</p>
<p><pre>
%token_type {Token*}
</pre></p>
<p>If the data type of terminals is not specified, the default value
is ``int''.</p>
<p>Non-terminal symbols can each have their own data types. Typically
the data type of a non-terminal is a pointer to the root of a parse-tree
structure that contains all information about that non-terminal.
For example:</p>
<p><pre>
%type expr {Expr*}
</pre></p>
<p>Each entry on the parser's stack is actually a union containing
instances of all data types for every non-terminal and terminal symbol.
Lemon will automatically use the correct element of this union depending
on what the corresponding non-terminal or terminal symbol is. But
the grammar designer should keep in mind that the size of the union
will be the size of its largest element. So if you have a single
non-terminal whose data type requires 1K of storage, then your 100
entry parser stack will require 100K of heap space. If you are willing
and able to pay that price, fine. You just need to know.</p>
<h3>Error Processing</h3>
<p>After extensive experimentation over several years, it has been
discovered that the error recovery strategy used by yacc is about
as good as it gets. And so that is what Lemon uses.</p>
<p>When a Lemon-generated parser encounters a syntax error, it
first invokes the code specified by the %syntax_error directive, if
any. It then enters its error recovery strategy. The error recovery
strategy is to begin popping the parsers stack until it enters a
state where it is permitted to shift a special non-terminal symbol
named ``error''. It then shifts this non-terminal and continues
parsing. But the %syntax_error routine will not be called again
until at least three new tokens have been successfully shifted.</p>
<p>If the parser pops its stack until the stack is empty, and it still
is unable to shift the error symbol, then the %parse_failed routine
is invoked and the parser resets itself to its start state, ready
to begin parsing a new file. This is what will happen at the very
first syntax error, of course, if there are no instances of the
``error'' non-terminal in your grammar.</p>
</body>
</html>

141
src/TODO Normal file
View file

@ -0,0 +1,141 @@
--- Things to fix before 1.0
* search for TODO and fix in all files
* review use of __os_malloc verses __os_umalloc
* strcasecmp.c: what about UNICODE?
* --enable-sqlite-compat create the sqlite compat api
* --disable-statistics
* command line tools
* dbsql
* --bcp bulk copy from file
* integrate the new 4.3 unique id generation
* replace NDEBUG with DIAGNOSTIC
* ask about optimizations for MySQL, incorporate into DBSQL
* modify types to be less ambiguous int -> u_int32_t
* work bottom up, and top down knitting DB access patterns in
* grep for 'return [0-9]+' and replace with #defines that make more sense
* change all 'return XXX;' statements to be 'return (XXX);'
* replace '(char*)0' with NULL or some such thing
* look for and try to replace (void*) casts
* move dbsql_get_encoding global into DBSQL->[get,set]_encoding()
* rewrite error reporting, get rid of __str_urealloc and err_msgs
* lint, lclint and splint checking
* spell check comments, docs, etc - add standard spell.ok etc stuff
* grep for "Malloc Failed", fix
* replace home grown linked lists(src_list) with macro implementations of same
* dbsql_create_env() should do the following as a default setup:
To minimize the amount of space taken up by the log files,
configure Berkeley DB to have small log files (see the
DbEnv.set_lg_max method), do frequent checkpoints (see the
DbEnv.txn_checkpoint method), and automatically remove log
files (see the DB_LOG_AUTOREMOVE flag to the DbEnv.set_flags
method). -- Keith
* purify - memory leak/buffer overrun check
* profile - gprof(1) - profile run, look for hot spots
* produce and examine a code coverage report
* fix places where I moved local scope vars to function scope vars (as I go)
* consider using a DB_SEQ for 'int priorNewRowid; /* Last generated ROWID */'
* what is the difference between DBSQL_STATUS_ERROR verses DBSQL_RUN_RECOVERY
when should one be used over the other? check usage.
* DBSQL->{sg}et_verbose
* stats?
* How will TRIGGERS work in a multi env setup or worse yet, when replicated?
* add .describe [command] ('.describe select') to dbsql
* add .edit [!n] to open $EDITOR on historical statement
* examine the MySQL command line interface, add best features
* TRUNCATE table [tablename]
* use something similar to readline in shell (but not readline, its GPL)
--- 1.1
* cxx
* Java
* JDBC type ???
* make the data types user definable via codec functions
* ASSOCIATE select_stmt WITH db_database_name [READ ONLY|READ WRITE]
KEY 'printf format expression' VALUE AS 'printf format expression'
* select @@IDENTITY
* SEQUENCE http://otn.oracle.com/products/rdb/pdf/0307_sequences.pdf
* XOpen CLI (==ODBC) implementation
* --enable-regex-like (e.g. 'SELECT * from Person where name like /B(u|i|y)rd/;')
--- 2.0
* note that cg_where.c has a WHERE clause limit of 100 search for wc_exprs[101]
* note in cg_where.c that if the 33rd table of a join has an index it won't
be found or used as the bitmask method uses an u_int_32, consider fixing this
* LibSDB interface http://siag.nu/libsdb/
* --enable-xml
http://www.throwingbeans.org/tech/postgresql_and_xml.html
http://weblog.infoworld.com/udell/2003/03/12.html#a637
http://www.sqlxml.org/
http://www.perfectxml.com/SQLXML.asp
http://www.sqlxml.org/faqs.aspx?faq=103
* 64bit clean http://www.treblig.org/articles/64bits.html
* Create View INFORMATION_SCHEMA_TABLES as
Select * from ( select 'main' as TABLE_CATALOG , 'sqlite' as TABLE_SCHEMA , tbl_name as TABLE_NAME , case when type = 'table' then 'BASE TABLE' when type = 'view' then 'VIEW' end as TABLE_TYPE, sql as TABLE_SOURCE from sqlite_master where type in('table','view') and tbl_name not like 'INFORMATION_SCHEMA_%' union select 'main' as TABLE_CATALOG , 'sqlite' as TABLE_SCHEMA , tbl_name as TABLE_NAME , case when type = 'table' then 'TEMPORARY TABLE' when type = 'view' then 'TEMPORARY VIEW' end as TABLE_TYPE, sql as TABLE_SOURCE from sqlite_temp_master where type in('table','view') and tbl_name not like 'INFORMATION_SCHEMA_%' ) BT order by TABLE_TYPE , TABLE_NAME
--- 3.0
* --enable-full-text-searching
CONTAINS full text index, stemming, etc.
* server
* replication
* build in severial replication methods, TCP p2p, TCP broadcast,
UDP broadcast, multicast
* discovery
* on mac, use rendevous
* on UNIX use SLRP
* use kqueues, /dev/poll, rt-signals etc - I think there is a lib that abstracts this
--- Debugging
* build dbsql_sim - randomly exercises the system hoping to uncover bugs
* build dbsql_perf - measures performance of things relase/release vs baseline
* OSDB http://osdb.sourceforge.net/
--- Missing SQL92 features
* TRUNCATE table [tablename]
* ???
--- Competition
* http://mindprod.com/jgloss/sql.html
--- Everything else...
* look at the API of http://www.xtgsystems.com/linux/simdb/doc.php
* http://www.sqlsummit.com/ODBCPORT.HTM
* http://en.wikipedia.org/wiki/ODBC
* dbExpress, is it some ODBC-like API
* http://www.thinksql.co.uk/Main/Documents/Multiversion.html
* http://www.rpbourret.com/xml/XMLDatabaseProds.htm
* http://www.rpbourret.com/xml/XMLAndDatabases.htm
--- Google AdWords
MySQL, sql, sql92, sqlite, jet database, ms access, access, sql engine,
--- References
http://www.wiscorp.com/SQLStandards.html
http://www.ocelot.ca/nist.htm
http://www.jcc.com/SQLPages/jccs_sql.htm
http://www.tdan.com/i016hy01.htm
http://www.mimer.com/news.asp?secId=176&itemId=10
http://www.itl.nist.gov/div897/ctg/sql-testing/sqlman60.htm
http://www.opengroup.org/public/tech/datam/sql.htm
http://www.dwm.uni-hildesheim.de/homes/r_maximi/SQL1998/CLICK_ME_SECOND.html
http://www.iam.unibe.ch/~scg/Archive/Software/FreeDB/FreeDB.list.html
http://www.infres.enst.fr/naw-home/doc/srfsqlhtml_bnf.html
http://www.ontko.com/~rayo/database.html
http://www.ocelot.ca/sites.htm
http://www.sqlcorner.com/
http://www.codebox.8m.com/sql.htm
http://sqlzoo.net/sql92.html
http://www.opengroup.org/testing/testsuites/nistsql.htm
http://ou800doc.caldera.com/SDK_netapi/CTOC-xtiN.intro.html
http://cui.unige.ch/db-research/Enseignement/analyseinfo/SQL7/BNFindex.html
http://cui.unige.ch/db-research/Enseignement/analyseinfo/SQL92/BNFindex.html
http://cui.unige.ch/db-research/Enseignement/analyseinfo/PLSQL21/BNFindex.html
http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?relational+algebra
http://support.openlinksw.com/support/mac-faq.html
@misc{ gukal-fast,
author = "Sreenivas Gukal and Edward Omiecinski and Umakishore Ramachandran",
title = "Fast Recovery in Transient-Versioned Databases",
url = "citeseer.nj.nec.com/38354.html" }

1492
src/api.c Normal file

File diff suppressed because it is too large Load diff

279
src/api_table.c Normal file
View file

@ -0,0 +1,279 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: api_table.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* This file contains the __api_get_table() and __api_free_table()
* interface routines. These are just wrappers around the main
* interface routine of DBSQL->exec().
*
* These routines are in a separate files so that they will not be linked
* if they are not used.
*/
#include "dbsql_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <stdlib.h>
#include <string.h>
#endif
#include "dbsql_int.h"
/*
* This structure is used to pass data from __get_table() through
* to the user's callback function.
*/
typedef struct table_result {
char **result;
char *err_msgs;
u_int32_t num_result;
u_int32_t num_alloc;
u_int32_t num_row;
u_int32_t num_col;
u_int32_t num_data;
u_int32_t rc;
} table_result_t;
/*
* __get_table_cb --
* This routine is called once for each row in the result table. Its job
* is to fill in the table_result_t structure appropriately, allocating
* new memory as necessary.
*
* STATIC: static int __get_table_cb __P((void *, int, char **, char **));
*/
static int
__get_table_cb(arg, ncol, argv, colv)
void *arg;
int ncol;
char **argv;
char **colv;
{
int rc;
table_result_t *p = (table_result_t*)arg;
int need;
int i;
char *z;
/*
* Make sure there is enough space in p->result to hold everything
* we need to remember from this invocation of the callback.
*/
if (p->num_row == 0 && argv != 0) {
need = ncol * 2;
} else {
need = ncol;
}
if (p->num_data + need >= p->num_alloc) {
p->num_alloc = (p->num_alloc * 2) + need + 1;
rc = __dbsql_realloc(NULL, sizeof(char*) * p->num_alloc,
&p->result);
if (rc == ENOMEM) {
p->rc = DBSQL_NOMEM;
return DBSQL_ERROR;
}
}
/*
* If this is the first row, then generate an extra row containing
* the names of all columns.
*/
if (p->num_row==0) {
p->num_col = ncol;
for (i = 0; i < ncol; i++) {
if (colv[i] == 0) {
z = 0;
} else {
int rc = __dbsql_malloc(NULL,
strlen(colv[i]) + 1, &z);
if (rc == ENOMEM) {
p->rc = DBSQL_NOMEM;
return DBSQL_ERROR;
}
strcpy(z, colv[i]);
}
p->result[p->num_data++] = z;
}
} else if (p->num_col != ncol) {
__str_append(&p->err_msgs,
"DBSQL->get_table() called with two or more "
"incompatible queries", (char*)0);
p->rc = DBSQL_ERROR;
return DBSQL_ERROR;
}
/*
* Copy over the row data.
*/
if (argv != 0) {
for (i = 0; i < ncol; i++) {
if (argv[i] == 0) {
z = 0;
} else {
if (__dbsql_malloc(NULL, strlen(argv[i]) + 1,
&z) == ENOMEM) {
p->rc = DBSQL_NOMEM;
return DBSQL_ERROR;
}
strcpy(z, argv[i]);
}
p->result[p->num_data++] = z;
}
p->num_row++;
}
return DBSQL_SUCCESS;
}
/*
* __api_get_table --
* Query the database. But instead of invoking a callback for each row,
* __dbsql_malloc() space to hold the result and return the entire results
* at the conclusion of the call.
* The result that is written to ***results is held in memory obtained
* from __dbsql_malloc(). But the caller cannot free this memory directly
* Instead, the entire table should be passed to DBSQL->free_table() when
* the calling procedure is finished using it.
*
* PUBLIC: int __api_get_table __P((DBSQL *, const char *, char ***, int *,
* PUBLIC: int *, char **));
*
* dbp The database on which the SQL executes
* sql The SQL to be executed
* results Write the result table here
* nrows Write the number of rows in the result here
* ncols Write the number of columns of result here
* err_msgs Write error messages here
*/
int
__api_get_table(dbp, sql, results, nrows, ncols, err_msgs)
DBSQL *dbp;
const char *sql;
char ***results;
int *nrows;
int *ncols;
char **err_msgs;
{
int rc;
table_result_t res;
DBSQL_ASSERT(results);
DBSQL_ASSERT(ncols);
DBSQL_ASSERT(nrows);
*results = 0;
*ncols = 0;
*nrows = 0;
res.err_msgs = 0;
res.num_result = 0;
res.num_row = 0;
res.num_col = 0;
res.num_data = 1;
res.num_alloc = 20;
res.rc = DBSQL_SUCCESS;
if (__dbsql_calloc(dbp, res.num_alloc, sizeof(char*),
&res.result) == ENOMEM)
return DBSQL_NOMEM;
rc = dbp->exec(dbp, sql, __get_table_cb, &res, err_msgs);
if (rc == DBSQL_ABORT) {
/* !!!
* We set this here because we're about to call free_table, but we
* have to set it again below because a realloc may have moved the
* memory around
*/
res.result[0] = res.result[1] + res.num_data;
dbp->free_table(&res.result[1]);
if (res.err_msgs) {
if(err_msgs) {
__dbsql_ufree(dbp, *err_msgs);
*err_msgs = res.err_msgs;
__str_urealloc(err_msgs);
} else {
__dbsql_free(dbp, res.err_msgs);
}
}
return res.rc;
}
__dbsql_free(dbp, res.err_msgs);
if (rc != DBSQL_SUCCESS) {
dbp->free_table(&res.result[1]);
return rc;
}
if (res.num_alloc > res.num_data) {
if(__dbsql_realloc(dbp, sizeof(char*) * (res.num_data + 1),
&res.result) == ENOMEM) {
dbp->free_table(&res.result[1]);
return DBSQL_NOMEM;
}
res.num_alloc = res.num_data + 1;
}
/* !!!
* free_table() will need to know when to stop freeing results. We use result[0]
* as a pointer to the last allocated row to be free'd. The number of rows to
* be free'd is 'result[0] - (&result[1])'.
*/
res.result[0] = res.result[1] + res.num_data;
*results = &res.result[1];
if (ncols)
*ncols = res.num_col;
if (nrows)
*nrows = res.num_row;
return rc;
}
/*
* __api_free_table --
* This routine frees the space the DBSQL->get_table() __dbsql_malloc'ed.
* There are two things to be free'd, (a) each row (results[0..n]) and then (b) the
* array 'results'. The number of rows to be free'd is 'result[-1] - (&result[0])'.
*
* PUBLIC: void __api_free_table __P((char **));
*
* result Result returned from from __api_get_table()
*/
void
__api_free_table(results)
char **results;
{
char *last_result;
DBSQL_ASSERT(results);
/* If this test is false then the result set is empty, only free (b) */
if (*(results - 1) != *results) {
/* !!!
* The address of the last results row is the value of the first element of
* the results array we created in get_table() but recall that we passed
* the address of the second element (&results[1]) to the user and so
* we need to read the memory of what used to be 'results[0]' which is
* now '*(results - 1)'.
*/
last_result = *(results - 1);
while (*results <= last_result) {
if (*results != NULL)
__dbsql_ufree(NULL, *results);
results++;
}
}
__dbsql_ufree(NULL, results);
}

394
src/cg_attach.c Normal file
View file

@ -0,0 +1,394 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: cg_attach.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* This file contains C code routines that are called by the parser
* to handle ATTACH and DETACH statements.
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
/*
* __attach --
* This routine is called by the parser to process an ATTACH statement:
*
* ATTACH DATABASE filename AS dbname
*
* The 'file' and 'db' arguments are the tokens that define the
* 'file' and 'db' in the ATTACH statement.
*
* PUBLIC: void __attach __P((parser_t *, token_t *, token_t *));
*/
void
__attach(parser, file, db)
parser_t *parser;
token_t *file;
token_t *db;
{
int rc, i;
dbsql_db_t *new;
char *filename, *databasename;
DBSQL *dbp;
vdbe_t *v;
v = __parser_get_vdbe(parser);
__vdbe_add_op(v, OP_Halt, 0, 0);
if (parser->explain)
return;
dbp = parser->db;
if (dbp->format_version < 1) {
__error_msg(parser, "cannot attach auxiliary databases to an "
"older format master database", 0);
parser->rc = DBSQL_ERROR;
return;
}
if (dbp->nDb >= (MAX_ATTACHED + 2)) {
__error_msg(parser, "too many attached databases - max %d",
MAX_ATTACHED);
parser->rc = DBSQL_ERROR;
return;
}
filename = 0;
__str_nappend(&filename, file->z, file->n, NULL);
if (filename == 0)
return;
__str_unquote(filename);
#ifndef DBSQL_NO_AUTH
if (__auth_check(parser, DBSQL_ATTACH, filename, 0, 0) !=
DBSQL_SUCCESS) {
__dbsql_free(dbp, filename);
return;
}
#endif /* DBSQL_NO_AUTH */
databasename = 0;
__str_nappend(&databasename, db->z, db->n, NULL);
if (databasename == 0)
return;
__str_unquote(databasename);
for (i = 0; i < dbp->nDb; i++) {
if (dbp->aDb[i].zName && strcasecmp(
dbp->aDb[i].zName, databasename) == 0) {
__error_msg(parser, "database %z is already in use",
databasename);
parser->rc = DBSQL_ERROR;
__dbsql_free(dbp, filename);
return;
}
}
if (__dbsql_realloc(dbp, (sizeof(dbp->aDb[0]) *
(dbp->nDb + 1)), &dbp->aDb) == ENOMEM)
return;
new = &dbp->aDb[(dbp->nDb++)];
memset(new, 0, sizeof(*new));
if (__sqldb_init(new, dbp, filename, 0, 0, 1) != 0) {
__error_msg(parser, "unable to open database: %s", filename);
}
new->zName = databasename;
__dbsql_free(dbp, filename);
dbp->flags &= ~DBSQL_Initialized;
if (parser->nErr)
return;
if (rc == DBSQL_SUCCESS) {
rc = __init_databases(parser->db, &parser->zErrMsg);
}
if (rc) {
i = dbp->nDb - 1;
DBSQL_ASSERT(i >= 2);
if (dbp->aDb[i].pBt) {
__sm_close_db(dbp->aDb[i].pBt);
dbp->aDb[i].pBt = 0;
}
__reset_internal_schema(dbp, 0);
parser->nErr++;
parser->rc = DBSQL_ERROR;
}
}
/*
* __detach --
* This routine is called by the parser to process a DETACH statement:
*
* DETACH DATABASE db
*
* The db argument is the name of the database in the DETACH statement.
*
* PUBLIC: void __detach __P((parser_t *, token_t *));
*/
void
__detach(parser, db)
parser_t *parser;
token_t *db;
{
int i;
DBSQL *dbp;
vdbe_t *v = __parser_get_vdbe(parser);
__vdbe_add_op(v, OP_Halt, 0, 0);
if (parser->explain)
return;
dbp = parser->db;
for (i = 0; i < dbp->nDb; i++) {
if (dbp->aDb[i].pBt == 0 ||
dbp->aDb[i].zName == 0)
continue;
if (strlen(dbp->aDb[i].zName) != db->n)
continue;
if (strncasecmp(dbp->aDb[i].zName, db->z, db->n) == 0)
break;
}
if (i >= dbp->nDb) {
__error_msg(parser, "no such database: %T", db);
return;
}
if (i < 2) {
__error_msg(parser, "cannot detach database %T", db);
return;
}
#ifndef DBSQL_NO_AUTH
if (__auth_check(parser, DBSQL_DETACH, dbp->aDb[i].zName, 0, 0) !=
DBSQL_SUCCESS) {
return;
}
#endif /* DBSQL_NO_AUTH */
__sm_close_db(dbp->aDb[i].pBt);
dbp->aDb[i].pBt = 0;
__dbsql_free(dbp, dbp->aDb[i].zName);
__reset_internal_schema(dbp, i);
dbp->nDb--;
if (i < dbp->nDb) {
dbp->aDb[i] = dbp->aDb[dbp->nDb];
memset(&dbp->aDb[dbp->nDb], 0, sizeof(dbp->aDb[0]));
__reset_internal_schema(dbp, i);
}
}
/*
* __ref_normalizer_ctx_init --
* Initialize a ref_normalizer_ctx_t structure. This routine must be
* called prior to passing the structure to one of the
* __ref_normalize_XXX() routines below. The return value indicates
* whether or not normalization is required. TRUE means we do need to
* fix the database references, FALSE means we do not.
*
* PUBLIC: int __ref_normalizer_ctx_init __P((ref_normalizer_ctx_t *,
* PUBLIC: parser_t *, int, const char *,
* PUBLIC: const token_t *));
*
* normctx The normalizer to be initialized
* parser Error messages will be written here
* dbnum This is the database that must must be used
* type "view", "trigger", or "index"
* name Name of the view, trigger, or index
*/
int
__ref_normalizer_ctx_init(normctx, parser, dbnum, type, name)
ref_normalizer_ctx_t *normctx;
parser_t *parser;
int dbnum;
const char *type;
const token_t *name;
{
DBSQL *dbp;
if (dbnum < 0 || dbnum == 1)
return 0;
dbp = parser->db;
DBSQL_ASSERT(dbp->nDb > dbnum);
normctx->pParse = parser;
normctx->zDb = dbp->aDb[dbnum].zName;
normctx->zType = type;
normctx->pName = name;
return 1;
}
/*
* __ref_normalize_src_list --
* The following set of routines walk through the parse tree and assign
* a specific database to all table references where the database name
* was left unspecified in the original SQL statement. The normctx
* structure must have been initialized by a prior call to
* __ref_normalizer_ctx_init().
*
* These routines are used to make sure that an index, trigger, or
* view in one database does not refer to objects in a different database.
* (Exception: indices, triggers, and views in the TEMP database are
* allowed to refer to anything.) If a reference is explicitly made
* to an object in a different database, an error message is added to
* parser->zErrMsg and these routines return non-zero. If everything
* checks out, these routines return 0.
*
* PUBLIC: int __ref_normalize_src_list __P((ref_normalizer_ctx_t *,
* PUBLIC: src_list_t *));
*
* normctx Context of the normalization
* src_list The source list to check and modify
*/
int __ref_normalize_src_list(normctx, src_list)
ref_normalizer_ctx_t *normctx;
src_list_t *src_list;
{
int i;
const char *db;
DBSQL *dbp = normctx->pParse->db;
if (src_list == 0)
return 0;
db = normctx->zDb;
for (i = 0; i < src_list->nSrc; i++) {
if (src_list->a[i].zDatabase == 0) {
__dbsql_strdup(dbp, db, &src_list->a[i].zDatabase);
} else if (strcasecmp(src_list->a[i].zDatabase, db) != 0) {
char *name;
__dbsql_strndup(dbp, normctx->pName->z, &name,
normctx->pName->n);
__error_msg(normctx->pParse, "%s %z cannot reference "
"objects in database %s", normctx->zType,
name, src_list->a[i].zDatabase);
return 1;
}
if (__ref_normalize_select(normctx, src_list->a[i].pSelect))
return 1;
if (__ref_normalize_expr(normctx, src_list->a[i].pOn))
return 1;
}
return 0;
}
/*
* __ref_normalize_select --
*
* PUBLIC: int __ref_normalize_select __P((ref_normalizer_ctx_t *,
* PUBLIC: select_t *));
*
* normctx Context of the normalization
* select The SELECT statement to be fixed to one
* database
*/
int
__ref_normalize_select(normctx, select)
ref_normalizer_ctx_t *normctx;
select_t *select;
{
while (select) {
if (__ref_normalize_expr_list(normctx, select->pEList)) {
return 1;
}
if (__ref_normalize_src_list(normctx, select->pSrc)) {
return 1;
}
if (__ref_normalize_expr(normctx, select->pWhere)) {
return 1;
}
if (__ref_normalize_expr(normctx, select->pHaving)) {
return 1;
}
select = select->pPrior;
}
return 0;
}
/*
* __ref_normalize_expr --
*
* PUBLIC: int __ref_normalize_expr __P((ref_normalizer_ctx_t *,
* PUBLIC: expr_t *));
*
* normctx Context of the normalization
* expr The expr_t to be fixed to one database
*/
int __ref_normalize_expr(normctx, expr)
ref_normalizer_ctx_t *normctx;
expr_t *expr;
{
while (expr) {
if (__ref_normalize_select(normctx, expr->pSelect)) {
return 1;
}
if (__ref_normalize_expr_list(normctx, expr->pList)) {
return 1;
}
if (__ref_normalize_expr(normctx, expr->pRight)) {
return 1;
}
expr = expr->pLeft;
}
return 0;
}
/*
* __ref_normalize_expr_list --
*
* PUBLIC: int __ref_normalize_expr_list __P((ref_normalizer_ctx_t *,
* PUBLIC: expr_list_t *));
*
* normctx Context of the normalization
* expr The expression to be fixed to one database
*/
int
__ref_normalize_expr_list(normctx, list)
ref_normalizer_ctx_t *normctx;
expr_list_t *list;
{
int i;
if (list == 0)
return 0;
for (i = 0; i < list->nExpr; i++) {
if (__ref_normalize_expr(normctx, list->a[i].pExpr)) {
return 1;
}
}
return 0;
}
/*
* __ref_normalize_trigger_step --
*
* PUBLIC: int __ref_normalize_trigger_step __P((ref_normalizer_ctx_t *,
* PUBLIC: trigger_step_t *));
*
* normctx Context of the normalization
* expr The trigger step to be fixed to one database
*/
int __ref_normalize_trigger_step(normctx, step)
ref_normalizer_ctx_t *normctx;
trigger_step_t *step;
{
while (step) {
if (__ref_normalize_select(normctx, step->pSelect)) {
return 1;
}
if (__ref_normalize_expr(normctx, step->pWhere)) {
return 1;
}
if (__ref_normalize_expr_list(normctx, step->pExprList)) {
return 1;
}
step = step->pNext;
}
return 0;
}

285
src/cg_auth.c Normal file
View file

@ -0,0 +1,285 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: cg_auth.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* This file contains code used to implement the __api_set_auth_callback()
* API. This facility is an optional feature of the library. Embedded
* systems that do not need this facility may omit it by reconfiguring
* with '--disable-auth'. Then recompile the entire library.
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
#ifndef DBSQL_OMIT_AUTHORIZATION
/*
* Set or clear the access authorization function.
* The access authorization function is be called during the compilation
* phase to verify that the user has read and/or write access permission
* on various fields of the database. The first argument to the auth
* function is a copy of the 3rd argument to this routine. The second
* argument to the auth function is one of these constants:
*
* DBSQL_COPY
* DBSQL_CREATE_INDEX
* DBSQL_CREATE_TABLE
* DBSQL_CREATE_TEMP_INDEX
* DBSQL_CREATE_TEMP_TABLE
* DBSQL_CREATE_TEMP_TRIGGER
* DBSQL_CREATE_TEMP_VIEW
* DBSQL_CREATE_TRIGGER
* DBSQL_CREATE_VIEW
* DBSQL_DELETE
* DBSQL_DROP_INDEX
* DBSQL_DROP_TABLE
* DBSQL_DROP_TEMP_INDEX
* DBSQL_DROP_TEMP_TABLE
* DBSQL_DROP_TEMP_TRIGGER
* DBSQL_DROP_TEMP_VIEW
* DBSQL_DROP_TRIGGER
* DBSQL_DROP_VIEW
* DBSQL_INSERT
* DBSQL_PRAGMA
* DBSQL_READ
* DBSQL_SELECT
* DBSQL_TRANSACTION
* DBSQL_UPDATE
*
* The third and fourth arguments to the auth function are the name of
* the table and the column that are being accessed. The auth function
* should return either DBSQL_SUCCESS, DBSQL_DENY, or DBSQL_IGNORE. If
* DBSQL_SUCCESS is returned, it means that access is allowed. DBSQL_DENY
* means that the SQL statement will never-run - the dbsql_exec() call
* will return with an error. DBSQL_IGNORE means that the SQL statement
* should run but attempts to read the specified column will return NULL
* and attempts to write the column will be ignored.
*
* Setting the auth function to NULL disables this hook. The default
* setting of the auth function is NULL.
*
* PUBLIC: int __api_set_authorizer __P((DBSQL *,
* PUBLIC: int (*auth)(void*,int,const char*, const char*,const char*,
* PUBLIC: const char*), void *));
*/
int __api_set_authorizer(dbp, auth, arg)
DBSQL *dbp;
int (*auth)(void*,int,const char*,const char*,const char*,const char*);
void *arg;
{
dbp->auth = auth;
dbp->pAuthArg = arg;
return DBSQL_SUCCESS;
}
/*
* __auth_bad_return_code --
* Write an error message into pParse->zErrMsg that explains that the
* user-supplied authorization function returned an illegal value.
*
* STATIC: static void __auth_bad_return_code __P((parser_t *, int));
*/
static void
__auth_bad_return_code(parser, rc)
parser_t *parser;
int rc;
{
char buf[20];
sprintf(buf, "(%d)", rc);
__str_append(&parser->zErrMsg, "illegal return value ",
buf, " from the authorization function - ",
"should be DBSQL_SUCCESS, DBSQL_IGNORE, or DBSQL_DENY",
(char*)0);
parser->nErr++;
parser->rc = DBSQL_MISUSE;
}
/*
* __auth_read --
* The 'expr' should be a TK_COLUMN expression. The table referred to
* is in 'tab_list' or else it is the NEW or OLD table of a trigger.
* Check to see if it is OK to read this particular column.
*
* If the auth function returns DBSQL_IGNORE, change the TK_COLUMN
* instruction into a TK_NULL. If the auth function returns DBSQL_DENY,
* then generate an error.
*
* PUBLIC: void __auth_read __P((parser_t *, expr_t *, src_list_t *));
*
* parser The parser context
* expr The expression to check authorization on
* tab_list All table that expr might refer to
*/
void
__auth_read(parser, expr, tab_list)
parser_t *parser;
expr_t *expr;
src_list_t *tab_list;
{
int rc;
DBSQL *dbp = parser->db;
table_t *table; /* The table being read */
const char *col; /* Name of the column of the table */
int src; /* Index in tab_list->a[] of table being read */
const char *databasename; /* Name of database being accessed */
trigger_stack_t *stack; /* The stack of current triggers */
if (dbp->auth == 0)
return;
DBSQL_ASSERT(expr->op == TK_COLUMN);
for (src = 0; src < tab_list->nSrc; src++) {
if (expr->iTable == tab_list->a[src].iCursor)
break;
}
if (src >= 0 && src < tab_list->nSrc) {
table = tab_list->a[src].pTab;
} else {
/*
* This must be an attempt to read the NEW or OLD pseudo-tables
* of a trigger.
*/
stack = parser->trigStack;
DBSQL_ASSERT(stack != 0);
DBSQL_ASSERT(expr->iTable == stack->newIdx ||
expr->iTable == stack->oldIdx);
table = stack->pTab;
}
if (table == 0)
return;
if (expr->iColumn >= 0) {
DBSQL_ASSERT(expr->iColumn < table->nCol);
col = table->aCol[expr->iColumn].zName;
} else if (table->iPKey >= 0) {
DBSQL_ASSERT(table->iPKey < table->nCol);
col = table->aCol[table->iPKey].zName;
} else {
col = "ROWID";
}
DBSQL_ASSERT(expr->iDb < dbp->nDb);
databasename = dbp->aDb[expr->iDb].zName;
rc = dbp->auth(dbp->pAuthArg, DBSQL_READ, table->zName,
col, databasename, parser->zAuthContext);
if (rc == DBSQL_IGNORE) {
expr->op = TK_NULL;
} else if (rc == DBSQL_DENY) {
if (dbp->nDb > 2 || expr->iDb != 0) {
__str_append(&parser->zErrMsg,"access to ",
databasename, ".", table->zName, ".",
col, " is prohibited", (char*)0);
} else {
__str_append(&parser->zErrMsg,"access to ",
table->zName, ".", col, " is prohibited",
(char*)0);
}
parser->nErr++;
parser->rc = DBSQL_AUTH;
} else if (rc != DBSQL_SUCCESS) {
__auth_bad_return_code(parser, rc);
}
}
/*
* __auth_check --
* Do an authorization check using the code and arguments given. Return
* either DBSQL_SUCCESS (zero) or DBSQL_IGNORE or DBSQL_DENY. If
* DBSQL_DENY is returned, then the error count and error message in
* parser are modified appropriately.
*
* PUBLIC: int __auth_check __P((parser_t *, int, const char *, const char *,
* PUBLIC: const char *));
*/
int
__auth_check(parser, code, arg1, arg2, arg3)
parser_t *parser;
int code;
const char *arg1;
const char *arg2;
const char *arg3;
{
int rc;
DBSQL *dbp = parser->db;
if (dbp->auth == 0) {
return DBSQL_SUCCESS;
}
rc = dbp->auth(dbp->pAuthArg, code, arg1, arg2, arg3,
parser->zAuthContext);
if (rc == DBSQL_DENY) {
__str_append(&parser->zErrMsg, "not authorized",
(char*)0);
parser->rc = DBSQL_AUTH;
parser->nErr++;
} else if (rc != DBSQL_SUCCESS && rc != DBSQL_IGNORE) {
rc = DBSQL_DENY;
__auth_bad_return_code(parser, rc);
}
return rc;
}
/*
* __auth_context_push --
* Push an authorization context. After this routine is called, the
* arg3 argument to authorization callbacks will be context until
* popped. Or if parser==0, this routine is a no-op.
*
* PUBLIC: void __auth_context_push __P((parser_t *, auth_context_t *,
* PUBLIC: const char *));
*/
void __auth_context_push(parser, authctx, context)
parser_t *parser;
auth_context_t *authctx;
const char *context;
{
authctx->pParse = parser;
if (parser) {
authctx->zAuthContext = parser->zAuthContext;
parser->zAuthContext = context;
}
}
/*
* __auth_context_pop --
* Pop an authorization context that was previously pushed
* by __auth_context_push.
*
* PUBLIC: void __auth_context_pop __P((auth_context_t *));
*/
void
__auth_context_pop(authctx)
auth_context_t *authctx;
{
if (authctx->pParse) {
authctx->pParse->zAuthContext = authctx->zAuthContext;
authctx->pParse = 0;
}
}
#else
/* TODO what is the difference between DBSQL_OMIT_AUTHORIZATION and
DBSQL_NO_AUTH? Which one should be used here? Setup a test case for this.*/
# define __auth_check(a,b,c,d,e) DBSQL_SUCCESS
#endif /* !defined(DBSQL_OMIT_AUTHORIZATION) */

2797
src/cg_build.c Normal file

File diff suppressed because it is too large Load diff

154
src/cg_copy.c Normal file
View file

@ -0,0 +1,154 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: cg_copy.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* This file contains code used to implement the COPY command.
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
/*
* __copy --
* The COPY command is for compatibility with PostgreSQL and specificially
* for the ability to read the output of pg_dump. The format is as
* follows:
*
* COPY table FROM file [USING DELIMITERS string]
*
* "table" is an existing table name. We will read lines of code from
* file to fill this table with data. File might be "stdin". The
* optional delimiter string identifies the field separators. The
* default is a tab.
*
* PUBLIC: void __copy __P((parser_t *, src_list_t *, token_t *,
* PUBLIC: token_t *, int));
*
* parser The parser context
* table_name The name of the table into which we will insert
* filename The file from which to obtain information
* delimiter Use this as the field delimiter
* on_error What to do if a constraint fails
*/
void __copy(parser, table_name, filename, delimiter, on_error)
parser_t *parser;
src_list_t *table_name;
token_t *filename;
token_t *delimiter;
int on_error;
{
table_t *table;
int i;
vdbe_t *v;
int addr, end;
index_t *index;
char *file = 0;
const char *db_name;
DBSQL *db = parser->db;
if (parser->rc != DBSQL_SUCCESS)
goto copy_cleanup;
DBSQL_ASSERT(table_name->nSrc == 1);
table = __src_list_lookup(parser, table_name);
if (table==0 || __is_table_read_only(parser, table, 0))
goto copy_cleanup;
__dbsql_strndup(parser->db, filename->z, &file, filename->n);
__str_unquote(file);
DBSQL_ASSERT(table->iDb < db->nDb);
db_name = db->aDb[table->iDb].zName;
if (__auth_check(parser, DBSQL_INSERT, table->zName, 0, db_name) ||
__auth_check(parser, DBSQL_COPY, table->zName, file, db_name)) {
goto copy_cleanup;
}
v = __parser_get_vdbe(parser);
if (v) {
__vdbe_prepare_write(parser, 1, table->iDb);
addr = __vdbe_add_op(v, OP_FileOpen, 0, 0);
__vdbe_change_p3(v, addr, filename->z, filename->n);
__vdbe_dequote_p3(v, addr);
__vdbe_add_op(v, OP_Integer, table->iDb, 0);
__vdbe_add_op(v, OP_OpenWrite, 0, table->tnum);
__vdbe_change_p3(v, -1, table->zName, P3_STATIC);
for(i = 1, index = table->pIndex; index;
index=index->pNext, i++) {
DBSQL_ASSERT(index->iDb == 1 || index->iDb == table->iDb);
__vdbe_add_op(v, OP_Integer, index->iDb, 0);
__vdbe_add_op(v, OP_OpenWrite, i, index->tnum);
__vdbe_change_p3(v, -1, index->zName, P3_STATIC);
}
if (db->flags & DBSQL_CountRows) {
/* Initialize the row count */
__vdbe_add_op(v, OP_Integer, 0, 0);
}
end = __vdbe_make_label(v);
addr = __vdbe_add_op(v, OP_FileRead, table->nCol, end);
if (delimiter) {
__vdbe_change_p3(v, addr, delimiter->z, delimiter->n);
__vdbe_dequote_p3(v, addr);
} else {
__vdbe_change_p3(v, addr, "\t", 1);
}
if (table->iPKey >= 0) {
__vdbe_add_op(v, OP_FileColumn, table->iPKey, 0);
__vdbe_add_op(v, OP_MustBeInt, 0, 0);
} else {
__vdbe_add_op(v, OP_NewRecno, 0, 0);
}
for(i = 0; i < table->nCol; i++) {
if (i == table->iPKey) {
/*
* The integer primary key column is filled
* with NULL since its value is always pulled
* from the record number.
*/
__vdbe_add_op(v, OP_String, 0, 0);
} else {
__vdbe_add_op(v, OP_FileColumn, i, 0);
}
}
__generate_constraint_checks(parser, table, 0, 0,
(table->iPKey >= 0), 0, on_error,
addr);
__complete_insertion(parser, table, 0, 0, 0, 0, -1);
if ((db->flags & DBSQL_CountRows) != 0) {
/* Increment row count */
__vdbe_add_op(v, OP_AddImm, 1, 0);
}
__vdbe_add_op(v, OP_Goto, 0, addr);
__vdbe_resolve_label(v, end);
__vdbe_add_op(v, OP_Noop, 0, 0);
__vdbe_conclude_write(parser);
if (db->flags & DBSQL_CountRows) {
__vdbe_add_op(v, OP_ColumnName, 0, 0);
__vdbe_change_p3(v, -1, "rows inserted", P3_STATIC);
__vdbe_add_op(v, OP_Callback, 1, 0);
}
}
copy_cleanup:
__src_list_delete(table_name);
__dbsql_free(parser->db, file);
return;
}

1052
src/cg_date.c Normal file

File diff suppressed because it is too large Load diff

500
src/cg_delete.c Normal file
View file

@ -0,0 +1,500 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: cg_delete.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* This file contains C code routines that are called by the parser
* to handle DELETE FROM statements.
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
/*
* __src_list_lookup --
* Look up every table that is named in 'src'. If any table is not found,
* add an error message to parse->zErrMsg and return NULL. If all tables
* are found, return a pointer to the last table.
*
* PUBLIC: table_t *__src_list_lookup __P((parser_t *, src_list_t *));
*/
table_t *
__src_list_lookup(parser, src)
parser_t *parser;
src_list_t *src;
{
table_t *table = 0;
int i;
for (i = 0; i < src->nSrc; i++) {
const char *tb_name = src->a[i].zName;
const char *db_name = src->a[i].zDatabase;
table = __locate_table(parser, tb_name, db_name);
src->a[i].pTab = table;
}
return table;
}
/*
* __is_table_read_only --
* Check to make sure the given table is writable. If it is not
* writable, generate an error message and return 1. If it is
* writable return 0;
*
* PUBLIC: int __is_table_read_only __P((parser_t *, table_t *, int));
*/
int
__is_table_read_only(parser, table, views_ok)
parser_t *parser;
table_t *table;
int views_ok;
{
if (table->readOnly) {
__error_msg(parser, "table %s may not be modified",
table->zName);
return 1;
}
if (!views_ok && table->pSelect) {
__error_msg(parser, "cannot modify %s because it is a view",
table->zName);
return 1;
}
return 0;
}
/*
* __delete_from --
* Process a DELETE FROM statement.
*
* PUBLIC: void __delete_from __P((parser_t *, src_list_t *, expr_t *));
*
* parser The parser context
* list The table from which we should delete things
* where The WHERE clause. May be null.
*/
void __delete_from(parser, list, where)
parser_t *parser;
src_list_t *list;
expr_t *where;
{
vdbe_t *v; /* The virtual database engine */
table_t *table; /* The table from which records will be deleted */
const char *name; /* Name of database holding 'table' */
int end, addr; /* A couple addresses of generated code */
int i; /* Loop counter */
where_info_t *info; /* Information about the WHERE clause */
index_t *idx; /* For looping over indices of the table */
int cur; /* VDBE Cursor number for 'table' */
DBSQL *dbp; /* Main database structure */
int view; /* True if attempting to delete from a view */
auth_context_t context;/* Authorization context */
int row_triggers_exist = 0;/* True if any triggers exist */
int before_triggers;/* True if there are BEFORE triggers */
int after_triggers; /* True if there are AFTER triggers */
int old_idx = -1; /* Cursor for the OLD table of AFTER triggers */
context.pParse = 0;
if (parser->nErr || parser->rc == ENOMEM) {
list = 0;
goto delete_from_cleanup;
}
dbp = parser->db;
DBSQL_ASSERT(list->nSrc == 1);
/*
* Locate the table which we want to delete. This table has to be
* put in an src_list_t structure because some of the subroutines we
* will be calling are designed to work with multiple tables and expect
* an src_list_t* parameter instead of just a table_t* parameter.
*/
table = __src_list_lookup(parser, list);
if (table == 0)
goto delete_from_cleanup;
before_triggers = __triggers_exist(parser, table->pTrigger,
TK_DELETE, TK_BEFORE, TK_ROW, 0);
after_triggers = __triggers_exist(parser, table->pTrigger,
TK_DELETE, TK_AFTER, TK_ROW, 0);
row_triggers_exist = (before_triggers || after_triggers);
view = (table->pSelect != 0);
if (__is_table_read_only(parser, table, before_triggers)) {
goto delete_from_cleanup;
}
DBSQL_ASSERT(table->iDb < dbp->nDb);
name = dbp->aDb[table->iDb].zName;
if (__auth_check(parser, DBSQL_DELETE, table->zName, 0, name)) {
goto delete_from_cleanup;
}
/*
* If pTab is really a view, make sure it has been initialized.
*/
if (view && __view_get_column_names(parser, table)) {
goto delete_from_cleanup;
}
/*
* Allocate a cursor used to store the old.* data for a trigger.
*/
if (row_triggers_exist) {
old_idx = parser->nTab++;
}
/*
* Resolve the column names in all the expressions.
*/
DBSQL_ASSERT(list->nSrc == 1);
cur = list->a[0].iCursor = parser->nTab++;
if (where) {
if (__expr_resolve_ids(parser, list, 0, where)) {
goto delete_from_cleanup;
}
if (__expr_check(parser, where, 0, 0)) {
goto delete_from_cleanup;
}
}
/*
* Start the view context.
*/
if (view) {
__auth_context_push(parser, &context, table->zName);
}
/*
* Begin generating code.
*/
v = __parser_get_vdbe(parser);
if (v == 0) {
goto delete_from_cleanup;
}
__vdbe_prepare_write(parser, row_triggers_exist, table->iDb);
/*
* If we are trying to delete from a view, construct that view into
* a temporary table.
*/
if (view) {
select_t *vsel = __select_dup(table->pSelect);
__select(parser, vsel, SRT_TempTable, cur, 0, 0, 0);
__select_delete(vsel);
}
/*
* Initialize the counter of the number of rows deleted, if
* we are counting rows.
*/
if (dbp->flags & DBSQL_CountRows) {
__vdbe_add_op(v, OP_Integer, 0, 0);
}
/*
* Special case: A DELETE without a WHERE clause deletes everything.
* It is easier just to erase the whole table. Note, however, that
* this means that the row change count will be incorrect.
*/
if (where == 0 && !row_triggers_exist) {
if (dbp->flags & DBSQL_CountRows) {
/*
* If counting rows deleted, just count the total
* number of entries in the table.
*/
int end_of_loop = __vdbe_make_label(v);
int addr;
if (!view) {
__vdbe_add_op(v, OP_Integer, table->iDb, 0);
__vdbe_add_op(v, OP_OpenRead, cur,
table->tnum);
}
__vdbe_add_op(v, OP_Rewind, cur,
(__vdbe_current_addr(v) + 2));
addr = __vdbe_add_op(v, OP_AddImm, 1, 0);
__vdbe_add_op(v, OP_Next, cur, addr);
__vdbe_resolve_label(v, end_of_loop);
__vdbe_add_op(v, OP_Close, cur, 0);
}
if (!view) {
__vdbe_add_op(v, OP_Clear, table->tnum, table->iDb);
for (idx = table->pIndex; idx; idx = idx->pNext) {
__vdbe_add_op(v, OP_Clear, idx->tnum,
idx->iDb);
}
}
} else {
/*
* The usual case: There is a WHERE clause so we have to
* scan through the table and pick which records to delete.
*/
/*
* Begin the database scan.
*/
info = __where_begin(parser, list, where, 1, 0);
if (info == 0)
goto delete_from_cleanup;
/*
* Remember the key of every item to be deleted.
*/
__vdbe_add_op(v, OP_ListWrite, 0, 0);
if (dbp->flags & DBSQL_CountRows) {
__vdbe_add_op(v, OP_AddImm, 1, 0);
}
/*
* End the database scan loop.
*/
__where_end(info);
/*
* Open the pseudo-table used to store OLD if there are
* triggers.
*/
if (row_triggers_exist) {
__vdbe_add_op(v, OP_OpenPseudo, old_idx, 0);
}
/*
* Delete every item whose key was written to the list
* during the database scan. We have to delete items
* after the scan is complete because deleting an item
* can change the scan order.
*/
__vdbe_add_op(v, OP_ListRewind, 0, 0);
end = __vdbe_make_label(v);
/*
* This is the beginning of the delete loop when there are
* row triggers.
*/
if (row_triggers_exist) {
addr = __vdbe_add_op(v, OP_ListRead, 0, end);
__vdbe_add_op(v, OP_Dup, 0, 0);
if (!view) {
__vdbe_add_op(v, OP_Integer, table->iDb, 0);
__vdbe_add_op(v, OP_OpenRead, cur,
table->tnum);
}
__vdbe_add_op(v, OP_MoveTo, cur, 0);
__vdbe_add_op(v, OP_Recno, cur, 0);
__vdbe_add_op(v, OP_RowData, cur, 0);
__vdbe_add_op(v, OP_PutIntKey, old_idx, 0);
if (!view) {
__vdbe_add_op(v, OP_Close, cur, 0);
}
__code_row_trigger(parser, TK_DELETE, 0, TK_BEFORE,
table, -1, old_idx,
((parser->trigStack) ?
parser->trigStack->orconf :
OE_Default), addr);
}
if (!view) {
/*
* Open cursors for the table we are deleting from
* and all its indices. If there are row triggers,
* this happens inside the OP_ListRead loop because
* the cursor have to all be closed before the trigger
* fires. If there are no row triggers, the cursors
* are opened only once on the outside the loop.
*/
parser->nTab = cur + 1;
__vdbe_add_op(v, OP_Integer, table->iDb, 0);
__vdbe_add_op(v, OP_OpenWrite, cur, table->tnum);
for (i = 1, idx = table->pIndex; idx;
i++, idx = idx->pNext) {
__vdbe_add_op(v, OP_Integer, idx->iDb, 0);
__vdbe_add_op(v, OP_OpenWrite, parser->nTab++,
idx->tnum);
}
/*
* This is the beginning of the delete loop when
* there are no row triggers.
*/
if (!row_triggers_exist) {
addr = __vdbe_add_op(v, OP_ListRead, 0, end);
}
/*
* Delete the row.
*/
__generate_row_delete(dbp, v, table, cur,
(parser->trigStack == 0));
}
/*
* If there are row triggers, close all cursors then invoke
* the AFTER triggers.
*/
if (row_triggers_exist) {
if (!view) {
for(i = 1, idx = table->pIndex; idx;
i++, idx = idx->pNext) {
__vdbe_add_op(v, OP_Close, cur + i,
idx->tnum);
}
__vdbe_add_op(v, OP_Close, cur, 0);
}
__code_row_trigger(parser, TK_DELETE, 0, TK_AFTER,
table, -1, old_idx,
((parser->trigStack) ?
parser->trigStack->orconf :
OE_Default), addr);
}
/*
* End of the delete loop.
*/
__vdbe_add_op(v, OP_Goto, 0, addr);
__vdbe_resolve_label(v, end);
__vdbe_add_op(v, OP_ListReset, 0, 0);
/*
* Close the cursors after the loop if there are no row
* triggers.
*/
if (!row_triggers_exist) {
for (i = 1, idx = table->pIndex; idx;
i++, idx = idx->pNext) {
__vdbe_add_op(v, OP_Close, cur + i, idx->tnum);
}
__vdbe_add_op(v, OP_Close, cur, 0);
parser->nTab = cur;
}
}
__vdbe_conclude_write(parser);
/*
* Return the number of rows that were deleted.
*/
if (dbp->flags & DBSQL_CountRows) {
__vdbe_add_op(v, OP_ColumnName, 0, 0);
__vdbe_change_p3(v, -1, "rows deleted", P3_STATIC);
__vdbe_add_op(v, OP_Callback, 1, 0);
}
delete_from_cleanup:
__auth_context_pop(&context);
__src_list_delete(list);
__expr_delete(where);
return;
}
/*
* __generate_row_delete --
* This routine generates VDBE code that causes a single row of a
* single table to be deleted.
*
* The VDBE must be in a particular state when this routine is called.
* These are the requirements:
*
* 1. A read/write cursor pointing to 'table', the table containing
* the row to be deleted, must be opened as cursor number "base".
*
* 2. Read/write cursors for all indices of pTab must be open as
* cursor number base+i for the i-th index.
*
* 3. The record number of the row to be deleted must be on the top
* of the stack.
*
* This routine pops the top of the stack to remove the record number
* and then generates code to remove both the table record and all index
* entries that point to that record.
*
* PUBLIC: void __generate_row_delete __P((DBSQL *, vdbe_t *, table_t *,
* PUBLIC: int, int));
*
* dbp The database containing the index
* v Generate code into this VDBE
* table Table containing the row to be deleted
* cur Cursor number for the table
* count Increment the row change counter
*/
void __generate_row_delete(dbp, v, table, cur, count)
DBSQL *dbp;
vdbe_t *v;
table_t *table;
int cur;
int count;
{
int addr;
addr = __vdbe_add_op(v, OP_NotExists, cur, 0);
__generate_row_index_delete(dbp, v, table, cur, 0);
__vdbe_add_op(v, OP_Delete, cur, count);
__vdbe_change_p2(v, addr, __vdbe_current_addr(v));
}
/*
* __generate_row_index_delete --
* This routine generates VDBE code that causes the deletion of all
* index entries associated with a single row of a single table.
*
* The VDBE must be in a particular state when this routine is called.
* These are the requirements:
*
* 1. A read/write cursor pointing to 'table', the table containing
* the row to be deleted, must be opened as cursor number 'cur'.
*
* 2. Read/write cursors for all indices of 'table' must be open as
* cursor number cur+i for the i-th index.
*
* 3. The 'cur' cursor must be pointing to the row that is to be
* deleted.
*
* PUBLIC: void __generate_row_index_delete __P((DBSQL *, vdbe_t *,
* PUBLIC: table_t *, int, char *));
*
* dbp The database containing the index
* v Generate code into this VDBE
* table Table containing the row to be deleted
* cur Cursor number for the table
* idx_used Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0
*/
void __generate_row_index_delete(dbp, v, table, cur, idx_used)
DBSQL *dbp;
vdbe_t *v;
table_t *table;
int cur;
char *idx_used;
{
int i;
index_t *idx;
for (i = 1, idx = table->pIndex; idx; i++, idx = idx->pNext) {
int j;
if (idx_used != 0 && idx_used[i-1] == 0)
continue;
__vdbe_add_op(v, OP_Recno, cur, 0);
for (j = 0; j < idx->nColumn; j++) {
int n = idx->aiColumn[j];
if (n == table->iPKey) {
__vdbe_add_op(v, OP_Dup, j, 0);
} else {
__vdbe_add_op(v, OP_Column, cur, n);
}
}
__vdbe_add_op(v, OP_MakeIdxKey, idx->nColumn, 0);
__add_idx_key_type(v, idx);
__vdbe_add_op(v, OP_IdxDelete, cur + i, 0);
}
}

1980
src/cg_expr.c Normal file

File diff suppressed because it is too large Load diff

1072
src/cg_insert.c Normal file

File diff suppressed because it is too large Load diff

397
src/cg_pragma.c Normal file
View file

@ -0,0 +1,397 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: cg_pragma.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* This file contains code used to implement the PRAGMA command.
*/
#include "dbsql_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <ctype.h>
#endif
#include "dbsql_int.h"
/*
* __get_boolean --
* Interpret the given string as a boolean value.
*
* STATIC: static int __get_boolean __P((char *));
*/
static int
__get_boolean(z)
char *z;
{
static char *true[] = { "yes", "on", "true" };
int i;
if (z[0] == 0)
return 0;
if (isdigit(z[0]) || (z[0]=='-' && isdigit(z[1]))) {
return atoi(z);
}
for(i = 0; i < sizeof(true) / sizeof(true[0]); i++) {
if (strcasecmp(z, true[i]) == 0)
return 1;
}
return 0;
}
/*
* __get_safety_level --
* Interpret the given string as a safety level. Return 0 for OFF,
* 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
* unrecognized string argument.
*
* Note that the values returned are one less that the values that
* should be passed into __sm_set_safety_level(). This is done
* to support legacy SQL code. The safety level used to be boolean
* and older scripts may have used numbers 0 for OFF and 1 for ON.
*
* STATIC: static int __get_safety_level __P((char *));
*/
static int
__get_safety_level(z)
char *z;
{
static const struct {
const char *word;
int val;
} key[] = {
{ "no", 0 },
{ "off", 0 },
{ "false", 0 },
{ "yes", 1 },
{ "on", 1 },
{ "true", 1 },
{ "full", 2 },
};
int i;
if (z[0] == 0)
return 1;
if (isdigit(z[0]) || (z[0] == '-' && isdigit(z[1]))) {
return atoi(z);
}
for (i = 0; i < sizeof(key)/sizeof(key[0]); i++) {
if (strcasecmp(z,key[i].word) == 0)
return key[i].val;
}
return 1;
}
/*
* __pragma --
* Process a pragma statement.
*
* Pragmas are of this form:
*
* PRAGMA id = value
*
* The identifier might also be a string. The value is a string, and
* identifier, or a number. If 'minus_p' is true, then the value is
* a number that was preceded by a minus sign.
*
* PUBLIC: void __pragma __P((parser_t *, token_t *, token_t *, int));
*/
void
__pragma(parser, left, right, minus_p)
parser_t *parser;
token_t *left;
token_t *right;
int minus_p;
{
char *left_name = 0;
char *right_name = 0;
DBSQL *dbp = parser->db;
vdbe_t *v = __parser_get_vdbe(parser);
if (v == 0)
return;
__dbsql_strndup(dbp, left->z, &left_name, left->n);
__str_unquote(left_name);
if (minus_p) {
right_name = 0;
__str_nappend(&right_name, "-", 1, right->z, right->n, NULL);
} else {
__dbsql_strndup(dbp, right->z, &right_name, right->n);
__str_unquote(right_name);
}
if (__auth_check(parser, DBSQL_PRAGMA, left_name, right_name, NULL)) {
__dbsql_free(dbp, left_name);
__dbsql_free(dbp, right_name);
return;
}
/*
* PRAGMA trigger_overhead_test
*/
if (strcasecmp(left_name, "trigger_overhead_test") == 0) {
if (__get_boolean(right_name)) {
always_code_trigger_setup = 1;
} else {
always_code_trigger_setup = 0;
}
} else
/*
* PRAGMA vdbe_trace
*/
if (strcasecmp(left_name, "vdbe_trace") == 0) {
if (__get_boolean(right_name)) {
dbp->flags |= DBSQL_VdbeTrace;
} else {
dbp->flags &= ~DBSQL_VdbeTrace;
}
} else
/*
* PRAGMA full_column_names
*/
if (strcasecmp(left_name, "full_column_names") == 0) {
if (__get_boolean(right_name)) {
dbp->flags |= DBSQL_FullColNames;
} else {
dbp->flags &= ~DBSQL_FullColNames;
}
} else
/*
* PRAGMA show_datatypes
*/
if (strcasecmp(left_name, "show_datatypes") == 0) {
if( __get_boolean(right_name)) {
dbp->flags |= DBSQL_ReportTypes;
} else {
dbp->flags &= ~DBSQL_ReportTypes;
}
} else
/*
* PRAGMA count_changes
*/
if (strcasecmp(left_name, "count_changes") == 0) {
if (__get_boolean(right_name)) {
dbp->flags |= DBSQL_CountRows;
} else {
dbp->flags &= ~DBSQL_CountRows;
}
} else
/*
* PRAGMA empty_result_callbacks
*/
if (strcasecmp(left_name, "empty_result_callbacks") == 0) {
if ( __get_boolean(right_name)) {
dbp->flags |= DBSQL_NullCallback;
} else {
dbp->flags &= ~DBSQL_NullCallback;
}
} else
/*
* PRAGMA table_info
*/
if (strcasecmp(left_name, "table_info") == 0) {
table_t *table;
table = __find_table(dbp, right_name, 0);
if (table) {
static vdbe_op_t table_info_preface[] = {
{ OP_ColumnName, 0, 0, "cid"},
{ OP_ColumnName, 1, 0, "name"},
{ OP_ColumnName, 2, 0, "type"},
{ OP_ColumnName, 3, 0, "notnull"},
{ OP_ColumnName, 4, 0, "dflt_value"},
{ OP_ColumnName, 5, 0, "pk"},
};
int i;
__vdbe_add_op_list(v, ARRAY_SIZE(table_info_preface),
table_info_preface);
__view_get_column_names(parser, table);
for (i = 0; i < table->nCol; i++) {
__vdbe_add_op(v, OP_Integer, i, 0);
__vdbe_add_op(v, OP_String, 0, 0);
__vdbe_change_p3(v, -1, table->aCol[i].zName,
P3_STATIC);
__vdbe_add_op(v, OP_String, 0, 0);
__vdbe_change_p3(v, -1,
table->aCol[i].zType ?
table->aCol[i].zType :
"numeric", P3_STATIC);
__vdbe_add_op(v, OP_Integer,
table->aCol[i].notNull, 0);
__vdbe_add_op(v, OP_String, 0, 0);
__vdbe_change_p3(v, -1, table->aCol[i].zDflt,
P3_STATIC);
__vdbe_add_op(v, OP_Integer,
table->aCol[i].isPrimKey, 0);
__vdbe_add_op(v, OP_Callback, 6, 0);
}
}
} else
/*
* PRAGMA index_info
*/
if (strcasecmp(left_name, "index_info") == 0) {
index_t *index;
table_t *table;
index = __find_index(dbp, right_name, 0);
if (index) {
static vdbe_op_t table_info_preface[] = {
{ OP_ColumnName, 0, 0, "seqno"},
{ OP_ColumnName, 1, 0, "cid"},
{ OP_ColumnName, 2, 0, "name"},
};
int i;
table = index->pTable;
__vdbe_add_op_list(v, ARRAY_SIZE(table_info_preface),
table_info_preface);
for (i = 0; i < index->nColumn; i++) {
int cnum = index->aiColumn[i];
__vdbe_add_op(v, OP_Integer, i, 0);
__vdbe_add_op(v, OP_Integer, cnum, 0);
__vdbe_add_op(v, OP_String, 0, 0);
DBSQL_ASSERT(table->nCol > cnum);
__vdbe_change_p3(v, -1,
table->aCol[cnum].zName,
P3_STATIC);
__vdbe_add_op(v, OP_Callback, 3, 0);
}
}
} else
/*
* PRAGMA index_list
*/
if (strcasecmp(left_name, "index_list") == 0) {
index_t *index;
table_t *table;
table = __find_table(dbp, right_name, 0);
if (table) {
v = __parser_get_vdbe(parser);
index = table->pIndex;
}
if (table && index) {
int i = 0;
static vdbe_op_t index_list_preface[] = {
{ OP_ColumnName, 0, 0, "seq"},
{ OP_ColumnName, 1, 0, "name"},
{ OP_ColumnName, 2, 0, "unique"},
};
__vdbe_add_op_list(v, ARRAY_SIZE(index_list_preface),
index_list_preface);
while(index) {
__vdbe_add_op(v, OP_Integer, i, 0);
__vdbe_add_op(v, OP_String, 0, 0);
__vdbe_change_p3(v, -1, index->zName,
P3_STATIC);
__vdbe_add_op(v, OP_Integer,
index->onError != OE_None, 0);
__vdbe_add_op(v, OP_Callback, 3, 0);
++i;
index = index->pNext;
}
}
} else
/*
* PRAGMA foreign_key_list
*/
if (strcasecmp(left_name, "foreign_key_list") == 0) {
foreign_key_t *fk;
table_t *table;
table = __find_table(dbp, right_name, 0);
if (table) {
v = __parser_get_vdbe(parser);
fk = table->pFKey;
}
if (table && fk) {
int i = 0;
static vdbe_op_t index_list_preface[] = {
{ OP_ColumnName, 0, 0, "id"},
{ OP_ColumnName, 1, 0, "seq"},
{ OP_ColumnName, 2, 0, "table"},
{ OP_ColumnName, 3, 0, "from"},
{ OP_ColumnName, 4, 0, "to"},
};
__vdbe_add_op_list(v, ARRAY_SIZE(index_list_preface),
index_list_preface);
while(fk) {
int j;
for (j = 0; j < fk->nCol; j++) {
__vdbe_add_op(v, OP_Integer, i, 0);
__vdbe_add_op(v, OP_Integer, j, 0);
__vdbe_add_op(v, OP_String, 0, 0);
__vdbe_change_p3(v, -1, fk->zTo,
P3_STATIC);
__vdbe_add_op(v, OP_String, 0, 0);
__vdbe_change_p3(v, -1,
table->aCol[fk->aCol[j].iFrom].zName,
P3_STATIC);
__vdbe_add_op(v, OP_String, 0, 0);
__vdbe_change_p3(v, -1,
fk->aCol[j].zCol, P3_STATIC);
__vdbe_add_op(v, OP_Callback, 5, 0);
}
++i;
fk = fk->pNextFrom;
}
}
} else
/*
* PRAGMA database_list
*/
if (strcasecmp(left_name, "database_list") == 0) {
int i;
static vdbe_op_t index_list_preface[] = {
{ OP_ColumnName, 0, 0, "seq"},
{ OP_ColumnName, 1, 0, "name"},
{ OP_ColumnName, 2, 0, "file"},
};
__vdbe_add_op_list(v, ARRAY_SIZE(index_list_preface),
index_list_preface);
for (i = 0; i < dbp->nDb; i++) {
if (dbp->aDb[i].pBt == 0)
continue;
DBSQL_ASSERT(dbp->aDb[i].zName != 0);
__vdbe_add_op(v, OP_Integer, i, 0);
__vdbe_add_op(v, OP_String, 0, 0);
__vdbe_change_p3(v, -1, dbp->aDb[i].zName, P3_STATIC);
__vdbe_add_op(v, OP_String, 0, 0);
__vdbe_change_p3(v, -1,
__sm_get_database_name(dbp->aDb[i].pBt), P3_STATIC);
__vdbe_add_op(v, OP_Callback, 3, 0);
}
} else
#ifndef NDEBUG
/*
* PRAGMA parser_trace
*/
if (strcasecmp(left_name, "parser_trace") == 0) {
extern void __sql_parser_trace(FILE*, char *);
if (__get_boolean(right_name)) {
__sql_parser_trace(stdout, "parser: ");
} else {
__sql_parser_trace(0, 0);
}
}
#endif
else {}
__dbsql_free(dbp, left_name);
__dbsql_free(dbp, right_name);
}

2975
src/cg_select.c Normal file

File diff suppressed because it is too large Load diff

978
src/cg_trigger.c Normal file
View file

@ -0,0 +1,978 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 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
* General Public License for more details.
*
* $Id: cg_trigger.c 7 2007-02-03 13:34:17Z gburd $
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
/*
* __vdbe_delete_trigger_step --
* Delete a linked list of TriggerStep structures.
*
* PUBLIC: void __vdbe_delete_trigger_step __P((trigger_step_t *));
*/
void
__vdbe_delete_trigger_step(ts)
trigger_step_t *ts;
{
while(ts) {
trigger_step_t * tmp = ts;
ts = ts->pNext;
if (tmp->target.dyn)
__dbsql_free(NULL, (char *)tmp->target.z);
__expr_delete(tmp->pWhere);
__expr_list_delete(tmp->pExprList);
__select_delete(tmp->pSelect);
__id_list_delete(tmp->pIdList);
__dbsql_free(NULL, tmp);
}
}
/*
* __begin_trigger --
* This is called by the parser when it sees a CREATE TRIGGER statement
* up to the point of the BEGIN before the trigger actions. A trigger_t
* structure is generated based on the information available and stored
* in parser->pNewTrigger. After the trigger actions have been parsed,
* the __finish_trigger() function is called to complete the trigger
* construction process.
*
* PUBLIC: void __begin_trigger __P((parser_t *, token_t *, int, int,
* PUBLIC: id_list_t *, src_list_t *, int, expr_t *, int));
*
* parser The parse context of the CREATE TRIGGER
* statement
* trigger The trigger of the trigger
* tr_tm One of TK_BEFORE, TK_AFTER, TK_INSTEAD
* op One of TK_INSERT, TK_UPDATE, TK_DELETE
* columns Column list if this is an UPDATE OF trigger
* tab_name The table name of the table/view for this
* trigger
* foreach One of TK_ROW or TK_STATEMENT
* when_clause WHEN clause
* temp_p True if the TEMPORARY keyword is present
*/
void
__begin_trigger(parser, trigger, tr_tm, op, columns, tab_name, foreach,
when_clause, temp_p)
parser_t *parser;
token_t *trigger;
int tr_tm;
int op;
id_list_t *columns;
src_list_t *tab_name;
int foreach;
expr_t *when_clause;
int temp_p;
{
trigger_t *nt;
table_t *table;
ref_normalizer_ctx_t normctx;
DBSQL *dbp = parser->db;
char *name = 0; /* Name of the trigger */
int db_idx; /* When database to store the trigger in */
/*
* Check that:
* 1. The trigger name does not already exist.
* 2. The table (or view) does exist in the same database as the
* trigger.
* 3. That we are not trying to create a trigger on either the
* master or master temp tables.
* 4. That we are not trying to create an INSTEAD OF trigger on a
* table.
* 5. That we are not trying to create a BEFORE or AFTER trigger on
* a view.
*/
if (parser->rc == ENOMEM)
goto trigger_cleanup;
DBSQL_ASSERT(tab_name->nSrc == 1);
if (parser->initFlag &&
__ref_normalizer_ctx_init(&normctx, parser, parser->iDb,
"trigger", trigger) &&
__ref_normalize_src_list(&normctx, tab_name)) {
goto trigger_cleanup;
}
table = __src_list_lookup(parser, tab_name);
if (!table) {
goto trigger_cleanup;
}
db_idx = (temp_p ? 1 : table->iDb);
if (db_idx >= 2 && !parser->initFlag) {
__error_msg(parser, "triggers may not be added to auxiliary "
"database %s", dbp->aDb[table->iDb].zName);
goto trigger_cleanup;
}
__dbsql_strndup(dbp, trigger->z, &name, trigger->n);
__str_unquote(name);
if( __hash_find(&(dbp->aDb[db_idx].trigHash), name,trigger->n+1) ){
__error_msg(parser, "trigger %T already exists", trigger);
goto trigger_cleanup;
}
if (strncasecmp(table->zName, MASTER_NAME,
strlen(MASTER_NAME)) == 0) {
__error_msg(parser, "cannot create trigger on system table");
parser->nErr++;
goto trigger_cleanup;
}
if (strncasecmp(table->zName, TEMP_MASTER_NAME,
strlen(TEMP_MASTER_NAME)) == 0) {
__error_msg(parser, "cannot create trigger on system table");
parser->nErr++;
goto trigger_cleanup;
}
if (table->pSelect && tr_tm != TK_INSTEAD) {
__error_msg(parser, "cannot create %s trigger on view: %S",
((tr_tm == TK_BEFORE) ? "BEFORE" : "AFTER"),
tab_name, 0);
goto trigger_cleanup;
}
if (!table->pSelect && tr_tm == TK_INSTEAD) {
__error_msg(parser, "cannot create INSTEAD OF"
" trigger on table: %S", tab_name, 0);
goto trigger_cleanup;
}
#ifndef DBSQL_NO_AUTH
{
int code = DBSQL_CREATE_TRIGGER;
const char *db = dbp->aDb[table->iDb].zName;
const char *db_trig = temp_p ? dbp->aDb[1].zName : db;
if (table->iDb == 1 || temp_p)
code = DBSQL_CREATE_TEMP_TRIGGER;
if (__auth_check(parser, code, name, table->zName, db_trig)) {
goto trigger_cleanup;
}
if (__auth_check(parser, DBSQL_INSERT,
SCHEMA_TABLE(table->iDb), 0, db)) {
goto trigger_cleanup;
}
}
#endif
/*
* INSTEAD OF triggers can only appear on views and BEGIN triggers
* cannot appear on views. So we might as well translate every
* INSTEAD OF trigger into a BEFORE trigger. It simplifies code
* elsewhere.
*/
if (tr_tm == TK_INSTEAD) {
tr_tm = TK_BEFORE;
}
/*
* Build the Trigger object.
*/
__dbsql_calloc(dbp, 1, sizeof(trigger_t), &nt);
if (nt == 0)
goto trigger_cleanup;
nt->name = name;
name = 0;
if (__dbsql_strdup(dbp, tab_name->a[0].zName, &nt->table) == ENOMEM)
goto trigger_cleanup;
nt->iDb = db_idx;
nt->iTabDb = table->iDb;
nt->op = op;
nt->tr_tm = tr_tm;
nt->pWhen = __expr_dup(when_clause);
nt->pColumns = __id_list_dup(columns);
nt->foreach = foreach;
__token_copy(&nt->nameToken,trigger);
DBSQL_ASSERT( parser->pNewTrigger==0 );
parser->pNewTrigger = nt;
trigger_cleanup:
__dbsql_free(dbp, name);
__src_list_delete(tab_name);
__id_list_delete(columns);
__expr_delete(when_clause);
}
/*
* __finish_trigger --
* This routine is called after all of the trigger actions have been
* parsed in order to complete the process of building the trigger.
*
* PUBLIC: void __finish_trigger __P((parser_t *, trigger_step_t *,
* PUBLIC: token_t *));
*
* parser The parse context of the CREATE TRIGGER
* statement
* steplist The triggered program
* all Token that describes the complete
* CREATE TRIGGER
*/
void
__finish_trigger(parser, steplist, all)
parser_t *parser;
trigger_step_t *steplist;
token_t *all;
{
ref_normalizer_ctx_t normctx;
trigger_t *nt = 0; /* The trigger whose construction is finishing up */
DBSQL *dbp = parser->db;
if (parser->nErr || parser->pNewTrigger == 0)
goto triggerfinish_cleanup;
nt = parser->pNewTrigger;
parser->pNewTrigger = 0;
nt->step_list = steplist;
while(steplist) {
steplist->pTrig = nt;
steplist = steplist->pNext;
}
if (__ref_normalizer_ctx_init(&normctx, parser, nt->iDb,
"trigger", &nt->nameToken) &&
__ref_normalize_trigger_step(&normctx, nt->step_list)) {
goto triggerfinish_cleanup;
}
/*
* if we are not initializing, and this trigger is not on a TEMP
* table, build the master entry.
*/
if (!parser->initFlag) {
static vdbe_op_t insert_trig[] = {
{ OP_NewRecno, 0, 0, 0 },
{ OP_String, 0, 0, "trigger" },
{ OP_String, 0, 0, 0 }, /* 2: trigger name */
{ OP_String, 0, 0, 0 }, /* 3: table name */
{ OP_Integer, 0, 0, 0 },
{ OP_String, 0, 0, 0 }, /* 5: SQL */
{ OP_MakeRecord, 5, 0, 0 },
{ OP_PutIntKey, 0, 0, 0 },
};
int addr;
vdbe_t *v;
/*
* Make an entry in the master table.
*/
v = __parser_get_vdbe(parser);
if (v == 0)
goto triggerfinish_cleanup;
__vdbe_prepare_write(parser, 0, 0);
__open_master_table(v, nt->iDb);
addr = __vdbe_add_op_list(v, ARRAY_SIZE(insert_trig),
insert_trig);
__vdbe_change_p3(v, (addr + 2), nt->name, 0);
__vdbe_change_p3(v, (addr + 3), nt->table, 0);
__vdbe_change_p3(v, (addr + 5), all->z, all->n);
if (nt->iDb == 0) {
__change_schema_signature(dbp, v);
}
__vdbe_add_op(v, OP_Close, 0, 0);
__vdbe_conclude_write(parser);
}
if (!parser->explain) {
table_t *table;
__hash_insert(&dbp->aDb[nt->iDb].trigHash,
nt->name, (strlen(nt->name) + 1), nt);
table = __locate_table(parser, nt->table,
dbp->aDb[nt->iTabDb].zName);
DBSQL_ASSERT(table != 0);
nt->pNext = table->pTrigger;
table->pTrigger = nt;
nt = 0;
}
triggerfinish_cleanup:
__vdbe_delete_trigger(nt);
__vdbe_delete_trigger(parser->pNewTrigger);
parser->pNewTrigger = 0;
__vdbe_delete_trigger_step(steplist);
}
/*
* __persist_trigger_step --
* Make a copy of all components of the given trigger step. This has
* the effect of copying all expr_t.token.z values into memory obtained
* from __dbsql_calloc(). As initially created, the expr_t.token.z values
* all point to the input string that was fed to the parser. But that
* string is ephemeral - it will go away as soon as the dbsql_exec()
* call that started the parser exits. This routine makes a persistent
* copy of all the Expr.token.z strings so that the trigger_step_t
* structure will be valid even after the dbsql_exec() call returns.
*
* STATIC: static void __persist_trigger_step __P((trigger_step_t *));
*/
static void
__persist_trigger_step(ts)
trigger_step_t *ts;
{
if (ts->target.z) {
__dbsql_strndup(NULL, ts->target.z, &ts->target.z, ts->target.n);
ts->target.dyn = 1;
}
if (ts->pSelect) {
select_t *new = __select_dup(ts->pSelect);
__select_delete(ts->pSelect);
ts->pSelect = new;
}
if( ts->pWhere ){
expr_t *new = __expr_dup(ts->pWhere);
__expr_delete(ts->pWhere);
ts->pWhere = new;
}
if (ts->pExprList) {
expr_list_t *new = __expr_list_dup(ts->pExprList);
__expr_list_delete(ts->pExprList);
ts->pExprList = new;
}
if (ts->pIdList) {
id_list_t *new = __id_list_dup(ts->pIdList);
__id_list_delete(ts->pIdList);
ts->pIdList = new;
}
}
/*
* __trigger_select_step --
* Turn a SELECT statement (that the 'select' parameter points to) into
* a trigger step. Return a pointer to a trigger_step_t structure.
*
* The parser calls this routine when it finds a SELECT statement in
* body of a TRIGGER.
*
* PUBLIC: trigger_step_t * __trigger_select_step __P((select_t *));
*/
trigger_step_t *
__trigger_select_step(select)
select_t *select;
{
trigger_step_t *ts;
if (__dbsql_calloc(NULL, 1, sizeof(trigger_step_t), &ts) == ENOMEM)
return 0;
ts->op = TK_SELECT;
ts->pSelect = select;
ts->orconf = OE_Default;
__persist_trigger_step(ts);
return ts;
}
/*
* __trigger_insert_step --
* Build a trigger step out of an INSERT statement. Return a pointer
* to the new trigger step.
*
* The parser calls this routine when it sees an INSERT inside the
* body of a trigger.
*
* PUBLIC: trigger_step_t *__trigger_insert_step __P((token_t *, id_list_t *,
* PUBLIC: expr_list_t *, select_t *, int));
*
* tab_name Name of the table into which we insert
* column List of columns in tab_name to insert into
* elist The VALUE clause: a list of values to be
* inserted
* select A SELECT statement that supplies values
* orconf The conflict algorithm (OE_Abort, OE_Replace,
* etc.)
*/
trigger_step_t *
__trigger_insert_step(tab_name, column, elist, select, orconf)
token_t *tab_name;
id_list_t *column;
expr_list_t *elist;
select_t *select;
int orconf;
{
trigger_step_t *ts;
if (__dbsql_calloc(NULL, 1, sizeof(trigger_step_t), &ts) == ENOMEM)
return 0;
DBSQL_ASSERT(elist == 0 || select == 0);
DBSQL_ASSERT(elist != 0 || select != 0);
ts->op = TK_INSERT;
ts->pSelect = select;
ts->target = *tab_name;
ts->pIdList = column;
ts->pExprList = elist;
ts->orconf = orconf;
__persist_trigger_step(ts);
return ts;
}
/*
* __trigger_update_step --
* Construct a trigger step that implements an UPDATE statement and return
* a pointer to that trigger step. The parser calls this routine when it
* sees an UPDATE statement inside the body of a CREATE TRIGGER.
*
* PUBLIC: trigger_step_t *__trigger_update_step __P((token_t *, expr_list_t *,
* PUBLIC: expr_t *, int));
*
* tab_name Name of the table to be updated
* elist The SET clause: list of column and new values
* where_clause The WHERE clause
* orconf The conflict algorithm. (OE_Abort, OE_Ignore,
* etc)
*/
trigger_step_t *
__trigger_update_step(tab_name, elist, where_clause, orconf)
token_t *tab_name;
expr_list_t *elist;
expr_t *where_clause;
int orconf;
{
trigger_step_t *ts;
if (__dbsql_calloc(NULL, 1, sizeof(trigger_step_t), &ts) == ENOMEM)
return 0;
ts->op = TK_UPDATE;
ts->target = *tab_name;
ts->pExprList = elist;
ts->pWhere = where_clause;
ts->orconf = orconf;
__persist_trigger_step(ts);
return ts;
}
/*
* __trigger_delete_step --
* Construct a trigger step that implements a DELETE statement and return
* a pointer to that trigger step. The parser calls this routine when it
* sees a DELETE statement inside the body of a CREATE TRIGGER.
*
* PUBLIC: trigger_step_t *__trigger_delete_step __P((token_t *, expr_t *));
*/
trigger_step_t *
__trigger_delete_step(tab_name, where_clause)
token_t *tab_name;
expr_t *where_clause;
{
trigger_step_t *ts;
if (__dbsql_calloc(NULL, 1, sizeof(trigger_step_t), &ts) == ENOMEM)
return 0;
ts->op = TK_DELETE;
ts->target = *tab_name;
ts->pWhere = where_clause;
ts->orconf = OE_Default;
__persist_trigger_step(ts);
return ts;
}
/*
* __vdbe_delete_trigger --
* Recursively delete a trigger_t structure
*
* PUBLIC: void __vdbe_delete_trigger __P((trigger_t *));
*/
void
__vdbe_delete_trigger(trigger)
trigger_t *trigger;
{
if (trigger == 0)
return;
__vdbe_delete_trigger_step(trigger->step_list);
__dbsql_free(NULL, trigger->name);
__dbsql_free(NULL, trigger->table);
__expr_delete(trigger->pWhen);
__id_list_delete(trigger->pColumns);
if (trigger->nameToken.dyn)
__dbsql_free(NULL, (char*)trigger->nameToken.z);
__dbsql_free(NULL, trigger);
}
/*
* __drop_trigger --
* This function is called to drop a trigger from the database schema.
*
* This may be called directly from the parser and therefore identifies
* the trigger by name. The __drop_trigger_ptr() routine does the
* same job as this routine except it take a spointer to the trigger
* instead of the trigger name.
*
* Note that this function does not delete the trigger entirely. Instead
* it removes it from the internal schema and places it in the trigDrop
* hash table. This is so that the trigger can be restored into the
* database schema if the transaction is rolled back.
*
* PUBLIC: void __drop_trigger __P((parser_t *, src_list_t *));
*/
void
__drop_trigger(parser, trig_list)
parser_t *parser;
src_list_t *trig_list;
{
int i;
trigger_t *trigger;
const char *db_name;
const char *trig_name;
int name_len;
DBSQL *dbp = parser->db;
if (parser->rc == ENOMEM)
goto err;
DBSQL_ASSERT(trig_list->nSrc == 1);
db_name = trig_list->a[0].zDatabase;
trig_name = trig_list->a[0].zName;
name_len = strlen(trig_name);
for (i = 0; i < dbp->nDb; i++) {
int j = (i < 2) ? (i ^ 1) : i; /* Search TEMP before MAIN. */
if (db_name &&
strcasecmp(dbp->aDb[j].zName, db_name))
continue;
trigger = __hash_find(&(dbp->aDb[j].trigHash), trig_name,
(name_len + 1));
if (trigger)
break;
}
if (!trigger) {
__error_msg(parser, "no such trigger: %S", trig_list, 0);
goto err;
}
__drop_trigger_ptr(parser, trigger, 0);
err:
__src_list_delete(trig_list);
}
/*
* __drop_trigger_ptr --
* Drop a trigger given a pointer to that trigger. If nested is false,
* then also generate code to remove the trigger from the DBSQL_MASTER
* table.
*
* PUBLIC: void __drop_trigger_ptr __P((parser_t *, trigger_t *, int));
*/
void
__drop_trigger_ptr(parser, trigger, nested)
parser_t *parser;
trigger_t *trigger;
int nested;
{
table_t *table;
vdbe_t *v;
DBSQL *dbp = parser->db;
DBSQL_ASSERT(trigger->iDb < dbp->nDb);
if (trigger->iDb >= 2) {
__error_msg(parser, "triggers may not be removed from "
"auxiliary database %s",
dbp->aDb[trigger->iDb].zName);
return;
}
table = __find_table(dbp, trigger->table,
dbp->aDb[trigger->iTabDb].zName);
DBSQL_ASSERT(table);
DBSQL_ASSERT(table->iDb == trigger->iDb || trigger->iDb == 1);
#ifndef DBSQL_NO_AUTH
{
int code = DBSQL_DROP_TRIGGER;
const char *db = dbp->aDb[trigger->iDb].zName;
const char *tab = SCHEMA_TABLE(trigger->iDb);
if (trigger->iDb)
code = DBSQL_DROP_TEMP_TRIGGER;
if (__auth_check(parser, code, trigger->name,
table->zName, db) ||
__auth_check(parser, DBSQL_DELETE, tab, 0, db)) {
return;
}
}
#endif
/*
* Generate code to destroy the database record of the trigger.
*/
if (table != 0 && !nested && (v = __parser_get_vdbe(parser)) != 0) {
int base;
static vdbe_op_t drop_trigger[] = {
{ OP_Rewind, 0, ADDR(9), 0},
{ OP_String, 0, 0, 0}, /* 1 */
{ OP_Column, 0, 1, 0},
{ OP_Ne, 0, ADDR(8), 0},
{ OP_String, 0, 0, "trigger"},
{ OP_Column, 0, 0, 0},
{ OP_Ne, 0, ADDR(8), 0},
{ OP_Delete, 0, 0, 0},
{ OP_Next, 0, ADDR(1), 0}, /* 8 */
};
__vdbe_prepare_write(parser, 0, 0);
__open_master_table(v, trigger->iDb);
base = __vdbe_add_op_list(v, ARRAY_SIZE(drop_trigger),
drop_trigger);
__vdbe_change_p3(v, base+1, trigger->name, 0);
if (trigger->iDb == 0) {
__change_schema_signature(dbp, v);
}
__vdbe_add_op(v, OP_Close, 0, 0);
__vdbe_conclude_write(parser);
}
/*
* If this is not an "explain", then delete the trigger structure.
*/
if (!parser->explain) {
const char *name = trigger->name;
int len = strlen(name);
if (table->pTrigger == trigger) {
table->pTrigger = trigger->pNext;
} else {
trigger_t *cc = table->pTrigger;
while(cc) {
if (cc->pNext == trigger) {
cc->pNext = cc->pNext->pNext;
break;
}
cc = cc->pNext;
}
DBSQL_ASSERT(cc);
}
__hash_insert(&(dbp->aDb[trigger->iDb].trigHash), name,
(len + 1), 0);
__vdbe_delete_trigger(trigger);
}
}
/*
* __check_column_overlap --
* 'elist' is the SET clause of an UPDATE statement. Each entry
* in 'elist' is of the format <id>=<expr>. If any of the entries
* in 'elist' have an <id> which matches an identifier in 'id_list',
* then return TRUE. If 'id_list'==NULL, then it is considered a
* wildcard that matches anything. Likewise if elist==NULL then
* it matches anything so always return true. Return false only
* if there is no match.
*
* STATIC: static int __check_column_overlap __P((id_list_t *, expr_list_t *));
*/
static int
__check_column_overlap(id_list, elist)
id_list_t *id_list;
expr_list_t *elist;
{
int e;
if (!id_list || !elist)
return 1;
for (e = 0; e < elist->nExpr; e++) {
if (__id_list_index(id_list, elist->a[e].zName) >= 0)
return 1;
}
return 0;
}
/*
* A global variable that is TRUE if we should always set up temp tables for
* for triggers, even if there are no triggers to code. This is used to test
* how much overhead the triggers algorithm is causing.
*
* This flag can be set or cleared using the "trigger_overhead_test" pragma.
* The pragma is not documented since it is not really part of the public
* interface, just the test procedure.
*/
int always_code_trigger_setup = 0; /* TODO, remove this global, place it
in the environment. */
/*
* __triggers_exist --
* Returns true if a trigger matching op, tr_tm and foreach that is NOT
* already on the parser_t objects trigger-stack (to prevent recursive
* trigger firing) is found in the list specified as trigger.
*
* PUBLIC: int __triggers_exist __P((parser_t *, trigger_t *, int, int, int,
* PUBLIC: expr_list_t *));
*
* parser Used to check for recursive triggers
* trigger A list of triggers associated with a table
* op One of TK_DELETE, TK_INSERT, TK_UPDATE
* tr_tm One of TK_BEFORE, TK_AFTER
* foreach One of TK_ROW or TK_STATEMENT
* changes Columns that change in an UPDATE statement
*/
int __triggers_exist(parser, trigger, op, tr_tm, foreach, changes)
parser_t *parser;
trigger_t *trigger;
int op;
int tr_tm;
int foreach;
expr_list_t *changes;
{
trigger_t * trig_cursor;
if (always_code_trigger_setup) {
return 1;
}
trig_cursor = trigger;
while (trig_cursor) {
if (trig_cursor->op == op &&
trig_cursor->tr_tm == tr_tm &&
trig_cursor->foreach == foreach &&
__check_column_overlap(trig_cursor->pColumns, changes)) {
trigger_stack_t *ss;
ss = parser->trigStack;
while (ss && ss->pTrigger != trigger) {
ss = ss->pNext;
}
if (!ss)
return 1;
}
trig_cursor = trig_cursor->pNext;
}
return 0;
}
/*
* __target_src_list --
* Convert the pStep->target token into a src_list_t and return a pointer
* to that src_list_t.
*
* This routine adds a specific database name, if needed, to the target
* when forming the src_list_t. This prevents a trigger in one database
* from referring to a target in another database. An exception is when
* the trigger is in TEMP in which case it can refer to any other database
* it wants.
*
* STATIC: static src_list_t *__target_src_list __P((parser_t *,
* STATIC: trigger_step_t *));
*
* parser The parsing context
* step The trigger containing the target token
*/
static src_list_t *targetSrcList(parser, step)
parser_t *parser;
trigger_step_t *step;
{
token_t db; /* Dummy database name token */
int db_idx; /* Index of the database to use */
src_list_t *src; /* SrcList to be returned */
db_idx = step->pTrig->iDb;
if (db_idx == 0 || db_idx >= 2) {
DBSQL_ASSERT(db_idx < parser->db->nDb);
db.z = parser->db->aDb[db_idx].zName;
db.n = strlen(db.z);
src = __src_list_append(0, &db, &step->target);
} else {
src = __src_list_append(0, &step->target, 0);
}
return src;
}
/*
* __code_trigger_prigram --
* Generate VDBE code for zero or more statements inside the body of a
* trigger.
*
* STATIC: static int __code_trigger_prigram __P(());
*
* parser The parser context
* steplist List of statements inside the trigger body
* orconfin Conflict algorithm. (OE_Abort, etc)
*/
static int
__code_trigger_program(parser, steplist, orconfin)
parser_t *parser;
trigger_step_t *steplist;
int orconfin;
{
int orconf;
trigger_step_t * ts = steplist;
while (ts) {
int saveNTab = parser->nTab;
orconf = (orconfin == OE_Default)?ts->orconf:orconfin;
parser->trigStack->orconf = orconf;
switch(ts->op) {
case TK_SELECT: {
select_t * ss = __select_dup(ts->pSelect);
DBSQL_ASSERT(ss);
DBSQL_ASSERT(ss->pSrc);
__select(parser, ss, SRT_Discard, 0, 0, 0, 0);
__select_delete(ss);
break;
}
case TK_UPDATE: {
src_list_t *src;
src = targetSrcList(parser, ts);
__vdbe_add_op(parser->pVdbe, OP_ListPush, 0, 0);
__update(parser, src,
__expr_list_dup(ts->pExprList),
__expr_dup(ts->pWhere), orconf);
__vdbe_add_op(parser->pVdbe, OP_ListPop, 0, 0);
break;
}
case TK_INSERT: {
src_list_t *src;
src = targetSrcList(parser, ts);
__insert(parser, src,
__expr_list_dup(ts->pExprList),
__select_dup(ts->pSelect),
__id_list_dup(ts->pIdList), orconf);
break;
}
case TK_DELETE: {
src_list_t *src;
__vdbe_add_op(parser->pVdbe, OP_ListPush, 0, 0);
src = targetSrcList(parser, ts);
__delete_from(parser, src, __expr_dup(ts->pWhere));
__vdbe_add_op(parser->pVdbe, OP_ListPop, 0, 0);
break;
}
default:
DBSQL_ASSERT(0);
}
parser->nTab = saveNTab;
ts = ts->pNext;
}
return 0;
}
/*
* __code_row_trigger --
* This is called to code FOR EACH ROW triggers.
*
* When the code that this function generates is executed, the following
* must be true:
*
* 1. No cursors may be open in the main database. (But newIdx and oldIdx
* can be indices of cursors in temporary tables. See below.)
*
* 2. If the triggers being coded are ON INSERT or ON UPDATE triggers,
* then a temporary vdbe cursor (index newIdx) must be open and
* pointing at a row containing values to be substituted for new.*
* expressions in the trigger program(s).
*
* 3. If the triggers being coded are ON DELETE or ON UPDATE triggers,
* then a temporary vdbe cursor (index oldIdx) must be open and
* pointing at a row containing values to be substituted for old.*
* expressions in the trigger program(s).
*
* PUBlIC: int __code_row_trigger __P(());
*
* parser Parser context
* op One of TK_UPDATE, TK_INSERT, TK_DELETE
* changes Changes list for any UPDATE OF triggers
* tr_tm One of TK_BEFORE, TK_AFTER
* table The table to code triggers from
* new_idx The indice of the "new" row to access
* old_idx The indice of the "old" row to access
* orconf ON CONFLICT policy
* ignore_jump Instruction to jump to for RAISE(IGNORE)
*/
int __code_row_trigger(parser, op, changes, tr_tm, table, new_idx, old_idx,
orconf, ignore_jump)
parser_t *parser;
int op;
expr_list_t *changes;
int tr_tm;
table_t *table;
int new_idx;
int old_idx;
int orconf;
int ignore_jump;
{
trigger_t * trigger;
trigger_stack_t * trig_stack;
DBSQL *dbp = parser->db;
DBSQL_ASSERT(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
DBSQL_ASSERT(tr_tm == TK_BEFORE || tr_tm == TK_AFTER );
DBSQL_ASSERT(new_idx != -1 || old_idx != -1);
trigger = table->pTrigger;
while(trigger) {
int fire_this = 0;
/*
* Determine whether we should code this trigger.
*/
if (trigger->op == op && trigger->tr_tm == tr_tm &&
trigger->foreach == TK_ROW) {
fire_this = 1;
trig_stack = parser->trigStack;
while(trig_stack) {
if (trig_stack->pTrigger == trigger) {
fire_this = 0;
}
trig_stack = trig_stack->pNext;
}
if (op == TK_UPDATE && trigger->pColumns &&
!__check_column_overlap(trigger->pColumns,
changes)) {
fire_this = 0;
}
}
if (fire_this && __dbsql_calloc(dbp, 1,sizeof(trigger_stack_t),
&trig_stack) != ENOMEM) {
int end_trigger;
src_list_t dummy_tab_list;
expr_t * when_expr;
auth_context_t authctx;
dummy_tab_list.nSrc = 0;
/*
* Push an entry on to the trigger stack.
*/
trig_stack->pTrigger = trigger;
trig_stack->newIdx = new_idx;
trig_stack->oldIdx = old_idx;
trig_stack->pTab = table;
trig_stack->pNext = parser->trigStack;
trig_stack->ignoreJump = ignore_jump;
parser->trigStack = trig_stack;
__auth_context_push(parser, &authctx, trigger->name);
/*
* Code the WHEN clause.
*/
end_trigger = __vdbe_make_label(parser->pVdbe);
when_expr = __expr_dup(trigger->pWhen);
if (__expr_resolve_ids(parser, &dummy_tab_list, 0,
when_expr)) {
parser->trigStack = parser->trigStack->pNext;
__dbsql_free(dbp, trig_stack);
__expr_delete(when_expr);
return 1;
}
__expr_if_false(parser, when_expr, end_trigger, 1);
__expr_delete(when_expr);
__code_trigger_program(parser, trigger->step_list,
orconf);
/*
* Pop the entry off the trigger stack.
*/
parser->trigStack = parser->trigStack->pNext;
__auth_context_pop(&authctx);
__dbsql_free(dbp, trig_stack);
__vdbe_resolve_label(parser->pVdbe, end_trigger);
}
trigger = trigger->pNext;
}
return 0;
}

531
src/cg_update.c Normal file
View file

@ -0,0 +1,531 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: cg_update.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* This file contains routines that handle UPDATE statements.
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
/*
* __update --
* Process an UPDATE statement.
*
* UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
* \_______/ \________/ \______/ \________________/
* on_error tab_list changes where
*
* PUBLIC: void __update __P((parser_t *, src_list_t *, expr_list_t *,
* PUBLIC: expr_t *, int));
*
* parser The parser context
* tab_list The table in which we should change things
* changes Things to be changed
* where The WHERE clause. May be null
* on_error How to handle constraint errors
*/
void __update(parser, tab_list, changes, where, on_error)
parser_t *parser;
src_list_t *tab_list;
expr_list_t *changes;
expr_t *where;
int on_error;
{
int rc;
int i, j; /* Loop counters */
table_t *table; /* The table to be updated */
int addr; /* VDBE instruction address of the start of
the loop */
where_info_t *winfo; /* Information about the WHERE clause */
vdbe_t *v; /* The virtual database engine */
index_t *idx; /* For looping over indices */
int num_idx; /* Number of indices that need updating */
int total_num_idx; /* Total number of indices */
int cur; /* VDBE Cursor number of table */
DBSQL *dbp; /* The database structure */
index_t **indices = 0;/* An array of indices that need updating too */
char *idx_used = 0; /* idx_used[i]==1 if the i-th index is used */
int *xref = 0; /* xref[i] is the index in changes->a[] of the
an expression for the i-th column of the
table. xref[i]==-1 if the i-th column is not
changed. */
int recno_will_change_p;/* True if the record number is being changed*/
expr_t *recno; /* Expression defining the new record number */
int open_all_p; /* True if all indices need to be opened */
int is_view_p; /* Trying to update a view */
auth_context_t auth; /* The authorization context */
int before_triggers; /* True if there are any BEFORE triggers */
int after_triggers; /* True if there are any AFTER triggers */
int row_triggers_exist = 0;/* True if any row triggers exist */
int new_idx = -1;/* index of trigger "new" temp table */
int old_idx = -1;/* index of trigger "old" temp table */
select_t *view;
auth.pParse = 0;
if (parser->nErr || parser->rc == ENOMEM)
goto update_cleanup;
dbp = parser->db;
DBSQL_ASSERT(tab_list->nSrc == 1);
/*
* Locate the table which we want to update.
*/
table = __src_list_lookup(parser, tab_list);
if (table == 0)
goto update_cleanup;
before_triggers = __triggers_exist(parser, table->pTrigger,
TK_UPDATE, TK_BEFORE, TK_ROW,
changes);
after_triggers = __triggers_exist(parser, table->pTrigger,
TK_UPDATE, TK_AFTER, TK_ROW,
changes);
row_triggers_exist = before_triggers || after_triggers;
is_view_p = (table->pSelect != 0);
if (__is_table_read_only(parser, table, before_triggers)) {
goto update_cleanup;
}
if (is_view_p) {
if (__view_get_column_names(parser, table)) {
goto update_cleanup;
}
}
if (__dbsql_calloc(dbp, table->nCol, sizeof(int), &xref) == ENOMEM)
goto update_cleanup;
for (i = 0; i < table->nCol; i++) {
xref[i] = -1;
}
/*
* If there are FOR EACH ROW triggers, allocate cursors for the
* special OLD and NEW tables.
*/
if (row_triggers_exist) {
new_idx = parser->nTab++;
old_idx = parser->nTab++;
}
/*
* Allocate a cursors for the main database table and for all indices.
* The index cursors might not be used, but if they are used they
* need to occur right after the database cursor. So go ahead and
* allocate enough space, just in case.
*/
tab_list->a[0].iCursor = cur = parser->nTab++;
for (idx = table->pIndex; idx; idx = idx->pNext) {
parser->nTab++;
}
/*
* Resolve the column names in all the expressions of the
* of the UPDATE statement. Also find the column index
* for each column to be updated in the changes array. For each
* column to be updated, make sure we have authorization to change
* that column.
*/
recno_will_change_p = 0;
for (i = 0; i < changes->nExpr; i++) {
if (__expr_resolve_ids(parser, tab_list, 0,
changes->a[i].pExpr)) {
goto update_cleanup;
}
if (__expr_check(parser, changes->a[i].pExpr, 0, 0)) {
goto update_cleanup;
}
for (j = 0; j < table->nCol; j++) {
if (strcasecmp(table->aCol[j].zName,
changes->a[i].zName) == 0) {
if (j == table->iPKey) {
recno_will_change_p = 1;
recno = changes->a[i].pExpr;
}
xref[j] = i;
break;
}
}
if (j >= table->nCol) {
if (__is_row_id(changes->a[i].zName)) {
recno_will_change_p = 1;
recno = changes->a[i].pExpr;
} else {
__error_msg(parser, "no such column: %s",
changes->a[i].zName);
goto update_cleanup;
}
}
#ifndef DBSQL_NO_AUTH
rc = __auth_check(parser, DBSQL_UPDATE, table->zName,
table->aCol[j].zName,
dbp->aDb[table->iDb].zName);
if (rc == DBSQL_DENY) {
goto update_cleanup;
} else if (rc == DBSQL_IGNORE) {
xref[j] = -1;
}
#endif
}
/*
* Allocate memory for the array indices[] and fill it with pointers
* to every index that needs to be updated. Indices only need
* updating if their key includes one of the columns named in changes
* or if the record number of the original table entry is changing.
*/
for (num_idx = total_num_idx = 0, idx = table->pIndex;
idx; idx = idx->pNext, total_num_idx++) {
if (recno_will_change_p) {
i = 0;
} else {
for (i = 0; i < idx->nColumn; i++) {
if (xref[idx->aiColumn[i]] >= 0)
break;
}
}
if (i < idx->nColumn)
num_idx++;
}
if (total_num_idx > 0) { /* TODO, is this the right amt to alloc? */
if (__dbsql_calloc(dbp, num_idx + total_num_idx,
sizeof(index_t *), &indices) == ENOMEM)
goto update_cleanup;
idx_used = (char*)&indices[num_idx];
}
for (num_idx = j = 0, idx = table->pIndex; idx; idx = idx->pNext, j++){
if (recno_will_change_p) {
i = 0;
} else {
for (i = 0; i < idx->nColumn; i++) {
if (xref[idx->aiColumn[i]] >= 0)
break;
}
}
if (i < idx->nColumn) {
indices[num_idx++] = idx;
idx_used[j] = 1;
} else {
idx_used[j] = 0;
}
}
/*
* Resolve the column names in all the expressions in the
* WHERE clause.
*/
if (where) {
if (__expr_resolve_ids(parser, tab_list, 0, where)) {
goto update_cleanup;
}
if (__expr_check(parser, where, 0, 0)) {
goto update_cleanup;
}
}
/*
* Start the view context.
*/
if (is_view_p) {
__auth_context_push(parser, &auth, table->zName);
}
/*
* Begin generating code.
*/
v = __parser_get_vdbe(parser);
if (v == 0)
goto update_cleanup;
__vdbe_prepare_write(parser, 1, table->iDb);
/*
* If we are trying to update a view, construct that view into
* a temporary table.
*/
if (is_view_p) {
view = __select_dup(table->pSelect);
__select(parser, view, SRT_TempTable, cur, 0, 0, 0);
__select_delete(view);
}
/*
* Begin the database scan.
*/
winfo = __where_begin(parser, tab_list, where, 1, 0);
if (winfo == 0)
goto update_cleanup;
/*
* Remember the index of every item to be updated.
*/
__vdbe_add_op(v, OP_ListWrite, 0, 0);
/*
* End the database scan loop.
*/
__where_end(winfo);
/*
* Initialize the count of updated rows.
*/
if (dbp->flags & DBSQL_CountRows && !parser->trigStack) {
__vdbe_add_op(v, OP_Integer, 0, 0);
}
if (row_triggers_exist) {
/*
* Create pseudo-tables for NEW and OLD
*/
__vdbe_add_op(v, OP_OpenPseudo, old_idx, 0);
__vdbe_add_op(v, OP_OpenPseudo, new_idx, 0);
/*
* The top of the update loop for when there are triggers.
*/
__vdbe_add_op(v, OP_ListRewind, 0, 0);
addr = __vdbe_add_op(v, OP_ListRead, 0, 0);
__vdbe_add_op(v, OP_Dup, 0, 0);
/*
* Open a cursor and make it point to the record that is
* being updated.
*/
__vdbe_add_op(v, OP_Dup, 0, 0);
if(!is_view_p) {
__vdbe_add_op(v, OP_Integer, table->iDb, 0);
__vdbe_add_op(v, OP_OpenRead, cur, table->tnum);
}
__vdbe_add_op(v, OP_MoveTo, cur, 0);
/*
* Generate the OLD table.
*/
__vdbe_add_op(v, OP_Recno, cur, 0);
__vdbe_add_op(v, OP_RowData, cur, 0);
__vdbe_add_op(v, OP_PutIntKey, old_idx, 0);
/*
* Generate the NEW table.
*/
if (recno_will_change_p) {
__expr_code(parser, recno);
} else {
__vdbe_add_op(v, OP_Recno, cur, 0);
}
for(i = 0; i < table->nCol; i++) {
if (i == table->iPKey) {
__vdbe_add_op(v, OP_String, 0, 0);
continue;
}
j = xref[i];
if (j < 0) {
__vdbe_add_op(v, OP_Column, cur, i);
}else{
__expr_code(parser, changes->a[j].pExpr);
}
}
__vdbe_add_op(v, OP_MakeRecord, table->nCol, 0);
__vdbe_add_op(v, OP_PutIntKey, new_idx, 0);
if (!is_view_p) {
__vdbe_add_op(v, OP_Close, cur, 0);
}
/*
* Fire the BEFORE and INSTEAD OF triggers.
*/
if (__code_row_trigger(parser, TK_UPDATE, changes,
TK_BEFORE, table, new_idx, old_idx,
on_error, addr)) {
goto update_cleanup;
}
}
if (!is_view_p) {
/*
* Open every index that needs updating. Note that if any
* index could potentially invoke a REPLACE conflict resolution
* action, then we need to open all indices because we might
* need to be deleting some records.
*/
__vdbe_add_op(v, OP_Integer, table->iDb, 0);
__vdbe_add_op(v, OP_OpenWrite, cur, table->tnum);
if (on_error == OE_Replace) {
open_all_p = 1;
} else {
open_all_p = 0;
for (idx = table->pIndex; idx; idx = idx->pNext) {
if (idx->onError == OE_Replace) {
open_all_p = 1;
break;
}
}
}
for(i = 0, idx = table->pIndex; idx; idx = idx->pNext, i++) {
if (open_all_p || idx_used[i]) {
__vdbe_add_op(v, OP_Integer, idx->iDb, 0);
__vdbe_add_op(v, OP_OpenWrite, (cur + i + 1),
idx->tnum);
DBSQL_ASSERT(parser->nTab > (cur + i + 1));
}
}
/*
* Loop over every record that needs updating. We have to load
* the old data for each record to be updated because some
* columns might not change and we will need to copy the old
* value. Also, the old data is needed to delete the old index
* entires. So make the cursor point at the old record.
*/
if (!row_triggers_exist) {
__vdbe_add_op(v, OP_ListRewind, 0, 0);
addr = __vdbe_add_op(v, OP_ListRead, 0, 0);
__vdbe_add_op(v, OP_Dup, 0, 0);
}
__vdbe_add_op(v, OP_NotExists, cur, addr);
/*
* If the record number will change, push the record number
* as it will be after the update. (The old record number is
* currently on top of the stack.)
*/
if (recno_will_change_p) {
__expr_code(parser, recno);
__vdbe_add_op(v, OP_MustBeInt, 0, 0);
}
/*
* Compute new data for this record.
*/
for (i = 0; i < table->nCol; i++) {
if (i == table->iPKey) {
__vdbe_add_op(v, OP_String, 0, 0);
continue;
}
j = xref[i];
if (j < 0) {
__vdbe_add_op(v, OP_Column, cur, i);
} else {
__expr_code(parser, changes->a[j].pExpr);
}
}
/*
* Do constraint checks.
*/
__generate_constraint_checks(parser, table, cur, idx_used,
recno_will_change_p, 1, on_error,
addr);
/*
* Delete the old indices for the current record.
*/
__generate_row_index_delete(dbp, v, table, cur, idx_used);
/*
* If changing the record number, delete the old record.
*/
if (recno_will_change_p) {
__vdbe_add_op(v, OP_Delete, cur, 0);
}
/*
* Create the new index entries and the new record.
*/
__complete_insertion(parser, table, cur, idx_used,
recno_will_change_p, 1, -1);
}
/*
* Increment the row counter.
*/
if (dbp->flags & DBSQL_CountRows && !parser->trigStack) {
__vdbe_add_op(v, OP_AddImm, 1, 0);
}
/*
* If there are triggers, close all the cursors after each iteration
* through the loop. The fire the after triggers.
*/
if (row_triggers_exist) {
if (!is_view_p) {
for(i = 0, idx = table->pIndex; idx;
idx = idx->pNext, i++) {
if (open_all_p || idx_used[i]) {
__vdbe_add_op(v, OP_Close,
(cur + i + 1), 0);
}
}
__vdbe_add_op(v, OP_Close, cur, 0);
parser->nTab = cur;
}
if (__code_row_trigger(parser, TK_UPDATE, changes,
TK_AFTER, table, new_idx, old_idx,
on_error, addr)) {
goto update_cleanup;
}
}
/*
* Repeat the above with the next record to be updated, until
* all record selected by the WHERE clause have been updated.
*/
__vdbe_add_op(v, OP_Goto, 0, addr);
__vdbe_change_p2(v, addr, __vdbe_current_addr(v));
__vdbe_add_op(v, OP_ListReset, 0, 0);
/*
* Close all tables if there were no FOR EACH ROW triggers.
*/
if (!row_triggers_exist) {
for (i = 0, idx = table->pIndex; idx; idx = idx->pNext, i++) {
if (open_all_p || idx_used[i]) {
__vdbe_add_op(v, OP_Close, (cur + i + 1), 0);
}
}
__vdbe_add_op(v, OP_Close, cur, 0);
parser->nTab = cur;
} else {
__vdbe_add_op(v, OP_Close, new_idx, 0);
__vdbe_add_op(v, OP_Close, old_idx, 0);
}
__vdbe_conclude_write(parser);
/*
* Return the number of rows that were changed.
*/
if (dbp->flags & DBSQL_CountRows && !parser->trigStack) {
__vdbe_add_op(v, OP_ColumnName, 0, 0);
__vdbe_change_p3(v, -1, "rows updated", P3_STATIC);
__vdbe_add_op(v, OP_Callback, 1, 0);
}
update_cleanup:
__auth_context_pop(&auth);
__dbsql_free(NULL, indices);
__dbsql_free(NULL, xref);
__src_list_delete(tab_list);
__expr_list_delete(changes);
__expr_delete(where);
return;
}

86
src/cg_vacuum.c Normal file
View file

@ -0,0 +1,86 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: cg_vacuum.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* This file contains code used to implement the VACUUM command.
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
#if !defined(DBSQL_OMIT_VACUUM) || DBSQL_OMIT_VACUUM
/*
* __vacuum --
* The non-standard VACUUM command is used to clean up the database,
* collapse free space, etc. It is modelled after the VACUUM command
* in PostgreSQL.
*
* PUBLIC: void __vacuum __P((parser_t *, token_t *));
*/
void
__vacuum(parser, tab_name)
parser_t *parser;
token_t *tab_name;
{
vdbe_t *v = __parser_get_vdbe(parser);
__vdbe_add_op(v, OP_Vacuum, 0, 0);
return;
}
/*
* __execute_vacuum --
* This routine implements the OP_Vacuum opcode of the VDBE. It works
* by running through each database asking each to reclaim space.
*
* PUBLIC: int __execute_vacuum __P((char **, DBSQL *));
*/
int
__execute_vacuum(err_msgs, dbp)
char **err_msgs;
DBSQL *dbp;
{
return DBSQL_SUCCESS; /* NOTE: When DB implements compaction (someday)
then this will be the place to invoke the
__sm_compact() function. For now, its
a no-op. */
}
#else
/*
* __execute_vacuum --
* A no-op.
*
* PUBLIC: int __execute_vacuum __P((char **, DBSQL *));
*/
int
__execute_vacuum(err_msgs, dbp)
char **err_msgs;
DBSQL *dbp;
{
return DBSQL_SUCCESS;
}
#endif

1450
src/cg_where.c Normal file

File diff suppressed because it is too large Load diff

213
src/clib/getopt.c Normal file
View file

@ -0,0 +1,213 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: getopt.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* Copyright (c) 1990-2004
* Sleepycat Software. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the DB software and any
* accompanying software that uses the DB software. The source code
* must either be included in the distribution or be available for no
* more than the cost of distribution plus a nominal fee, and must be
* freely redistributable under reasonable conditions. For an
* executable file, complete source code means the source code for all
* modules it contains. It does not include source code for modules or
* files that typically accompany the major components of the operating
* system on which the executable file runs.
*
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1990, 1993, 1994, 1995
*The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1995, 1996
*The President and Fellows of Harvard University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions
*/
#include "dbsql_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "dbsql_int.h"
int __dbsql_getopt_reset; /* global reset for VxWorks. */
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#undef BADCH
#define BADCH (int)'?'
#undef BADARG
#define BADARG (int)':'
#undef EMSG
#define EMSG ""
/*
* getopt --
* Parse argc/argv argument vector.
*
* PUBLIC: #ifndef HAVE_GETOPT
* PUBLIC: int getopt __P((int, char * const *, const char *));
* PUBLIC: #endif
*/
int
getopt(nargc, nargv, ostr)
int nargc;
char * const *nargv;
const char *ostr;
{
static char *progname;
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
/*
* VxWorks needs to be able to repeatedly call getopt from multiple
* programs within its global name space.
*/
if (__dbsql_getopt_reset) {
__dbsql_getopt_reset = 0;
opterr = optind = 1;
optopt = optreset = 0;
optarg = NULL;
progname = NULL;
place = EMSG;
}
if (!progname) {
if ((progname = __os_rpath(*nargv)) == NULL)
progname = *nargv;
else
++progname;
}
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = EMSG;
return (EOF);
}
if (place[1] && *++place == '-') { /* found "--" */
++optind;
place = EMSG;
return (EOF);
}
} /* option letter okay? */
if ((optopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means EOF.
*/
if (optopt == (int)'-')
return (EOF);
if (!*place)
++optind;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
"%s: illegal option -- %c\n", progname, optopt);
return (BADCH);
}
if (*++oli != ':') { /* don't need argument */
optarg = NULL;
if (!*place)
++optind;
}
else { /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (nargc <= ++optind) { /* no arg */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (opterr)
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
progname, optopt);
return (BADCH);
}
else /* white space */
optarg = nargv[optind];
place = EMSG;
++optind;
}
return (optopt); /* dump back option letter */
}

128
src/clib/memcmp.c Normal file
View file

@ -0,0 +1,128 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: memcmp.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* Copyright (c) 1990-2004
* Sleepycat Software. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the DB software and any
* accompanying software that uses the DB software. The source code
* must either be included in the distribution or be available for no
* more than the cost of distribution plus a nominal fee, and must be
* freely redistributable under reasonable conditions. For an
* executable file, complete source code means the source code for all
* modules it contains. It does not include source code for modules or
* files that typically accompany the major components of the operating
* system on which the executable file runs.
*
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1990, 1993, 1994, 1995
*The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1995, 1996
*The President and Fellows of Harvard University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions
*/
#include "dbsql_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#endif
/*
* memcmp --
*
* PUBLIC: #ifndef HAVE_MEMCMP
* PUBLIC: int memcmp __P((const void *, const void *, size_t));
* PUBLIC: #endif
*/
#ifndef HAVE_MEMCMP
int
memcmp(s1, s2, n)
char *s1, *s2;
size_t n;
{
if (n != 0) {
unsigned char *p1 = (unsigned char *)s1,
*p2 = (unsigned char *)s2;
do {
if (*p1++ != *p2++)
return (*--p1 - *--p2);
} while (--n != 0);
}
return (0);
}
#endif

241
src/clib/random.c Normal file
View file

@ -0,0 +1,241 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*/
/*
* Copyright (c) 1990-2004
* Sleepycat Software. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the DB software and any
* accompanying software that uses the DB software. The source code
* must either be included in the distribution or be available for no
* more than the cost of distribution plus a nominal fee, and must be
* freely redistributable under reasonable conditions. For an
* executable file, complete source code means the source code for all
* modules it contains. It does not include source code for modules or
* files that typically accompany the major components of the operating
* system on which the executable file runs.
*
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1990, 1993, 1994, 1995
*The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1995, 1996
*The President and Fellows of Harvard University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions
*/
#include "dbsql_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdio.h>
#endif
#include "dbsql_int.h"
#define SEED_SZ 256
/*
* __rng_seed --
* Produce a sutable seed for our random number generator. In
* this case that means using the current time. The seed is
* written to a char[SEED_SZ] buffer passed by the caller.
* Note that when testing its useful to generate the same pattern
* of random numbers. We accomplish that by initializing the contents
* of 'buf' to '\0' when CONFIG_TEST is defined. In this way, tests
* are repeatable.
*/
#ifndef HAVE_SRAND48_R
void
__rng_seed(buf)
char *buf;
{
u_int32_t pid;
double jt;
u_int32_t i;
memset(buf, 0, SEED_SZ);
#ifdef CONFIG_TEST
return;
#else
__os_pid(&pid);
__os_jtime(&jt);
for (i = 0; i < SEED_SZ; i++) {
if (i % 2)
buf[i] = (char)(pid & 0xf);
else
buf[i] = (char)((u_int32_t)jt & 0xf);
}
return;
#endif
}
#endif
/*
* srand48_r --
* Seed the random number generator before use.
*
* PUBLIC: #ifndef HAVE_SRAND48_R
* PUBLIC: int srand48_r __P((struct drand48_data *));
* PUBLIC: #endif
*/
#ifndef HAVE_SRAND48_R
int
srand48_r(seedval, buffer)
struct drand48_data *buffer;
{
int i;
char k[SEED_SZ];
buffer->j = 0;
buffer->i = 0;
__rng_seed(k);
for(i = 0; i < 256; i++) {
buffer->s[i] = i;
}
for(i = 0; i < 256; i++) {
int t;
buffer->j = (buffer->j + buffer->s[i] + k[i]) & 0xff;
t = buffer->s[buffer->j];
buffer->s[buffer->j] = buffer->s[i];
buffer->s[i] = t;
}
buffer->init_p = 1;
}
#endif
/*
* lrand48_r --
* A re-entrant version of a random number generator. This
* random number generator is based on the RC4 algorithm.
*
* STATIC: #ifndef HAVE_LRAND48_R
* STATIC: int lrand48_r __P((struct drand48_data *, double *));
* STATIC: #endif
*/
#ifndef HAVE_LRAND48_R
static int
lrand48_r(buffer, result)
struct drand48_data *buffer;
double *result;
{
/* TODO: am I sure there isn't a race in here? */
int t;
buffer->i = (buffer->i + 1) & 0xff;
buffer->j = (buffer->j + buffer->s[buffer->i]) & 0xff;
t = buffer->s[buffer->i];
buffer->s[buffer->i] = buffer->s[buffer->j];
buffer->s[buffer->j] = t;
t = buffer->s[buffer->i] + buffer->s[buffer->j];
*result = buffer->s[t & 0xff];
return 0;
}
#endif
/*
* rand8_r --
*
* PUBLIC: int rand8_r __P((struct drand48_data *, u_int8_t *));
*/
int
rand8_r(buffer, result)
struct drand48_data *buffer;
u_int8_t *result;
{
long int i;
int rc = lrand48_r(buffer, &i);
*result = i & 0xf;
return 0;
}
/*
* rand32_r --
*
* PUBLIC: int rand32_r __P((struct drand48_data *, u_int32_t *));
*/
int
rand32_r(buffer, result)
struct drand48_data *buffer;
u_int32_t *result;
{
int rc, i;
long int r, s;
rc = lrand48_r(buffer, &r);
for(i = 1; i < 4; i++) {
rc = lrand48_r(buffer, &s);
r = (r << 8) + s;
}
*result = r;
return rc;
}

159
src/clib/snprintf.c Normal file
View file

@ -0,0 +1,159 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*/
/*
* Copyright (c) 1990-2004
* Sleepycat Software. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the DB software and any
* accompanying software that uses the DB software. The source code
* must either be included in the distribution or be available for no
* more than the cost of distribution plus a nominal fee, and must be
* freely redistributable under reasonable conditions. For an
* executable file, complete source code means the source code for all
* modules it contains. It does not include source code for modules or
* files that typically accompany the major components of the operating
* system on which the executable file runs.
*
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1990, 1993, 1994, 1995
*The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1995, 1996
*The President and Fellows of Harvard University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions
*/
#include "dbsql_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdio.h>
#endif
#include "dbsql_int.h"
/*
* snprintf --
* Bounded version of sprintf.
*
* PUBLIC: #ifndef HAVE_SNPRINTF
* PUBLIC: int snprintf __P((char *, size_t, const char *, ...));
* PUBLIC: #endif
*/
#ifndef HAVE_SNPRINTF
int
#ifdef STDC_HEADERS
snprintf(char *str, size_t n, const char *fmt, ...)
#else
snprintf(str, n, fmt, va_alist)
char *str;
size_t n;
const char *fmt;
va_dcl
#endif
{
static int ret_charpnt = -1;
va_list ap;
int len;
COMPQUIET(n, 0);
/*
* Some old versions of sprintf return a pointer to the first argument
* instead of a character count. Assume the return value of snprintf,
* vsprintf, etc. will be the same as sprintf, and check the easy one.
*
* We do this test at run-time because it's not a test we can do in a
* cross-compilation environment.
*/
if (ret_charpnt == -1) {
char buf[10];
ret_charpnt =
(int)sprintf(buf, "123") != 3 ||
(int)sprintf(buf, "123456789") != 9 ||
(int)sprintf(buf, "1234") != 4;
}
#ifdef STDC_HEADERS
va_start(ap, fmt);
#else
va_start(ap);
#endif
len = vsprintf(str, fmt, ap);
va_end(ap);
return (ret_charpnt ? (int)strlen(str) : len);
}
#endif

155
src/clib/strcasecmp.c Normal file
View file

@ -0,0 +1,155 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*/
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: strcasecmp.c 7 2007-02-03 13:34:17Z gburd $
*/
#include "dbsql_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <string.h>
#endif
/*
* This array is designed for mapping upper and lower case letter
* together for a case independent comparison. The mappings are
* based upon ascii character sequences.
*/
static const unsigned char charmap[] = {
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
'\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
'\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
'\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
'\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377'
};
/*
* strcasecmp --
* Do strcmp(3) in a case-insensitive manner.
*
* PUBLIC: #ifndef HAVE_STRCASECMP
* PUBLIC: int strcasecmp __P((const char *, const char *));
* PUBLIC: #endif
*/
#ifndef HAVE_STRCASECMP
int
strcasecmp(s1, s2)
const char *s1, *s2;
{
register const unsigned char *cm = charmap,
*us1 = (const unsigned char *)s1,
*us2 = (const unsigned char *)s2;
while (cm[*us1] == cm[*us2++])
if (*us1++ == '\0')
return (0);
return (cm[*us1] - cm[*--us2]);
}
#endif
/*
* strncasecmp --
* Do strncmp(3) in a case-insensitive manner.
*
* PUBLIC: #ifndef HAVE_STRNCASECMP
* PUBLIC: int strncasecmp __P((const char *, const char *, size_t));
* PUBLIC: #endif
*/
#ifndef HAVE_STRNCASECMP
int
strncasecmp(s1, s2, n)
const char *s1, *s2;
register size_t n;
{
if (n != 0) {
register const unsigned char *cm = charmap,
*us1 = (const unsigned char *)s1,
*us2 = (const unsigned char *)s2;
do {
if (cm[*us1] != cm[*us2++])
return (cm[*us1] - cm[*--us2]);
if (*us1++ == '\0')
break;
} while (--n != 0);
}
return (0);
}
#endif

112
src/clib/strdup.c Normal file
View file

@ -0,0 +1,112 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*/
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: strdup.c 7 2007-02-03 13:34:17Z gburd $
*/
#include "dbsql_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#endif
/*
* strdup --
*
* PUBLIC: #ifndef HAVE_STRDUP
* PUBLIC: char *strdup __P((const char *));
* PUBLIC: #endif
*/
#ifndef HAVE_STRDUP
char *
strdup(str)
const char *str;
{
size_t len;
char *copy;
len = strlen(str) + 1;
if (!(copy = malloc((u_int)len)))
return (NULL);
memcpy(copy, str, len);
return (copy);
}
#endif
/*
* strndup --
*
* PUBLIC: #ifndef HAVE_STRNDUP
* PUBLIC: char *strndup __P((const char *, size_t));
* PUBLIC: #endif
*/
#ifndef HAVE_STRNDUP
char *
strndup(str, len)
const char *str;
size_t len;
{
char *copy;
if (len > strlen(str))
len = strlen(str);
if (!(copy = malloc((u_int)len + 1)))
return (NULL);
memcpy(copy, str, len + 1);
return (copy);
}
#endif

845
src/clib/xvprintf.c Normal file
View file

@ -0,0 +1,845 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: xvprintf.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* The following is an printf with some extra features (as well as some
* missing features). A few extensions to the formatting notation are
* supported:
* * The "=" flag (similar to "-") causes the output to be
* be centered in the appropriately sized field.
*
* * The %b field outputs an integer in binary notation.
*
* * The %c field now accepts a precision. The character output
* is repeated by the number of times the precision specifies.
*
* * The %' field works like %c, but takes as its character the
* next character of the format string, instead of the next
* argument. For example, printf("%.78'-") prints 78 minus
* signs, the same as printf("%.78c",'-').
*
* When compiled using GCC on a SPARC, this version of printf is
* faster than the library printf for SUN OS 4.1. Also, all functions
* are fully reentrant.
*
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
/*
* Conversion types fall into various categories as defined by the
* following enumeration.
*/
#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */
#define etFLOAT 2 /* Floating point. %f */
#define etEXP 3 /* Exponentional notation. %e and %E */
#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g*/
#define etSIZE 5 /* Return number of characters processed so far. %n */
#define etSTRING 6 /* Strings. %s */
#define etDYNSTRING 7 /* Dynamically allocated strings. %z */
#define etPERCENT 8 /* Percent symbol. %% */
#define etCHARX 9 /* Characters. %c */
#define etERROR 10 /* Used to indicate no such conversion type */
/* The rest are extensions, not normally found in printf() */
#define etCHARLIT 11 /* Literal characters. %' */
#define etSQLESCAPE 12 /* Strings with '\'' doubled. %q */
#define etSQLESCAPE2 13 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */
/*
* Each builtin conversion character (ex: the 'd' in "%d") is described
* by an instance of the following structure
*/
typedef struct et_info {
char fmttype; /* The format field code letter */
u_int8_t base; /* The base for radix conversion */
u_int8_t flags; /* One or more of FLAG_ constants below */
#define FLAG_SIGNED 1 /* True if the value to convert is signed */
#define FLAG_INTERN 2 /* True if for internal use only */
u_int8_t type; /* Conversion paradigm */
char *charset; /* The character set for conversion */
char *prefix; /* Prefix on non-zero values in alt format */
} et_info_t;
/*
* The following table is searched linearly, so it is good to put the
* most frequently used conversion types first.
*/
static et_info_t fmtinfo[] = {
{ 'd', 10, 1, etRADIX, "0123456789", 0 },
{ 's', 0, 0, etSTRING, 0, 0 },
{ 'z', 0, 2, etDYNSTRING, 0, 0 },
{ 'q', 0, 0, etSQLESCAPE, 0, 0 },
{ 'Q', 0, 0, etSQLESCAPE2, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 },
{ 'o', 8, 0, etRADIX, "01234567", "0" },
{ 'u', 10, 0, etRADIX, "0123456789", 0 },
{ 'x', 16, 0, etRADIX, "0123456789abcdef", "x0" },
{ 'X', 16, 0, etRADIX, "0123456789ABCDEF", "X0" },
{ 'f', 0, 1, etFLOAT, 0, 0 },
{ 'e', 0, 1, etEXP, "e", 0 },
{ 'E', 0, 1, etEXP, "E", 0 },
{ 'g', 0, 1, etGENERIC, "e", 0 },
{ 'G', 0, 1, etGENERIC, "E", 0 },
{ 'i', 10, 1, etRADIX, "0123456789", 0 },
{ 'n', 0, 0, etSIZE, 0, 0 },
{ '%', 0, 0, etPERCENT, 0, 0 },
{ 'p', 10, 0, etRADIX, "0123456789", 0 },
};
#define etNINFO (sizeof(fmtinfo) / sizeof(fmtinfo[0]))
/*
* If NOFLOATINGPOINT is defined, then none of the floating point
* conversions will work.
*/
#ifndef etNOFLOATINGPOINT
/*
* et_get_digit --
* "*val" is a double such that 0.1 <= *val < 10.0
* Return the ascii code for the leading digit of *val, then
* multiply "*val" by 10.0 to renormalize.
*
* Example:
* input: *val = 3.14159
* output: *val = 1.4159 function return = '3'
*
* The counter *cnt is incremented each time. After counter exceeds
* 16 (the number of significant digits in a 64-bit float) '0' is
* always returned.
*/
static int
et_getdigit(val, cnt)
long_double_t *val;
int *cnt;
{
int digit;
long_double_t d;
if ((*cnt)++ >= 16 )
return '0';
digit = (int)*val;
d = digit;
digit += '0';
*val = (*val - d) * 10.0;
return digit;
}
#endif
#define etBUFSIZE 1024 /* Size of the output buffer */
/*
* __et_printf --
* The root printf-like program used by all variations implemented herein.
*
* INPUTS:
* func This is a pointer to a function taking three arguments
* 1. A pointer to anything. Same as the "arg" parameter.
* 2. A pointer to the list of characters to be output
* (Note, this list is NOT null terminated.)
* 3. An integer number of characters to be output.
* (Note: This number might be zero.)
*
* arg This is the pointer to anything which will be passed as the
* first argument to "func". Use it for whatever you like.
*
* fmt This is the format string, as in the usual print.
*
* ap This is a pointer to a list of arguments. Same as in
* vfprint.
*
* OUTPUTS:
* The return value is the total number of characters sent to
* the function "func". Returns -1 on a error.
*
* NOTE: The order in which automatic variables are declared below
* seems to make a big difference in determining how fast this function
* runs.
*/
static int
__et_printf(dbp, func, arg, fmt, ap)
DBSQL *dbp;
void (*func)(void*,char*,int);
void *arg;
const char *fmt;
va_list ap;
{
int c; /* Next character in the format string */
char *bufpt; /* Pointer to the conversion buffer */
int precision; /* Precision of the current field */
int length; /* Length of the field */
int idx; /* A general purpose loop counter */
int count; /* Total number of characters output */
int width; /* Width of the current field */
u_int8_t flag_leftjustify; /* True if "-" flag is present */
u_int8_t flag_plussign; /* True if "+" flag is present */
u_int8_t flag_blanksign; /* True if " " flag is present */
u_int8_t flag_alternateform; /* True if "#" flag is present */
u_int8_t flag_zeropad; /* True if field width constant starts
with zero */
u_int8_t flag_long; /* True if "l" flag is present */
unsigned long longvalue; /* Value for integer types */
long_double_t realvalue; /* Value for real types */
et_info_t *infop; /* Pointer to the appropriate info
structure */
char buf[etBUFSIZE]; /* Conversion buffer */
char prefix; /* Prefix character. "+" or "-" or " " or
'\0'. */
u_int8_t errorflag = 0; /* True if an error is encountered */
u_int8_t xtype; /* Conversion paradigm */
char *extra; /* Extra memory used for etTCLESCAPE
conversions */
static char spaces[] =
" "
" ";
#define etSPACESIZE (sizeof(spaces)-1)
#ifndef etNOFLOATINGPOINT
int exp; /* exponent of real numbers */
double rounder; /* Used for rounding floating point values*/
u_int8_t flag_dp; /* True if decimal point should be shown */
u_int8_t flag_rtz; /* True if trailing zeros should be
removed */
u_int8_t flag_exp; /* True to force display of the exponent */
int nsd; /* Number of significant digits returned */
#endif
count = length = 0;
bufpt = 0;
for(; (c = (*fmt)) != 0; ++fmt) {
if (c != '%') {
int amt;
bufpt = (char *)fmt;
amt = 1;
while((c = (*++fmt)) != '%' && c != 0)
amt++;
(*func)(arg, bufpt, amt);
count += amt;
if (c == 0)
break;
}
if ((c = (*++fmt)) == 0) {
errorflag = 1;
(*func)(arg, "%", 1);
count++;
break;
}
/* Find out what flags are present. */
flag_leftjustify = flag_plussign = flag_blanksign =
flag_alternateform = flag_zeropad = 0;
do {
switch(c) {
case '-': flag_leftjustify = 1; c = 0; break;
case '+': flag_plussign = 1; c = 0; break;
case ' ': flag_blanksign = 1; c = 0; break;
case '#': flag_alternateform = 1; c = 0; break;
case '0': flag_zeropad = 1; c = 0; break;
default: break;
}
} while(c == 0 && (c = (*++fmt)) != 0);
/* Get the field width. */
width = 0;
if (c == '*') {
width = va_arg(ap, int);
if (width < 0) {
flag_leftjustify = 1;
width = -width;
}
c = *++fmt;
} else {
while(c >= '0' && c <= '9') {
width = (width * 10) + c - '0';
c = *++fmt;
}
}
if (width > etBUFSIZE - 10) {
width = etBUFSIZE - 10;
}
/* Get the precision. */
if (c == '.') {
precision = 0;
c = *++fmt;
if (c == '*') {
precision = va_arg(ap,int);
#ifndef etCOMPATIBILITY
/* This is sensible, but SUN OS 4.1 doesn't
do it. */
if (precision < 0)
precision = -precision;
#endif
c = *++fmt;
} else {
while(c >= '0' && c <= '9') {
precision = (precision * 10) + c - '0';
c = *++fmt;
}
}
/*
* Limit the precision to prevent overflowing buf[]
* during conversion
*/
if (precision > etBUFSIZE - 40)
precision = etBUFSIZE - 40;
} else {
precision = -1;
}
/* Get the conversion type modifier. */
if (c == 'l') {
flag_long = 1;
c = *++fmt;
} else {
flag_long = 0;
}
/* Fetch the info entry for the field. */
infop = 0;
xtype = etERROR;
for(idx = 0; idx < etNINFO; idx++) {
if (c == fmtinfo[idx].fmttype) {
infop = &fmtinfo[idx];
xtype = infop->type;
break;
}
}
extra = 0;
/*
* At this point, variables are initialized as follows:
*
* flag_alternateform TRUE if a '#' is present.
* flag_plussign TRUE if a '+' is present.
* flag_leftjustify TRUE if a '-' is present or
* if the field width was
* negative.
* flag_zeropad TRUE if the width began
* with 0.
* flag_long TRUE if the letter 'l' (ell)
* prefixed the conversion
* character.
* flag_blanksign TRUE if a ' ' is present.
* width The specified field width.
* This is always non-negative.
* Zero is the default.
* precision The specified precision. The
* default is -1.
* xtype The class of the conversion.
* infop Pointer to the appropriate
* info struct.
*/
switch(xtype) {
case etRADIX:
if (flag_long) {
longvalue = va_arg(ap, long);
} else{
longvalue = va_arg(ap, int);
}
#ifdef etCOMPATIBILITY
/*
* For the format %#x, the value zero is printed "0"
* not "0x0". I think this is stupid.
*/
if (longvalue == 0)
flag_alternateform = 0;
#else
/*
* More sensible: turn off the prefix for octal
* (to prevent "00"), but leave the prefix for hex.
*/
if (longvalue == 0 && infop->base == 8)
flag_alternateform = 0;
#endif
if (infop->flags & FLAG_SIGNED) {
if (*(long *)&longvalue < 0) {
longvalue = -*(long *)&longvalue;
prefix = '-';
} else if (flag_plussign) {
prefix = '+';
} else if (flag_blanksign) {
prefix = ' ';
} else {
prefix = 0;
}
} else {
prefix = 0;
}
if (flag_zeropad && precision < width - (prefix != 0)){
precision = width - (prefix != 0);
}
bufpt = &buf[etBUFSIZE];
{
register char *cset;
register int base;
cset = infop->charset;
base = infop->base;
do { /* Convert to ascii */
*(--bufpt) = cset[longvalue % base];
longvalue = longvalue / base;
} while(longvalue > 0);
}
length = &buf[etBUFSIZE] - bufpt;
for(idx = precision - length; idx > 0; idx--) {
*(--bufpt) = '0'; /* Zero pad */
}
if (prefix)
*(--bufpt) = prefix; /* Add sign */
if (flag_alternateform && infop->prefix) {
/* Add "0" or "0x" */
char *pre, x;
pre = infop->prefix;
if (*bufpt != pre[0]) {
for(pre = infop->prefix;
(x = (*pre)) != 0; pre++) {
*(--bufpt) = x;
}
}
}
length = &buf[etBUFSIZE] - bufpt;
break;
case etFLOAT:
case etEXP:
case etGENERIC:
realvalue = va_arg(ap, double);
#ifndef etNOFLOATINGPOINT
if (precision < 0)
precision = 6; /* Set default precision */
if (precision > etBUFSIZE - 10)
precision = etBUFSIZE - 10;
if (realvalue < 0.0) {
realvalue = -realvalue;
prefix = '-';
} else {
if (flag_plussign)
prefix = '+';
else if (flag_blanksign)
prefix = ' ';
else
prefix = 0;
}
if (infop->type == etGENERIC && precision > 0)
precision--;
rounder = 0.0;
#ifdef COMPATIBILITY
/*
* Rounding works like BSD when the constant 0.4999 is
* used. Wierd!
*/
for(idx = precision, rounder = 0.4999; idx > 0;
idx--, rounder *= 0.1);
#else
/*
* It makes more sense to use 0.5
*/
for(idx = precision, rounder = 0.5; idx > 0;
idx--, rounder *= 0.1);
#endif
if (infop->type == etFLOAT)
realvalue += rounder;
/*
* Normalize realvalue to within
* 10.0 > realvalue >= 1.0
*/
exp = 0;
if (realvalue > 0.0) {
int k = 0;
while(realvalue >= 1e8 && k++ < 100) {
realvalue *= 1e-8;
exp+=8;
}
while(realvalue >= 10.0 && k++ < 100) {
realvalue *= 0.1;
exp++;
}
while(realvalue < 1e-8 && k++ < 100) {
realvalue *= 1e8;
exp-=8;
}
while(realvalue < 1.0 && k++ < 100) {
realvalue *= 10.0;
exp--;
}
if (k >= 100) {
bufpt = "NaN";
length = 3;
break;
}
}
bufpt = buf;
/*
* If the field type is etGENERIC, then convert to
* either etEXP or etFLOAT, as appropriate.
*/
flag_exp = (xtype == etEXP);
if (xtype != etFLOAT) {
realvalue += rounder;
if (realvalue >= 10.0) {
realvalue *= 0.1;
exp++;
}
}
if (xtype == etGENERIC) {
flag_rtz = !flag_alternateform;
if (exp<-4 || exp > precision) {
xtype = etEXP;
} else {
precision = precision - exp;
xtype = etFLOAT;
}
} else {
flag_rtz = 0;
}
/*
* The "exp+precision" test causes output to be of
* type etEXP if the precision is too large to fit
* in buf[].
*/
nsd = 0;
if (xtype == etFLOAT &&
exp + precision < etBUFSIZE - 30) {
flag_dp =(precision > 0 || flag_alternateform);
if (prefix) {
*(bufpt++) = prefix; /* Sign */
}
if (exp < 0) {
*(bufpt++) = '0'; /* Digits before
"." */
} else {
for(; exp >= 0; exp--) {
*(bufpt++) =
et_getdigit(&realvalue,
&nsd);
}
}
if (flag_dp) {
*(bufpt++) = '.';/* The decimal point*/
}
for(exp++; exp < 0 && precision > 0;
precision--, exp++) {
*(bufpt++) = '0';
}
while((precision--) > 0) {
*(bufpt++) = et_getdigit(&realvalue,
&nsd);
}
*(bufpt--) = 0; /* Null terminate */
if (flag_rtz && flag_dp) {
/* Remove trailing zeros and "." */
while( bufpt >= buf && *bufpt == '0') {
*(bufpt--) = 0;
}
if (bufpt >= buf && *bufpt == '.' ) {
*(bufpt--) = 0;
}
}
bufpt++; /* point to next free slot */
} else { /* etEXP or etGENERIC */
flag_dp = (precision>0 || flag_alternateform);
if (prefix) {
*(bufpt++) = prefix; /* Sign */
}
/* First digit */
*(bufpt++) = et_getdigit(&realvalue,&nsd);
if (flag_dp) {
*(bufpt++) = '.'; /* Decimal point */
}
while((precision--) > 0) {
*(bufpt++) = et_getdigit(&realvalue,
&nsd);
}
bufpt--; /* point to last digit */
if (flag_rtz && flag_dp) {
/* Remove tail zeros */
while(bufpt >= buf && *bufpt == '0') {
*(bufpt--) = 0;
}
if (bufpt >= buf && *bufpt == '.' ) {
*(bufpt--) = 0;
}
}
bufpt++; /* point to next free slot */
if (exp || flag_exp) {
*(bufpt++) = infop->charset[0];
if (exp < 0) { /* sign of exp */
*(bufpt++) = '-';
exp = -exp;
} else {
*(bufpt++) = '+';
}
if (exp >= 100) {
/* 100's digit */
*(bufpt++) = (exp/100) + '0';
exp %= 100;
}
/* 10's digit */
*(bufpt++) = exp/10+'0';
/* 1's digit */
*(bufpt++) = exp%10+'0';
}
}
/*
* The converted number is in buf[] and zero
* terminated. Output it. Note that the number is
* in the usual order, not reversed as with integer
* conversions.
*/
length = bufpt - buf;
bufpt = buf;
/*
* Special Case: Add leading zeros if the
* flag_zeropad flag is set and we are not left
* justified.
*/
if (flag_zeropad && !flag_leftjustify &&
length < width) {
int i;
int nPad = width - length;
for(i = width; i >= nPad; i--) {
bufpt[i] = bufpt[i - nPad];
}
i = (prefix != 0);
while(nPad--)
bufpt[i++] = '0';
length = width;
}
#endif
break;
case etSIZE:
*(va_arg(ap,int*)) = count;
length = width = 0;
break;
case etPERCENT:
buf[0] = '%';
bufpt = buf;
length = 1;
break;
case etCHARLIT: /* FALLTHROUGH */
case etCHARX:
c = buf[0] = (xtype == etCHARX ?
va_arg(ap, int) : *++fmt);
if (precision >= 0) {
for(idx = 1; idx < precision; idx++) {
buf[idx] = c;
}
length = precision;
} else {
length = 1;
}
bufpt = buf;
break;
case etSTRING:
case etDYNSTRING:
bufpt = va_arg(ap, char*);
if (bufpt == 0) {
bufpt = "";
} else if (xtype == etDYNSTRING) {
extra = bufpt;
}
length = strlen(bufpt);
if (precision >= 0 && precision < length ) {
length = precision;
}
break;
case etSQLESCAPE: /* FALLTHROUGH */
case etSQLESCAPE2:
{
int i, j, n, c, isnull;
char *arg = va_arg(ap,char*);
isnull = (arg == 0);
if( isnull ) arg = (xtype == etSQLESCAPE2 ?
"NULL" : "(NULL)");
for(i = n = 0; (c = arg[i]) != 0; i++) {
if (c == '\'')
n++;
}
n += i + 1 + ((!isnull && xtype == etSQLESCAPE2) ?
2 : 0);
if (n > etBUFSIZE) {
if (__dbsql_calloc(dbp, 1, n, extra) == ENOMEM)
return -1;
bufpt = extra;
} else {
bufpt = buf;
}
j = 0;
if (!isnull && xtype == etSQLESCAPE2)
bufpt[j++] = '\'';
for(i = 0; (c = arg[i]) != 0; i++) {
bufpt[j++] = c;
if (c == '\'')
bufpt[j++] = c;
}
if (!isnull && xtype == etSQLESCAPE2)
bufpt[j++] = '\'';
bufpt[j] = 0;
length = j;
if (precision >= 0 && precision < length)
length = precision;
}
break;
case etERROR:
buf[0] = '%';
buf[1] = c;
errorflag = 0;
idx = 1 + (c != 0);
(*func)(arg, "%", idx);
count += idx;
if (c == 0)
fmt--;
break;
} /* End switch over the format type */
/*
* The text of the conversion is pointed to by "bufpt" and is
* "length" characters long. The field width is "width". Do
* the output.
*/
if (!flag_leftjustify) {
register int nspace;
nspace = width - length;
if (nspace > 0) {
count += nspace;
while(nspace >= etSPACESIZE) {
(*func)(arg, spaces, etSPACESIZE);
nspace -= etSPACESIZE;
}
if (nspace > 0)
(*func)(arg, spaces, nspace);
}
}
if (length > 0) {
(*func)(arg, bufpt, length);
count += length;
}
if (flag_leftjustify) {
register int nspace;
nspace = width - length;
if (nspace > 0) {
count += nspace;
while(nspace >= etSPACESIZE) {
(*func)(arg, spaces, etSPACESIZE);
nspace -= etSPACESIZE;
}
if (nspace > 0)
(*func)(arg, spaces, nspace);
}
}
if (extra) {
if (xtype == etDYNSTRING) {
__dbsql_free(dbp, extra); /* TODO which free? */
} else {
__dbsql_free(dbp, extra);
}
}
} /* End for loop over the format string */
return errorflag ? -1 : count;
}
/*
* __mout --
* This function implements the callback from vxprintf.
* This routine add nNewChar characters of text in zNewText to
* the sgMprintf structure pointed to by "arg".
*
* STATIC: static void mout __P((void *, char *, int));
*/
static void
__mout(arg, zNewText, nNewChar)
void *arg;
char *zNewText;
int nNewChar;
{
xvprintf_t *pM = (xvprintf_t*)arg;
if (pM->len + nNewChar + 1 > pM->amt) {
pM->amt = pM->len + (nNewChar * 2) + 1;
if (pM->text == pM->base) {
__dbsql_calloc(NULL, 1, pM->amt, &pM->text);
if (pM->text && pM->len)
memcpy(pM->text, pM->base, pM->len);
} else {
if (__dbsql_realloc(NULL, pM->amt, &pM->text) == ENOMEM) {
__dbsql_free(NULL, pM->text);
pM->len = 0;
pM->amt = 0;
pM->text = 0;
}
}
}
if (pM->text) {
memcpy(&pM->text[pM->len], zNewText, nNewChar);
pM->len += nNewChar;
pM->text[pM->len] = 0;
}
}
/*
* xvprintf --
*
* PUBLIC: char *xvprintf __P((DBSQL *, const char *, va_list));
*/
char *
xvprintf(dbp, fmt, ap)
DBSQL *dbp;
const char *fmt;
va_list ap;
{
xvprintf_t s;
char *new;
char buf[200];
s.len = 0;
s.text = buf;
s.amt = sizeof(buf);
s.base = buf;
__et_printf(dbp, __mout, &s, fmt, ap);
s.text[s.len] = 0;
__dbsql_malloc(dbp, s.len + 1, &new);
if (new)
strcpy(new, s.text);
if (s.text != s.base)
__dbsql_free(dbp, s.text);
return new;
}
#ifdef CONFIG_TEST
/*
* xprintf --
*
* PUBLIC: char *xprintf __P((DBSQL *, const char *, ...));
*/
char *
#ifdef STDC_HEADERS
xprintf(DBSQL *dbp, const char *fmt, ...)
#else
xprintf(dbp, fmt, va_alist)
DBSQL *dbp;
const char *fmt;
va_dcl
#endif
{
char *result;
va_list ap;
va_start(ap, fmt);
result = xvprintf(dbp, fmt, ap);
va_end(ap);
return result;
}
#endif

179
src/common/dbsql_alloc.c Normal file
View file

@ -0,0 +1,179 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: dbsql_alloc.c 7 2007-02-03 13:34:17Z gburd $
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
/*
* __dbsql_umalloc --
* A malloc(3) function that will use use the _os_umalloc call of DB
* to obtain memory.
*
* PUBLIC: int __dbsql_umalloc __P((DBSQL *, size_t, void *));
*/
int
__dbsql_umalloc(dbp, size, storep)
DBSQL *dbp;
size_t size;
void *storep;
{
return (__os_umalloc((dbp ? dbp->dbenv : NULL), size, storep));
}
/*
* __dbsql_urealloc --
* realloc(3) counterpart to __dbsql_umalloc.
*
* PUBLIC: int __dbsql_urealloc __P((DBSQL *, size_t, void *));
*/
int
__dbsql_urealloc(dbp, size, storep)
DBSQL *dbp;
size_t size;
void *storep;
{
return (__os_urealloc((dbp ? dbp->dbenv : NULL), size, storep));
}
/*
* __dbsql_ufree --
* free(3) counterpart to __dbsql_umalloc.
*
* PUBLIC: void __dbsql_ufree __P((DBSQL *, void *));
*/
void
__dbsql_ufree(dbp, ptr)
DBSQL *dbp;
void *ptr;
{
__os_ufree((dbp ? dbp->dbenv : NULL), ptr);
}
/*
* __dbsql_strdup --
* The __dbsql_strdup(3) function for DBSQL.
*
* PUBLIC: int __dbsql_strdup __P((DBSQL *, const char *, void *));
*/
int
__dbsql_strdup(dbp, str, storep)
DBSQL *dbp;
const char *str;
void *storep;
{
return (__os_strdup((dbp ? dbp->dbenv : NULL), str, storep));
}
/*
* __dbsql_strndup --
* The __dbsql_strndup(3) function for DBSQL.
*
* PUBLIC: int __dbsql_strndup __P((DBSQL *, const char *, void *, size_t));
*/
int
__dbsql_strndup(dbp, str, storep, len)
DBSQL *dbp;
const char *str;
void *storep;
size_t len;
{
size_t size;
int ret;
void *p;
DB_ENV *dbenv = (dbp->dbenv ? NULL : dbp->dbenv);
*(void **)storep = NULL;
if (len > strlen(str))
size = strlen(str);
else
size = len;
if ((ret = __os_calloc(dbenv, 1, size + 1, &p)) != 0)
return (ret);
memcpy(p, str, size);
*(void **)storep = p;
return (0);
}
/*
* __dbsql_calloc --
* The calloc(3) function for DBSQL.
*
* PUBLIC: int __dbsql_calloc __P((DBSQL *, size_t, size_t, void *));
*/
int
__dbsql_calloc(dbp, num, size, storep)
DBSQL *dbp;
size_t num, size;
void *storep;
{
return (__os_calloc((dbp ? dbp->dbenv : NULL), num, size,
storep));
}
/*
* __dbsql_malloc --
* The malloc(3) function for DBSQL.
*
* PUBLIC: int __dbsql_malloc __P((DBSQL *, size_t, void *));
*/
int
__dbsql_malloc(dbp, size, storep)
DBSQL *dbp;
size_t size;
void *storep;
{
return (__os_malloc((dbp ? dbp->dbenv : NULL), size, storep));
}
/*
* __dbsql_realloc --
* The realloc(3) function for DBSQL.
*
* PUBLIC: int __dbsql_realloc __P((DBSQL *, size_t, void *));
*/
int
__dbsql_realloc(dbp, size, storep)
DBSQL *dbp;
size_t size;
void *storep;
{
return (__os_realloc((dbp ? dbp->dbenv : NULL), size, storep));
}
/*
* __dbsql_free --
* The free(3) function for DBSQL.
*
* PUBLIC: void __dbsql_free __P((DBSQL *, void *));
*/
void
__dbsql_free(dbp, ptr)
DBSQL *dbp;
void *ptr;
{
__os_free((dbp ? dbp->dbenv : NULL), ptr);
}

107
src/common/dbsql_atof.c Normal file
View file

@ -0,0 +1,107 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: dbsql_atof.c 7 2007-02-03 13:34:17Z gburd $
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
/*
* __dbsql_atof --
* The string z[] is an ascii representation of a real number.
* Convert this string to a double.
*
* This routine assumes that z[] really is a valid number. If it
* is not, the result is undefined.
*
* This routine is used instead of the library atof() function because
* the library atof() might want to use "," as the decimal point instead
* of "." depending on how locale is set. But that would cause problems
* for SQL. So this routine always uses "." regardless of locale.
*
* PUBLIC: double __dbsql_atof __P((const char *));
*/
double
__dbsql_atof(z)
const char *z;
{
int sign = 1;
long_double_t v1 = 0.0;
if (*z == '-') {
sign = -1;
z++;
} else if (*z == '+') {
z++;
}
while(isdigit(*z)) {
v1 = v1 * 10.0 + (*z - '0');
z++;
}
if (*z == '.') {
long_double_t divisor = 1.0;
z++;
while(isdigit(*z)) {
v1 = v1 * 10.0 + (*z - '0');
divisor *= 10.0;
z++;
}
v1 /= divisor;
}
if (*z == 'e' || *z == 'E') {
int esign = 1;
int eval = 0;
long_double_t scale = 1.0;
z++;
if (*z == '-') {
esign = -1;
z++;
} else if (*z == '+') {
z++;
}
while(isdigit(*z)) {
eval = eval * 10 + *z - '0';
z++;
}
while(eval >= 64) {
scale *= 1.0e+64;
eval -= 64;
}
while(eval >= 16) {
scale *= 1.0e+16;
eval -= 16;
}
while(eval >= 4) {
scale *= 1.0e+4;
eval -= 4;
}
while(eval >= 1) {
scale *= 1.0e+1;
eval -= 1;
}
if (esign < 0) {
v1 /= scale;
} else {
v1 *= scale;
}
}
return sign < 0 ? -v1 : v1;
}

56
src/common/dbsql_atoi.c Normal file
View file

@ -0,0 +1,56 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: dbsql_atoi.c 7 2007-02-03 13:34:17Z gburd $
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
/*
* __dbsql_atoi --
* Return TRUE if 'str' is a 32-bit signed integer and write
* the value of the integer into '*num'. If 'str' is not an integer
* or is an integer that is too large to be expressed with just 32
* bits, then return false.
*
* PUBLIC: int __dbsql_atoi __P((const char *, int *));
*/
int
__dbsql_atoi(str, num)
const char *str;
int *num;
{
int v = 0;
int neg;
int i, c;
if (*str == '-') {
neg = 1;
str++;
} else if (*str == '+') {
neg = 0;
str++;
} else {
neg = 0;
}
for (i = 0; (c = str[i]) >= '0' && c <= '9'; i++) {
v = (v * 10) + c - '0';
}
*num = neg ? -v : v;
return (c == 0 && i > 0 &&
(i < 10 || (i == 10 && memcmp(str,"2147483647", 10) <= 0)));
}

469
src/common/dbsql_err.c Normal file
View file

@ -0,0 +1,469 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: dbsql_err.c 7 2007-02-03 13:34:17Z gburd $
*/
#include "dbsql_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /* Declare STDERR_FILENO. */
#endif
#include "dbsql_int.h"
#ifdef DIAGNOSTIC
/*
* __dbsql_assert --
* Error when an assertion fails. Only checked if #DIAGNOSTIC defined.
*
* PUBLIC: #ifdef DIAGNOSTIC
* PUBLIC: void __dbsql_assert __P((const char *, const char *, int));
* PUBLIC: #endif
*/
void
__dbsql_assert(failedexpr, file, line)
const char *failedexpr, *file;
int line;
{
(void)fprintf(stderr,
"__dbsql_assert: \"%s\" failed: file \"%s\", line %d\n",
failedexpr, file, line);
(void)fflush(stderr);
/* We want a stack trace of how this could possibly happen. */
abort();
/* NOTREACHED */
}
#endif
/*
* __dbsql_panic_msg --
* Just report that someone else paniced.
*
* PUBLIC: int __dbsql_panic_msg __P((DBSQL *));
*/
int
__dbsql_panic_msg(dbp)
DBSQL *dbp;
{
__dbsql_err(dbp, "PANIC: fatal database error detected; run recovery");
if (dbp && dbp->dbsql_paniccall != NULL)
dbp->dbsql_paniccall(dbp, DB_RUNRECOVERY);
return (DB_RUNRECOVERY);
}
/*
* __dbsql_panic --
* Lock out the database due to unrecoverable error.
*
* PUBLIC: int __dbsql_panic __P((DBSQL *, int));
*/
int
__dbsql_panic(dbp, errval)
DBSQL *dbp;
int errval;
{
if (dbp != NULL) {
PANIC_SET(dbp, 1);
__dbsql_err(dbp, "PANIC: %s", dbsql_strerror(errval));
if (dbp->dbsql_paniccall != NULL)
dbp->dbsql_paniccall(dbp, errval);
}
#if defined(DIAGNOSTIC) && !defined(CONFIG_TEST)
/*
* We want a stack trace of how this could possibly happen.
*
* Don't drop core if it's the test suite -- it's reasonable for the
* test suite to check to make sure that DBSQL_RUNRECOVERY is returned
* under certain conditions.
*/
abort();
#endif
/*
* Chaos reigns within.
* Reflect, repent, and reboot.
* Order shall return.
*/
return (DBSQL_RUNRECOVERY);
}
/*
* dbsql_strerror --
* ANSI C strerror(3) for DBSQL.
*
* EXTERN: char *dbsql_strerror __P((int));
*/
char *
dbsql_strerror(error)
int error;
{
char *p;
if (error == 0)
return ("Successful return: 0");
if (error > 0) {
if ((p = strerror(error)) != NULL)
return (p);
goto unknown_err;
}
if (error <= -30999 && error >= -30800) {
if ((p = db_strerror(error)) != NULL)
return (p);
goto unknown_err;
}
/*
* !!!
* The Tcl API requires that some of these return strings be compared
* against strings stored in application scripts. So, any of these
* errors that do not invariably result in a Tcl exception may not be
* altered.
*/
switch (error) {
case DBSQL_ERROR:
return ("DBSQL_ERROR: SQL logic error or missing database");
case DBSQL_INTERNAL:
return ("DBSQL_INTERNAL: Internal implementation flaw");
case DBSQL_PERM:
return ("DBSQL_PERM: Access denied due to permissions.");
case DBSQL_ABORT:
return ("DBSQL_ABORT: Callback requested query abort");
case DBSQL_BUSY:
return ("DBSQL_BUSY: Database is locked");
case DBSQL_LOCKED:
return ("DBSQL_LOCKED: Database table is locked");
case DBSQL_NOMEM:
return ("DBSQL_NOMEM: Unable to allocate additional memory.");
case DBSQL_READONLY:
return
("DBSQL_READONLY: Attempt to write a readonly database");
case DBSQL_INTERRUPTED:
return ("DBSQL_INTERRUPTED: Interrupted during processing");
case DBSQL_IOERR:
return ("DBSQL_IOERROR: Disk I/O error");
case DBSQL_NOTFOUND:
return ("DBSQL_NOTFOUND: Table or record not found");
case DBSQL_FULL:
return ("DBSQL_FULL: Database is full");
case DBSQL_CANTOPEN:
return ("DBSQL_CANTOPEN: Unable to open database file");
case DBSQL_PROTOCOL:
return ("DBSQL_PROTOCOL: Database locking protocol failure");
case DBSQL_EMPTY:
return ("DBSQL_EMPTY: Table contains no data");
case DBSQL_SCHEMA:
return ("DBSQL_SCHEMA: Database schema has changed");
case DBSQL_CONSTRAINT:
return ("DBSQL_CONSTRAINT: Constraint failed");
case DBSQL_MISMATCH:
return ("DBSQL_MISMATCH: Datatype mismatch");
case DBSQL_MISUSE:
return
("DBSQL_MISUSE: Library routine called out of sequence");
case DBSQL_AUTH:
return ("DBSQL_AUTH: Authorization denied");
case DBSQL_FORMAT:
return ("DBSQL_FORMAT: Auxiliary database format error");
case DBSQL_RANGE:
return ("DBSQL_RANGE: Bind index out of range");
case DBSQL_CORRUPT:
return ("DBSQL_CORRUPT: Data record is malformed");
case DBSQL_RUNRECOVERY:
return (
"DBSQL_RUNRECOVERY: Shutdown and run recovery on the database environment.");
case DBSQL_INVALID_NAME:
return (
"DBSQL_INVALID_NAME: Empty or invalid file name supplied");
}
unknown_err: {
/*
* !!!
* Room for a 64-bit number + slop. This buffer is only used
* if we're given an unknown error, which should never happen.
* Note, however, we're no longer thread-safe if it does.
*/
static char ebuf[40];
(void)snprintf(ebuf, sizeof(ebuf), "Unknown error: %d", error);
return (ebuf);
}
}
/*
* __dbsql_err --
* Standard DBSQL error routine. The same as errx, except we don't write
* to stderr if no output mechanism was specified.
*
* PUBLIC: void __dbsql_err __P((const DBSQL *, const char *, ...))
* PUBLIC: __attribute__ ((__format__ (__printf__, 2, 3)));
*/
void
#ifdef STDC_HEADERS
__dbsql_err(const DBSQL *dbp, const char *fmt, ...)
#else
__dbsql_err(dbp, fmt, va_alist)
const DBSQL *dbp;
const char *fmt;
va_dcl
#endif
{
DBSQL_REAL_ERR(dbp, 0, 0, 0, fmt);
}
#ifndef HAVE_VSNPRINTF
#define OVERFLOW_ERROR "internal buffer overflow, process aborted\n"
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
#endif
/*
* __dbsql_errcall --
* Do the error message work for callback functions.
*
* PUBLIC: void __dbsql_errcall __P((const DBSQL *, int, int, const char *,
* PUBLIC: va_list));
*/
void
__dbsql_errcall(dbp, error, error_set, fmt, ap)
const DBSQL *dbp;
int error, error_set;
const char *fmt;
va_list ap;
{
char *p;
char errbuf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
p = errbuf;
if (fmt != NULL)
p += vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
if (error_set)
p += snprintf(p,
sizeof(errbuf) - (size_t)(p - errbuf), ": %s",
dbsql_strerror(error));
#ifndef HAVE_VSNPRINTF
/*
* !!!
* We're potentially manipulating strings handed us by the application,
* and on systems without a real snprintf() the sprintf() calls could
* have overflowed the buffer. We can't do anything about it now, but
* we don't want to return control to the application, we might have
* overwritten the stack with a Trojan horse. We're not trying to do
* anything recoverable here because systems without snprintf support
* are pretty rare anymore.
*/
if ((size_t)(p - errbuf) > sizeof(errbuf)) {
write(
STDERR_FILENO, OVERFLOW_ERROR, sizeof(OVERFLOW_ERROR) - 1);
abort();
/* NOTREACHED */
}
#endif
dbp->dbsql_errcall(dbp->dbsql_errpfx, errbuf);
}
/*
* __dbsql_errfile --
* Do the error message work for FILE *s.
*
* PUBLIC: void __dbsql_errfile
* PUBLIC: __P((const DBSQL *, int, int, const char *, va_list));
*/
void
__dbsql_errfile(dbp, error, error_set, fmt, ap)
const DBSQL *dbp;
int error, error_set;
const char *fmt;
va_list ap;
{
FILE *fp;
fp = dbp == NULL ||
dbp->dbsql_errfile == NULL ? stderr : dbp->dbsql_errfile;
if (dbp != NULL && dbp->dbsql_errpfx != NULL)
(void)fprintf(fp, "%s: ", dbp->dbsql_errpfx);
if (fmt != NULL) {
(void)vfprintf(fp, fmt, ap);
if (error_set)
(void)fprintf(fp, ": ");
}
if (error_set)
(void)fprintf(fp, "%s", dbsql_strerror(error));
(void)fprintf(fp, "\n");
(void)fflush(fp);
}
/*
* __error_msg --
* Add an error message to pParse->zErrMsg and increment pParse->nErr.
* The following formatting characters are allowed:
*
* %s Insert a string
* %z A string that should be freed after use
* %d Insert an integer
* %T Insert a token
* %S Insert the first element of a SrcList
*
* PUBLIC: void __error_msg __P((parser_t *, const char *, ...));
*/
void
#ifdef STDC_HEADERS
__error_msg(parser_t *parser, const char *fmt, ...)
#else
__error_msg(parser, fmt, va_alist)
parser_t parser;
const char *fmt;
va_dcl
#endif
{
va_list ap;
int len;
int i, j;
char *z;
static char null[] = "NULL";
parser->nErr++;
len = 1 + strlen(fmt);
va_start(ap, fmt);
for(i = 0; fmt[i]; i++) {
if (fmt[i] != '%' || fmt[i + 1] == 0)
continue;
i++;
switch(fmt[i]) {
case 'd': {
(void)va_arg(ap, int);
len += 20;
break;
}
case 'z': /* FALLTHROUGH */
case 's': {
char *z2 = va_arg(ap, char*);
if (z2 == 0)
z2 = null;
len += strlen(z2);
break;
}
case 'T': {
token_t *p = va_arg(ap, token_t*);
len += p->n;
break;
}
case 'S': {
src_list_t *p = va_arg(ap, src_list_t*);
int k = va_arg(ap, int);
DBSQL_ASSERT(p->nSrc > k && k >= 0);
len += strlen(p->a[k].zName);
if (p->a[k].zDatabase && p->a[k].zDatabase[0]) {
len += strlen(p->a[k].zDatabase) + 1;
}
break;
}
default:
len++;
break;
}
}
va_end(ap);
__dbsql_calloc(parser->db, 1, len, &z);
if (z == 0)
return;
__dbsql_free(parser->db, parser->zErrMsg);
parser->zErrMsg = z;
va_start(ap, fmt);
for(i = j = 0; fmt[i]; i++) {
if (fmt[i] != '%' || fmt[i + 1] == 0)
continue;
if (i > j) {
memcpy(z, &fmt[j], i - j);
z += i - j;
}
j = i + 2;
i++;
switch(fmt[i]) {
case 'd': {
int x = va_arg(ap, int);
sprintf(z, "%d", x);
z += strlen(z);
break;
}
case 'z': /* FALLTHROUGH */
case 's': {
int len;
char *z2 = va_arg(ap, char*);
if (z2 == 0)
z2 = null;
len = strlen(z2);
memcpy(z, z2, len);
z += len;
if (fmt[i] == 'z' && z2 != null) {
__dbsql_free(NULL, z2);
}
break;
}
case 'T': {
token_t *p = va_arg(ap, token_t*);
memcpy(z, p->z, p->n);
z += p->n;
break;
}
case 'S': {
int len;
src_list_t *p = va_arg(ap, src_list_t*);
int k = va_arg(ap, int);
assert(p->nSrc > k && k >= 0);
if (p->a[k].zDatabase && p->a[k].zDatabase[0]) {
len = strlen(p->a[k].zDatabase);
memcpy(z, p->a[k].zDatabase, len);
z += len;
*(z++) = '.';
}
len = strlen(p->a[k].zName);
memcpy(z, p->a[k].zName, len);
z += len;
break;
}
default:
*(z++) = fmt[i];
break;
}
}
va_end(ap);
if (i > j) {
memcpy(z, &fmt[j], i - j);
z += i - j;
}
DBSQL_ASSERT((z - parser->zErrMsg) < len);
*z = 0;
}

592
src/common/hash.c Normal file
View file

@ -0,0 +1,592 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: hash.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* Copyright (c) 1990-2004
* Sleepycat Software. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the DB software and any
* accompanying software that uses the DB software. The source code
* must either be included in the distribution or be available for no
* more than the cost of distribution plus a nominal fee, and must be
* freely redistributable under reasonable conditions. For an
* executable file, complete source code means the source code for all
* modules it contains. It does not include source code for modules or
* files that typically accompany the major components of the operating
* system on which the executable file runs.
*
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1990, 1993, 1994, 1995
*The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1995, 1996
*The President and Fellows of Harvard University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions
*/
/*
* Basic hash-tables.
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
/*
* __hash_init --
* Turn bulk memory into a hash table object by initializing the
* fields of the hash_t structure.
*
* 'this' is a pointer to the hash table that is to be initialized.
* 'class' is one of the constants DBSQL_HASH_INT, DBSQL_HASH_POINTER,
* DBSQL_HASH_BINARY, or DBSQL_HASH_STRING. The value of 'class'
* determines what kind of key the hash table will use. 'copy_key_p' is
* true if the hash table should make its own private copy of keys and
* false if it should just use the supplied pointer. 'copy_key_p' only
* makes sense for DBSQL_HASH_STRING and DBSQL_HASH_BINARY and is ignored
* for other key classes.
*
* PUBLIC: void __hash_init __P((hash_t *, int, int));
*/
void
__hash_init(this, class, copy_key_p)
hash_t *this;
int class;
int copy_key_p;
{
DBSQL_ASSERT(this != 0);
DBSQL_ASSERT(class >= DBSQL_HASH_INT && class <= DBSQL_HASH_BINARY);
this->keyClass = class;
this->copyKey = copy_key_p &&
(class==DBSQL_HASH_STRING || class==DBSQL_HASH_BINARY);
this->first = 0;
this->count = 0;
this->htsize = 0;
this->ht = 0;
}
/*
* __hash_clear --
* Remove all entries from a hash table. Reclaim all memory.
* Call this routine to delete a hash table or to reset a hash table
* to the empty state.
*
* PUBLIC: void __hash_clear __P((hash_t *));
*/
void
__hash_clear(this)
hash_t *this;
{
hash_ele_t *elem;
DBSQL_ASSERT(this != 0);
elem = this->first;
this->first = 0;
if( this->ht )
__dbsql_free(NULL, this->ht);
this->ht = 0;
this->htsize = 0;
while(elem) {
hash_ele_t *next_elem = elem->next;
if( this->copyKey && elem->pKey ){
__dbsql_free(NULL, elem->pKey);
}
__dbsql_free(NULL, elem);
elem = next_elem;
}
this->count = 0;
}
/*
* __int_hash --
* Hash and comparison functions when the mode is DBSQL_HASH_INT
*
* STATIC: static int __int_hash __P((const void *, int));
*/
static int
__int_hash(key, len)
const void *key;
int len;
{
return len ^ (len << 8) ^ (len >> 8);
}
/*
* __int_cmp --
*
* STATIC: static int __h_int_cmp __P((const void *, int, const void *, int));
*/
static int
__h_int_cmp(k1, n1, k2, n2)
const void *k1;
int n1;
const void *k2;
int n2;
{
return n2 - n1;
}
/*
* __str_hash --
* Hash and comparison functions when the mode is DBSQL_HASH_STRING
*
* STATIC: static int __str_hash
*/
static int
__str_hash(key, len)
const void *key;
int len;
{
return __hash_ignore_case((const char*)key, len);
}
/*
* __str_cmp --
*
* STATIC: static int __h_str_cmp __P((const void *, int, const void *, int));
*/
static int
__h_str_cmp(k1, n1, k2, n2)
const void *k1;
int n1;
const void *k2;
int n2;
{
if (n1 != n2)
return (n2 - n1);
return strncasecmp((const char*)k1, (const char*)k2, n1);
}
/*
* __bin_hash --
* Hash and comparison functions when the mode is DBSQL_HASH_BINARY
*
* STATIC: static int __bin_hash __((const void *, int));
*/
static int
__bin_hash(key, len)
const void *key;
int len;
{
int h = 0;
const char *z = (const char *)key;
while(len-- > 0) {
h = (h << 3) ^ h ^ * (z++);
}
return h & 0x7fffffff;
}
/*
* __bin_cmp --
*
* STATIC: static int __h_bin_cmp __P((const void *, int, const void *, int));
*/
static int
__h_bin_cmp(k1, n1, k2, n2)
const void *k1;
int n1;
const void *k2;
int n2;
{
if (n1 != n2)
return (n2 - n1);
return memcmp(k1, k2, n1);
}
/*
* __hash_fn --
* Return a pointer to the appropriate hash function given the key class.
*
* The C syntax in this function definition may be unfamilar to some
* programmers, so we provide the following additional explanation:
*
* The name of the function is '__hash_fn'. The function takes a
* single parameter 'class'. The return value of __hash_fn()
* is a pointer to another function. Specifically, the return value
* of __hash_fn() is a pointer to a function that takes two parameters
* with types "const void*" and "int" and returns an "int".
*/
static int
(*__hash_fn(int class))(const void*, int)
{
switch(class) {
case DBSQL_HASH_INT:
return &__int_hash;
case DBSQL_HASH_STRING:
return &__str_hash;
case DBSQL_HASH_BINARY:
return &__bin_hash;;
default:
break;
}
return 0;
}
/*
* __cmp_fn --
* Return a pointer to the appropriate hash function given the key class.
*
* For help in interpreted the obscure C code in the function definition,
* see the header comment on the previous function.
*/
static int
(*__cmp_fn(int class))(const void*, int, const void*, int)
{
switch(class) {
case DBSQL_HASH_INT:
return &__h_int_cmp;
case DBSQL_HASH_STRING:
return &__h_str_cmp;
case DBSQL_HASH_BINARY:
return &__h_bin_cmp;
default:
break;
}
return 0;
}
/*
* __rehash --
* Resize the hash table so that it cantains 'new_size' buckets.
* 'new_size' must be a power of 2. The hash table might fail
* to resize if __dbsql_calloc() fails.
*
* STATIC: static void __rehash __P((hash_t *, int));
*/
static void
__rehash(this, new_size)
hash_t *this;
int new_size;
{
struct _ht *new_ht; /* The new hash table */
hash_ele_t *elem, *next_elem; /* For looping over existing elements */
hash_ele_t *x; /* Element being copied to new hash
table */
int (*hash)(const void*,int); /* The hash function */
DBSQL_ASSERT((new_size & (new_size - 1)) == 0);
if (__dbsql_calloc(NULL, new_size, sizeof(struct _ht), &new_ht) == ENOMEM)
return;
if (this->ht)
__dbsql_free(NULL, this->ht);
this->ht = new_ht;
this->htsize = new_size;
hash = __hash_fn(this->keyClass);
for (elem = this->first, this->first = 0; elem; elem = next_elem) {
int h = (*hash)(elem->pKey, elem->nKey) & (new_size - 1);
next_elem = elem->next;
x = new_ht[h].chain;
if (x) {
elem->next = x;
elem->prev = x->prev;
if (x->prev)
x->prev->next = elem;
else
this->first = elem;
x->prev = elem;
} else {
elem->next = this->first;
if (this->first)
this->first->prev = elem;
elem->prev = 0;
this->first = elem;
}
new_ht[h].chain = elem;
new_ht[h].count++;
}
}
/*
* __hash_search --
* This function locates an element in an hash table that matches
* the given key. The hash for this key has already been computed
* and is passed as the 4th parameter.
*
* STATIC: static hash_ele_t * __hash_search __P((const hast_t *, const void *,
* STATIC: int, int));
*
* this The hash_t to be searched
* key The the object of our search
* len The size of the key
* h The hash value for this key
*/
static hash_ele_t *__hash_search(this, key, len, h)
const hash_t *this;
const void *key;
int len;
int h;
{
hash_ele_t *elem;
int count;
int (*cmp)(const void*, int, const void*, int);
if (this->ht) {
elem = this->ht[h].chain;
count = this->ht[h].count;
cmp = __cmp_fn(this->keyClass);
while (count-- && elem) {
if ((*cmp)(elem->pKey, elem->nKey, key, len) == 0) {
return elem;
}
elem = elem->next;
}
}
return 0;
}
/*
* __hash_remove --
* Remove a single entry from the hash table given a pointer to that
* element and a hash on the element's key.
*
* STATIC: static void __hash_remove __P((hash_t *, hash_ele_t *, int));
*
* this The hash_t to be searched
* elem The element to be removed
* h The hash value for this key
*/
static void __hash_remove(this, elem, h)
hash_t *this;
hash_ele_t* elem;
int h;
{
if (elem->prev) {
elem->prev->next = elem->next;
} else {
this->first = elem->next;
}
if (elem->next) {
elem->next->prev = elem->prev;
}
if (this->ht[h].chain == elem) {
this->ht[h].chain = elem->next;
}
this->ht[h].count--;
if (this->ht[h].count <= 0) {
this->ht[h].chain = 0;
}
if (this->copyKey && elem->pKey) {
__dbsql_free(NULL, elem->pKey);
}
__dbsql_free(NULL, elem);
this->count--;
}
/*
* __hash_find --
* Attempt to locate an element of the hash table this with a key
* that matches 'key', 'len'. Return the data for this element if it is
* found, or NULL if there is no match.
*
* PUBLIC: void *__hash_find __P((const hash_t *, const void *, int));
*/
void *__hash_find(this, key, len)
const hash_t *this;
const void *key;
int len;
{
int h;
hash_ele_t *elem;
int (*hash)(const void*, int);
if (this == 0 || this->ht == 0)
return 0;
hash = __hash_fn(this->keyClass);
DBSQL_ASSERT(hash != 0);
h = (*hash)(key, len);
DBSQL_ASSERT((this->htsize & (this->htsize - 1)) == 0);
elem = __hash_search(this, key, len, h & (this->htsize - 1));
return (elem ? elem->data : 0);
}
/*
* __hash_insert --
* Insert an element into the hash table this. The key is 'key', 'len'
* and the data is 'data'.
*
* If no element exists with a matching key, then a new
* element is created. A copy of the key is made if the copy_key_p
* flag is set. NULL is returned.
*
* If another element already exists with the same key, then the
* new data replaces the old data and the old data is returned.
* The key is not copied in this instance. If a __dbsql_malloc fails,
* then the new data is returned and the hash table is unchanged.
*
* If the 'data' parameter to this function is NULL, then the
* element corresponding to 'key' is removed from the hash table.
*
* PUBLIC: void *__hash_insert __P((hash_t *, const void *, int, void *));
*/
void *
__hash_insert(this, key, len, data)
hash_t *this;
const void *key;
int len;
void *data;
{
int hraw; /* Raw hash value of the key */
int h; /* the hash of the key modulo hash table size */
hash_ele_t *elem; /* Used to loop thru the element list */
hash_ele_t *new_elem; /* New element added to the pH */
int (*hash)(const void*,int); /* The hash function */
DBSQL_ASSERT(this != 0);
hash = __hash_fn(this->keyClass);
DBSQL_ASSERT(hash != 0);
hraw = (*hash)(key, len);
DBSQL_ASSERT((this->htsize & (this->htsize - 1)) == 0);
h = hraw & (this->htsize - 1);
elem = __hash_search(this, key, len, h);
if (elem) {
void *old_data = elem->data;
if (data == 0) {
__hash_remove(this, elem, h);
} else {
elem->data = data;
}
return old_data;
}
if (data == 0)
return 0;
if (__dbsql_calloc(NULL, 1, sizeof(hash_ele_t), &new_elem) == ENOMEM)
return data;
if (this->copyKey && key != 0) {
if (__dbsql_calloc(NULL, 1, len, &new_elem->pKey) == ENOMEM) {
__dbsql_free(NULL, new_elem);
return data;
}
memcpy((void*)new_elem->pKey, key, len);
} else {
new_elem->pKey = (void*)key;
}
new_elem->nKey = len;
this->count++;
if (this->htsize == 0)
__rehash(this, 8);
if (this->htsize == 0) {
this->count = 0;
__dbsql_free(NULL, new_elem);
return data;
}
if (this->count > this->htsize) {
__rehash(this, this->htsize * 2);
}
DBSQL_ASSERT((this->htsize & (this->htsize - 1)) == 0);
h = hraw & (this->htsize - 1);
elem = this->ht[h].chain;
if (elem) {
new_elem->next = elem;
new_elem->prev = elem->prev;
if (elem->prev) {
elem->prev->next = new_elem;
} else {
this->first = new_elem;
}
elem->prev = new_elem;
} else {
new_elem->next = this->first;
new_elem->prev = 0;
if (this->first) {
this->first->prev = new_elem;
}
this->first = new_elem;
}
this->ht[h].count++;
this->ht[h].chain = new_elem;
new_elem->data = data;
return 0;
}
/*
* __hash_ignore_case --
* This function computes a hash on the name of a keyword.
* Case is not significant.
*
* PUBLIC: int __hash_ignore_case __P((const char *, int));
*/
int
__hash_ignore_case(z, n)
const char *z;
int n;
{
int h = 0;
if (n <= 0)
n = strlen(z);
while(n > 0) {
h = (h<<3) ^ h ^ __str_upper_to_lower[(unsigned char) * z++];
n--;
}
return h & 0x7fffffff;
}

892
src/common/str.c Normal file
View file

@ -0,0 +1,892 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: str.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* Copyright (c) 1990-2004
* Sleepycat Software. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the DB software and any
* accompanying software that uses the DB software. The source code
* must either be included in the distribution or be available for no
* more than the cost of distribution plus a nominal fee, and must be
* freely redistributable under reasonable conditions. For an
* executable file, complete source code means the source code for all
* modules it contains. It does not include source code for modules or
* files that typically accompany the major components of the operating
* system on which the executable file runs.
*
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1990, 1993, 1994, 1995
*The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1995, 1996
*The President and Fellows of Harvard University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
unsigned char __str_upper_to_lower[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
252,253,254,255
};
/*
* __str_append --
* Create a string from the 2nd and subsequent arguments (up
* to the first NULL argument), store the string in memory
* obtained from __dbsql_calloc() and make the pointer indicated
* by the 1st argument point to that string. The 1st argument
* must either be NULL or point to memory obtained from
* __dbsql_calloc().
*
* PUBLIC: void __str_append __P((char **, const char *, ...));
*/
void
#ifdef STDC_HEADERS
__str_append(char **result, const char *fmt, ...)
#else
__str_append(result, fmt, va_alist)
char **result;
const char *fmt;
va_dcl
#endif
{
va_list ap;
size_t len;
const char *tmp;
char *r;
if (result == 0)
return;
len = strlen(fmt) + 1;
va_start(ap, fmt);
while((tmp = va_arg(ap, const char*)) != NULL) {
len += strlen(tmp);
}
va_end(ap);
__dbsql_free(NULL, *result);
if (__dbsql_calloc(NULL, 1, len, &r) == ENOMEM)
return;
*result = r;
strcpy(r, fmt);
r += strlen(r);
va_start(ap, fmt);
while((tmp = va_arg(ap, const char*)) != NULL) {
strcpy(r, tmp);
r += strlen(r);
}
va_end(ap);
}
/*
* __str_nappend --
* Works like __str_append, but each string is now followed by
* a length integer which specifies how much of the source string
* to copy (in bytes). -1 means use the whole string. The 1st
* argument must either be NULL or point to memory obtained from
* __dbsql_calloc().
*
* PUBLIC: void __str_nappend __P((char **, ...));
*/
void
#ifdef STDC_HEADERS
__str_nappend(char **result, ...)
#else
__str_nappend(result, va_alist)
char **result;
va_dcl
#endif
{
va_list ap;
size_t len;
const char *tmp;
char *r;
int n;
if (result == 0)
return;
len = 0;
va_start(ap, result);
while((tmp = va_arg(ap, const char*)) != NULL) {
n = va_arg(ap, int);
if (n <= 0)
n = strlen(tmp);
len += (size_t)n;
}
va_end(ap);
__dbsql_free(NULL, *result);
if (__dbsql_calloc(NULL, 1, len + 1, &r) == ENOMEM)
return;
*result = r;
va_start(ap, result);
while((tmp = va_arg(ap, const char*)) != NULL) {
n = va_arg(ap, int);
if (n <= 0)
n = strlen(tmp);
strncpy(r, tmp, n);
r += n;
}
*r = 0;
va_end(ap);
}
/*
* __str_unquote --
* Convert an SQL-style quoted string into a normal string by removing
* the quote characters. The conversion is done in-place. If the
* input does not begin with a quote character, then this routine
* is a no-op. Quotes can be of the form "'a-b-c'" or the MS-Access style
* brackets around identifers such as: "[a-b-c]". In both cases the
* result is "a-b-c".
*
* PUBLIC: void __str_unquote __P((char *));
*/
void
__str_unquote(z)
char *z;
{
int quote;
int i, j;
if (z == NULL)
return;
quote = z[0];
switch(quote) {
case '\'': break;
case '"': break;
case '[': quote = ']'; break;
default: return;
}
for(i = 1, j = 0; z[i]; i++) {
if (z[i] == quote) {
if (z[i + 1] == quote) {
z[j++] = quote;
i++;
} else {
z[j++] = 0;
break;
}
} else {
z[j++] = z[i];
}
}
}
/*
* __str_urealloc --
* Make a duplicate of a string into memory obtained from
* __dbsql_umalloc() Free the original string using __dbsql_free().
* This routine is called on all strings that are passed outside of
* the library. That way clients can free the string using
* __dbsql_ufree() rather than having to call __dbsql_free().
*
* PUBLIC: int __str_urealloc __P((char **));
*/
int
__str_urealloc(pz)
char **pz;
{
int rc = DBSQL_SUCCESS;
char *new;
if (pz == 0 || *pz == NULL)
return;
if (__dbsql_umalloc(NULL, strlen(*pz) + 1, &new) == ENOMEM) {
rc = ENOMEM;
__dbsql_free(NULL, *pz);
*pz = 0;
}
strcpy(new, *pz);
__dbsql_free(NULL, *pz);
*pz = new;
return rc;
}
/*
* __str_is_numeric --
* Return TRUE if z is a pure numeric string. Return FALSE if the
* string contains any character which is not part of a number.
* An empty string is considered non-numeric.
*
* PUBLIC: int __str_is_numeric __P((const char *));
*/
int
__str_is_numeric(z)
const char *z;
{
if (*z == '-' || *z == '+')
z++;
if (!isdigit(*z)) {
return 0;
}
z++;
while(isdigit(*z)) {
z++;
}
if (*z == '.') {
z++;
if (!isdigit(*z))
return 0;
while(isdigit(*z)) {
z++;
}
}
if (*z == 'e' || *z == 'E') {
z++;
if (*z == '+' || *z == '-')
z++;
if (!isdigit(*z))
return 0;
while(isdigit(*z)) {
z++;
}
}
return (*z == '\0');
}
#ifdef DBSQL_UTF8_ENCODING
/*
* Convert the UTF-8 character to which z points into a 31-bit
* UCS character. This only works right if z points to a well-formed
* UTF-8 string.
*/
static int __utf8_to_int(const unsigned char *z) {
int c;
static const int init_val[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 0, 1, 2,
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 0, 1, 254,
255,
};
c = init_val[*(z++)];
while((0xc0 & *z) == 0x80) {
c = (c<<6) | (0x3f & *(z++));
}
return c;
}
/*
* X is a pointer to the first byte of a UTF-8 character. Increment
* X so that it points to the next character. This only works right
* if X points to a well-formed UTF-8 string.
*/
#define __next_char(X) while((0xc0 & *++(X)) == 0x80) {}
#define __char_val(X) __utf8_to_int(X)
#else /* !defined(DBSQL_UTF8_ENCODING) */
/*
* For iso8859 encoding, the next character is just the next byte.
*/
#define __next_char(X) (++(X));
#define __char_val(X) ((int)*(X))
#endif /* defined(DBSQL_UTF8_ENCODING) */
/*
* __str_glob_cmp --
* Compare two UTF-8 strings for equality where the first string can
* potentially be a "glob" expression. Return true (1) if they
* are the same and false (0) if they are different.
*
* Globbing rules:
*
* '*' Matches any sequence of zero or more characters.
*
* '?' Matches exactly one character.
*
* [...] Matches one character from the enclosed list of
* characters.
*
* [^...] Matches one character not in the enclosed list.
*
* With the [...] and [^...] matching, a ']' character can be included
* in the list by making it the first character after '[' or '^'. A
* range of characters can be specified using '-'. Example:
* "[a-z]" matches any single lower-case letter. To match a '-', make
* it the last character in the list.
*
* This routine is usually quick, but can be N**2 in the worst case.
*
* Hints: to match '*' or '?', put them in "[]". Like this:
*
* abc[*]xyz Matches "abc*xyz" only
*
* PUBLIC: int __str_glob_cmp __P((const unsigned char *,
* PUBLIC: const unsigned char *));
*/
int
__str_glob_cmp(pattern, string)
const unsigned char *pattern;
const unsigned char *string;
{
char c;
int invert;
int seen;
char c2;
while((c = *pattern) != 0) {
switch(c) {
case '*':
while((c = pattern[1]) == '*' || c == '?') {
if (c == '?') {
if (*string == 0)
return 0;
__next_char(string);
}
pattern++;
}
if (c == 0)
return 1;
if (c == '[') {
while(*string &&
__str_glob_cmp(&pattern[1],
string) == 0) {
__next_char(string);
}
return (*string != 0);
} else {
while((c2 = *string) != 0) {
while(c2 != 0 && c2 != c) {
c2 = *++string;
}
if (c2 == 0)
return 0;
if (__str_glob_cmp(&pattern[1],
string))
return 1;
__next_char(string);
}
return 0;
}
case '?': {
if (*string == 0)
return 0;
__next_char(string);
pattern++;
break;
}
case '[': {
int prior_c = 0;
seen = 0;
invert = 0;
c = __char_val(string);
if (c == 0)
return 0;
c2 = *++pattern;
if (c2 == '^') {
invert = 1;
c2 = *++pattern;
}
if (c2 == ']') {
if (c == ']')
seen = 1;
c2 = *++pattern;
}
while((c2 = __char_val(pattern)) != 0 && c2 != ']') {
if (c2 == '-' && pattern[1] != ']' &&
pattern[1] != 0 && prior_c > 0) {
pattern++;
c2 = __char_val(pattern);
if (c >= prior_c && c <= c2)
seen = 1;
prior_c = 0;
} else if (c == c2) {
seen = 1;
prior_c = c2;
} else {
prior_c = c2;
}
__next_char(pattern);
}
if (c2 == 0 || (seen ^ invert) == 0)
return 0;
__next_char(string);
pattern++;
break;
}
default: {
if (c != *string )
return 0;
pattern++;
string++;
break;
}
}
}
return (*string == 0);
}
/*
* __str_like_cmp --
* Compare two UTF-8 strings for equality using the "LIKE" operator of
* SQL. The '%' character matches any sequence of 0 or more
* characters and '_' matches any single character. Case is
* not significant. This routine is just an adaptation of the
* __str_glob_cmp() routine above.
*
* PUBLIC: int __str_like_cmp __P((const unsigned char *,
* PUBLIC: const unsigned char *));
*/
int
__str_like_cmp(pattern, string)
const unsigned char *pattern;
const unsigned char *string;
{
register int c;
int c2;
while((c = __str_upper_to_lower[*pattern]) != 0) {
switch(c) {
case '%': {
while((c = pattern[1]) == '%' || c == '_') {
if (c == '_') {
if (*string == 0)
return 0;
__next_char(string);
}
pattern++;
}
if (c == 0)
return 1;
c = __str_upper_to_lower[c];
while((c2 = __str_upper_to_lower[*string]) != 0) {
while(c2 != 0 && c2 != c) {
c2 = __str_upper_to_lower[*++string];
}
if (c2 == 0)
return 0;
if (__str_like_cmp(&pattern[1], string))
return 1;
__next_char(string);
}
return 0;
}
case '_': {
if (*string == 0)
return 0;
__next_char(string);
pattern++;
break;
}
default: {
if (c != __str_upper_to_lower[*string])
return 0;
pattern++;
string++;
break;
}
}
}
return (*string == 0);
}
/*
* __str_numeric_cmp --
* This comparison routine is what we use for comparison operations
* between numeric values in an SQL expression. "Numeric" is a little
* bit misleading here. What we mean is that the strings have a
* type of "numeric" from the point of view of SQL. The strings
* do not necessarily contain numbers. They could contain text.
*
* If the input strings both look like actual numbers then they
* compare in numerical order. Numerical strings are always less
* than non-numeric strings so if one input string looks like a
* number and the other does not, then the one that looks like
* a number is the smaller. Non-numeric strings compare in
* lexigraphical order (the same order as strcmp()).
*
* PUBLIC: int __str_numeric_cmp __P((const char *, const char *));
*/
int
__str_numeric_cmp(left, right)
const char *left;
const char *right;
{
int result;
int left_is_num, right_is_num;
if (left == 0) {
return -1;
} else if (right == 0) {
return 1;
}
left_is_num = __str_is_numeric(left);
right_is_num = __str_is_numeric(right);
if (left_is_num) {
if (!right_is_num) {
result = -1;
} else {
double rl, rr;
rl = __dbsql_atof(left);
rr = __dbsql_atof(right);
if (rl < rr){
result = -1;
} else if (rl > rr) {
result = +1;
} else {
result = 0;
}
}
} else if (right_is_num) {
result = +1;
} else {
result = strcmp(left, right);
}
return result;
}
/*
* __str_int_in32b --
* The string 'num' represents an integer. There might be some other
* information following the integer too, but that part is ignored.
* If the integer that the prefix of 'num' represents will fit in a
* 32-bit signed integer, return TRUE. Otherwise return FALSE.
*
* This routine returns FALSE for the string -2147483648 even though that
* that number will, in theory fit in a 32-bit integer. But positive
* 2147483648 will not fit in 32 bits. So it seems safer to return
* false.
*
* PUBLIC: int __str_int_in32b __P((const char *));
*/
int
__str_int_in32b(num)
const char *num;
{
int c, i = 0;
if (*num == '-' || *num == '+')
num++;
while ((c = num[i]) >= '0' && c <= '9') {
i++;
}
return (i < 10 || (i == 10 && memcmp(num, "2147483647", 10) <= 0));
}
/*
* Some powers of 64. These constants are needed in the
* __str_real_as_sortable() routine below.
*/
#define _64e3 (64.0 * 64.0 * 64.0)
#define _64e4 (64.0 * 64.0 * 64.0 * 64.0)
#define _64e15 (_64e3 * _64e4 * _64e4 * _64e4)
#define _64e16 (_64e4 * _64e4 * _64e4 * _64e4)
#define _64e63 (_64e15 * _64e16 * _64e16 * _64e16)
#define _64e64 (_64e16 * _64e16 * _64e16 * _64e16)
/*
* __str_real_as_sortable --
* The following procedure converts a double-precision floating point
* number into a string. The resulting string has the property that
* two such strings comparied using strcmp() or memcmp() will give the
* same results as a numeric comparison of the original floating point
* numbers.
*
* This routine is used to generate database keys from floating point
* numbers such that the keys sort in the same order as the original
* floating point numbers even though the keys are compared using
* memcmp().
*
* The calling function should have allocated at least 14 characters
* of space for the buffer z[].
*
* PUBLIC: void __str_real_as_sortable __P((double, char *));
*/
void
__str_real_as_sortable(r, z)
double r;
char *z;
{
int neg;
int exp;
int cnt = 0;
/*
* This array maps integers between 0 and 63 into base-64 digits.
* The digits must be chosen such at their ASCII codes are increasing.
* This means we can not use the traditional base-64 digit set.
*/
static const char digit[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"|~";
if (r < 0.0) {
neg = 1;
r = -r;
*z++ = '-';
} else {
neg = 0;
*z++ = '0';
}
exp = 0;
if (r == 0.0) {
exp = -1024;
} else if (r < (0.5 / 64.0)) {
while(r < 0.5 / _64e64 && exp > -961) {
r *= _64e64;
exp -= 64;
}
while(r < 0.5 / _64e16 && exp > -1009) {
r *= _64e16;
exp -= 16;
}
while(r < 0.5 / _64e4 && exp > -1021) {
r *= _64e4;
exp -= 4;
}
while(r < 0.5 / 64.0 && exp > -1024) {
r *= 64.0;
exp -= 1;
}
} else if (r >= 0.5) {
while(r >= 0.5 * _64e63 && exp < 960) {
r *= 1.0 / _64e64;
exp += 64;
}
while(r >= 0.5 * _64e15 && exp < 1008) {
r *= 1.0 / _64e16;
exp += 16;
}
while(r >= 0.5 * _64e3 && exp < 1020) {
r *= 1.0 / _64e4;
exp += 4;
}
while(r >= 0.5 && exp < 1023) {
r *= 1.0/64.0;
exp += 1;
}
}
if (neg) {
exp = -exp;
r = -r;
}
exp += 1024;
r += 0.5;
if (exp < 0)
return;
if (exp >= 2048 || r >= 1.0) {
strcpy(z, "~~~~~~~~~~~~");
return;
}
*z++ = digit[(exp >> 6) & 0x3f];
*z++ = digit[exp & 0x3f];
while(r > 0.0 && cnt < 10) {
int d;
r *= 64.0;
d = (int)r;
DBSQL_ASSERT(d >= 0 && d < 64);
*z++ = digit[d & 0x3f];
r -= d;
cnt++;
}
*z = 0;
}
/*
* __str_cmp --
* This routine is used for sorting. Each key is a list of one or more
* null-terminated elements. The list is terminated by two nulls in
* a row. For example, the following text is a key with three elements
*
* Aone\000Dtwo\000Athree\000\000
*
* All elements begin with one of the characters "+-AD" and end with
* "\000" with zero or more text elements in between. Except, NULL
* elements consist of the special two-character sequence "N\000".
*
* Both arguments will have the same number of elements. This routine
* returns negative, zero, or positive if the first argument is less
* than, equal to, or greater than the first. (Result is a-b).
*
* Each element begins with one of the characters "+", "-", "A", "D".
* This character determines the sort order and collating sequence:
*
* + Sort numerically in ascending order
* - Sort numerically in descending order
* A Sort as strings in ascending order
* D Sort as strings in descending order.
*
* For the "+" and "-" sorting, pure numeric strings (strings for which
* the __str_is_numeric() function above returns TRUE) always compare
* less than strings that are not pure numerics. Non-numeric strings
* compare in memcmp() order. This is the same sort order as the
* __str_numeric_cmp() function above generates.
*
* Elements that begin with 'A' or 'D' compare in memcmp() order
* regardless of whether or not they look like a number.
*
* Note that the sort order imposed by the rules above is the same
* from the ordering defined by the "<", "<=", ">", and ">=" operators
* of expressions and for indices.
*
* PUBLIC: int __str_cmp __P((const char *, const char *));
*/
int
__str_cmp(a, b)
const char *a;
const char *b;
{
int res = 0;
int a_numeric_p, b_numeric_p;
int dir = 0;
while(res == 0 && *a && *b) {
if (a[0] == 'N' || b[0] == 'N') {
if (a[0] == b[0]) {
a += 2;
b += 2;
continue;
}
if (a[0] == 'N') {
dir = b[0];
res = -1;
} else {
dir = a[0];
res = +1;
}
break;
}
DBSQL_ASSERT(a[0] == b[0]);
if ((dir = a[0]) == 'A' || a[0] == 'D') {
res = strcmp(&a[1], &b[1]);
if (res)
break;
} else {
a_numeric_p = __str_is_numeric(&a[1]);
b_numeric_p = __str_is_numeric(&b[1]);
if (a_numeric_p) {
double rA, rB;
if (!b_numeric_p) {
res = -1;
break;
}
rA = __dbsql_atof(&a[1]);
rB = __dbsql_atof(&b[1]);
if (rA < rB) {
res = -1;
break;
}
if (rA > rB) {
res = +1;
break;
}
} else if (b_numeric_p) {
res = +1;
break;
} else {
res = strcmp(&a[1], &b[1]);
if (res)
break;
}
}
a += strlen(&a[1]) + 2;
b += strlen(&b[1]) + 2;
}
if (dir == '-' || dir == 'D')
res = -res;
return res;
}

434
src/dbsql.in Normal file
View file

@ -0,0 +1,434 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: dbsql.in 7 2007-02-03 13:34:17Z gburd $
*/
#ifndef _DBSQL_H_
#define _DBSQL_H_
#ifndef __NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdlib.h> /* Needed for drand48 */
#include <stdarg.h> /* Needed for the definition of va_list */
@inttypes_decl@
#include <stdio.h>
#endif
#include <db.h>
#if defined(__cplusplus)
extern "C" {
#endif
@DB_CONST@
@DB_PROTO1@
@DB_PROTO2@
/*
* DBSQL version information.
*/
#define DBSQL_VERSION_MAJOR @DBSQL_VERSION_MAJOR@
#define DBSQL_VERSION_MINOR @DBSQL_VERSION_MINOR@
#define DBSQL_VERSION_PATCH @DBSQL_VERSION_PATCH@
#define DBSQL_VERSION_STRING @DBSQL_VERSION_STRING@
/*
* !!!
* DBSQL uses specifically sized types. If they're not provided by
* the system, typedef them here.
*
* We protect them against multiple inclusion using __BIT_TYPES_DEFINED__,
* as does BIND and Kerberos, since we don't know for sure what #include
* files the user is using.
*
* !!!
* We also provide the standard u_int, u_long etc., if they're not provided
* by the system.
*/
#ifndef __BIT_TYPES_DEFINED__
#define __BIT_TYPES_DEFINED__
@u_int8_decl@
@int16_decl@
@u_int16_decl@
@int32_decl@
@u_int32_decl@
#endif
@u_char_decl@
@u_short_decl@
@u_int_decl@
@u_long_decl@
@ssize_t_decl@
@long_double_decl@
/*
* Forward structure declarations, so we can declare pointers and
* applications can get type checking.
*/
struct __dbsql; typedef struct __dbsql DBSQL;
struct __dbsql_func; typedef struct __dbsql_func dbsql_func_t;
struct __dbsql_stmt; typedef struct __dbsql_vm dbsql_stmt_t;
struct __dbsql_db; typedef struct __dbsql_db dbsql_db_t;
struct __dbsql_value; typedef struct __dbsql_value dbsql_value_t;
typedef int (*dbsql_callback)(void *, int, char **, char **);
/*
* Name of the master database table. The master database table
* is a special table that holds the names and attributes of all
* user tables and indices.
*/
#define MASTER_NAME "master"
#define TEMP_MASTER_NAME "temp_master"
/*
* If the following macro is set to 1, then NULL values are considered
* distinct for the SELECT DISTINCT statement and for UNION or EXCEPT
* compound queries. No other SQL database engine (among those tested)
* works this way except for OCELOT. But the SQL92 spec implies that
* this is how things should work.
*
* If the following macro is set to 0, then NULLs are indistinct for
* SELECT DISTINCT and for UNION.
*/
#define NULL_ALWAYS_DISTINCT 0
/*
* If the following macro is set to 1, then NULL values are considered
* distinct when determining whether or not two entries are the same
* in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL,
* OCELOT, and Firebird all work. The SQL92 spec explicitly says this
* is the way things are suppose to work.
*
* If the following macro is set to 0, the NULLs are indistinct for
* a UNIQUE index. In this mode, you can only have a single NULL entry
* for a column declared UNIQUE. This is the way Informix and SQL Server
* work.
*/
#define NULL_DISTINCT_FOR_UNIQUE 1
/*
* The name of the schema tables.
*/
#define SCHEMA_TABLE(x) (x?TEMP_MASTER_NAME:MASTER_NAME)
/*
* Character Encoding:
* DBSQL supports the major character encodings.
* - ASCII (American Standard Code for Information Interchange)
* - UTF-8 (8-bit UCS/Unicode Transformation Format)
* - UTF-16 (16-bit UCS/Unicode Transformation Format)
* - ISO-8859-1 (The IANA registered the character map ISO_8859-1:1987)
*
* The following constant holds one of two strings, "UTF-8" or "iso8859",
* depending on which character encoding the library expects to see.
* The character encoding makes a difference for the LIKE and GLOB
* operators and for the LENGTH() and SUBSTR() functions.
*/
extern const char dbsql_encoding[];
#define DBSQL_ASCII_ENCODED 1
#define DBSQL_UTF8_ENCODED 2
#define DBSQL_UTF16_ENCODED 3
#define DBSQL_ISO8859_ENCODED 4
/*
* The DBSQL_UTF8_ENCODING macro is defined if the library expects to see
* UTF-8 encoded data. The DBSQL_ISO8859_ENCODING macro is defined if the
* iso8859 encoding should be used.
*/
#define DBSQL_@ENCODING@_ENCODING 1
/* DBSQL (user visible) successful return code. */
#define DBSQL_SUCCESS 0
/*
* DBSQL (user visible) error return codes.
*
* !!!
* We don't want our error returns to conflict with other packages where
* possible, so pick a base error value that's hopefully not common. We
* document that we own the error name space from -50,800 to -50,999.
*/
/* DBSQL (public) error return codes. */
#define DBSQL_ERROR (-50999)/* SQL error or missing database */
#define DBSQL_INTERNAL (-50998)/* An internal logic error */
#define DBSQL_PERM (-50997)/* Access permission denied */
#define DBSQL_ABORT (-50996)/* Callback routine requested an abort */
#define DBSQL_BUSY (-50995)/* The database file is locked */
#define DBSQL_LOCKED (-50994)/* A table in the database is locked */
#define DBSQL_NOMEM (-50993)/* A call to allocate memory failed */
#define DBSQL_READONLY (-50992)/* Attempt to write a readonly database */
#define DBSQL_INTERRUPTED (-50991)/* Operation terminated by interrupt() */
#define DBSQL_IOERR (-50990)/* Some kind of disk I/O error occurred */
#define DBSQL_FULL (-50989)/* Failed because database is full */
#define DBSQL_CANTOPEN (-50988)/* Unable to open the database file */
#define DBSQL_PROTOCOL (-50987)/* Database lock protocol error */
#define DBSQL_SCHEMA (-50986)/* The database schema changed */
#define DBSQL_CONSTRAINT (-50985)/* Abort due to contraint violation */
#define DBSQL_MISMATCH (-50984)/* Data type mismatch */
#define DBSQL_MISUSE (-50983)/* Library used incorrectly */
#define DBSQL_AUTH (-50982)/* Authorization denied */
#define DBSQL_FORMAT (-50981)/* Auxiliary database format error */
#define DBSQL_RANGE (-50980)/* 2nd parameter to bind() out of range */
#define DBSQL_ROW (-50979)/* step() has another row ready */
#define DBSQL_DONE (-50978)/* step() has finished executing */
#define DBSQL_CORRUPT (-50977)/* The data record is malformed */
#define DBSQL_RUNRECOVERY (-50976)/* Database environment requires recovery */
#define DBSQL_INVALID_NAME (-50975)/* Empty or invalid file name supplied */
/* DBSQL (private) error return codes. */
#define DBSQL_NOTFOUND (-50801)/* Table or record not found */
#define DBSQL_EMPTY (-50800)/* Database table is empty */
/*
* SQL Database Environment handle.
*/
struct __dbsql {
void *app_private; /* For use by the application. */
/* Basic API functions. */
const char *(*encoding)(void);
int (*open) __P((DBSQL *, const char *, int, char **));
int (*close) __P((DBSQL *));
int (*rowid) __P((DBSQL *));
int (*last_change_count) __P((DBSQL *));
int (*total_change_count) __P((DBSQL *));
void (*interrupt) __P((DBSQL *));
void (*set_errcall) __P((DBSQL *, void (*)(const char *, char *)));
void (*set_errfile) __P((DBSQL *, FILE *));
void (*get_errfile) __P((DBSQL *, FILE **));
void (*set_errpfx) __P((DBSQL *, const char *));
void (*get_errpfx) __P((DBSQL *, const char **));
DB_ENV *(*get_dbenv) __P((DBSQL *));
/* Callback access functions. */
void *(*set_tracecall) __P((DBSQL *, void(*)(void *, const char *),\
void *));
#ifndef DBSQL_NO_PROGRESS
void (*set_progresscall) __P((DBSQL *, int, int(*)(void*), void*));
#endif
void *(*set_commitcall) __P((DBSQL *, int(*)(void*), void*));
void (*set_busycall) __P((DBSQL *, int(*)(int, const char *, int),\
void *));
void (*set_timeout) __P((DBSQL *, int ms));
int (*get_table) __P((DBSQL *, const char *, char ***, int *,\
int *, char **));
void (*free_table) __P((char **));
int (*exec_printf) __P((DBSQL *, const char *, dbsql_callback,\
void *, char **, ...));
int (*exec_vprintf) __P((DBSQL *, const char *, dbsql_callback,\
void *, char **, va_list ap));
int (*exec_table_printf) __P((DBSQL *, const char *, char ***,\
int *, int *, char **, ...));
int (*exec_table_vprintf) __P((DBSQL *, const char *, char ***,\
int *, int *, char **, va_list));
int (*exec) __P((DBSQL *, const char *, dbsql_callback, void *,\
char **));
int (*step) __P((dbsql_stmt_t *, int *, const char ***,\
const char ***));
int (*create_function) __P((DBSQL *, const char *, int, int, void *,\
void (*)(dbsql_func_t *, int, const char**),\
void (*)(dbsql_func_t *, int, const char**),\
void (*)(dbsql_func_t *)));
int (*func_return_type) __P((DBSQL *, const char *, int));
#define DBSQL_NUMERIC (-1)
#define DBSQL_TEXT (-2)
#define DBSQL_ARGS (-3)
int (*set_authorizer) __P((DBSQL *, int (*)(void *, int, const char *,\
const char *, const char *,\
const char *), void *));
/*
* The return value of the authorization function should be one of the
* following constants:
*
define DBSQL_SUCCESS 0 Allow access (This is actually defined above) */
#define DBSQL_DENY 1 /* Abort the SQL statement with an error */
#define DBSQL_IGNORE 2 /* Don't allow access, but don't generate an error */
/*
* The second parameter to the access authorization function above will
* be one of the values below. These values signify what kind of operation
* is to be authorized. The 3rd and 4th parameters to the authorization
* function will be parameters or NULL depending on which of the following
* codes is used as the second parameter. The 5th parameter is the name
* of the database ("main", "temp", etc.) if applicable. The 6th parameter
* is the name of the inner-most trigger or view that is responsible for
* the access attempt or NULL if this access attempt is directly from
* input SQL code.
* Arg-3 Arg-4
*/
#define DBSQL_COPY 0 /* Table Name File Name */
#define DBSQL_CREATE_INDEX 1 /* Index Name Table Name */
#define DBSQL_CREATE_TABLE 2 /* Table Name NULL */
#define DBSQL_CREATE_TEMP_INDEX 3 /* Index Name Table Name */
#define DBSQL_CREATE_TEMP_TABLE 4 /* Table Name NULL */
#define DBSQL_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */
#define DBSQL_CREATE_TEMP_VIEW 6 /* View Name NULL */
#define DBSQL_CREATE_TRIGGER 7 /* Trigger Name Table Name */
#define DBSQL_CREATE_VIEW 8 /* View Name NULL */
#define DBSQL_DELETE 9 /* Table Name NULL */
#define DBSQL_DROP_INDEX 10 /* Index Name Table Name */
#define DBSQL_DROP_TABLE 11 /* Table Name NULL */
#define DBSQL_DROP_TEMP_INDEX 12 /* Index Name Table Name */
#define DBSQL_DROP_TEMP_TABLE 13 /* Table Name NULL */
#define DBSQL_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */
#define DBSQL_DROP_TEMP_VIEW 15 /* View Name NULL */
#define DBSQL_DROP_TRIGGER 16 /* Trigger Name Table Name */
#define DBSQL_DROP_VIEW 17 /* View Name NULL */
#define DBSQL_INSERT 18 /* Table Name NULL */
#define DBSQL_PRAGMA 19 /* Pragma Name 1st arg or NULL */
#define DBSQL_READ 20 /* Table Name Column Name */
#define DBSQL_SELECT 21 /* NULL NULL */
#define DBSQL_TRANSACTION 22 /* NULL NULL */
#define DBSQL_UPDATE 23 /* Table Name Column Name */
#define DBSQL_ATTACH 24 /* Filename NULL */
#define DBSQL_DETACH 25 /* Database Name NULL */
/* Non-callback access functions. */
int (*prepare) __P((DBSQL *, const char *, const char **, dbsql_stmt_t **,\
char **));
int (*finalize) __P((dbsql_stmt_t *, char **));
int (*reset) __P((dbsql_stmt_t *, char **));
int (*bind) __P((dbsql_stmt_t *, int, const char *, int, int));
/*
* From here on out, fields are internal and subject to change.
*/
DB_ENV *dbenv; /* The Berkeley DB Environment */
int txn_flags;
void (*dbsql_errcall)(const char *, char *); /* Error callback */
FILE *dbsql_errfile; /* The error file */
char *dbsql_errpfx; /* The error prefix string */
void (*dbsql_paniccall)(DBSQL *, int); /* The panic callback */
struct drand48_data rand; /* Random generator state */
int panic; /* If non-zero, shut down the application */
dbsql_db_t *aDb; /* One for each open SQL database + 2 */
int nDb; /* Number of open dbsql_db_t's open */
int flags; /* Flags, see below */
#define DBSQL_VdbeTrace 0x00000001 /* True to trace VDBE execution */
#define DBSQL_Initialized 0x00000002 /* True after initialization */
#define DBSQL_Interrupt 0x00000004 /* Cancel current operation */
#define DBSQL_InTrans 0x00000008 /* True if in a transaction */
#define DBSQL_InternChanges 0x00000010 /* Uncommitted Hash table changes */
#define DBSQL_FullColNames 0x00000020 /* Show full column names on SELECT */
#define DBSQL_CountRows 0x00000040 /* Count rows changed by INSERT,
DELETE, or UPDATE and return
the count using a callback. */
#define DBSQL_NullCallback 0x00000080 /* Invoke the callback once if the
result set is empty */
#define DBSQL_ReportTypes 0x00000200 /* Include information on datatypes
in 4th argument of callback */
#define DBSQL_DurableTemp 0x00000400 /* Back temp databases on disk. */
#define DBSQL_Threaded 0x00000800 /* Set when we're expected to be
thread safe. */
u_int8_t want_to_close; /* Close after all VDBEs are deallocated */
int next_sig; /* Next value of aDb[0].schema_sig */
int nTable; /* Number of tables in the database */
void *pBusyArg; /* 1st Argument to the busy callback */
int (*xBusyCallback)(DBSQL *, void *, const char*, int);
void *pCommitArg; /* Argument to xCommitCallback() */
int (*xCommitCallback)(void*);/* Invoked at every commit. */
void *aFunc; /* All functions that can be in SQL exprs */
int lastRowid; /* ROWID of most recent insert */
int priorNewRowid; /* Last generated ROWID */
int onError; /* Default conflict algorithm */
int magic; /* Magic number to detect library misuse */
#define DBSQL_STATUS_OPEN 0xa029a697 /* Database is open */
#define DBSQL_STATUS_CLOSED 0x9f3c2d33 /* Database is closed */
#define DBSQL_STATUS_BUSY 0xf03b7906 /* Database currently in use */
#define DBSQL_STATUS_ERROR 0xb5357930 /* An DBSQL_MISUSE error occurred */
u_int32_t _num_last_changes; /* Number of rows changed */
u_int32_t _num_total_changes; /* Total number of rows changed */
struct vdbe *pVdbe; /* List of active virtual machines */
void (*xTrace)(void*,const char*); /* Trace function */
void *pTraceArg; /* Argument to the trace function */
#ifndef DBSQL_NO_AUTH /* Access authorization functions */
int (*auth)(void*,int,const char*,const char*,const char*,const char*);
void *pAuthArg; /* 1st argument to the access auth function */
#endif
#ifndef DBSQL_NO_PROGRESS
int (*xProgress)(void *);/* The progress callback */
void *pProgressArg; /* Argument to the progress callback */
int nProgressOps; /* Number of opcodes for progress callback */
#endif
u_int32_t format_version;/* The version of the representation */
};
#define DBSQL_THREAD 0x00001 /* When set the library is thread
safe. */
#define DBSQL_DURABLE_TEMP 0x00002 /* Store temp data on disk rather
than in memory */
int dbsql_create_env __P((DBSQL **, const char *, const char *, int, u_int32_t));
int dbsql_create __P((DBSQL **, DB_ENV *, u_int32_t));
int dbsql_complete_stmt __P((const char *));
char *dbsql_strerror __P((int));
const char * dbsql_version __P((int *, int *, int *));
void dbsql_set_result_null __P((dbsql_func_t *));
char *dbsql_set_result_string __P((dbsql_func_t *, const char *, int));
void dbsql_set_result_int __P((dbsql_func_t *, int));
void dbsql_set_result_int64 __P((dbsql_func_t *, int64_t));
void dbsql_set_result_blob __P((dbsql_func_t *, const void *, size_t,\
void(*)(void*)));
void dbsql_set_result_varchar __P((dbsql_func_t *, const char *, size_t,\
void(*)(void*)));
void dbsql_set_result_double __P((dbsql_func_t *, double));
void dbsql_set_result_error __P((dbsql_func_t *, const char *, int));
void *dbsql_user_data __P((dbsql_func_t *));
void *dbsql_aggregate_context __P((dbsql_func_t *, int));
int dbsql_aggregate_count __P((dbsql_func_t *));
/*
* The fifth parameter to dbsql_set_result_blob(), and
* dbsql_set_result_varchar() is a destructor used to dispose of the BLOB
* or text after DBSQL has finished with it. If the fifth argument is the
* special value DBSQL_STATIC, then the library assumes that the information
* is in static, unmanaged space and does not need to be freed. If the fifth
* argument has the value DBSQL_TRANSIENT, then DBSQL makes its own private
* copy of the data.
*/
#define DBSQL_STATIC ((void(*)(void *))0)
#define DBSQL_TRANSIENT ((void(*)(void *))-1)
/*
* Values are stored in the database in one of the following fundamental
* types. TODO
*/
#define DBSQL_INTEGER 1
#define DBSQL_FLOAT 2
#define DBSQL_VARCHAR 3
#define DBSQL_BLOB 4
#define DBSQL_NULL 5
#ifdef __cplusplus
}
#endif
#endif /* !_DBSQL_H_ */

1517
src/dbsql/dbsql.c Normal file

File diff suppressed because it is too large Load diff

106
src/dbsql_tclsh.c Normal file
View file

@ -0,0 +1,106 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: dbsql_tclsh.c 7 2007-02-03 13:34:17Z gburd $
*/
/*
* A TCL Shell for testing DBSQL.
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
static char main_loop[] =
"set line {}\n"
"while {![eof stdin]} {\n"
"if {$line!=\"\"} {\n"
"puts -nonewline \"> \"\n"
"} else {\n"
"puts -nonewline \"% \"\n"
"}\n"
"flush stdout\n"
"append line [gets stdin]\n"
"if {[info complete $line]} {\n"
"if {[catch {uplevel #0 $line} result]} {\n"
"puts stderr \"Error: $result\"\n"
"} elseif {$result!=\"\"} {\n"
"puts $result\n"
"}\n"
"set line {}\n"
"} else {\n"
"append line \\n\n"
"}\n"
"}\n"
;
/*
* main --
*/
int
main(argc, argv)
int argc;
char **argv;
{
int i;
const char *info;
Tcl_Interp *interp;
Tcl_FindExecutable(argv[0]);
interp = Tcl_CreateInterp();
dbsql_init_tcl_interface(interp);
#ifdef CONFIG_TEST
extern int Sqlitetest1_Init(Tcl_Interp*);
extern int Sqlitetest2_Init(Tcl_Interp*);
extern int Sqlitetest3_Init(Tcl_Interp*);
extern int Sqlitetest4_Init(Tcl_Interp*);
extern int Md5_Init(Tcl_Interp*);
Sqlitetest1_Init(interp);
Sqlitetest2_Init(interp);
Sqlitetest3_Init(interp);
Sqlitetest4_Init(interp);
Md5_Init(interp);
#endif
if (argc >= 2) {
Tcl_SetVar(interp, "argv0", argv[1], TCL_GLOBAL_ONLY);
Tcl_SetVar(interp, "argv", "", TCL_GLOBAL_ONLY);
for (i = 2; i < argc; i++) {
Tcl_SetVar(interp, "argv", argv[i],
TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT |
TCL_APPEND_VALUE);
}
if (Tcl_EvalFile(interp, argv[1]) != TCL_OK) {
info = Tcl_GetVar(interp, "errorInfo",
TCL_GLOBAL_ONLY);
if (info == 0)
info = interp->result;
fprintf(stderr, "%s: %s\n", *argv, info);
return 1;
}
} else {
Tcl_GlobalEval(interp, main_loop);
}
return 0;
}

41
src/inc/clib_ext.h Normal file
View file

@ -0,0 +1,41 @@
/* DO NOT EDIT: automatically built by dist/s_include. */
#ifndef _clib_ext_h_
#define _clib_ext_h_
#if defined(__cplusplus)
extern "C" {
#endif
#ifndef HAVE_GETOPT
int getopt __P((int, char * const *, const char *));
#endif
#ifndef HAVE_MEMCMP
int memcmp __P((const void *, const void *, size_t));
#endif
#ifndef HAVE_SRAND48_R
int srand48_r __P((struct drand48_data *));
#endif
int rand8_r __P((struct drand48_data *, u_int8_t *));
int rand32_r __P((struct drand48_data *, u_int32_t *));
#ifndef HAVE_SNPRINTF
int snprintf __P((char *, size_t, const char *, ...));
#endif
#ifndef HAVE_STRCASECMP
int strcasecmp __P((const char *, const char *));
#endif
#ifndef HAVE_STRNCASECMP
int strncasecmp __P((const char *, const char *, size_t));
#endif
#ifndef HAVE_STRDUP
char *strdup __P((const char *));
#endif
#ifndef HAVE_STRNDUP
char *strndup __P((const char *, size_t));
#endif
char *xvprintf __P((DBSQL *, const char *, va_list));
char *xprintf __P((DBSQL *, const char *, ...));
#if defined(__cplusplus)
}
#endif
#endif /* !_clib_ext_h_ */

49
src/inc/common_ext.h Normal file
View file

@ -0,0 +1,49 @@
/* DO NOT EDIT: automatically built by dist/s_include. */
#ifndef _common_ext_h_
#define _common_ext_h_
#if defined(__cplusplus)
extern "C" {
#endif
int __dbsql_umalloc __P((DBSQL *, size_t, void *));
int __dbsql_urealloc __P((DBSQL *, size_t, void *));
void __dbsql_ufree __P((DBSQL *, void *));
int __dbsql_strdup __P((DBSQL *, const char *, void *));
int __dbsql_strndup __P((DBSQL *, const char *, void *, size_t));
int __dbsql_calloc __P((DBSQL *, size_t, size_t, void *));
int __dbsql_malloc __P((DBSQL *, size_t, void *));
int __dbsql_realloc __P((DBSQL *, size_t, void *));
void __dbsql_free __P((DBSQL *, void *));
double __dbsql_atof __P((const char *));
int __dbsql_atoi __P((const char *, int *));
#ifdef DIAGNOSTIC
void __dbsql_assert __P((const char *, const char *, int));
#endif
int __dbsql_panic_msg __P((DBSQL *));
int __dbsql_panic __P((DBSQL *, int));
void __dbsql_err __P((const DBSQL *, const char *, ...)) __attribute__ ((__format__ (__printf__, 2, 3)));
void __dbsql_errcall __P((const DBSQL *, int, int, const char *, va_list));
void __dbsql_errfile __P((const DBSQL *, int, int, const char *, va_list));
void __error_msg __P((parser_t *, const char *, ...));
void __hash_init __P((hash_t *, int, int));
void __hash_clear __P((hash_t *));
void *__hash_find __P((const hash_t *, const void *, int));
void *__hash_insert __P((hash_t *, const void *, int, void *));
int __hash_ignore_case __P((const char *, int));
void __str_append __P((char **, const char *, ...));
void __str_nappend __P((char **, ...));
void __str_unquote __P((char *));
int __str_urealloc __P((char **));
int __str_is_numeric __P((const char *));
int __str_glob_cmp __P((const unsigned char *, const unsigned char *));
int __str_like_cmp __P((const unsigned char *, const unsigned char *));
int __str_numeric_cmp __P((const char *, const char *));
int __str_int_in32b __P((const char *));
void __str_real_as_sortable __P((double, char *));
int __str_cmp __P((const char *, const char *));
#if defined(__cplusplus)
}
#endif
#endif /* !_common_ext_h_ */

53
src/inc/db_int.h Normal file
View file

@ -0,0 +1,53 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: db_int.h 7 2007-02-03 13:34:17Z gburd $
*/
#ifndef _DB_INT_H_
#define _DB_INT_H_
/*
* These are function prototypes to non-public API parts of DB we use
* in DBSQL. DB may have been compiled with --uniquename, so we have
* to manage that here. We also have to smooth out differences from
* version to version here as internal API is bound to change.
*/
#if defined(__cplusplus)
extern "C" {
#endif
extern void *__ua_memcpy__DB_UNIQUE_NAME__ __P((void *, const void *, size_t));
extern int __os_get_errno__DB_UNIQUE_NAME__ __P((void));
extern void __os_set_errno__DB_UNIQUE_NAME__ __P((int));
extern void __os_sleep__DB_UNIQUE_NAME__ __P((DB_ENV *, u_long, u_long));
extern void __os_free__DB_UNIQUE_NAME__ __P((DB_ENV *, void *));
extern int __os_realloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
extern int __os_malloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
extern int __os_calloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, size_t, void *));
extern int __os_strdup__DB_UNIQUE_NAME__ __P((DB_ENV *, const char *, void *));
extern void __os_ufree__DB_UNIQUE_NAME__ __P((DB_ENV *, void *));
extern int __os_urealloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
extern int __os_umalloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
extern int __os_exists__DB_UNIQUE_NAME__ __P((const char *, int *));
extern int __db_omode__DB_UNIQUE_NAME__ __P((const char *));
#if defined(__cplusplus)
}
#endif
#endif /* !_DB_INT_H_ */

198
src/inc/dbsql_ext.h Normal file
View file

@ -0,0 +1,198 @@
/* DO NOT EDIT: automatically built by dist/s_include. */
#ifndef _dbsql_ext_h_
#define _dbsql_ext_h_
#if defined(__cplusplus)
extern "C" {
#endif
int __init_databases __P((DBSQL *, char**));
int __sqldb_init __P((dbsql_db_t *, DBSQL *, const char *, int, int, int));
void __api_interrupt __P((DBSQL *));
int __api_get_table __P((DBSQL *, const char *, char ***, int *, int *, char **));
void __api_free_table __P((char **));
void __attach __P((parser_t *, token_t *, token_t *));
void __detach __P((parser_t *, token_t *));
int __ref_normalizer_ctx_init __P((ref_normalizer_ctx_t *, parser_t *, int, const char *, const token_t *));
int __ref_normalize_src_list __P((ref_normalizer_ctx_t *, src_list_t *));
int __ref_normalize_select __P((ref_normalizer_ctx_t *, select_t *));
int __ref_normalize_expr __P((ref_normalizer_ctx_t *, expr_t *));
int __ref_normalize_expr_list __P((ref_normalizer_ctx_t *, expr_list_t *));
int __ref_normalize_trigger_step __P((ref_normalizer_ctx_t *, trigger_step_t *));
int __api_set_authorizer __P((DBSQL *, int (*auth)(void*,int,const char*, const char*,const char*, const char*), void *));
void __auth_read __P((parser_t *, expr_t *, src_list_t *));
int __auth_check __P((parser_t *, int, const char *, const char *, const char *));
void __auth_context_push __P((parser_t *, auth_context_t *, const char *));
void __auth_context_pop __P((auth_context_t *));
void __parse_begin __P((parser_t *, int));
void __parse_exec __P((parser_t *));
table_t *__find_table __P((DBSQL *, const char *, const char *));
table_t *__locate_table __P((parser_t *, const char *, const char *));
index_t *__find_index __P((DBSQL *, const char *, const char *));
void __unlink_and_delete_index __P((DBSQL *, index_t *));
void __reset_internal_schema __P((DBSQL *, int));
void __rollback_internal_changes __P((DBSQL *));
void __commit_internal_changes __P((DBSQL *));
void __vdbe_delete_table __P((DBSQL *, table_t *));
char *__table_name_from_token __P((token_t *));
void __open_master_table __P((vdbe_t *, int));
void __start_table __P((parser_t *, token_t *, token_t *, int, int));
void __add_column __P((parser_t *, token_t *));
void __add_not_null __P((parser_t *, int));
void __add_column_type __P((parser_t *, token_t *, token_t *));
void __add_default_value __P((parser_t *, token_t *, int));
void __add_primary_key __P((parser_t *, id_list_t *, int));
int __collate_type __P((const char *, int));
void __add_collate_type __P((parser_t *, int));
void __change_schema_signature __P((DBSQL *, vdbe_t *));
void __ending_create_table_paren __P((parser_t *, token_t *, select_t *));
void __create_view __P((parser_t *, token_t *, token_t *, select_t *, int));
int __view_get_column_names __P((parser_t *, table_t *));
table_t *__table_from_token __P((parser_t *, token_t *));
void __drop_table __P((parser_t *, token_t *name, int));
void __add_idx_key_type __P((vdbe_t *, index_t *));
void __create_foreign_key __P((parser_t *, id_list_t *, token_t *, id_list_t *, int));
void __defer_foreign_key __P((parser_t *, int));
void __create_index __P((parser_t *, token_t *, src_list_t *, id_list_t *, int, token_t *, token_t *));
id_list_t *__id_list_append __P((id_list_t *, token_t *));
src_list_t *__src_list_append __P((src_list_t *, token_t *, token_t *));
void __src_list_add_alias __P((src_list_t *, token_t *));
void __id_list_delete __P((id_list_t *));
int __id_list_index __P((id_list_t *, const char *));
void __src_list_delete __P((src_list_t *));
void __dbsql_txn_begin __P((parser_t *, int));
void __dbsql_txn_commit __P((parser_t *));
void __dbsql_txn_abort __P((parser_t *));
void __code_verify_schema __P((parser_t *, int));
void __vdbe_prepare_write __P((parser_t*, int, int));
void __vdbe_conclude_write __P((parser_t *));
void __copy __P((parser_t *, src_list_t *, token_t *, token_t *, int));
void __register_datetime_funcs __P((DBSQL *));
table_t *__src_list_lookup __P((parser_t *, src_list_t *));
int __is_table_read_only __P((parser_t *, table_t *, int));
void __delete_from __P((parser_t *, src_list_t *, expr_t *));
void __generate_row_delete __P((DBSQL *, vdbe_t *, table_t *, int, int));
void __generate_row_index_delete __P((DBSQL *, vdbe_t *, table_t *, int, char *));
expr_t *__expr __P((int, expr_t *, expr_t *, token_t *));
void __expr_span __P((expr_t *, token_t *, token_t *));
expr_t *__expr_function __P((expr_list_t *, token_t *));
void __expr_delete __P((expr_t *));
expr_t *__expr_dup __P((expr_t *));
void __token_copy __P((token_t *, token_t *));
expr_list_t *__expr_list_dup __P((expr_list_t *));
src_list_t *__src_list_dup __P((src_list_t *));
id_list_t *__id_list_dup __P((id_list_t *));
select_t *__select_dup __P((select_t *));
expr_list_t *__expr_list_append __P((expr_list_t *, expr_t *, token_t *));
void __expr_list_delete __P((expr_list_t *));
int __expr_is_constant __P((expr_t *));
int __expr_is_integer __P((expr_t *, int *));
int __is_row_id __P((const char *));
int __expr_resolve_ids __P((parser_t *, src_list_t *, expr_list_t *, expr_t *));
int __expr_check __P((parser_t *, expr_t *, int, int *));
int __expr_type __P((expr_t *));
void __expr_code __P((parser_t *, expr_t *));
void __expr_if_false __P((parser_t *, expr_t *, int, int));
int __expr_compare __P((expr_t *, expr_t *));
int __expr_analyze_aggregates __P((parser_t *, expr_t *));
func_def_t *__find_function __P((DBSQL *, const char *, int, int, int));
void __insert __P((parser_t *, src_list_t *, expr_list_t *, select_t *, id_list_t *, int));
void __generate_constraint_checks __P((parser_t *, table_t *, int, char *, int, int, int, int));
void __complete_insertion __P((parser_t *, table_t *, int, char *, int, int, int));
void __pragma __P((parser_t *, token_t *, token_t *, int));
select_t *__select_new __P((expr_list_t *, src_list_t *, expr_t *, expr_list_t *, expr_t *, expr_list_t *, int, int, int));
int __join_type __P((parser_t *, token_t *, token_t *, token_t *));
void __select_delete __P((select_t *));
void __add_key_type __P((vdbe_t *, expr_list_t *));
void __select_unbind __P((select_t *));
vdbe_t *__parser_get_vdbe __P((parser_t *));
int __select __P((parser_t *, select_t *, int, int, select_t *, int, int *));
table_t *__select_result_set __P((parser_t *, char *, select_t *));
void __vdbe_delete_trigger_step __P((trigger_step_t *));
void __begin_trigger __P((parser_t *, token_t *, int, int, id_list_t *, src_list_t *, int, expr_t *, int));
void __finish_trigger __P((parser_t *, trigger_step_t *, token_t *));
trigger_step_t * __trigger_select_step __P((select_t *));
trigger_step_t *__trigger_insert_step __P((token_t *, id_list_t *, expr_list_t *, select_t *, int));
trigger_step_t *__trigger_update_step __P((token_t *, expr_list_t *, expr_t *, int));
trigger_step_t *__trigger_delete_step __P((token_t *, expr_t *));
void __vdbe_delete_trigger __P((trigger_t *));
void __drop_trigger __P((parser_t *, src_list_t *));
void __drop_trigger_ptr __P((parser_t *, trigger_t *, int));
int __triggers_exist __P((parser_t *, trigger_t *, int, int, int, expr_list_t *));
void __update __P((parser_t *, src_list_t *, expr_list_t *, expr_t *, int));
void __vacuum __P((parser_t *, token_t *));
int __execute_vacuum __P((char **, DBSQL *));
int __execute_vacuum __P((char **, DBSQL *));
where_info_t *__where_begin __P((parser_t *, src_list_t *, expr_t *, int, expr_list_t **));
void __where_end __P((where_info_t *));
int __safety_on __P((DBSQL *));
int __safety_off __P((DBSQL *));
int __safety_check __P((DBSQL *));
int __sm_bt_compare __P((DB *, const DBT *, const DBT *));
int __sm_create __P((DBSQL *, const char *, int, int, sm_t **));
int __sm_close_db __P((sm_t *));
int __sm_checkpoint __P((sm_t *));
char *__sm_get_database_name __P((sm_t *));
int __sm_begin_txn __P((sm_t *));
int __sm_commit_txn __P((sm_t *));
int __sm_abort_txn __P((sm_t *));
int __sm_cursor __P((sm_t *, int, int, sm_cursor_t **));
int __sm_close_cursor __P((sm_cursor_t *));
int __sm_moveto __P((sm_cursor_t *, const void *, int, int *));
int __sm_next __P((sm_cursor_t *, int *));
int __sm_prev __P((sm_cursor_t *, int *));
int __sm_key_size __P((sm_cursor_t *, int *));
int __sm_data_size __P((sm_cursor_t *, int *));
int __sm_key_compare __P((sm_cursor_t *, const void *, int, int, int *));
size_t __sm_key __P((sm_cursor_t *, size_t, size_t, const void *));
size_t __sm_data __P((sm_cursor_t *, size_t, size_t, char *));
int __sm_first __P((sm_cursor_t *, int *));
int __sm_last __P((sm_cursor_t *, int *));
int __sm_insert __P((sm_cursor_t *, const void *, int, const void *, int));
int __sm_delete __P((sm_cursor_t *));
int __sm_drop_table __P((sm_t *, int));
int __sm_clear_table __P((sm_t *, int));
int __sm_open_table __P((sm_t *, int *));
int __sm_create_table __P((sm_t *, int *));
int __sm_create_index __P((sm_t *, int *));
int __sm_set_format_version __P((sm_t *, int, u_int32_t));
int __sm_get_format_version __P((sm_t *, u_int32_t *));
int __sm_set_schema_sig __P((sm_t *, u_int32_t));
int __sm_get_schema_sig __P((sm_t *, u_int32_t *));
void __register_builtin_funcs __P((DBSQL *));
int get_keyword_code __P((const char *, int));
int __run_sql_parser __P((parser_t *, const char *, char **));
int __api_step __P((dbsql_stmt_t *, int *, const char ***, const char ***));
int __vdbe_exec __P((vdbe_t *));
vdbe_t *__vdbe_create __P((DBSQL *));
void __vdbe_trace __P((vdbe_t *, FILE *));
int __vdbe_add_op __P((vdbe_t *, int, int, int));
int __vdbe_make_label __P((vdbe_t *));
void __vdbe_resolve_label __P((vdbe_t *, int));
int __vdbe_current_addr __P((vdbe_t *));
int __vdbe_add_op_list __P((vdbe_t *, int, const vdbe_op_t *));
void __vdbe_change_p1 __P((vdbe_t *, int, int));
void __vdbe_change_p2 __P((vdbe_t *, int, int));
void __vdbe_change_p3 __P((vdbe_t *, int, const char *, int));
void __vdbe_dequote_p3 __P((vdbe_t *, int));
void __vdbe_compress_space __P((vdbe_t *, int));
int __vdbe_find_op __P((vdbe_t *, int, int));
vdbe_op_t *__vdbe_get_op __P((vdbe_t *, int));
void __vdbe_print_op __P((FILE *, int, vdbe_op_t *));
int __vdbe_list __P((vdbe_t *));
void __vdbe_make_ready __P((vdbe_t *, int, dbsql_callback, void *, int));
void __vdbe_sorter_reset __P((vdbe_t *));
void __vdbe_agg_reset __P((agg_t *));
void __vdbe_keylist_free __P((keylist_t *));
void __vdbe_cleanup_cursor __P((cursor_t *));
int __vdbe_reset __P((vdbe_t *, char **));
int __vdbe_finalize __P((vdbe_t *, char **));
int __api_bind __P((dbsql_stmt_t *, int, const char *, int, int));
void __vdbe_delete __P((vdbe_t *));
int __vdbe_byte_swap __P((int));
int __vdbe_cursor_moveto __P((cursor_t *));
#if defined(__cplusplus)
}
#endif
#endif /* !_dbsql_ext_h_ */

1019
src/inc/dbsql_int.in Normal file

File diff suppressed because it is too large Load diff

126
src/inc/debug.h Normal file
View file

@ -0,0 +1,126 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1998-2004
* Sleepycat Software. All rights reserved.
*
* $Id: debug.h 7 2007-02-03 13:34:17Z gburd $
*/
#ifndef _DBSQL_DEBUG_H_
#define _DBSQL_DEBUG_H_
#if defined(__cplusplus)
extern "C" {
#endif
/*
* Turn on additional error checking in gcc 3.X.
*/
#if !defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
#define __attribute__(s)
#endif
/*
* When running with #DIAGNOSTIC defined, we smash memory and do memory
* guarding with a special byte value.
*/
#define CLEAR_BYTE 0xdb
#define GUARD_BYTE 0xdc
/*
* DBSQL assertions.
*
* Use __STDC__ rather than STDC_HEADERS, the #e construct is ANSI C specific.
*/
#if defined(__STDC__) && defined(DIAGNOSTIC)
#define DBSQL_ASSERT(e) ((e) ? (void)0 :__dbsql_assert(#e, __FILE__, __LINE__))
#else
#define DBSQL_ASSERT(e)
#endif
/*
* "Shut that bloody compiler up!"
*
* Unused, or not-used-yet variable. We need to write and then read the
* variable, some compilers are too bloody clever by half.
*/
#define COMPQUIET(n, v) \
(n) = (v); \
(n) = (n)
/*
* Purify and other run-time tools complain about uninitialized reads/writes
* of structure fields whose only purpose is padding, as well as when heap
* memory that was never initialized is written to disk.
*/
#ifdef UMRW
#define UMRW_SET(v) (v) = 0
#else
#define UMRW_SET(v)
#endif
/*
* Error message handling. Use a macro instead of a function because va_list
* references to variadic arguments cannot be reset to the beginning of the
* variadic argument list (and then rescanned), by functions other than the
* original routine that took the variadic list of arguments.
*/
#if defined(STDC_HEADERS) || defined(__cplusplus)
#define DBSQL_REAL_ERR(dbp, error, error_set, stderr_default, fmt) { \
va_list ap; \
\
/* Call the user's callback function, if specified. */ \
va_start(ap, fmt); \
if ((dbp) != NULL && (dbp)->dbsql_errcall != NULL) \
__dbsql_errcall(dbp, error, error_set, fmt, ap); \
va_end(ap); \
\
/* Write to the user's file descriptor, if specified. */ \
va_start(ap, fmt); \
if ((dbp) != NULL && (dbp)->dbsql_errfile != NULL) \
__dbsql_errfile(dbp, error, error_set, fmt, ap); \
va_end(ap); \
\
/* \
* If we have a default and we didn't do either of the above, \
* write to the default. \
*/ \
va_start(ap, fmt); \
if ((stderr_default) && ((dbp) == NULL || \
((dbp)->dbsql_errcall == NULL && (dbp)->dbsql_errfile == NULL)))\
__dbsql_errfile(dbp, error, error_set, fmt, ap); \
va_end(ap); \
}
#else
#define DBSQL_REAL_ERR(dbp, error, error_set, stderr_default, fmt) { \
va_list ap; \
\
/* Call the user's callback function, if specified. */ \
va_start(ap); \
if ((dbp) != NULL && (dbp)->dbsql_errcall != NULL) \
__dbsql_errcall(dbp, error, error_set, fmt, ap); \
va_end(ap); \
\
/* Write to the user's file descriptor, if specified. */ \
va_start(ap); \
if ((dbp) != NULL && (dbp)->dbsql_errfile != NULL) \
__dbsql_errfile(dbp, error, error_set, fmt, ap); \
va_end(ap); \
\
/* \
* If we have a default and we didn't do either of the above, \
* write to the default. \
*/ \
va_start(ap); \
if ((stderr_default) && ((dbp) == NULL || \
((dbp)->dbsql_errcall == NULL && (dbp)->dbsql_errfile == NULL)))\
__dbsql_errfile(dbp, error, error_set, fmt, ap); \
va_end(ap); \
}
#endif
#if defined(__cplusplus)
}
#endif
#endif /* !_DBSQL_DEBUG_H_ */

27
src/inc/globals.h Normal file
View file

@ -0,0 +1,27 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Sleepycat Software. All rights reserved.
*
* $Id: globals.h 7 2007-02-03 13:34:17Z gburd $
*/
/*******************************************************
* Global variables.
*
* Held in a single structure to minimize the name-space
* pollution.
*******************************************************/
#ifdef HAVE_VXWORKS
#include "semLib.h"
#endif
typedef struct __dbsql_globals {
const char *encoding;
int dbseq_has_wrapped;
} DBSQL_GLOBALS;
extern DBSQL_GLOBALS __dbsql_global_values;
#define DBSQL_GLOBAL(v) __dbsql_global_values.v

189
src/inc/hash.h Normal file
View file

@ -0,0 +1,189 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: hash.h 7 2007-02-03 13:34:17Z gburd $
*/
/*
* Copyright (c) 1990-2004
* Sleepycat Software. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the DB software and any
* accompanying software that uses the DB software. The source code
* must either be included in the distribution or be available for no
* more than the cost of distribution plus a nominal fee, and must be
* freely redistributable under reasonable conditions. For an
* executable file, complete source code means the source code for all
* modules it contains. It does not include source code for modules or
* files that typically accompany the major components of the operating
* system on which the executable file runs.
*
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1990, 1993, 1994, 1995
*The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1995, 1996
*The President and Fellows of Harvard University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions
*/
#ifndef _DBSQL_HASH_H_
#define _DBSQL_HASH_H_
/*
* This is the header file for the generic hash-table implemenation.
*/
#if defined(__cplusplus)
extern "C" {
#endif
/* Forward declarations of structures. */
typedef struct __hash hash_t;
typedef struct __hash_ele hash_ele_t;
/*
* A complete hash table is an instance of the following structure.
* The internals of this structure are intended to be opaque -- client
* code should not attempt to access or modify the fields of this structure
* directly. Change this structure only by using the routines below.
* However, many of the "procedures" and "functions" for modifying and
* accessing this structure are really macros, so we can't really make
* this structure opaque.
*/
struct __hash {
char keyClass; /* DBSQL_HASH_INT, _POINTER, _STRING, _BINARY */
char copyKey; /* True if copy of key made on insert */
int count; /* Number of entries in this table */
hash_ele_t *first;/* The first element of the array */
int htsize; /* Number of buckets in the hash table */
struct _ht { /* the hash table */
int count; /* Number of entries with this hash */
hash_ele_t *chain; /* Pointer to first entry with this hash */
} *ht;
};
/*
* Each element in the hash table is an instance of the following
* structure. All elements are stored on a single doubly-linked list.
*
* Again, this structure is intended to be opaque, but it can't really
* be opaque because it is used by macros.
*/
struct __hash_ele {
hash_ele_t *next, *prev; /* Next and previous elements in the table */
void *data; /* Data associated with this element */
void *pKey; int nKey; /* Key associated with this element */
};
/*
* There are 4 different modes of operation for a hash table:
*
* DBSQL_HASH_INT nKey is used as the key and pKey is ignored.
*
* DBSQL_HASH_STRING pKey points to a string that is nKey bytes long
* (including the null-terminator, if any). Case
* is ignored in comparisons.
*
* DBSQL_HASH_BINARY pKey points to binary data nKey bytes long.
* __os_memcmp() is used to compare keys.
*
* A copy of the key is made for DBSQL_HASH_STRING and DBSQL_HASH_BINARY
* if the copyKey parameter to HashInit is 1.
*/
#define DBSQL_HASH_INT 1
#define DBSQL_HASH_STRING 3
#define DBSQL_HASH_BINARY 4
/*
* Macros for looping over all elements of a hash table. The idiom is
* like this:
*
* hash_t h;
* hash_ele_t *p;
* ...
* for(p=__hash_first(&h); p; p=__hash_next(p)){
* SomeStructure *pData = __hash_data(p);
* // do something with pData
* }
*/
#define __hash_first(H) ((H)->first)
#define __hash_next(E) ((E)->next)
#define __hash_data(E) ((E)->data)
#define __hash_key(E) ((E)->pKey)
#define __hash_keysize(E) ((E)->nKey)
/*
* Number of entries in a hash table
*/
#define __hash_count(H) ((H)->count)
#if defined(__cplusplus)
}
#endif
#endif /* !_DBSQL_HASH_H_ */

14
src/inc/os_ext.h Normal file
View file

@ -0,0 +1,14 @@
/* DO NOT EDIT: automatically built by dist/s_include. */
#ifndef _os_ext_h_
#define _os_ext_h_
#if defined(__cplusplus)
extern "C" {
#endif
int __os_jtime __P((double *));
#if defined(__cplusplus)
}
#endif
#endif /* !_os_ext_h_ */

564
src/inc/queue.h Normal file
View file

@ -0,0 +1,564 @@
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
* $FreeBSD: src/sys/sys/queue.h,v 1.54 2002/08/05 05:18:43 alfred Exp $
*/
#ifndef _DB_QUEUE_H_
#define _DB_QUEUE_H_
#if defined(__cplusplus)
extern "C" {
#endif
/*
* This file defines four types of data structures: singly-linked lists,
* singly-linked tail queues, lists and tail queues.
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A singly-linked tail queue is headed by a pair of pointers, one to the
* head of the list and the other to the tail of the list. The elements are
* singly linked for minimum space and pointer manipulation overhead at the
* expense of O(n) removal for arbitrary elements. New elements can be added
* to the list after an existing element, at the head of the list, or at the
* end of the list. Elements being removed from the head of the tail queue
* should use the explicit macro for this purpose for optimum efficiency.
* A singly-linked tail queue may only be traversed in the forward direction.
* Singly-linked tail queues are ideal for applications with large datasets
* and few or no removals or for implementing a FIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* For details on the use of these macros, see the queue(3) manual page.
*
*
* SLIST LIST STAILQ TAILQ
* _HEAD + + + +
* _HEAD_INITIALIZER + + + +
* _ENTRY + + + +
* _INIT + + + +
* _EMPTY + + + +
* _FIRST + + + +
* _NEXT + + + +
* _PREV - - - +
* _LAST - - + +
* _FOREACH + + + +
* _FOREACH_REVERSE - - - +
* _INSERT_HEAD + + + +
* _INSERT_BEFORE - + - +
* _INSERT_AFTER + + + +
* _INSERT_TAIL - - + +
* _CONCAT - - + +
* _REMOVE_HEAD + - + -
* _REMOVE + + + +
*
*/
/*
* XXX
* We #undef all of the macros because there are incompatible versions of this
* file and these macros on various systems. What makes the problem worse is
* they are included and/or defined by system include files which we may have
* already loaded into Berkeley DB before getting here. For example, FreeBSD's
* <rpc/rpc.h> includes its system <sys/queue.h>, and VxWorks UnixLib.h defines
* several of the LIST_XXX macros. Visual C.NET 7.0 also defines some of these
* same macros in Vc7\PlatformSDK\Include\WinNT.h. Make sure we use ours.
*/
#undef LIST_EMPTY
#undef LIST_ENTRY
#undef LIST_FIRST
#undef LIST_FOREACH
#undef LIST_HEAD
#undef LIST_HEAD_INITIALIZER
#undef LIST_INIT
#undef LIST_INSERT_AFTER
#undef LIST_INSERT_BEFORE
#undef LIST_INSERT_HEAD
#undef LIST_NEXT
#undef LIST_REMOVE
#undef QMD_TRACE_ELEM
#undef QMD_TRACE_HEAD
#undef QUEUE_MACRO_DEBUG
#undef SLIST_EMPTY
#undef SLIST_ENTRY
#undef SLIST_FIRST
#undef SLIST_FOREACH
#undef SLIST_FOREACH_PREVPTR
#undef SLIST_HEAD
#undef SLIST_HEAD_INITIALIZER
#undef SLIST_INIT
#undef SLIST_INSERT_AFTER
#undef SLIST_INSERT_HEAD
#undef SLIST_NEXT
#undef SLIST_REMOVE
#undef SLIST_REMOVE_HEAD
#undef STAILQ_CONCAT
#undef STAILQ_EMPTY
#undef STAILQ_ENTRY
#undef STAILQ_FIRST
#undef STAILQ_FOREACH
#undef STAILQ_HEAD
#undef STAILQ_HEAD_INITIALIZER
#undef STAILQ_INIT
#undef STAILQ_INSERT_AFTER
#undef STAILQ_INSERT_HEAD
#undef STAILQ_INSERT_TAIL
#undef STAILQ_LAST
#undef STAILQ_NEXT
#undef STAILQ_REMOVE
#undef STAILQ_REMOVE_HEAD
#undef STAILQ_REMOVE_HEAD_UNTIL
#undef TAILQ_CONCAT
#undef TAILQ_EMPTY
#undef TAILQ_ENTRY
#undef TAILQ_FIRST
#undef TAILQ_FOREACH
#undef TAILQ_FOREACH_REVERSE
#undef TAILQ_HEAD
#undef TAILQ_HEAD_INITIALIZER
#undef TAILQ_INIT
#undef TAILQ_INSERT_AFTER
#undef TAILQ_INSERT_BEFORE
#undef TAILQ_INSERT_HEAD
#undef TAILQ_INSERT_TAIL
#undef TAILQ_LAST
#undef TAILQ_NEXT
#undef TAILQ_PREV
#undef TAILQ_REMOVE
#undef TRACEBUF
#undef TRASHIT
#define QUEUE_MACRO_DEBUG 0
#if QUEUE_MACRO_DEBUG
/* Store the last 2 places the queue element or head was altered */
struct qm_trace {
char * lastfile;
int lastline;
char * prevfile;
int prevline;
};
#define TRACEBUF struct qm_trace trace;
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
#define QMD_TRACE_HEAD(head) do { \
(head)->trace.prevline = (head)->trace.lastline; \
(head)->trace.prevfile = (head)->trace.lastfile; \
(head)->trace.lastline = __LINE__; \
(head)->trace.lastfile = __FILE__; \
} while (0)
#define QMD_TRACE_ELEM(elem) do { \
(elem)->trace.prevline = (elem)->trace.lastline; \
(elem)->trace.prevfile = (elem)->trace.lastfile; \
(elem)->trace.lastline = __LINE__; \
(elem)->trace.lastfile = __FILE__; \
} while (0)
#else
#define QMD_TRACE_ELEM(elem)
#define QMD_TRACE_HEAD(head)
#define TRACEBUF
#define TRASHIT(x)
#endif /* QUEUE_MACRO_DEBUG */
/*
* Singly-linked List declarations.
*/
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List functions.
*/
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_FOREACH(var, head, field) \
for ((var) = SLIST_FIRST((head)); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
for ((varp) = &SLIST_FIRST((head)); \
((var) = *(varp)) != NULL; \
(varp) = &SLIST_NEXT((var), field))
#define SLIST_INIT(head) do { \
SLIST_FIRST((head)) = NULL; \
} while (0)
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
SLIST_NEXT((slistelm), field) = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
SLIST_FIRST((head)) = (elm); \
} while (0)
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_REMOVE(head, elm, type, field) do { \
if (SLIST_FIRST((head)) == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = SLIST_FIRST((head)); \
while (SLIST_NEXT(curelm, field) != (elm)) \
curelm = SLIST_NEXT(curelm, field); \
SLIST_NEXT(curelm, field) = \
SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
} \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0)
/*
* Singly-linked Tail queue declarations.
*/
#define STAILQ_HEAD(name, type) \
struct name { \
struct type *stqh_first;/* first element */ \
struct type **stqh_last;/* addr of last next element */ \
}
#define STAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).stqh_first }
#define STAILQ_ENTRY(type) \
struct { \
struct type *stqe_next; /* next element */ \
}
/*
* Singly-linked Tail queue functions.
*/
#define STAILQ_CONCAT(head1, head2) do { \
if (!STAILQ_EMPTY((head2))) { \
*(head1)->stqh_last = (head2)->stqh_first; \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_INIT((head2)); \
} \
} while (0)
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
#define STAILQ_FIRST(head) ((head)->stqh_first)
#define STAILQ_FOREACH(var, head, field) \
for ((var) = STAILQ_FIRST((head)); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_NEXT((tqelm), field) = (elm); \
} while (0)
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_FIRST((head)) = (elm); \
} while (0)
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
STAILQ_NEXT((elm), field) = NULL; \
*(head)->stqh_last = (elm); \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? \
NULL : \
((struct type *) \
((char *)((head)->stqh_last) - __offsetof(struct type, field))))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_REMOVE(head, elm, type, field) do { \
if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = STAILQ_FIRST((head)); \
while (STAILQ_NEXT(curelm, field) != (elm)) \
curelm = STAILQ_NEXT(curelm, field); \
if ((STAILQ_NEXT(curelm, field) = \
STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
} \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
/*
* List declarations.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List functions.
*/
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_FOREACH(var, head, field) \
for ((var) = LIST_FIRST((head)); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_INIT(head) do { \
LIST_FIRST((head)) = NULL; \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
LIST_NEXT((listelm), field)->field.le_prev = \
&LIST_NEXT((elm), field); \
LIST_NEXT((listelm), field) = (elm); \
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
LIST_NEXT((elm), field) = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
LIST_FIRST((head)) = (elm); \
(elm)->field.le_prev = &LIST_FIRST((head)); \
} while (0)
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_REMOVE(elm, field) do { \
if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
} while (0)
/*
* Tail queue declarations.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
TRACEBUF \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
TRACEBUF \
}
/*
* Tail queue functions.
*/
#define TAILQ_CONCAT(head1, head2, field) do { \
if (!TAILQ_EMPTY(head2)) { \
*(head1)->tqh_last = (head2)->tqh_first; \
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
(head1)->tqh_last = (head2)->tqh_last; \
TAILQ_INIT((head2)); \
QMD_TRACE_HEAD(head); \
QMD_TRACE_HEAD(head2); \
} \
} while (0)
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \
QMD_TRACE_HEAD(head); \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
TAILQ_NEXT((elm), field)->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else { \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
QMD_TRACE_HEAD(head); \
} \
TAILQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
QMD_TRACE_ELEM(&(elm)->field); \
QMD_TRACE_ELEM(&listelm->field); \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
TAILQ_NEXT((elm), field) = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
QMD_TRACE_ELEM(&(elm)->field); \
QMD_TRACE_ELEM(&listelm->field); \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
TAILQ_FIRST((head))->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
QMD_TRACE_HEAD(head); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
TAILQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
QMD_TRACE_HEAD(head); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_REMOVE(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field)) != NULL) \
TAILQ_NEXT((elm), field)->field.tqe_prev = \
(elm)->field.tqe_prev; \
else { \
(head)->tqh_last = (elm)->field.tqe_prev; \
QMD_TRACE_HEAD(head); \
} \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
TRASHIT((elm)->field.tqe_next); \
TRASHIT((elm)->field.tqe_prev); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#if defined(__cplusplus)
}
#endif
#endif /* !_DB_QUEUE_H_ */

33
src/inc/random.h Normal file
View file

@ -0,0 +1,33 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2004
* Sleepycat Software. All rights reserved.
*
* $Id: random.h 7 2007-02-03 13:34:17Z gburd $
*/
#ifndef _LRAND48_R_H_
#define _LRAND48_R_H_
/*
* A re-entrant version of a random number generator. This
* random number generator is based on the RC4 algorithm.
*/
#if defined(__cplusplus)
extern "C" {
#endif
#ifndef HAVE_SRAND48_R
struct drand48_data {
int init_p; /* True if initialized */
int i, j; /* State variables */
int s[256]; /* State variables */
};
#endif
#if defined(__cplusplus)
}
#endif
#endif /* !_SRAND48_R_H_ */

111
src/inc/str.h Normal file
View file

@ -0,0 +1,111 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: str.h 7 2007-02-03 13:34:17Z gburd $
*/
/*
* Copyright (c) 1990-2004
* Sleepycat Software. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the DB software and any
* accompanying software that uses the DB software. The source code
* must either be included in the distribution or be available for no
* more than the cost of distribution plus a nominal fee, and must be
* freely redistributable under reasonable conditions. For an
* executable file, complete source code means the source code for all
* modules it contains. It does not include source code for modules or
* files that typically accompany the major components of the operating
* system on which the executable file runs.
*
* THIS SOFTWARE IS PROVIDED BY ORACLE CORPORATION ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE CORPORATION
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1990, 1993, 1994, 1995
*The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1995, 1996
*The President and Fellows of Harvard University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions
*/
#ifndef _DBSQL_STR_H_
#define _DBSQL_STR_H_
#if defined(__cplusplus)
extern "C" {
#endif
/*
* An array to map all upper-case characters into their corresponding
* lower-case character.
*/
extern unsigned char __str_upper_to_lower[];
#if defined(__cplusplus)
}
#endif
#endif /* !_DBSQL_STR_H_ */

88
src/inc/vdbe.h Normal file
View file

@ -0,0 +1,88 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: vdbe.h 7 2007-02-03 13:34:17Z gburd $
*/
#ifndef _VDBE_H_
#define _VDBE_H_
#include <stdio.h>
/*
* This header defines the interface to the virtual database engine
* or VDBE. The VDBE implements an abstract machine that runs a
* simple program to access and modify the underlying database.
*/
#if defined(__cplusplus)
extern "C" {
#endif
/*
* A single VDBE is an opaque structure named "vdbe_t". Only routines
* in the source file vdbe_aux.c are allowed to see the insides
* of this structure.
*/
typedef struct vdbe vdbe_t;
/*
* As SQL is translated into a sequence of instructions to be
* executed by a virtual machine each instruction is an instance
* of the following structure. A single instruction of the virtual
* machine has an opcode and as many as three operands.
*/
struct vdbe_op {
int opcode; /* What operation to perform */
int p1; /* First operand */
int p2; /* Second parameter (often the jump destination) */
char *p3; /* Third parameter */
int p3type; /* P3_STATIC, P3_DYNAMIC or P3_POINTER */
#ifdef VDBE_PROFILE
int cnt; /* Number of times this instruction was executed */
long long cycles; /* Total time spend executing this instruction */
#endif
};
typedef struct vdbe_op vdbe_op_t;
/*
** Allowed values of vdbe_op_t.p3type
*/
#define P3_NOTUSED 0 /* The P3 parameter is not used */
#define P3_DYNAMIC (-1) /* Pointer to a string obtained from __os_calloc() */
#define P3_STATIC (-2) /* Pointer to a static string */
#define P3_POINTER (-3) /* P3 is a pointer to some structure or object */
/*
** The following macro converts a relative address in the p2 field
** of a vdbe_op_t structure into a negative number so that
** __vdbe_add_op_list() knows that the address is relative. Calling
** the macro again restores the address.
*/
#define ADDR(X) (-1-(X))
/*
** The makefile scans the vdbe.c source file and creates the "opcodes.h"
** header file that defines a number for each opcode used by the VDBE.
*/
#include "opcodes.h"
#if defined(__cplusplus)
}
#endif
#endif /* !_VDBE_H_ */

303
src/inc/vdbe_int.h Normal file
View file

@ -0,0 +1,303 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: vdbe_int.h 7 2007-02-03 13:34:17Z gburd $
*/
#ifndef _VDBE_INT_H_
#define _VDBE_INT_H_
#if defined(__cplusplus)
extern "C" {
#endif
/*
* This is the header file for information that is private to the
* VDBE.
*/
/*
* When converting from the native format to the key format and back
* again, in addition to changing the byte order we invert the high-order
* bit of the most significant byte. This causes negative numbers to
* sort before positive numbers in the memcmp() function.
*/
#define KEY_TO_INT(X) (__vdbe_byte_swap(X) ^ 0x80000000)
#define INT_TO_KEY(X) (__vdbe_byte_swap((X) ^ 0x80000000))
/*
* The makefile scans this source file and creates the following
* array of string constants which are the names of all VDBE opcodes.
* This array is defined in a separate source code file named opcode.c
* which is automatically generated by the makefile.
*/
extern char *__opcode_names[];
/*
* Boolean values
*/
typedef unsigned char bool_t;
/*
* The cursor can seek to a btree entry with a particular key, or
* loop over all entries of the btree. You can also insert new
* entries or retrieve the key or data from the entry that the cursor
* is currently pointing to.
*
* Every cursor that the virtual machine has open is represented by an
* instance of the following structure.
*
* If the cursor_t.isTriggerRow flag is set it means that this cursor is
* really a single row that represents the NEW or OLD pseudo-table of
* a row trigger. The data for the row is stored in cursor_t.pData and
* the rowid is in cursor_t.iKey.
*/
struct cursor {
sm_cursor_t *pCursor; /* The cursor structure of the backend */
int lastRecno; /* Last recno from a Next or NextIdx operation */
int nextRowid; /* Next rowid returned by OP_NewRowid */
bool_t recnoIsValid; /* True if lastRecno is valid */
bool_t keyAsData; /* The OP_Column command works on key instead
of data */
bool_t atFirst; /* True if pointing to first entry */
bool_t useRandomRowid;/* Generate new record numbers semi-randomly */
bool_t nullRow; /* True if pointing to a row with no data */
bool_t nextRowidValid;/* True if the nextRowid field is valid */
bool_t pseudoTable; /* This is a NEW or OLD pseudo-tables of a
trigger */
bool_t deferredMoveto;/* A call to __sm_moveto() is needed */
int movetoTarget; /* Argument to the deferred __sm_moveto() */
sm_t *pBt; /* Separate database holding temporary tables */
int nData; /* Number of bytes in pData */
char *pData; /* Data for a NEW or OLD pseudo-table */
int iKey; /* Key for the NEW or OLD pseudo-table row */
};
/*
* A sorter builds a list of elements to be sorted. Each element of
* the list is an instance of the following structure.
*/
typedef struct sorter sorter_t;
struct sorter {
int nKey; /* Number of bytes in the key */
char *zKey; /* The key by which we will sort */
int nData; /* Number of bytes in the data */
char *pData; /* The data associated with this key */
sorter_t *pNext; /* Next in the list */
};
/*
* Number of buckets used for merge-sort.
*/
#define NSORT 30
/*
* Number of bytes of string storage space available to each stack
* layer without having to malloc. NBFS is short for Number of Bytes
* For Strings.
*/
#define NBFS 32
/*
* A single level of the stack or a single memory cell
* is an instance of the following structure.
*/
struct mem {
int i; /* Integer value */
int n; /* Number of characters in string value,
including '\0' */
int flags; /* Some combination of MEM_Null, MEM_Str,
MEM_Dyn, etc. */
/* Allowed values for mem_t.flags */
#define MEM_Null 0x0001 /* Value is NULL */
#define MEM_Str 0x0002 /* Value is a string */
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Dyn 0x0010 /* Need to call __os_free() on mem_t.z */
#define MEM_Static 0x0020 /* mem_t.z points to a static string */
#define MEM_Ephem 0x0040 /* mem_t.z points to an ephemeral string */
#define MEM_Short 0x0080 /* mem_t.z points to mem_t.zShort */
/*
* The following MEM_ value appears only in AggElem.aMem.s.flag fields.
* It indicates that the corresponding AggElem.aMem.z points to a
* aggregate function context that needs to be finalized.
*/
#define MEM_AggCtx 0x0100 /* mem_t.z points to an agg function context */
double r; /* Real value */
char *z; /* String value */
char zShort[NBFS]; /* Space for short strings */
};
typedef struct mem mem_t;
/*
* The "context" argument for a installable function. A pointer to an
* instance of this structure is the first argument to the routines used
* implement the SQL functions.
*
* There is a typedef for this structure in dbsql.h. So all routines,
* even the public interface, can use a pointer to this structure.
* But this file is the only place where the internal details of this
* structure are known.
*
* This structure is defined inside of vdbe.c because it uses substructures
* (mem_t) which are only defined there.
*/
struct __dbsql_func {
func_def_t *pFunc; /* Pointer to function information.
!!! MUST BE FIRST IN STRUCT */
mem_t s; /* The return value is stored here */
void *pAgg; /* Aggregate context */
u_int8_t isError; /* Set to true for an error */
u_int8_t isStep; /* Current in the step function */
int cnt; /* Number of times that the step function
has been called */
};
/*
* An agg_t structure describes an Aggregator. Each agg_t consists of
* zero or more Aggregator elements (agg_elem_t). Each agg_elem_t contains
* a key and one or more values. The values are used in processing
* aggregate functions in a SELECT. The key is used to implement
* the GROUP BY clause of a select.
*/
struct agg {
int nMem; /* Number of values stored in each AggElem */
agg_elem_t *pCurrent; /* The AggElem currently in focus */
hash_ele_t *pSearch; /* The hash element for pCurrent */
hash_t hash; /* Hash table of all aggregate elements */
func_def_t **apFunc; /* Information about aggregate functions */
};
struct agg_elem {
char *zKey; /* The key to this AggElem */
int nKey; /* Number of bytes in the key, including '\0'
at end */
mem_t aMem[1]; /* The values for this AggElem */
};
/*
* A Set structure is used for quick testing to see if a value
* is part of a small set. Sets are used to implement code like
* this:
* x.y IN ('hi','hoo','hum')
*/
typedef struct set set_t;
struct set {
hash_t hash; /* A set is just a hash table */
hash_ele_t *prev; /* Previously accessed hash elemen */
};
/*
* A keylist_t is a bunch of keys into a table. The keylist can
* grow without bound. The keylist stores the ROWIDs of database
* records that need to be deleted or updated.
*/
struct keylist {
int nKey; /* Number of slots in aKey[] */
int nUsed; /* Next unwritten slot in aKey[] */
int nRead; /* Next unread slot in aKey[] */
keylist_t *pNext; /* Next block of keys */
int aKey[1]; /* One or more keys. Extra space allocated
as needed */
};
/*
* An instance of the virtual machine. This structure contains the complete
* state of the virtual machine.
*
* The "sqlvm_t" structure pointer that is returned by dbsql_compile()
* is really a pointer to an instance of this structure.
*/
struct vdbe {
DBSQL *db; /* The whole database */
vdbe_t *pPrev,*pNext; /* Linked list of VDBEs with the same
vdbe_t.db */
FILE *trace; /* Write an execution trace here, if not NULL */
int nOp; /* Number of instructions in the program */
int nOpAlloc; /* Number of slots allocated for aOp[] */
vdbe_op_t *aOp; /* Space to hold the virtual machine's program */
int nLabel; /* Number of labels used */
int nLabelAlloc; /* Number of slots allocated in aLabel[] */
int *aLabel; /* Space to hold the labels */
mem_t *aStack; /* The operand stack, except string values */
mem_t *pTos; /* Top entry in the operand stack */
char **zArgv; /* Text values used by the callback */
char **azColName; /* Becomes the 4th parameter to callbacks */
int nCursor; /* Number of slots in aCsr[] */
cursor_t *aCsr; /* One element of this array for each open
cursor */
sorter_t *pSort; /* A linked list of objects to be sorted */
FILE *pFile; /* At most one open file handler */
int nField; /* Number of file fields */
char **azField; /* Data for each file field */
int nVar; /* Number of entries in azVariable[] */
char **azVar; /* Values for the OP_Variable opcode */
int *anVar; /* Length of each value in azVariable[] */
u_int8_t *abVar; /* TRUE if azVariable[i] needs to be
__os_free()ed */
char *zLine; /* A single line from the input file */
int nLineAlloc; /* Number of spaces allocated for zLine */
int magic; /* Magic number for sanity checking */
int nMem; /* Number of memory locations currently
allocated */
mem_t *aMem; /* The memory locations */
agg_t agg; /* Aggregate information */
int nSet; /* Number of sets allocated */
set_t *aSet; /* An array of sets */
int nCallback; /* Number of callbacks invoked so far */
keylist_t *pList; /* A list of ROWIDs */
int keylistStackDepth; /* The size of the "keylist" stack */
keylist_t **keylistStack; /* The stack used by opcodes ListPush &
ListPop */
int pc; /* The program counter */
int rc; /* Value to return */
unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */
int errorAction; /* Recovery action to do in case of an error */
int undoTransOnError; /* If error, either ROLLBACK or COMMIT */
int inTempTrans; /* True if temp database is transactioned */
int returnStack[100]; /* Return address stack for OP_Gosub &
OP_Return */
int returnDepth; /* Next unused element in returnStack[] */
int nResColumn; /* Number of columns in one row of the result
set */
char **azResColumn; /* Values for one row of result */
int (*xCallback)(void*,int,char**,char**); /* Callback for SELECT
results */
void *pCbArg; /* First argument to xCallback() */
int popStack; /* Pop the stack this much on entry to
__vdbe_exec() */
char *zErrMsg; /* Error message written here */
u_int8_t explain; /* True if EXPLAIN present on SQL command */
#ifdef CONFIG_TEST
u_int32_t search_count; /* The number of OP_MoveTo or the OP_Next
executed */
#endif
};
/*
** The following are allowed values for vdbe_t.magic
*/
#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */
#define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */
#define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */
#define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */
#if defined(__cplusplus)
}
#endif
#endif /* !_VDBE_INT_H_ */

54
src/inc/xvprintf.h Normal file
View file

@ -0,0 +1,54 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: xvprintf.h 7 2007-02-03 13:34:17Z gburd $
*/
#ifndef _XVPRINTF_H_
#define _XVPRINTF_H_
/*
* A printf with some extra formatting features.
*/
#if defined(__cplusplus)
extern "C" {
#endif
/*
* Undefine COMPATIBILITY to make some slight changes in the way things
* work. I think the changes are an improvement, but they are not
* backwards compatible.
*/
/* #define COMPATIBILITY / * Compatible with SUN OS 4.1 */
/*
* This structure is used to store state information about the
* write to memory that is currently in progress.
*/
typedef struct {
char *base; /* A base allocation */
char *text; /* The string collected so far */
int len; /* Length of the string so far */
int amt; /* Amount of space allocated in text */
} xvprintf_t;
#if defined(__cplusplus)
}
#endif
#endif /* !_ _H_ */

4379
src/lemon/lemon.c Normal file

File diff suppressed because it is too large Load diff

688
src/lemon/lempar.c Normal file
View file

@ -0,0 +1,688 @@
/* Driver template for the LEMON parser generator.
** The author disclaims copyright to this source code.
*/
/* First off, code is include which follows the "include" declaration
** in the input file. */
#include <stdio.h>
%%
/* Next is all token values, in a form suitable for use by makeheaders.
** This section will be null unless lemon is run with the -m switch.
*/
/*
** These constants (all generated automatically by the parser generator)
** specify the various kinds of tokens (terminals) that the parser
** understands.
**
** Each symbol here is a terminal symbol in the grammar.
*/
%%
/* Make sure the INTERFACE macro is defined.
*/
#ifndef INTERFACE
# define INTERFACE 1
#endif
/* The next thing included is series of defines which control
** various aspects of the generated parser.
** YYCODETYPE is the data type used for storing terminal
** and nonterminal numbers. "unsigned char" is
** used if there are fewer than 250 terminals
** and nonterminals. "int" is used otherwise.
** YYNOCODE is a number of type YYCODETYPE which corresponds
** to no legal terminal or nonterminal number. This
** number is used to fill in empty slots of the hash
** table.
** YYFALLBACK If defined, this indicates that one or more tokens
** have fall-back values which should be used if the
** original value of the token will not parse.
** YYACTIONTYPE is the data type used for storing terminal
** and nonterminal numbers. "unsigned char" is
** used if there are fewer than 250 rules and
** states combined. "int" is used otherwise.
** ParseTOKENTYPE is the data type used for minor tokens given
** directly to the parser from the tokenizer.
** YYMINORTYPE is the data type used for all minor tokens.
** This is typically a union of many types, one of
** which is ParseTOKENTYPE. The entry in the union
** for base tokens is called "yy0".
** YYSTACKDEPTH is the maximum depth of the parser's stack.
** ParseARG_SDECL A static variable declaration for the %extra_argument
** ParseARG_PDECL A parameter declaration for the %extra_argument
** ParseARG_STORE Code to store %extra_argument into yypParser
** ParseARG_FETCH Code to extract %extra_argument from yypParser
** YYNSTATE the combined number of states.
** YYNRULE the number of rules in the grammar
** YYERRORSYMBOL is the code number of the error symbol. If not
** defined, then do no error processing.
*/
%%
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
/* Next are that tables used to determine what action to take based on the
** current state and lookahead token. These tables are used to implement
** functions that take a state number and lookahead value and return an
** action integer.
**
** Suppose the action integer is N. Then the action is determined as
** follows
**
** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
** token onto the stack and goto state N.
**
** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
**
** N == YYNSTATE+YYNRULE A syntax error has occurred.
**
** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
**
** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
** slots in the yy_action[] table.
**
** The action table is constructed as a single large table named yy_action[].
** Given state S and lookahead X, the action is computed as
**
** yy_action[ yy_shift_ofst[S] + X ]
**
** If the index value yy_shift_ofst[S]+X is out of range or if the value
** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
** and that yy_default[S] should be used instead.
**
** The formula above is for computing the action when the lookahead is
** a terminal symbol. If the lookahead is a non-terminal (as occurs after
** a reduce action) then the yy_reduce_ofst[] array is used in place of
** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
** YY_SHIFT_USE_DFLT.
**
** The following are the tables generated in this section:
**
** yy_action[] A single table containing all actions.
** yy_lookahead[] A table containing the lookahead for each entry in
** yy_action. Used to detect hash collisions.
** yy_shift_ofst[] For each state, the offset into yy_action for
** shifting terminals.
** yy_reduce_ofst[] For each state, the offset into yy_action for
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
*/
%%
#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
/* The next table maps tokens into fallback tokens. If a construct
** like the following:
**
** %fallback ID X Y Z.
**
** appears in the grammer, then ID becomes a fallback token for X, Y,
** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
** but it does not parse, the type of the token is changed to ID and
** the parse is retried before an error is thrown.
*/
#ifdef YYFALLBACK
static const YYCODETYPE yyFallback[] = {
%%
};
#endif /* YYFALLBACK */
/* The following structure represents a single element of the
** parser's stack. Information stored includes:
**
** + The state number for the parser at this level of the stack.
**
** + The value of the token stored at this level of the stack.
** (In other words, the "major" token.)
**
** + The semantic value stored at this level of the stack. This is
** the information used by the action routines in the grammar.
** It is sometimes called the "minor" token.
*/
struct yyStackEntry {
int stateno; /* The state-number */
int major; /* The major token value. This is the code
** number for the token at this stack level */
YYMINORTYPE minor; /* The user-supplied minor token value. This
** is the value of the token */
};
typedef struct yyStackEntry yyStackEntry;
/* The state of the parser is completely contained in an instance of
** the following structure */
struct yyParser {
int yyidx; /* Index of top element in stack */
int yyerrcnt; /* Shifts left before out of the error */
ParseARG_SDECL /* A place to hold %extra_argument */
yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
};
typedef struct yyParser yyParser;
#ifndef NDEBUG
#include <stdio.h>
static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */
#ifndef NDEBUG
/*
** Turn parser tracing on by giving a stream to which to write the trace
** and a prompt to preface each trace message. Tracing is turned off
** by making either argument NULL
**
** Inputs:
** <ul>
** <li> A FILE* to which trace output should be written.
** If NULL, then tracing is turned off.
** <li> A prefix string written at the beginning of every
** line of trace output. If NULL, then tracing is
** turned off.
** </ul>
**
** Outputs:
** None.
*/
void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
yyTraceFILE = TraceFILE;
yyTracePrompt = zTracePrompt;
if( yyTraceFILE==0 ) yyTracePrompt = 0;
else if( yyTracePrompt==0 ) yyTraceFILE = 0;
}
#endif /* NDEBUG */
#ifndef NDEBUG
/* For tracing shifts, the names of all terminals and nonterminals
** are required. The following table supplies these names */
static const char *yyTokenName[] = {
%%
};
#endif /* NDEBUG */
#ifndef NDEBUG
/* For tracing reduce actions, the names of all rules are required.
*/
static const char *yyRuleName[] = {
%%
};
#endif /* NDEBUG */
/*
** This function returns the symbolic name associated with a token
** value.
*/
const char *ParseTokenName(int tokenType){
#ifndef NDEBUG
if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
return yyTokenName[tokenType];
}else{
return "Unknown";
}
#else
return "";
#endif
}
/*
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
** malloc.
**
** Inputs:
** A pointer to the function used to allocate memory.
**
** Outputs:
** A pointer to a parser. This pointer is used in subsequent calls
** to Parse and ParseFree.
*/
void *ParseAlloc(DBSQL *dbp, int (*mallocProc)(DBSQL *, size_t, void *)){
yyParser *pParser = 0;
int rc = (*mallocProc)( dbp, (size_t)sizeof(yyParser), &pParser );
if( rc != ENOMEM && pParser ){
pParser->yyidx = -1;
}
return pParser;
}
/* The following function deletes the value associated with a
** symbol. The symbol can be either a terminal or nonterminal.
** "yymajor" is the symbol code, and "yypminor" is a pointer to
** the value.
*/
static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
switch( yymajor ){
/* Here is inserted the actions which take place when a
** terminal or non-terminal is destroyed. This can happen
** when the symbol is popped from the stack during a
** reduce or during error processing or when a parser is
** being destroyed before it is finished parsing.
**
** Note: during a reduce, the only symbols destroyed are those
** which appear on the RHS of the rule, but which are not used
** inside the C code.
*/
%%
default: break; /* If no destructor action specified: do nothing */
}
}
/*
** Pop the parser's stack once.
**
** If there is a destructor routine associated with the token which
** is popped from the stack, then call it.
**
** Return the major token number for the symbol popped.
*/
static int yy_pop_parser_stack(yyParser *pParser){
YYCODETYPE yymajor;
yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
if( pParser->yyidx<0 ) return 0;
#ifndef NDEBUG
if( yyTraceFILE && pParser->yyidx>=0 ){
fprintf(yyTraceFILE,"%sPopping %s\n",
yyTracePrompt,
yyTokenName[yytos->major]);
}
#endif
yymajor = yytos->major;
yy_destructor( yymajor, &yytos->minor);
pParser->yyidx--;
return yymajor;
}
/*
** Deallocate and destroy a parser. Destructors are all called for
** all stack elements before shutting the parser down.
**
** Inputs:
** <ul>
** <li> A pointer to the parser. This should be a pointer
** obtained from ParseAlloc.
** <li> A pointer to a function used to reclaim memory obtained
** from malloc.
** </ul>
*/
void ParseFree(
DBSQL *dbp,
void *p, /* The parser to be deleted */
void (*freeProc)(DBSQL *, void*) /* Function used to reclaim memory */
){
yyParser *pParser = (yyParser*)p;
if( pParser==0 ) return;
while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
(*freeProc)(dbp, (void*)pParser);
}
/*
** Find the appropriate action for a parser given the terminal
** look-ahead token iLookAhead.
**
** If the look-ahead token is YYNOCODE, then check to see if the action is
** independent of the look-ahead. If it is, return the action, otherwise
** return YY_NO_ACTION.
*/
static int yy_find_shift_action(
yyParser *pParser, /* The parser */
int iLookAhead /* The look-ahead token */
){
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
/* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
i = yy_shift_ofst[stateno];
if( i==YY_SHIFT_USE_DFLT ){
return yy_default[stateno];
}
if( iLookAhead==YYNOCODE ){
return YY_NO_ACTION;
}
i += iLookAhead;
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
#ifdef YYFALLBACK
int iFallback; /* Fallback token */
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
&& (iFallback = yyFallback[iLookAhead])!=0 ){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
}
#endif
return yy_find_shift_action(pParser, iFallback);
}
#endif
return yy_default[stateno];
}else{
return yy_action[i];
}
}
/*
** Find the appropriate action for a parser given the non-terminal
** look-ahead token iLookAhead.
**
** If the look-ahead token is YYNOCODE, then check to see if the action is
** independent of the look-ahead. If it is, return the action, otherwise
** return YY_NO_ACTION.
*/
static int yy_find_reduce_action(
yyParser *pParser, /* The parser */
int iLookAhead /* The look-ahead token */
){
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
i = yy_reduce_ofst[stateno];
if( i==YY_REDUCE_USE_DFLT ){
return yy_default[stateno];
}
if( iLookAhead==YYNOCODE ){
return YY_NO_ACTION;
}
i += iLookAhead;
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
return yy_default[stateno];
}else{
return yy_action[i];
}
}
/*
** Perform a shift action.
*/
static void yy_shift(
yyParser *yypParser, /* The parser to be shifted */
int yyNewState, /* The new state to shift in */
int yyMajor, /* The major token to shift in */
YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */
){
yyStackEntry *yytos;
yypParser->yyidx++;
if( yypParser->yyidx>=YYSTACKDEPTH ){
ParseARG_FETCH;
yypParser->yyidx--;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
}
#endif
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will execute if the parser
** stack every overflows */
%%
ParseARG_STORE; /* Suppress warning about unused %extra_argument var */
return;
}
yytos = &yypParser->yystack[yypParser->yyidx];
yytos->stateno = yyNewState;
yytos->major = yyMajor;
yytos->minor = *yypMinor;
#ifndef NDEBUG
if( yyTraceFILE && yypParser->yyidx>0 ){
int i;
fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
for(i=1; i<=yypParser->yyidx; i++)
fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
fprintf(yyTraceFILE,"\n");
}
#endif
}
/* The following table contains information about every rule that
** is used during the reduce.
*/
static struct {
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
unsigned char nrhs; /* Number of right-hand side symbols in the rule */
} yyRuleInfo[] = {
%%
};
static void yy_accept(yyParser*); /* Forward Declaration */
/*
** Perform a reduce action and the shift that must immediately
** follow the reduce.
*/
static void yy_reduce(
yyParser *yypParser, /* The parser */
int yyruleno /* Number of the rule by which to reduce */
){
int yygoto; /* The next state */
int yyact; /* The next action */
YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
yyStackEntry *yymsp; /* The top of the parser's stack */
int yysize; /* Amount to pop the stack */
ParseARG_FETCH;
yymsp = &yypParser->yystack[yypParser->yyidx];
#ifndef NDEBUG
if( yyTraceFILE && yyruleno>=0
&& yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
yyRuleName[yyruleno]);
}
#endif /* NDEBUG */
switch( yyruleno ){
/* Beginning here are the reduction cases. A typical example
** follows:
** case 0:
** #line <lineno> <grammarfile>
** { ... } // User supplied code
** #line <lineno> <thisfile>
** break;
*/
%%
};
yygoto = yyRuleInfo[yyruleno].lhs;
yysize = yyRuleInfo[yyruleno].nrhs;
yypParser->yyidx -= yysize;
yyact = yy_find_reduce_action(yypParser,yygoto);
if( yyact < YYNSTATE ){
yy_shift(yypParser,yyact,yygoto,&yygotominor);
}else if( yyact == YYNSTATE + YYNRULE + 1 ){
yy_accept(yypParser);
}
}
/*
** The following code executes when the parse fails
*/
static void yy_parse_failed(
yyParser *yypParser /* The parser */
){
ParseARG_FETCH;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
}
#endif
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will be executed whenever the
** parser fails */
%%
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
/*
** The following code executes when a syntax error first occurs.
*/
static void yy_syntax_error(
yyParser *yypParser, /* The parser */
int yymajor, /* The major type of the error token */
YYMINORTYPE yyminor /* The minor type of the error token */
){
ParseARG_FETCH;
#define TOKEN (yyminor.yy0)
%%
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
/*
** The following is executed when the parser accepts
*/
static void yy_accept(
yyParser *yypParser /* The parser */
){
ParseARG_FETCH;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
}
#endif
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will be executed whenever the
** parser accepts */
%%
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
/* The main parser program.
** The first argument is a pointer to a structure obtained from
** "ParseAlloc" which describes the current state of the parser.
** The second argument is the major token number. The third is
** the minor token. The fourth optional argument is whatever the
** user wants (and specified in the grammar) and is available for
** use by the action routines.
**
** Inputs:
** <ul>
** <li> A pointer to the parser (an opaque structure.)
** <li> The major token number.
** <li> The minor token number.
** <li> An option argument of a grammar-specified type.
** </ul>
**
** Outputs:
** None.
*/
void Parse(
void *yyp, /* The parser */
int yymajor, /* The major token code number */
ParseTOKENTYPE yyminor /* The value for the token */
ParseARG_PDECL /* Optional %extra_argument parameter */
){
YYMINORTYPE yyminorunion;
int yyact; /* The parser action. */
int yyendofinput; /* True if we are at the end of input */
int yyerrorhit = 0; /* True if yymajor has invoked an error */
yyParser *yypParser; /* The parser */
/* (re)initialize the parser, if necessary */
yypParser = (yyParser*)yyp;
if( yypParser->yyidx<0 ){
if( yymajor==0 ) return;
yypParser->yyidx = 0;
yypParser->yyerrcnt = -1;
yypParser->yystack[0].stateno = 0;
yypParser->yystack[0].major = 0;
}
yyminorunion.yy0 = yyminor;
yyendofinput = (yymajor==0);
ParseARG_STORE;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
}
#endif
do{
yyact = yy_find_shift_action(yypParser,yymajor);
if( yyact<YYNSTATE ){
yy_shift(yypParser,yyact,yymajor,&yyminorunion);
yypParser->yyerrcnt--;
if( yyendofinput && yypParser->yyidx>=0 ){
yymajor = 0;
}else{
yymajor = YYNOCODE;
}
}else if( yyact < YYNSTATE + YYNRULE ){
yy_reduce(yypParser,yyact-YYNSTATE);
}else if( yyact == YY_ERROR_ACTION ){
int yymx;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
}
#endif
#ifdef YYERRORSYMBOL
/* A syntax error has occurred.
** The response to an error depends upon whether or not the
** grammar defines an error token "ERROR".
**
** This is what we do if the grammar does define ERROR:
**
** * Call the %syntax_error function.
**
** * Begin popping the stack until we enter a state where
** it is legal to shift the error symbol, then shift
** the error symbol.
**
** * Set the error count to three.
**
** * Begin accepting and shifting new tokens. No new error
** processing will occur until three tokens have been
** shifted successfully.
**
*/
if( yypParser->yyerrcnt<0 ){
yy_syntax_error(yypParser,yymajor,yyminorunion);
}
yymx = yypParser->yystack[yypParser->yyidx].major;
if( yymx==YYERRORSYMBOL || yyerrorhit ){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sDiscard input token %s\n",
yyTracePrompt,yyTokenName[yymajor]);
}
#endif
yy_destructor(yymajor,&yyminorunion);
yymajor = YYNOCODE;
}else{
while(
yypParser->yyidx >= 0 &&
yymx != YYERRORSYMBOL &&
(yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
){
yy_pop_parser_stack(yypParser);
}
if( yypParser->yyidx < 0 || yymajor==0 ){
yy_destructor(yymajor,&yyminorunion);
yy_parse_failed(yypParser);
yymajor = YYNOCODE;
}else if( yymx!=YYERRORSYMBOL ){
YYMINORTYPE u2;
u2.YYERRSYMDT = 0;
yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
}
}
yypParser->yyerrcnt = 3;
yyerrorhit = 1;
#else /* YYERRORSYMBOL is not defined */
/* This is what we do if the grammar does not define ERROR:
**
** * Report an error message, and throw away the input token.
**
** * If the input token is $, then fail the parse.
**
** As before, subsequent error messages are suppressed until
** three input tokens have been successfully shifted.
*/
if( yypParser->yyerrcnt<=0 ){
yy_syntax_error(yypParser,yymajor,yyminorunion);
}
yypParser->yyerrcnt = 3;
yy_destructor(yymajor,&yyminorunion);
if( yyendofinput ){
yy_parse_failed(yypParser);
}
yymajor = YYNOCODE;
#endif
}else{
yy_accept(yypParser);
yymajor = YYNOCODE;
}
}while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
return;
}

78
src/os/os_jtime.c Normal file
View file

@ -0,0 +1,78 @@
/*-
* DBSQL - A SQL database engine.
*
* Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to this software. View the full text of the exception in file
* LICENSE_EXCEPTIONS in the directory of this software distribution.
*
* 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
* General Public License for more details.
*
* http://creativecommons.org/licenses/GPL/2.0/
*
* $Id: os_jtime.c 7 2007-02-03 13:34:17Z gburd $
*/
#include "dbsql_config.h"
#if DB_WIN32
#include <winbase.h>
#endif
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdio.h>
#endif
#include "dbsql_int.h"
/*
* The following variable, if set to a now-zero value, become the result
* returned from __os_current_time(). This is used for testing only.
*/
#ifdef CONFIG_TEST
int _fake_current_time = 0;
#endif
/*
* __os_jtime --
* The Julian time in UTC now.
*
* PUBLIC: int __os_jtime __P((double *));
*/
int
__os_jtime(result)
double *result;
{
#ifndef DB_WIN32
time_t t;
time(&t);
*result = t / 86400.0 + 2440587.5;
#else /* DB_WIN32 */
/*
* FILETIME structure is a 64-bit value representing the number of
* 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
*/
FILETIME ft;
double now;
GetSystemTimeAsFileTime(&ft);
now = ((double)ft.dwHighDateTime) * 4294967296.0;
*result = (now + ft.dwLowDateTime) / 864000000000.0 + 2305813.5;
#endif
#ifdef CONFIG_TEST
if (_fake_current_time) {
*result = _fake_current_time / 86400.0 + 2440587.5;
}
#endif
return DBSQL_SUCCESS;
}

25
src/py/LICENSE Normal file
View file

@ -0,0 +1,25 @@
See the LICENSE and LICENSE_EXCEPTION files in the top level DBSQL
distribution directory for license information. This copyright and license
is preserved from the PySqlite2 project which was forked to produce the
PyDbsql API.
------------------------------------------------------------------------------
Copyright (c) 2004 Gerhard Haering
This software is provided 'as-is', without any express or implied warranty. In
no event will the authors be held liable for any damages arising from the use
of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in
a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

9
src/py/MANIFEST.in Normal file
View file

@ -0,0 +1,9 @@
include MANIFEST.in
include README
include LICENSE
include docutilsupport.py
include src/*.h
include doc/*.html
include doc/*.txt
include doc/*.css
include doc/code/*.py

4
src/py/Makefile Normal file
View file

@ -0,0 +1,4 @@
all:
python setup.py -v bdist

7
src/py/README Normal file
View file

@ -0,0 +1,7 @@
This is a fork of the pysqlite2 Python API for SQLite project found at:
http://www.initd.org/tracker/pysqlite/wiki/pysqlite
svn co http://initd.org/svn/pysqlite/pysqlite/trunk/
The branch was started Feb 14, 2007. Changes since then are copyright by
The DBSQL Group, Inc. and not written by Gerhard Haering. Changes to
the pysqlite2 package are periodically examined and integrated.

118
src/py/benchmarks/fetch.py Normal file
View file

@ -0,0 +1,118 @@
# DBSQL - A SQL database engine.
#
# Copyright (C) 2007 The DBSQL Group, Inc. - All rights reserved.
#
# This library 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.1 of the License, or (at your option) any later version.
#
# There are special exceptions to the terms and conditions of the GPL as it
# is applied to this software. View the full text of the exception in file
# LICENSE_EXCEPTIONS in the directory of this software distribution.
#
# 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
# General Public License for more details.
#
# http://creativecommons.org/licenses/GPL/2.0/
#
import time
def yesno(question):
val = raw_input(question + " ")
return val.startswith("y") or val.startswith("Y")
use_dbsql = yesno("Use pydbsql?")
if use_dbsql:
use_custom_types = yesno("Use custom types?")
use_dictcursor = yesno("Use dict cursor?")
use_rowcursor = yesno("Use row cursor?")
else:
use_tuple = yesno("Use rowclass=tuple?")
if use_dbsql:
from dbsql import dbapi2 as dbsql
else:
import dbsql
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
if use_dbsql:
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
class DictCursor(dbsql.Cursor):
def __init__(self, *args, **kwargs):
dbsql.Cursor.__init__(self, *args, **kwargs)
self.row_factory = dict_factory
class RowCursor(dbsql.Cursor):
def __init__(self, *args, **kwargs):
dbsql.Cursor.__init__(self, *args, **kwargs)
self.row_factory = dbsql.Row
def create_db():
if dbsql.version_info > (2, 0):
if use_custom_types:
con = dbsql.connect(":memory:", detect_types=dbsql.PARSE_DECLTYPES|dbsql.PARSE_COLNAMES)
dbsql.register_converter("text", lambda x: "<%s>" % x)
else:
con = dbsql.connect(":memory:")
if use_dictcursor:
cur = con.cursor(factory=DictCursor)
elif use_rowcursor:
cur = con.cursor(factory=RowCursor)
else:
cur = con.cursor()
else:
if use_tuple:
con = dbsql.connect(":memory:")
con.rowclass = tuple
cur = con.cursor()
else:
con = dbsql.connect(":memory:")
cur = con.cursor()
cur.execute("""
create table test(v text, f float, i integer)
""")
return (con, cur)
def test():
row = ("sdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffasfd", 3.14, 42)
l = []
for i in range(1000):
l.append(row)
con, cur = create_db()
if dbsql.version_info > (0, 1):
sql = "insert into test(v, f, i) values (?, ?, ?)"
else:
sql = "insert into test(v, f, i) values (%s, %s, %s)"
for i in range(50):
cur.executemany(sql, l)
cur.execute("select count(*) as cnt from test")
starttime = time.time()
for i in range(50):
cur.execute("select v, f, i from test")
l = cur.fetchall()
endtime = time.time()
print "elapsed:", endtime - starttime
if __name__ == "__main__":
test()

View file

@ -0,0 +1,61 @@
import time
def yesno(question):
val = raw_input(question + " ")
return val.startswith("y") or val.startswith("Y")
use_pydbsql = yesno("Use pydbsql?")
use_autocommit = yesno("Use autocommit?")
use_executemany= yesno("Use executemany?")
if use_pydbsql:
from pydbsql import dbapi2 as dbsql
else:
import dbsql
def create_db():
con = dbsql.connect(":memory:")
if use_autocommit:
if use_pydbsql:
con.isolation_level = None
else:
con.autocommit = True
cur = con.cursor()
cur.execute("""
create table test(v text, f float, i integer)
""")
cur.close()
return con
def test():
row = ("sdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffasfd", 3.14, 42)
l = []
for i in range(1000):
l.append(row)
con = create_db()
cur = con.cursor()
if dbsql.version_info > (2, 0):
sql = "insert into test(v, f, i) values (?, ?, ?)"
else:
sql = "insert into test(v, f, i) values (%s, %s, %s)"
starttime = time.time()
for i in range(50):
if use_executemany:
cur.executemany(sql, l)
else:
for r in l:
cur.execute(sql, r)
endtime = time.time()
print "elapsed", endtime - starttime
cur.execute("select count(*) from test")
print "rows:", cur.fetchone()[0]
if __name__ == "__main__":
test()

Some files were not shown because too many files have changed in this diff Show more