mirror of
https://github.com/mdbtools/mdbtools.git
synced 2025-06-28 15:39:02 +08:00
Compare commits
87 Commits
v1.0.0-bet
...
dev
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c6486ce68c | ||
![]() |
11607108be | ||
![]() |
6ed4188994 | ||
![]() |
b81b1c9271 | ||
![]() |
c5d4d1d4ee | ||
![]() |
7625bfaebf | ||
![]() |
4c4ff13237 | ||
![]() |
2b2ef525c8 | ||
![]() |
3a954c00d4 | ||
![]() |
98d17badc6 | ||
![]() |
997f4ec846 | ||
![]() |
f517db5df0 | ||
![]() |
7e057e3197 | ||
![]() |
bb83142d47 | ||
![]() |
bf77523c1d | ||
![]() |
c423097326 | ||
![]() |
57d9e7a65e | ||
![]() |
6640f9c707 | ||
![]() |
328249a628 | ||
![]() |
0d67eb4c73 | ||
![]() |
633d1c091f | ||
![]() |
1097a48b80 | ||
![]() |
d9025dbf22 | ||
![]() |
0e77b68e76 | ||
![]() |
9aa68a6ba1 | ||
![]() |
f7ae5e3f3c | ||
![]() |
f14fbea093 | ||
![]() |
d54f7b669f | ||
![]() |
0b96ecaff1 | ||
![]() |
9e1ec2a588 | ||
![]() |
ff544c0b76 | ||
![]() |
ab5beff0fa | ||
![]() |
22af793623 | ||
![]() |
ff085816b2 | ||
![]() |
03391fc913 | ||
![]() |
2da65ffdb3 | ||
![]() |
4febc7b5c6 | ||
![]() |
bcad261464 | ||
![]() |
ab9e4088a9 | ||
![]() |
1f88aac676 | ||
![]() |
c3df30837e | ||
![]() |
22c379a611 | ||
![]() |
5946750058 | ||
![]() |
5ddad8660b | ||
![]() |
6de0227a36 | ||
![]() |
b0a1f00113 | ||
![]() |
77ee311eec | ||
![]() |
c04a3fb9a7 | ||
![]() |
ee5834d239 | ||
![]() |
f0d435ecdb | ||
![]() |
c137d64d13 | ||
![]() |
4369721363 | ||
![]() |
30d55a87ef | ||
![]() |
a0e72c5dfa | ||
![]() |
16b2970931 | ||
![]() |
98ef4a1663 | ||
![]() |
92dc91bfe8 | ||
![]() |
9b57c3ff66 | ||
![]() |
d94796d79b | ||
![]() |
dccc88b722 | ||
![]() |
4c61f2d49b | ||
![]() |
036f9b95c6 | ||
![]() |
f4ca6b9e57 | ||
![]() |
f557e6525b | ||
![]() |
fa336fd325 | ||
![]() |
2aea0e2e41 | ||
![]() |
6faf1b8615 | ||
![]() |
ddd1be91a8 | ||
![]() |
41d2a797ab | ||
![]() |
0164b4df1a | ||
![]() |
00d597b6d3 | ||
![]() |
d3eea5f38e | ||
![]() |
d1369407c5 | ||
![]() |
0346f00735 | ||
![]() |
fadd536e2e | ||
![]() |
6a15f6b1e6 | ||
![]() |
f9c11b52cf | ||
![]() |
49ee8272ab | ||
![]() |
f71924dab6 | ||
![]() |
89c7aa27b4 | ||
![]() |
148eed1546 | ||
![]() |
3ad1669b2e | ||
![]() |
05d1b373d5 | ||
![]() |
45dcdbc5a6 | ||
![]() |
0f0ecb0202 | ||
![]() |
00e4437a17 | ||
![]() |
05cb0449db |
85
.github/workflows/build.yml
vendored
85
.github/workflows/build.yml
vendored
@ -1,29 +1,35 @@
|
||||
name: build
|
||||
on: [ push, pull_request ]
|
||||
env:
|
||||
TEST_DATA_URL: https://github.com/mdbtools/mdbtestdata/archive/refs/heads/master.tar.gz
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
compiler: [ clang, gcc, gcc-9, gcc-10 ]
|
||||
compiler: [ clang, gcc, gcc-11, gcc-12 ]
|
||||
iconv: [ enable-iconv, disable-iconv]
|
||||
glib: [ enable-glib, disable-glib ]
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: sudo apt install gettext
|
||||
run: sudo apt install gettext unixodbc gcc-11 gcc-12
|
||||
- uses: actions/checkout@v2
|
||||
- name: Fetch test data
|
||||
run: git clone https://github.com/mdbtools/mdbtestdata.git test
|
||||
run: |
|
||||
rm -rf test
|
||||
mkdir test
|
||||
curl -sSLf "$TEST_DATA_URL" | tar xz --strip-components=1 -C test
|
||||
- name: Autoconf
|
||||
run: autoreconf -i -f
|
||||
- name: Configure
|
||||
run: ./configure --disable-silent-rules --${{ matrix.glib }} --with-unixodbc=/usr
|
||||
run: ./configure --disable-silent-rules --${{ matrix.glib }} --${{ matrix.iconv }} --with-unixodbc=/usr
|
||||
env:
|
||||
CC: ${{ matrix.compiler }}
|
||||
- name: Make
|
||||
run: make
|
||||
- name: CLI tests
|
||||
run: bash -e -x ./test_script.sh
|
||||
run: ./test_script.sh --github
|
||||
- name: SQL tests
|
||||
run: bash -e -x ./test_sql.sh
|
||||
- name: ODBC tests
|
||||
@ -44,24 +50,28 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
compiler: [ clang, gcc ]
|
||||
iconv: [ enable-iconv, disable-iconv]
|
||||
glib: [ enable-glib, disable-glib ]
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: brew install bison gawk automake
|
||||
run: brew install bison gawk automake libtool unixodbc
|
||||
- uses: actions/checkout@v2
|
||||
- name: Fetch test data
|
||||
run: git clone https://github.com/mdbtools/mdbtestdata.git test
|
||||
run: |
|
||||
rm -rf test
|
||||
mkdir test
|
||||
curl -sSLf "$TEST_DATA_URL" | tar xz --strip-components=1 -C test
|
||||
- name: Autoconf
|
||||
run: autoreconf -i -f
|
||||
run: autoreconf -i -f -I $(brew --prefix)/share/gettext/m4
|
||||
- name: Configure
|
||||
run: ./configure --disable-silent-rules --${{ matrix.glib }} --with-unixodbc=/usr/local/opt
|
||||
run: ./configure --disable-silent-rules --${{ matrix.glib }} --${{ matrix.iconv }} --with-unixodbc=/opt/homebrew/opt/unixodbc
|
||||
env:
|
||||
CC: ${{ matrix.compiler }}
|
||||
YACC: /usr/local/opt/bison/bin/bison
|
||||
YACC: /opt/homebrew/opt/bison/bin/bison
|
||||
- name: Make
|
||||
run: make
|
||||
- name: CLI tests
|
||||
run: bash -e -x ./test_script.sh
|
||||
run: ./test_script.sh --github
|
||||
- name: SQL tests
|
||||
run: bash -e -x ./test_sql.sh
|
||||
- name: ODBC tests
|
||||
@ -84,20 +94,23 @@ jobs:
|
||||
compiler: [ clang, gcc ]
|
||||
glib: [ enable-glib, disable-glib ]
|
||||
steps:
|
||||
- name: Remove packages
|
||||
run: brew unlink unixodbc
|
||||
- name: Install packages
|
||||
run: brew install libiodbc bison gawk automake
|
||||
run: brew install bison gawk automake libtool libiodbc
|
||||
- name: Add path
|
||||
run: echo /opt/homebrew/opt/libiodbc/bin >> $GITHUB_PATH
|
||||
- uses: actions/checkout@v2
|
||||
- name: Fetch test data
|
||||
run: git clone https://github.com/mdbtools/mdbtestdata.git test
|
||||
run: |
|
||||
rm -rf test
|
||||
mkdir test
|
||||
curl -sSLf "$TEST_DATA_URL" | tar xz --strip-components=1 -C test
|
||||
- name: Autoconf
|
||||
run: autoreconf -i -f
|
||||
run: autoreconf -i -f -I $(brew --prefix)/share/gettext/m4
|
||||
- name: Configure
|
||||
run: ./configure --disable-silent-rules --${{ matrix.glib }} --with-iodbc=/usr/local/opt
|
||||
run: ./configure --disable-silent-rules --${{ matrix.glib }} --with-iodbc=/opt/homebrew/opt/libiodbc
|
||||
env:
|
||||
CC: ${{ matrix.compiler }}
|
||||
YACC: /usr/local/opt/bison/bin/bison
|
||||
YACC: /opt/homebrew/opt/bison/bin/bison
|
||||
- name: Make
|
||||
run: make
|
||||
- name: ODBC tests
|
||||
@ -106,19 +119,37 @@ jobs:
|
||||
MDBPATH: test/data
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
MSYSTEM: MINGW64
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
iconv: [ enable-iconv, disable-iconv]
|
||||
glib: [ enable-glib, disable-glib ]
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
update: true
|
||||
install: >-
|
||||
autotools
|
||||
base-devel
|
||||
gcc
|
||||
git
|
||||
glib2-devel
|
||||
- uses: actions/checkout@v2
|
||||
- name: Check out test data
|
||||
run: git clone https://github.com/mdbtools/mdbtestdata.git test
|
||||
- name: Fetch test data
|
||||
run: |
|
||||
rm -rf test
|
||||
mkdir test
|
||||
curl -sSLf "$TEST_DATA_URL" | tar xz --strip-components=1 -C test
|
||||
- name: Autoconf
|
||||
run: C:\msys64\usr\bin\bash -c -l 'cd "$GITHUB_WORKSPACE" && autoreconf -i -f'
|
||||
run: autoreconf -i -f
|
||||
- name: Configure
|
||||
run: C:\msys64\usr\bin\bash -c -l 'cd "$GITHUB_WORKSPACE" && ./configure'
|
||||
run: ./configure --${{ matrix.glib }} --${{ matrix.iconv }}
|
||||
- name: Make
|
||||
run: C:\msys64\usr\bin\bash -c -l 'cd "$GITHUB_WORKSPACE" && make'
|
||||
run: make
|
||||
- name: Test
|
||||
run: C:\msys64\usr\bin\bash -c -l 'cd "$GITHUB_WORKSPACE" && bash -e -x ./test_script.sh'
|
||||
run: ./test_script.sh --github
|
||||
- name: SQL Test
|
||||
run: C:\msys64\usr\bin\bash -c -l 'cd "$GITHUB_WORKSPACE" && bash -e -x ./test_sql.sh'
|
||||
run: bash -e -x ./test_sql.sh
|
||||
|
9
.gitignore
vendored
9
.gitignore
vendored
@ -17,14 +17,18 @@ m4/
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
/configure~
|
||||
Makefile.in
|
||||
Makefile
|
||||
doc/*.1
|
||||
INSTALL
|
||||
include/mdbver.h
|
||||
include/mdbtools.h
|
||||
libmdb.pc
|
||||
libmdbsql.pc
|
||||
libtool
|
||||
mdbtools-*.tar.gz
|
||||
mdbtools-*.zip
|
||||
src/extras/mdb-hexdump
|
||||
src/odbc/unittest
|
||||
src/sql/lexer.c
|
||||
@ -51,9 +55,10 @@ src/util/prkkd
|
||||
src/util/prole
|
||||
src/util/prtable
|
||||
src/util/updrow
|
||||
|
||||
/test/
|
||||
/.vscode/
|
||||
## apidocs docs related
|
||||
public/
|
||||
.sass-cache/
|
||||
*.css.map
|
||||
temp-man-pages/
|
||||
|
||||
|
@ -259,7 +259,7 @@ offset_start of memo = (int16*) LVAL_page[offset_num_rows + (row_id * 2) + 2]
|
||||
if (row_id = 0)
|
||||
offset_stop of memo = 2048(jet3) or 4096(jet4)
|
||||
else
|
||||
offset_stop of memo = (int16*) LVAL_page[offset_num_row + (row_id * 2)]
|
||||
offset_stop of memo = (int16*) LVAL_page[offset_num_row + (row_id * 2)] & offset_mask // offset_mask = 0x1fff
|
||||
```
|
||||
|
||||
The length (partial if type 2) for the memo is:
|
||||
|
65
NEWS
65
NEWS
@ -1,33 +1,62 @@
|
||||
Version 1.0.0 (Beta 2)
|
||||
Version 1.0.0
|
||||
=============
|
||||
|
||||
MDB Tools 1.0 includes a number of new features compared to the 0.9 series. The
|
||||
most significant change is that mdbtools.h is now generated at build time, and
|
||||
its internal HAVE_ macros have been removed. This means that it is now safe for
|
||||
clients to compile against mdbtools.h without needing to provide the same
|
||||
HAVE_ICONV and HAVE_GLIB flags that were present when the library was first
|
||||
compiled. For most users, MDB Tools 1.0 will be ABI and API compatible with the
|
||||
0.9 series but see the notes in the "Install" section below.
|
||||
|
||||
The SQL engine has two new operators: ILIKE (case-insensitive pattern matching)
|
||||
and <> (not equals).
|
||||
|
||||
Changes since 0.9.4:
|
||||
|
||||
Build:
|
||||
* Ensure compiler supports thread-local storage
|
||||
|
||||
libmdb:
|
||||
* Copy date formats when cloning handles #326
|
||||
* Restore previous `mdb_register_backend` API
|
||||
* Restore previous `MdbBackend` struct layout
|
||||
|
||||
Version 1.0.0 (Beta 1)
|
||||
=============
|
||||
|
||||
libmdb:
|
||||
* Generate platform-specific `mdbtools.h` at configure-time #316
|
||||
* Ensure compiler supports thread-local storage
|
||||
* Fix `AC_PROG_LEX` warning with autoconf 2.70
|
||||
* Rely on autoconf to define appropriate values of `_XOPEN_SOURCE` and friends
|
||||
* New `--disable-iconv` configure option (falls back to `wcstombs` where possible)
|
||||
* Fix a build error when `./configure` detected iconv, but thought it was not working
|
||||
* Generating the configure script now requires autoconf 2.64 or later
|
||||
|
||||
SQL:
|
||||
* New case-insensitive, Unicode-aware `ILIKE` operator #244
|
||||
Install:
|
||||
* Install `libmdbodbc.so` and `libmdbodbcW.so` into ${libdir}/odbc #315
|
||||
* Do not install `mdb-sql` if SQL support was not built #276
|
||||
* Do not install `libmdbsql.pc` if SQL support was not built
|
||||
|
||||
ODBC:
|
||||
* Install libmdbodbc.so and libmdbodbcW.so into ${libdir}/odbc #315
|
||||
`pkg-config`:
|
||||
* Simplify `--cflags` for libmdb
|
||||
* Provide correct `--cflags` for libmdbsql
|
||||
|
||||
mdb-export:
|
||||
libmdb:
|
||||
* Copy date formats when cloning handles #326
|
||||
* Fix incorrect reading of double values #339 #342
|
||||
* Fix accidental reads of non-index data #335 #343
|
||||
* New `mdb_set_repid_fmt()` for setting the format of Rep IDs (UUIDs) #344
|
||||
|
||||
SQL:
|
||||
* New case-insensitive, Unicode-aware `ILIKE` operator #244
|
||||
* New `<>` (not equal) operator #329
|
||||
* Improved support for comparing floating-point values to integers
|
||||
* Improved support for floating point literals with no fractional digits (e.g. "3.")
|
||||
* Add support for querying Rep IDs
|
||||
|
||||
ODBC:
|
||||
* Format boolean values correctly as `SQL_C_CHAR` #327
|
||||
* Add support for the `SQL_C_WCHAR` (UTF-16) return type #347 #348
|
||||
* The Unicode driver (`libmdbodbcW.so`) no longer uses iconv #332 #333
|
||||
* Add support for older iODBC installations lacking `odbcinst.h`
|
||||
|
||||
`mdb-export`:
|
||||
* Convert table names to lower case when exporting to PostgreSQL #322
|
||||
* Use `CREATE IF NOT EXISTS` when exporting to PostgreSQL #321
|
||||
* Fix issue where byte columns with values > 127 were exported as negative numbers (regression introduced in v0.9.3-beta1) #350
|
||||
|
||||
mdb-hexdump:
|
||||
`mdb-hexdump`:
|
||||
* Deprecate tool
|
||||
|
||||
Version 0.9.4
|
||||
|
27
README.md
27
README.md
@ -74,7 +74,7 @@ First, you must have reasonably current installations of:
|
||||
|
||||
* [libtool](https://www.gnu.org/software/libtool/)
|
||||
* [automake](https://www.gnu.org/software/automake/)
|
||||
* [autoconf](https://www.gnu.org/software/autoconf/) (version >= 2.58)
|
||||
* [autoconf](https://www.gnu.org/software/autoconf/) (version >= 2.64)
|
||||
|
||||
If you want to build the SQL engine, you'll need
|
||||
[bison](https://www.gnu.org/software/bison/) (version >= 3.0) or
|
||||
@ -116,19 +116,26 @@ If you have cloned the Git repository, you will first need to generate the
|
||||
`configure` file (skip this step if you have downloaded a formal release):
|
||||
|
||||
```bash
|
||||
$ autoreconf -i -f
|
||||
autoreconf -i -f
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```bash
|
||||
$ ./configure
|
||||
./configure
|
||||
```
|
||||
|
||||
OR with mingw32 (--disable-shared --enable-static are optional as you knew):
|
||||
|
||||
```bash
|
||||
./configure --host=x86_64-w64-mingw32 --disable-shared --enable-static
|
||||
```
|
||||
|
||||
|
||||
OR for a complete install (requires bison, flex, and unixODBC):
|
||||
|
||||
```bash
|
||||
$ ./configure --with-unixodbc=/usr/local
|
||||
./configure --with-unixodbc=/usr/local
|
||||
```
|
||||
|
||||
By default, MDB Tools is linked against the copy of
|
||||
@ -149,11 +156,13 @@ mutually exclusive.
|
||||
causes the iODBC driver to be built.
|
||||
```
|
||||
|
||||
A list of general options is available in the [INSTALL](./INSTALL) file, and
|
||||
`configure --help` will give you the list of mdbtools specific options.
|
||||
By default, the ODBC driver will be installed as /usr/local/lib/odbc/libmdbodbc.so,
|
||||
with a Unicode-capable driver at /usr/local/lib/odbc/libmdbodbcW.so.
|
||||
|
||||
The command `configure --help` will give you the list of mdbtools specific options.
|
||||
|
||||
```bash
|
||||
$ make
|
||||
make
|
||||
```
|
||||
|
||||
Once MDB Tools has been compiled, libmdb.[so|a] will be in the src/libmdb
|
||||
@ -162,14 +171,14 @@ directory and the utility programs will be in the src/util directory.
|
||||
You can then install (to /usr/local by default) by running the following as root:
|
||||
|
||||
```bash
|
||||
$ make install
|
||||
make install
|
||||
```
|
||||
|
||||
Some systems will also need the ld cache to be updated after installation;
|
||||
You can do that running:
|
||||
|
||||
```bash
|
||||
$ ldconfig
|
||||
ldconfig
|
||||
```
|
||||
|
||||
## Hacking
|
||||
|
32
TODO.md
32
TODO.md
@ -1,34 +1,4 @@
|
||||
TODO
|
||||
----
|
||||
|
||||
### file format:
|
||||
|
||||
- export VBA script
|
||||
- re-examine KKD records for form design (OLE streams?)
|
||||
- write support (understood, not coded)
|
||||
|
||||
### libmdb:
|
||||
|
||||
- Complete the list of datatypes
|
||||
- Straighten out which functions in libmdb are meant to be used and which
|
||||
ones should be static.
|
||||
- Create an API reference for libmdb (maybe some man pages).
|
||||
- Sargs need to support all datatypes
|
||||
- Add support for index scanning when using sargs (partial)
|
||||
- write support
|
||||
|
||||
### utils:
|
||||
|
||||
- need program to unpack VBA script to file (see prole)
|
||||
- Access forms to glade converter ?
|
||||
- need --version flag (done using -M flag on mdb-ver)
|
||||
|
||||
### SQL Engine:
|
||||
|
||||
- Joins
|
||||
- insert/updates
|
||||
- bogus column name in where clause not caught
|
||||
|
||||
### ODBC:
|
||||
|
||||
- many unimplemented funtions
|
||||
See the list of [open issues tagged "enhancement"](https://github.com/mdbtools/mdbtools/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement).
|
||||
|
File diff suppressed because one or more lines are too long
@ -17,8 +17,10 @@ clone_folder: c:\projects\mdbtools
|
||||
|
||||
skip_tags: true
|
||||
|
||||
# Installing packages leads to the error:
|
||||
# Can't locate threads.pm in @INC (you may need to install the threads module)
|
||||
# So disable the SQL tests on this platform for now
|
||||
build_script:
|
||||
- C:\cygwin64\setup-x86_64.exe -q -P bison -P flex -P libiconv-devel
|
||||
- C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && git clone https://github.com/mdbtools/mdbtestdata.git test"
|
||||
- C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && autoreconf -i -f"
|
||||
- C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && ./configure --disable-man --disable-silent-rules"
|
||||
@ -26,4 +28,3 @@ build_script:
|
||||
|
||||
test_script:
|
||||
- C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && ./test_script.sh"
|
||||
- C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && ./test_sql.sh"
|
||||
|
78
configure.ac
78
configure.ac
@ -1,5 +1,5 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT([mdbtools],[1.0.0-beta2],[https://github.com/mdbtools/mdbtools/issues],[],[https://github.com/mdbtools/mdbtools])
|
||||
AC_INIT([mdbtools],[1.0.1],[https://github.com/mdbtools/mdbtools/issues],[],[https://github.com/mdbtools/mdbtools])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_SRCDIR(src/extras/mdb-dump.c)
|
||||
@ -7,17 +7,18 @@ AM_INIT_AUTOMAKE([foreign dist-zip])
|
||||
|
||||
MDBTOOLS_VERSION_MAJOR=1
|
||||
MDBTOOLS_VERSION_MINOR=0
|
||||
MDBTOOLS_VERSION_MICRO=0
|
||||
MDBTOOLS_VERSION_MICRO=1
|
||||
|
||||
# Update these numbers with every release
|
||||
# See https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
VERSION_INFO=4:0:0
|
||||
VERSION_INFO=4:1:1
|
||||
AC_SUBST(VERSION_INFO)
|
||||
AC_SUBST(MDBTOOLS_CFLAGS)
|
||||
|
||||
AM_MAINTAINER_MODE([enable])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
AC_PROG_CC(gcc)
|
||||
AC_PROG_CXX
|
||||
AX_TLS([FOO=bar], AC_MSG_ERROR([$CC does not support thread-local storage. A newer compiler is required.]))
|
||||
@ -25,7 +26,7 @@ dnl Checks for programs.
|
||||
AC_PROG_MAKE_SET
|
||||
m4_pattern_allow([AM_PROG_AR], [AM_PROG_AR])
|
||||
LT_INIT([win32-dll])
|
||||
AC_PROG_LEX
|
||||
AC_PROG_LEX([noyywrap])
|
||||
AC_PROG_YACC
|
||||
|
||||
dnl Checks for header files.
|
||||
@ -37,13 +38,8 @@ AC_CHECK_DECLS([program_invocation_short_name], [], [], [[
|
||||
|
||||
dnl Checks for library functions.
|
||||
VL_LIB_READLINE
|
||||
AC_CHECK_FUNCS(strptime fmemopen gmtime_r reallocf wcstombs_l vasprintf vasnprintf)
|
||||
AC_CHECK_FUNCS(strptime fmemopen gmtime_r reallocf wcstombs_l mbstowcs_l vasprintf vasnprintf)
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
AC_TYPE_SIZE_T
|
||||
|
||||
AM_ICONV
|
||||
AM_GCC_ATTRIBUTE_ALIAS
|
||||
|
||||
dnl Enable large files on 32-bit systems
|
||||
@ -87,13 +83,31 @@ AM_CONDITIONAL(SQL, test x$sql = xtrue)
|
||||
AC_SUBST(SQL)
|
||||
AC_SUBST(LFLAGS)
|
||||
|
||||
CFLAGS="$CFLAGS -Wall -Werror"
|
||||
CFLAGS="$CFLAGS -Wall"
|
||||
LOCALE_T=locale_t
|
||||
AS_CASE([$host],
|
||||
[*mingw*|*cygwin*], [LDFLAGS="$LDFLAGS -no-undefined"], [])
|
||||
[*mingw*], [LDFLAGS="$LDFLAGS -no-undefined" CFLAGS="$CFLAGS -D_spawnv=_spawnv"], [])
|
||||
AC_SUBST(LOCALE_T)
|
||||
|
||||
dnl See if iconv is present and wanted
|
||||
AC_ARG_ENABLE(iconv,
|
||||
AS_HELP_STRING([--disable-iconv], [do not use iconv for character conversions (use locale.h where possible)]),
|
||||
[enable_iconv=$enableval], [enable_iconv=yes])
|
||||
|
||||
HAVE_ICONV_H=0
|
||||
if test "$enable_iconv" = "yes"; then
|
||||
AM_ICONV
|
||||
# Use the "working iconv" test instead of the "iconv" ($am_cv_func_iconv) test
|
||||
# so that our HAVE_ICONV_H substitution variable has the same value as the HAVE_ICONV
|
||||
# C macro
|
||||
if test "$am_func_iconv" = "yes"; then
|
||||
HAVE_ICONV_H=1
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(HAVE_ICONV_H)
|
||||
|
||||
dnl Fuzz testing
|
||||
|
||||
AC_ARG_ENABLE([fuzz-testing], AS_HELP_STRING([--enable-fuzz-testing], ["Enable fuzz testing (requires Clang 6 or later)"]), [
|
||||
AC_ARG_ENABLE([fuzz-testing], AS_HELP_STRING([--enable-fuzz-testing], [enable fuzz testing (requires Clang 6 or later)]), [
|
||||
AC_MSG_CHECKING([whether $CC accepts -fsanitize=fuzzer])
|
||||
tmp_saved_flags=$[]_AC_LANG_PREFIX[]FLAGS
|
||||
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS -fsanitize=fuzzer"
|
||||
@ -139,7 +153,6 @@ if test "$with_iodbc"; then
|
||||
ODBC_CFLAGS=$(iodbc-config --prefix="$with_iodbc" --cflags)
|
||||
ODBC_LIBS=$(iodbc-config --prefix="$with_iodbc" --libs)
|
||||
ODBC_LDFLAGS=""
|
||||
CFLAGS="$CFLAGS -DIODBC"
|
||||
|
||||
OLDLDFLAGS=$LDFLAGS
|
||||
LDFLAGS="$LDFLAGS $ODBC_LIBS"
|
||||
@ -154,8 +167,7 @@ AC_ARG_WITH(unixodbc,
|
||||
if test "$with_unixodbc"; then
|
||||
HAVE_ODBC=true
|
||||
ODBC_CFLAGS="-I$with_unixodbc/include"
|
||||
ODBC_LIBS="-L$with_unixodbc/$libdir"
|
||||
CFLAGS="$CFLAGS -DUNIXODBC"
|
||||
ODBC_LIBS="-L$with_unixodbc/lib"
|
||||
|
||||
dnl SIZEOF_LONG_INT and HAVE_LONG_LONG are required by some versions of unixODBC
|
||||
dnl https://github.com/lurcher/unixODBC/issues/40
|
||||
@ -178,21 +190,24 @@ if test "$with_unixodbc"; then
|
||||
ODBC_LDFLAGS=""])
|
||||
LDFLAGS=$OLDLDFLAGS
|
||||
fi
|
||||
AM_CONDITIONAL([UNIXODBC], test "$with_unixodbc")
|
||||
|
||||
if test "x$HAVE_ODBC" = "xtrue"; then
|
||||
if test "x$sql" != "xtrue" ; then
|
||||
AC_MSG_ERROR([ODBC requires flex and bison for the SQL engine])
|
||||
fi
|
||||
|
||||
OLDCFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS $ODBC_CFLAGS"
|
||||
AC_CHECK_HEADERS(odbcinst.h iodbcinst.h)
|
||||
CFLAGS=$OLDCFLAGS
|
||||
|
||||
AC_SUBST(ODBC_CFLAGS)
|
||||
AC_SUBST(ODBC_LIBS)
|
||||
AC_SUBST(ODBC_LDFLAGS)
|
||||
OPTDIRS="$OPTDIRS odbc"
|
||||
fi
|
||||
|
||||
dnl Conditionally build odbc wide version
|
||||
AM_CONDITIONAL(ICONV, test "$am_cv_func_iconv" = "yes")
|
||||
|
||||
dnl Testing presence of pkg-config
|
||||
AC_MSG_CHECKING([pkg-config m4 macros])
|
||||
if test m4_ifdef([PKG_CHECK_MODULES], [yes], [no]) = yes; then
|
||||
@ -211,10 +226,9 @@ AC_ARG_ENABLE(glib,
|
||||
|
||||
if test "$enable_glib" = "yes"; then
|
||||
GLIB_PACKAGE=glib-2.0
|
||||
PKG_CHECK_MODULES([GLIB], [$GLIB_PACKAGE], HAVE_GLIB=true, HAVE_GLIB=false)
|
||||
PKG_CHECK_MODULES([GLIB], [$GLIB_PACKAGE >= 2.68], HAVE_GLIB=true, HAVE_GLIB=false)
|
||||
if test "x$HAVE_GLIB" = "xtrue"; then
|
||||
GLIB_CFLAGS="$GLIB_CFLAGS -DHAVE_GLIB=1"
|
||||
AC_CHECK_LIB($GLIB_PACKAGE, g_memdup2, [GLIB_CFLAGS="$GLIB_CFLAGS -DHAVE_G_MEMDUP2=1"])
|
||||
AC_SUBST(GLIB_PACKAGE)
|
||||
else
|
||||
enable_glib=no
|
||||
@ -223,22 +237,12 @@ fi
|
||||
AM_CONDITIONAL(FAKE_GLIB, test "x$enable_glib" != "xyes")
|
||||
|
||||
dnl Set up substitution variables
|
||||
if test "$am_cv_func_iconv" = "yes"; then
|
||||
ICONV_INCLUDE_HEADER=iconv.h
|
||||
ICONV_TYPE=iconv_t
|
||||
else
|
||||
ICONV_INCLUDE_HEADER=stdbool.h
|
||||
ICONV_TYPE=[void *]
|
||||
fi
|
||||
AC_SUBST(ICONV_INCLUDE_HEADER)
|
||||
AC_SUBST(ICONV_TYPE)
|
||||
|
||||
if test "$ac_cv_header_xlocale_h" = "yes"; then
|
||||
XLOCALE_INCLUDE_HEADER=xlocale.h
|
||||
HAVE_XLOCALE_H=1
|
||||
else
|
||||
XLOCALE_INCLUDE_HEADER=stdbool.h
|
||||
HAVE_XLOCALE_H=0
|
||||
fi
|
||||
AC_SUBST(XLOCALE_INCLUDE_HEADER)
|
||||
AC_SUBST(HAVE_XLOCALE_H)
|
||||
|
||||
if test "$enable_glib" = "yes"; then
|
||||
GLIB_INCLUDE_HEADER=glib.h
|
||||
@ -319,6 +323,8 @@ if test x$HAVE_ODBC = xtrue; then summary=${bold_green}enabled; else summary=${b
|
||||
AC_MSG_NOTICE([ ODBC : ${summary}${reset}])
|
||||
if test x$enable_glib = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
|
||||
AC_MSG_NOTICE([ GLib : ${summary}${reset}])
|
||||
if test x$enable_iconv = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
|
||||
AC_MSG_NOTICE([ iconv : ${summary}${reset}])
|
||||
if test x$enable_man = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
|
||||
AC_MSG_NOTICE([ man pages : ${summary}${reset}])
|
||||
if test "x$with_bash_completion_dir" != "xno"; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
|
||||
|
@ -1,5 +1,5 @@
|
||||
SHELL = /bin/sh
|
||||
TXT2MAN = ./txt2man
|
||||
TXT2MAN = $(srcdir)/txt2man
|
||||
PRODUCT = MDBTools
|
||||
|
||||
dist_man_MANS =
|
||||
|
@ -9,7 +9,7 @@ SYNOPSIS
|
||||
DESCRIPTION
|
||||
mdb-json is a utility program distributed with MDB Tools.
|
||||
|
||||
It produces a CSV (comma separated value) output for the given table. Such output is suitable for importation into databases or spreadsheets.
|
||||
It produces JSON output for the given table. Such output is suitable for parsing in a variety of languages.
|
||||
|
||||
OPTIONS
|
||||
-D, --date-format fmt Set the date format (see strftime(3) for details).
|
||||
|
@ -117,6 +117,7 @@ typedef struct GOptionContext {
|
||||
#define g_malloc malloc
|
||||
#define g_free free
|
||||
#define g_realloc realloc
|
||||
#define g_memdup2 g_memdup
|
||||
|
||||
#define G_STR_DELIMITERS "_-|> <."
|
||||
|
||||
|
@ -26,10 +26,6 @@
|
||||
* used within mdbtools so they won't be exported to calling programs.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_G_MEMDUP2
|
||||
#define g_memdup2 g_memdup
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -18,9 +18,9 @@
|
||||
#ifndef _mdbtools_h_
|
||||
#define _mdbtools_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#define MDBTOOLS_H_HAVE_ICONV_H @HAVE_ICONV_H@
|
||||
#define MDBTOOLS_H_HAVE_XLOCALE_H @HAVE_XLOCALE_H@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
@ -31,14 +31,24 @@
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
#include <@ICONV_INCLUDE_HEADER@>
|
||||
#include <@XLOCALE_INCLUDE_HEADER@>
|
||||
#include <@GLIB_INCLUDE_HEADER@>
|
||||
|
||||
#if MDBTOOLS_H_HAVE_ICONV_H
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
#if MDBTOOLS_H_HAVE_XLOCALE_H
|
||||
#include <xlocale.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \addtogroup mdbtools
|
||||
* @{
|
||||
*/
|
||||
@ -58,6 +68,15 @@
|
||||
// M$VC see http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc
|
||||
#define MDB_DEPRECATED(type, funcname) type __attribute__((deprecated)) funcname
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <stdlib.h>
|
||||
#ifndef locale_t
|
||||
typedef _locale_t locale_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef @LOCALE_T@ mdb_locale_t;
|
||||
|
||||
enum {
|
||||
MDB_PAGE_DB = 0,
|
||||
MDB_PAGE_DATA,
|
||||
@ -122,6 +141,7 @@ enum {
|
||||
MDB_ISNULL,
|
||||
MDB_NOTNULL,
|
||||
MDB_ILIKE,
|
||||
MDB_NEQ,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@ -146,6 +166,11 @@ enum {
|
||||
MDB_NO_MEMO = 0x0080, /* don't follow memo fields */
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
MDB_BRACES_4_2_2_8, /* "{XXXX-XX-XX-XXXXXXXX}" format */
|
||||
MDB_NOBRACES_4_2_2_2_6, /* "XXXX-XX-XX-XX-XXXXXX" format (matches MS Access ODBC driver) */
|
||||
} MdbUuidFormat;
|
||||
|
||||
#define mdb_is_logical_op(x) (x == MDB_OR || \
|
||||
x == MDB_AND || \
|
||||
x == MDB_NOT )
|
||||
@ -155,6 +180,7 @@ enum {
|
||||
x == MDB_LT || \
|
||||
x == MDB_GTEQ || \
|
||||
x == MDB_LTEQ || \
|
||||
x == MDB_NEQ || \
|
||||
x == MDB_LIKE || \
|
||||
x == MDB_ILIKE || \
|
||||
x == MDB_ISNULL || \
|
||||
@ -287,6 +313,7 @@ typedef struct {
|
||||
size_t bind_size;
|
||||
char date_fmt[64];
|
||||
char shortdate_fmt[64];
|
||||
MdbUuidFormat repid_fmt;
|
||||
const char *boolean_false_value;
|
||||
const char *boolean_true_value;
|
||||
unsigned int num_catalog;
|
||||
@ -299,12 +326,11 @@ typedef struct {
|
||||
char *relationships_values[5];
|
||||
MdbStatistics *stats;
|
||||
GHashTable *backends;
|
||||
@ICONV_TYPE@ iconv_in;
|
||||
@ICONV_TYPE@ iconv_out;
|
||||
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
|
||||
_locale_t locale;
|
||||
#if MDBTOOLS_H_HAVE_ICONV_H
|
||||
iconv_t iconv_in;
|
||||
iconv_t iconv_out;
|
||||
#else
|
||||
locale_t locale;
|
||||
mdb_locale_t locale;
|
||||
#endif
|
||||
} MdbHandle;
|
||||
|
||||
@ -518,7 +544,8 @@ int mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr,
|
||||
void mdb_data_dump(MdbTableDef *table);
|
||||
void mdb_date_to_tm(double td, struct tm *t);
|
||||
void mdb_tm_to_date(struct tm *t, double *td);
|
||||
char *mdb_uuid_to_string(const void *buf, int start);
|
||||
char *mdb_uuid_to_string(const void *buf, int start); /* Uses default MDB_BRACES_4_2_2_8 format */
|
||||
char *mdb_uuid_to_string_fmt(const void *buf, int start, MdbUuidFormat format);
|
||||
int mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr, int *len_ptr);
|
||||
int mdb_rewind_table(MdbTableDef *table);
|
||||
int mdb_fetch_row(MdbTableDef *table);
|
||||
@ -535,6 +562,7 @@ void* mdb_ole_read_full(MdbHandle *mdb, MdbColumn *col, size_t *size);
|
||||
void mdb_set_bind_size(MdbHandle *mdb, size_t bind_size);
|
||||
void mdb_set_date_fmt(MdbHandle *mdb, const char *);
|
||||
void mdb_set_shortdate_fmt(MdbHandle *mdb, const char *);
|
||||
void mdb_set_repid_fmt(MdbHandle *mdb, MdbUuidFormat format);
|
||||
void mdb_set_boolean_fmt_words(MdbHandle *mdb);
|
||||
void mdb_set_boolean_fmt_numbers(MdbHandle *mdb);
|
||||
int mdb_read_row(MdbTableDef *table, unsigned int row);
|
||||
|
@ -12,4 +12,4 @@ Description: core MDB file support library
|
||||
Requires: @GLIB_PACKAGE@
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lmdb
|
||||
Cflags: @MDBTOOLS_CFLAGS@
|
||||
Cflags: -I${includedir}
|
||||
|
@ -12,5 +12,4 @@ Description: libmdb based SQL engine
|
||||
Requires: libmdb
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lmdbsql
|
||||
Cflags:
|
||||
|
||||
Cflags: -I${includedir}
|
||||
|
86
m4/iconv.m4
86
m4/iconv.m4
@ -1,11 +1,18 @@
|
||||
# iconv.m4 serial 19 (gettext-0.18.2)
|
||||
dnl Copyright (C) 2000-2002, 2007-2014, 2016 Free Software Foundation, Inc.
|
||||
# iconv.m4 serial 24
|
||||
dnl Copyright (C) 2000-2002, 2007-2014, 2016-2021 Free Software Foundation,
|
||||
dnl Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_PREREQ([2.64])
|
||||
|
||||
dnl Note: AM_ICONV is documented in the GNU gettext manual
|
||||
dnl <https://www.gnu.org/software/gettext/manual/html_node/AM_005fICONV.html>.
|
||||
dnl Don't make changes that are incompatible with that documentation!
|
||||
|
||||
AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
|
||||
[
|
||||
dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
|
||||
@ -85,8 +92,9 @@ AC_DEFUN([AM_ICONV_LINK],
|
||||
#endif
|
||||
]],
|
||||
[[int result = 0;
|
||||
/* Test against AIX 5.1 bug: Failures are not distinguishable from successful
|
||||
returns. */
|
||||
/* Test against AIX 5.1...7.2 bug: Failures are not distinguishable from
|
||||
successful returns. This is even documented in
|
||||
<https://www.ibm.com/support/knowledgecenter/ssw_aix_72/i_bostechref/iconv.html> */
|
||||
{
|
||||
iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
|
||||
if (cd_utf8_to_88591 != (iconv_t)(-1))
|
||||
@ -167,15 +175,27 @@ AC_DEFUN([AM_ICONV_LINK],
|
||||
#endif
|
||||
/* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
|
||||
provided. */
|
||||
if (/* Try standardized names. */
|
||||
iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
|
||||
{
|
||||
/* Try standardized names. */
|
||||
iconv_t cd1 = iconv_open ("UTF-8", "EUC-JP");
|
||||
/* Try IRIX, OSF/1 names. */
|
||||
&& iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
|
||||
iconv_t cd2 = iconv_open ("UTF-8", "eucJP");
|
||||
/* Try AIX names. */
|
||||
&& iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
|
||||
iconv_t cd3 = iconv_open ("UTF-8", "IBM-eucJP");
|
||||
/* Try HP-UX names. */
|
||||
&& iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
|
||||
iconv_t cd4 = iconv_open ("utf8", "eucJP");
|
||||
if (cd1 == (iconv_t)(-1) && cd2 == (iconv_t)(-1)
|
||||
&& cd3 == (iconv_t)(-1) && cd4 == (iconv_t)(-1))
|
||||
result |= 16;
|
||||
if (cd1 != (iconv_t)(-1))
|
||||
iconv_close (cd1);
|
||||
if (cd2 != (iconv_t)(-1))
|
||||
iconv_close (cd2);
|
||||
if (cd3 != (iconv_t)(-1))
|
||||
iconv_close (cd3);
|
||||
if (cd4 != (iconv_t)(-1))
|
||||
iconv_close (cd4);
|
||||
}
|
||||
return result;
|
||||
]])],
|
||||
[am_cv_func_iconv_works=yes], ,
|
||||
@ -212,8 +232,7 @@ AC_DEFUN([AM_ICONV_LINK],
|
||||
AC_SUBST([LTLIBICONV])
|
||||
])
|
||||
|
||||
dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to
|
||||
dnl avoid warnings like
|
||||
dnl Define AM_ICONV using AC_DEFUN_ONCE, in order to avoid warnings like
|
||||
dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required".
|
||||
dnl This is tricky because of the way 'aclocal' is implemented:
|
||||
dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN.
|
||||
@ -221,22 +240,13 @@ dnl Otherwise aclocal's initial scan pass would miss the macro definition.
|
||||
dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions.
|
||||
dnl Otherwise aclocal would emit many "Use of uninitialized value $1"
|
||||
dnl warnings.
|
||||
m4_define([gl_iconv_AC_DEFUN],
|
||||
m4_version_prereq([2.64],
|
||||
[[AC_DEFUN_ONCE(
|
||||
[$1], [$2])]],
|
||||
[m4_ifdef([gl_00GNULIB],
|
||||
[[AC_DEFUN_ONCE(
|
||||
[$1], [$2])]],
|
||||
[[AC_DEFUN(
|
||||
[$1], [$2])]])]))
|
||||
gl_iconv_AC_DEFUN([AM_ICONV],
|
||||
AC_DEFUN_ONCE([AM_ICONV],
|
||||
[
|
||||
AM_ICONV_LINK
|
||||
if test "$am_cv_func_iconv" = yes; then
|
||||
AC_MSG_CHECKING([for iconv declaration])
|
||||
AC_CACHE_VAL([am_cv_proto_iconv], [
|
||||
AC_COMPILE_IFELSE(
|
||||
AC_CACHE_CHECK([whether iconv is compatible with its POSIX signature],
|
||||
[gl_cv_iconv_nonconst],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <stdlib.h>
|
||||
@ -245,27 +255,29 @@ extern
|
||||
#ifdef __cplusplus
|
||||
"C"
|
||||
#endif
|
||||
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus)
|
||||
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
|
||||
#else
|
||||
size_t iconv();
|
||||
#endif
|
||||
]],
|
||||
[[]])],
|
||||
[am_cv_proto_iconv_arg1=""],
|
||||
[am_cv_proto_iconv_arg1="const"])
|
||||
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
|
||||
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
|
||||
AC_MSG_RESULT([
|
||||
$am_cv_proto_iconv])
|
||||
AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1],
|
||||
[gl_cv_iconv_nonconst=yes],
|
||||
[gl_cv_iconv_nonconst=no])
|
||||
])
|
||||
else
|
||||
dnl When compiling GNU libiconv on a system that does not have iconv yet,
|
||||
dnl pick the POSIX compliant declaration without 'const'.
|
||||
gl_cv_iconv_nonconst=yes
|
||||
fi
|
||||
if test $gl_cv_iconv_nonconst = yes; then
|
||||
iconv_arg1=""
|
||||
else
|
||||
iconv_arg1="const"
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([ICONV_CONST], [$iconv_arg1],
|
||||
[Define as const if the declaration of iconv() needs const.])
|
||||
dnl Also substitute ICONV_CONST in the gnulib generated <iconv.h>.
|
||||
m4_ifdef([gl_ICONV_H_DEFAULTS],
|
||||
[AC_REQUIRE([gl_ICONV_H_DEFAULTS])
|
||||
if test -n "$am_cv_proto_iconv_arg1"; then
|
||||
if test $gl_cv_iconv_nonconst != yes; then
|
||||
ICONV_CONST="const"
|
||||
fi
|
||||
])
|
||||
fi
|
||||
])
|
||||
|
@ -111,7 +111,7 @@ static const MdbBackendType mdb_mysql_types[] = {
|
||||
[MDB_LONGINT] = { .name = "int" },
|
||||
[MDB_MONEY] = { .name = "float" },
|
||||
[MDB_FLOAT] = { .name = "float" },
|
||||
[MDB_DOUBLE] = { .name = "float" },
|
||||
[MDB_DOUBLE] = { .name = "double" },
|
||||
[MDB_DATETIME] = { .name = "datetime" },
|
||||
[MDB_BINARY] = { .name = "blob" },
|
||||
[MDB_TEXT] = { .name = "varchar", .needs_char_length = 1 },
|
||||
@ -294,7 +294,7 @@ mdb_get_colbacktype_string(const MdbColumn *col)
|
||||
const MdbBackendType *type = mdb_get_colbacktype(col);
|
||||
if (!type) {
|
||||
// return NULL;
|
||||
static __thread char buf[16];
|
||||
static TLS char buf[16];
|
||||
snprintf(buf, sizeof(buf), "Unknown_%04x", col->col_type);
|
||||
return buf;
|
||||
}
|
||||
@ -401,7 +401,7 @@ void mdb_init_backends(MdbHandle *mdb)
|
||||
"COMMENT %s",
|
||||
quote_schema_name_rquotes_merge);
|
||||
mdb_register_backend(mdb, "sqlite",
|
||||
MDB_SHEXP_DROPTABLE|MDB_SHEXP_DEFVALUES|MDB_SHEXP_BULK_INSERT,
|
||||
MDB_SHEXP_DROPTABLE|MDB_SHEXP_DEFVALUES|MDB_SHEXP_BULK_INSERT|MDB_SHEXP_INDEXES|MDB_SHEXP_CST_NOTNULL,
|
||||
mdb_sqlite_types, NULL, NULL,
|
||||
"date('now')", "date('now')",
|
||||
"%Y-%m-%d %H:%M:%S",
|
||||
@ -471,8 +471,8 @@ void mdb_register_backend(MdbHandle *mdb, char *backend_name, guint32 capabiliti
|
||||
short_now, long_now,
|
||||
date_fmt, shortdate_fmt,
|
||||
charset_statement,
|
||||
drop_statement,
|
||||
"CREATE TABLE %s\n",
|
||||
drop_statement,
|
||||
constraint_not_empty_statement,
|
||||
column_comment_statement,
|
||||
per_column_comment_statement,
|
||||
@ -571,7 +571,47 @@ mdb_get_index_name(int backend, MdbTableDef *table, MdbIndex *idx)
|
||||
|
||||
return index_name;
|
||||
}
|
||||
/**
|
||||
* mdb_print_pk - print primary key constraint
|
||||
* @output: Where to print the sql
|
||||
* @table: Table to process
|
||||
*/
|
||||
static void
|
||||
mdb_print_pk_if_sqlite(FILE *outfile, MdbTableDef *table)
|
||||
{
|
||||
unsigned int i, j;
|
||||
MdbHandle *mdb = table->entry->mdb;
|
||||
MdbIndex *idx;
|
||||
MdbColumn *col;
|
||||
char *quoted_name;
|
||||
// this is only necessary for sqlite
|
||||
if (strcmp(mdb->backend_name, "sqlite") != 0)
|
||||
return;
|
||||
|
||||
if (table->indices==NULL)
|
||||
mdb_read_indices(table);
|
||||
|
||||
for (i = 0; i < table->num_idxs; i++) {
|
||||
idx = g_ptr_array_index(table->indices, i);
|
||||
if (idx->index_type == 1) {
|
||||
fprintf(outfile, "\t, PRIMARY KEY (");
|
||||
for (j = 0; j < idx->num_keys; j++) {
|
||||
if (j)
|
||||
fprintf(outfile, ", ");
|
||||
col = g_ptr_array_index(table->columns, idx->key_col_num[j] - 1);
|
||||
quoted_name = mdb->default_backend->quote_schema_name(NULL, col->name);
|
||||
quoted_name = mdb_normalise_and_replace(mdb, "ed_name);
|
||||
fprintf(outfile, "%s", quoted_name);
|
||||
if (idx->index_type != 1 && idx->key_col_order[j])
|
||||
/* no DESC for primary keys */
|
||||
fprintf(outfile, " DESC");
|
||||
|
||||
g_free(quoted_name);
|
||||
}
|
||||
fprintf(outfile, ")\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* mdb_print_indexes
|
||||
* @output: Where to print the sql
|
||||
@ -596,12 +636,15 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace)
|
||||
backend = MDB_BACKEND_MYSQL;
|
||||
} else if (!strcmp(mdb->backend_name, "oracle")) {
|
||||
backend = MDB_BACKEND_ORACLE;
|
||||
} else if (!strcmp(mdb->backend_name, "sqlite")) {
|
||||
backend = MDB_BACKEND_SQLITE;
|
||||
} else {
|
||||
fprintf(outfile, "-- Indexes are not implemented for %s\n\n", mdb->backend_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* read indexes */
|
||||
if (table->indices==NULL)
|
||||
mdb_read_indices(table);
|
||||
|
||||
fprintf (outfile, "-- CREATE INDEXES ...\n");
|
||||
@ -613,6 +656,9 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace)
|
||||
idx = g_ptr_array_index (table->indices, i);
|
||||
if (idx->index_type==2)
|
||||
continue;
|
||||
/* Sqlite3 primary keys have to be issued as a table constraint */
|
||||
if (idx->index_type == 1 && backend == MDB_BACKEND_SQLITE)
|
||||
continue;
|
||||
|
||||
index_name = mdb_get_index_name(backend, table, idx);
|
||||
switch (backend) {
|
||||
@ -630,7 +676,10 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace)
|
||||
}
|
||||
|
||||
quoted_name = mdb_normalise_and_replace(mdb, "ed_name);
|
||||
|
||||
if (idx->num_keys == 0) {
|
||||
fprintf(outfile, "-- WARNING: found no keys for index %s - ignored\n", quoted_name);
|
||||
continue;
|
||||
}
|
||||
if (idx->index_type==1) {
|
||||
switch (backend) {
|
||||
case MDB_BACKEND_ORACLE:
|
||||
@ -645,6 +694,7 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace)
|
||||
switch (backend) {
|
||||
case MDB_BACKEND_ORACLE:
|
||||
case MDB_BACKEND_POSTGRES:
|
||||
case MDB_BACKEND_SQLITE:
|
||||
fprintf(outfile, "CREATE");
|
||||
if (idx->flags & MDB_IDX_UNIQUE)
|
||||
fprintf (outfile, " UNIQUE");
|
||||
@ -872,6 +922,10 @@ generate_table_schema(FILE *outfile, MdbCatalogEntry *entry, char *dbnamespace,
|
||||
fprintf (outfile, " (\n");
|
||||
|
||||
table = mdb_read_table (entry);
|
||||
if (!table) {
|
||||
fprintf(stderr, "Error: Table %s does not exist\n", entry->object_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* get the columns */
|
||||
mdb_read_columns(table);
|
||||
@ -964,6 +1018,11 @@ generate_table_schema(FILE *outfile, MdbCatalogEntry *entry, char *dbnamespace,
|
||||
fputs("\n", outfile);
|
||||
} /* for */
|
||||
|
||||
if (export_options & MDB_SHEXP_INDEXES) {
|
||||
// sqlite does not support ALTER TABLE PRIMARY KEY, so we need to place it directly into CREATE TABLE
|
||||
mdb_print_pk_if_sqlite(outfile, table);
|
||||
}
|
||||
|
||||
fputs(")", outfile);
|
||||
if (mdb->default_backend->per_table_comment_statement && export_options & MDB_SHEXP_COMMENTS) {
|
||||
prop_value = mdb_table_get_prop(table, "Description");
|
||||
|
@ -193,7 +193,7 @@ mdb_dump_catalog(MdbHandle *mdb, int obj_type)
|
||||
entry = g_ptr_array_index(mdb->catalog,i);
|
||||
if (obj_type==MDB_ANY || entry->object_type==obj_type) {
|
||||
printf("Type: %-12s Name: %-48s Page: %06lx\n",
|
||||
mdb_get_objtype_string(entry->object_type),
|
||||
mdb_get_objtype_string(entry->object_type) ?: "Unknown",
|
||||
entry->object_name,
|
||||
entry->table_pg);
|
||||
}
|
||||
|
@ -68,6 +68,11 @@ void mdb_set_shortdate_fmt(MdbHandle *mdb, const char *fmt)
|
||||
snprintf(mdb->shortdate_fmt, sizeof(mdb->shortdate_fmt), "%s", fmt);
|
||||
}
|
||||
|
||||
void mdb_set_repid_fmt(MdbHandle *mdb, MdbUuidFormat format)
|
||||
{
|
||||
mdb->repid_fmt = format;
|
||||
}
|
||||
|
||||
void mdb_set_boolean_fmt_numbers(MdbHandle *mdb)
|
||||
{
|
||||
mdb->boolean_false_value = boolean_false_number;
|
||||
@ -946,15 +951,20 @@ mdb_date_to_string(MdbHandle *mdb, const char *fmt, void *buf, int start)
|
||||
}
|
||||
|
||||
char *mdb_uuid_to_string(const void *buf, int pos)
|
||||
{
|
||||
return mdb_uuid_to_string_fmt(buf,pos,MDB_BRACES_4_2_2_8);
|
||||
}
|
||||
|
||||
char *mdb_uuid_to_string_fmt(const void *buf, int pos, MdbUuidFormat format)
|
||||
{
|
||||
const unsigned char *kkd = (const unsigned char *)buf;
|
||||
return g_strdup_printf("{%02X%02X%02X%02X" "-" "%02X%02X" "-" "%02X%02X"
|
||||
"-" "%02X%02X" "%02X%02X%02X%02X%02X%02X}",
|
||||
return g_strdup_printf(format == MDB_BRACES_4_2_2_8
|
||||
? "{%02X%02X%02X%02X" "-" "%02X%02X" "-" "%02X%02X" "-" "%02X%02X%02X%02X%02X%02X%02X%02X}"
|
||||
: "%02X%02X%02X%02X" "-" "%02X%02X" "-" "%02X%02X" "-" "%02X%02X" "-" "%02X%02X%02X%02X%02X%02X",
|
||||
kkd[pos+3], kkd[pos+2], kkd[pos+1], kkd[pos], // little-endian
|
||||
kkd[pos+5], kkd[pos+4], // little-endian
|
||||
kkd[pos+7], kkd[pos+6], // little-endian
|
||||
kkd[pos+8], kkd[pos+9], // big-endian
|
||||
|
||||
kkd[pos+10], kkd[pos+11],
|
||||
kkd[pos+12], kkd[pos+13],
|
||||
kkd[pos+14], kkd[pos+15]); // big-endian
|
||||
@ -999,7 +1009,7 @@ char *mdb_col_to_string(MdbHandle *mdb, void *buf, int start, int datatype, int
|
||||
|
||||
switch (datatype) {
|
||||
case MDB_BYTE:
|
||||
text = g_strdup_printf("%hhd", mdb_get_byte(buf, start));
|
||||
text = g_strdup_printf("%hhu", mdb_get_byte(buf, start));
|
||||
break;
|
||||
case MDB_INT:
|
||||
text = g_strdup_printf("%hd",
|
||||
@ -1046,7 +1056,7 @@ char *mdb_col_to_string(MdbHandle *mdb, void *buf, int start, int datatype, int
|
||||
text = mdb_money_to_string(mdb, start);
|
||||
break;
|
||||
case MDB_REPID:
|
||||
text = mdb_uuid_to_string(buf, start);
|
||||
text = mdb_uuid_to_string_fmt(buf, start, mdb->repid_fmt);
|
||||
break;
|
||||
default:
|
||||
/* shouldn't happen. bools are handled specially
|
||||
|
@ -18,7 +18,6 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include "mdbfakeglib.h"
|
||||
|
||||
#include <stddef.h>
|
||||
@ -256,7 +255,8 @@ gchar *g_locale_to_utf8(const gchar *opsysstring, size_t len,
|
||||
mbstowcs(utf16, opsysstring, wlen+1);
|
||||
gchar *utf8 = malloc(3*len+1);
|
||||
gchar *dst = utf8;
|
||||
for (size_t i=0; i<len; i++) {
|
||||
size_t i;
|
||||
for (i=0; i<len; i++) {
|
||||
// u >= 0x10000 requires surrogate pairs, ignore
|
||||
dst += g_unichar_to_utf8(utf16[i], dst);
|
||||
}
|
||||
@ -333,7 +333,8 @@ void g_hash_table_insert(GHashTable *table, void *key, void *value) {
|
||||
|
||||
gboolean g_hash_table_remove(GHashTable *table, gconstpointer key) {
|
||||
int found = 0;
|
||||
for (guint i=0; i<table->array->len; i++) {
|
||||
guint i;
|
||||
for (i=0; i<table->array->len; i++) {
|
||||
MyNode *node = g_ptr_array_index(table->array, i);
|
||||
if (found) {
|
||||
table->array->pdata[i-1] = table->array->pdata[i];
|
||||
@ -399,7 +400,8 @@ void g_ptr_array_add(GPtrArray *array, void *entry) {
|
||||
|
||||
gboolean g_ptr_array_remove(GPtrArray *array, gpointer data) {
|
||||
int found = 0;
|
||||
for (guint i=0; i<array->len; i++) {
|
||||
guint i;
|
||||
for (i=0; i<array->len; i++) {
|
||||
if (found) {
|
||||
array->pdata[i-1] = array->pdata[i];
|
||||
} else if (!found && array->pdata[i] == data) {
|
||||
|
@ -130,6 +130,7 @@ static MdbHandle *mdb_handle_from_stream(FILE *stream, MdbFileFlags flags) {
|
||||
mdb_set_shortdate_fmt(mdb, "%x");
|
||||
mdb_set_bind_size(mdb, MDB_BIND_SIZE);
|
||||
mdb_set_boolean_fmt_numbers(mdb);
|
||||
mdb_set_repid_fmt(mdb, MDB_BRACES_4_2_2_8);
|
||||
#ifdef HAVE_ICONV
|
||||
mdb->iconv_in = (iconv_t)-1;
|
||||
mdb->iconv_out = (iconv_t)-1;
|
||||
@ -315,10 +316,11 @@ MdbHandle *mdb_clone_handle(MdbHandle *mdb)
|
||||
mdb_iconv_init(newmdb);
|
||||
mdb_set_default_backend(newmdb, mdb->backend_name);
|
||||
|
||||
// date formats for the source handle may have been changed from
|
||||
// formats for the source handle may have been changed from
|
||||
// the backend's default formats, so we need to explicitly copy them here
|
||||
mdb_set_date_fmt(newmdb, mdb->date_fmt);
|
||||
mdb_set_shortdate_fmt(newmdb, mdb->shortdate_fmt);
|
||||
mdb_set_repid_fmt(newmdb, mdb->repid_fmt);
|
||||
|
||||
if (mdb->f) {
|
||||
mdb->f->refs++;
|
||||
@ -379,7 +381,7 @@ static ssize_t _mdb_read_pg(MdbHandle *mdb, void *pg_buf, unsigned long pg)
|
||||
*/
|
||||
if (pg != 0 && mdb->f->db_key != 0)
|
||||
{
|
||||
guint32 tmp_key_i = mdb->f->db_key ^ pg;
|
||||
uint32_t tmp_key_i = mdb->f->db_key ^ pg;
|
||||
unsigned char tmp_key[4] = {
|
||||
tmp_key_i & 0xFF, (tmp_key_i >> 8) & 0xFF,
|
||||
(tmp_key_i >> 16) & 0xFF, (tmp_key_i >> 24) & 0xFF };
|
||||
@ -412,7 +414,7 @@ unsigned char mdb_pg_get_byte(MdbHandle *mdb, int offset)
|
||||
int mdb_get_int16(void *buf, int offset)
|
||||
{
|
||||
unsigned char *u8_buf = (unsigned char *)buf + offset;
|
||||
return u8_buf[0] + (u8_buf[1] << 8);
|
||||
return ((uint32_t)u8_buf[0] << 0) + ((uint32_t)u8_buf[1] << 8);
|
||||
}
|
||||
int mdb_pg_get_int16(MdbHandle *mdb, int offset)
|
||||
{
|
||||
@ -424,12 +426,20 @@ int mdb_pg_get_int16(MdbHandle *mdb, int offset)
|
||||
long mdb_get_int32_msb(void *buf, int offset)
|
||||
{
|
||||
unsigned char *u8_buf = (unsigned char *)buf + offset;
|
||||
return (u8_buf[0] << 24) + (u8_buf[1] << 16) + (u8_buf[2] << 8) + u8_buf[3];
|
||||
return
|
||||
((uint32_t)u8_buf[0] << 24) +
|
||||
((uint32_t)u8_buf[1] << 16) +
|
||||
((uint32_t)u8_buf[2] << 8) +
|
||||
((uint32_t)u8_buf[3] << 0);
|
||||
}
|
||||
long mdb_get_int32(void *buf, int offset)
|
||||
{
|
||||
unsigned char *u8_buf = (unsigned char *)buf + offset;
|
||||
return u8_buf[0] + (u8_buf[1] << 8) + (u8_buf[2] << 16) + (u8_buf[3] << 24);
|
||||
return
|
||||
((uint32_t)u8_buf[0] << 0) +
|
||||
((uint32_t)u8_buf[1] << 8) +
|
||||
((uint32_t)u8_buf[2] << 16) +
|
||||
((uint32_t)u8_buf[3] << 24);
|
||||
}
|
||||
long mdb_pg_get_int32(MdbHandle *mdb, int offset)
|
||||
{
|
||||
@ -440,9 +450,12 @@ long mdb_pg_get_int32(MdbHandle *mdb, int offset)
|
||||
|
||||
float mdb_get_single(void *buf, int offset)
|
||||
{
|
||||
union {guint32 g; float f;} f;
|
||||
union {uint32_t g; float f;} f;
|
||||
unsigned char *u8_buf = (unsigned char *)buf + offset;
|
||||
f.g = u8_buf[0] + (u8_buf[1] << 8) + (u8_buf[2] << 16) + (u8_buf[3] << 24);
|
||||
f.g = ((uint32_t)u8_buf[0] << 0) +
|
||||
((uint32_t)u8_buf[1] << 8) +
|
||||
((uint32_t)u8_buf[2] << 16) +
|
||||
((uint32_t)u8_buf[3] << 24);
|
||||
return f.f;
|
||||
}
|
||||
float mdb_pg_get_single(MdbHandle *mdb, int offset)
|
||||
@ -454,13 +467,19 @@ float mdb_pg_get_single(MdbHandle *mdb, int offset)
|
||||
|
||||
double mdb_get_double(void *buf, int offset)
|
||||
{
|
||||
union {guint64 g; double d;} d;
|
||||
union {uint64_t g; double d;} d;
|
||||
unsigned char *u8_buf = (unsigned char *)buf + offset;
|
||||
d.g = u8_buf[0] + (u8_buf[1] << 8) + (u8_buf[2] << 16) + (u8_buf[3] << 24) +
|
||||
((guint64)u8_buf[4] << 32) + ((guint64)u8_buf[5] << 40) +
|
||||
((guint64)u8_buf[6] << 48) + ((guint64)u8_buf[7] << 56);
|
||||
d.g = ((uint64_t)u8_buf[0] << 0) +
|
||||
((uint64_t)u8_buf[1] << 8) +
|
||||
((uint64_t)u8_buf[2] << 16) +
|
||||
((uint64_t)u8_buf[3] << 24) +
|
||||
((uint64_t)u8_buf[4] << 32) +
|
||||
((uint64_t)u8_buf[5] << 40) +
|
||||
((uint64_t)u8_buf[6] << 48) +
|
||||
((uint64_t)u8_buf[7] << 56);
|
||||
return d.d;
|
||||
}
|
||||
|
||||
double mdb_pg_get_double(MdbHandle *mdb, int offset)
|
||||
{
|
||||
if (offset <0 || offset+8 > mdb->fmt->pg_size) return -1;
|
||||
@ -468,7 +487,6 @@ double mdb_pg_get_double(MdbHandle *mdb, int offset)
|
||||
return mdb_get_double(mdb->pg_buf, offset);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mdb_set_pos(MdbHandle *mdb, int pos)
|
||||
{
|
||||
|
@ -88,15 +88,7 @@ static size_t latin1_to_utf8_without_iconv(const char *in_ptr, size_t len_in, ch
|
||||
return out - dest;
|
||||
}
|
||||
|
||||
static size_t decompressed_to_utf8_without_iconv(MdbHandle *mdb, const char *in_ptr, size_t len_in, char *dest, size_t dlen) {
|
||||
if (IS_JET3(mdb)) {
|
||||
if (mdb->f->code_page == 1252) {
|
||||
return latin1_to_utf8_without_iconv(in_ptr, len_in, dest, dlen);
|
||||
}
|
||||
int count = 0;
|
||||
snprintf(dest, dlen, "%.*s%n", (int)len_in, in_ptr, &count);
|
||||
return count;
|
||||
}
|
||||
static size_t unicode2ascii_locale(mdb_locale_t locale, const char *in_ptr, size_t len_in, char *dest, size_t dlen) {
|
||||
size_t i;
|
||||
size_t count = 0;
|
||||
size_t len_out = dlen - 1;
|
||||
@ -109,11 +101,11 @@ static size_t decompressed_to_utf8_without_iconv(MdbHandle *mdb, const char *in_
|
||||
w[len_in/2] = '\0';
|
||||
|
||||
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
|
||||
count = _wcstombs_l(dest, w, len_out, mdb->locale);
|
||||
count = _wcstombs_l(dest, w, len_out, locale);
|
||||
#elif defined(HAVE_WCSTOMBS_L)
|
||||
count = wcstombs_l(dest, w, len_out, mdb->locale);
|
||||
count = wcstombs_l(dest, w, len_out, locale);
|
||||
#else
|
||||
locale_t oldlocale = uselocale(mdb->locale);
|
||||
locale_t oldlocale = uselocale(locale);
|
||||
count = wcstombs(dest, w, len_out);
|
||||
uselocale(oldlocale);
|
||||
#endif
|
||||
@ -124,6 +116,18 @@ static size_t decompressed_to_utf8_without_iconv(MdbHandle *mdb, const char *in_
|
||||
dest[count] = '\0';
|
||||
return count;
|
||||
}
|
||||
|
||||
static size_t decompressed_to_utf8_without_iconv(MdbHandle *mdb, const char *in_ptr, size_t len_in, char *dest, size_t dlen) {
|
||||
if (IS_JET3(mdb)) {
|
||||
if (mdb->f->code_page == 1252) {
|
||||
return latin1_to_utf8_without_iconv(in_ptr, len_in, dest, dlen);
|
||||
}
|
||||
int count = 0;
|
||||
snprintf(dest, dlen, "%.*s%n", (int)len_in, in_ptr, &count);
|
||||
return count;
|
||||
}
|
||||
return unicode2ascii_locale(mdb->locale, in_ptr, len_in, dest, dlen);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -271,6 +275,8 @@ static const char *mdb_iconv_name_from_code_page(int code_page) {
|
||||
case 860: jet3_iconv_code="IBM860"; break;
|
||||
case 861: jet3_iconv_code="IBM861"; break;
|
||||
case 862: jet3_iconv_code="IBM862"; break;
|
||||
case 863: jet3_iconv_code="IBM863"; break;
|
||||
case 864: jet3_iconv_code="IBM864"; break;
|
||||
case 865: jet3_iconv_code="IBM865"; break;
|
||||
case 866: jet3_iconv_code="IBM866"; break;
|
||||
case 869: jet3_iconv_code="IBM869"; break;
|
||||
|
@ -236,7 +236,7 @@ mdb_read_indices(MdbTableDef *table)
|
||||
*/
|
||||
//fprintf(stderr, "num_idxs:%d num_real_idxs:%d\n", table->num_idxs, table->num_real_idxs);
|
||||
|
||||
table->num_real_idxs = 0;
|
||||
unsigned int num_idxs_type_other_than_2 = 0;
|
||||
tmpbuf = g_malloc(idx2_sz);
|
||||
for (i=0;i<table->num_idxs;i++) {
|
||||
if (!read_pg_if_n(mdb, tmpbuf, &cur_pos, idx2_sz)) {
|
||||
@ -264,8 +264,11 @@ mdb_read_indices(MdbTableDef *table)
|
||||
fprintf(stderr, "idx #%d: %d %d %d %d %d/%d\n", i, idx_marker, rel_idx_type, rel_idx_number, rel_idx_page, update_action_flags, delete_action_flags);
|
||||
}*/
|
||||
if (pidx->index_type!=2)
|
||||
table->num_real_idxs++;
|
||||
num_idxs_type_other_than_2++;
|
||||
}
|
||||
if (num_idxs_type_other_than_2<table->num_real_idxs)
|
||||
table->num_real_idxs=num_idxs_type_other_than_2;
|
||||
|
||||
//fprintf(stderr, "num_idxs:%d num_real_idxs:%d\n", table->num_idxs, table->num_real_idxs);
|
||||
g_free(tmpbuf);
|
||||
|
||||
|
@ -24,8 +24,8 @@
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
static __thread unsigned long opts;
|
||||
static __thread int optset;
|
||||
static TLS unsigned long opts;
|
||||
static TLS int optset;
|
||||
|
||||
static void load_options(void);
|
||||
|
||||
|
@ -67,6 +67,9 @@ int rc;
|
||||
case MDB_LTEQ:
|
||||
if (rc>=0) return 1;
|
||||
break;
|
||||
case MDB_NEQ:
|
||||
if (rc!=0) return 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_string() for operator %d\n",node->op);
|
||||
break;
|
||||
@ -75,22 +78,26 @@ int rc;
|
||||
}
|
||||
int mdb_test_int(MdbSargNode *node, gint32 i)
|
||||
{
|
||||
gint32 val = node->val_type == MDB_INT ? node->value.i : node->value.d;
|
||||
switch (node->op) {
|
||||
case MDB_EQUAL:
|
||||
//fprintf(stderr, "comparing %ld and %ld\n", i, node->value.i);
|
||||
if (node->value.i == i) return 1;
|
||||
if (val == i) return 1;
|
||||
break;
|
||||
case MDB_GT:
|
||||
if (node->value.i < i) return 1;
|
||||
if (val < i) return 1;
|
||||
break;
|
||||
case MDB_LT:
|
||||
if (node->value.i > i) return 1;
|
||||
if (val > i) return 1;
|
||||
break;
|
||||
case MDB_GTEQ:
|
||||
if (node->value.i <= i) return 1;
|
||||
if (val <= i) return 1;
|
||||
break;
|
||||
case MDB_LTEQ:
|
||||
if (node->value.i >= i) return 1;
|
||||
if (val >= i) return 1;
|
||||
break;
|
||||
case MDB_NEQ:
|
||||
if (val != i) return 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_int() for operator %d\n",node->op);
|
||||
@ -129,6 +136,9 @@ int mdb_test_double(int op, double vd, double d)
|
||||
case MDB_LTEQ:
|
||||
ret = (vd >= d);
|
||||
break;
|
||||
case MDB_NEQ:
|
||||
ret = (vd != d);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_double() for operator %d\n",op);
|
||||
break;
|
||||
@ -235,16 +245,17 @@ mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNode *node, MdbField *field
|
||||
ret = mdb_test_int(node, (gint32)mdb_get_int32(field->value, 0));
|
||||
break;
|
||||
case MDB_FLOAT:
|
||||
ret = mdb_test_double(node->op, node->value.d, mdb_get_single(field->value, 0));
|
||||
ret = mdb_test_double(node->op, node->val_type == MDB_INT ? node->value.i : node->value.d, mdb_get_single(field->value, 0));
|
||||
break;
|
||||
case MDB_DOUBLE:
|
||||
ret = mdb_test_double(node->op, node->value.d, mdb_get_double(field->value, 0));
|
||||
ret = mdb_test_double(node->op, node->val_type == MDB_INT ? node->value.i : node->value.d, mdb_get_double(field->value, 0));
|
||||
break;
|
||||
case MDB_TEXT:
|
||||
mdb_unicode2ascii(mdb, field->value, field->siz, tmpbuf, sizeof(tmpbuf));
|
||||
ret = mdb_test_string(node, tmpbuf);
|
||||
break;
|
||||
case MDB_MEMO:
|
||||
case MDB_REPID:
|
||||
val = mdb_col_to_string(mdb, mdb->pg_buf, field->start, col->col_type, (gint32)mdb_get_int32(field->value, 0));
|
||||
//printf("%s\n",val);
|
||||
ret = mdb_test_string(node, val);
|
||||
|
@ -92,6 +92,12 @@ MdbTableDef *mdb_read_table(MdbCatalogEntry *entry)
|
||||
mdb_free_tabledef(table);
|
||||
return NULL;
|
||||
}
|
||||
/* First byte of usage_map is the map-type and must always be present */
|
||||
if (table->map_sz < 1) {
|
||||
fprintf(stderr, "mdb_read_table: invalid map-size: %zu\n", table->map_sz);
|
||||
mdb_free_tabledef(table);
|
||||
return NULL;
|
||||
}
|
||||
table->usage_map = g_memdup2((char*)buf + row_start, table->map_sz);
|
||||
if (mdb_get_option(MDB_DEBUG_USAGE))
|
||||
mdb_buffer_dump(buf, row_start, table->map_sz);
|
||||
@ -355,6 +361,9 @@ unsigned int i, bitn;
|
||||
guint32 pgnum;
|
||||
|
||||
table = mdb_read_table(entry);
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
fprintf(stdout,"definition page = %lu\n",entry->table_pg);
|
||||
fprintf(stdout,"number of datarows = %d\n",table->num_rows);
|
||||
fprintf(stdout,"number of columns = %d\n",table->num_cols);
|
||||
|
@ -5,14 +5,14 @@ lib_LTLIBRARIES = libmdbodbc.la
|
||||
libdir=@libdir@/odbc
|
||||
AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(ODBC_CFLAGS)
|
||||
libmdbodbc_la_SOURCES = odbc.c connectparams.c
|
||||
if UNIXODBC
|
||||
libmdbodbc_la_SOURCES += getproperties.c
|
||||
endif
|
||||
libmdbodbc_la_LIBADD = ../libmdb/libmdb.la ../sql/libmdbsql.la $(ODBC_LIBS)
|
||||
libmdbodbc_la_LDFLAGS = -avoid-version -export-symbols-regex '^(SQL|ODBCINST)' $(ODBC_LDFLAGS)
|
||||
if ICONV
|
||||
lib_LTLIBRARIES += libmdbodbcW.la
|
||||
libmdbodbcW_la_SOURCES = $(libmdbodbc_la_SOURCES)
|
||||
libmdbodbcW_la_LIBADD = $(libmdbodbc_la_LIBADD) @LIBICONV@
|
||||
libmdbodbcW_la_SOURCES = $(libmdbodbc_la_SOURCES) odbcw.c
|
||||
libmdbodbcW_la_LIBADD = $(libmdbodbc_la_LIBADD)
|
||||
libmdbodbcW_la_LDFLAGS = $(libmdbodbc_la_LDFLAGS)
|
||||
libmdbodbcW_la_CFLAGS = $(AM_CFLAGS) -D ENABLE_ODBC_W=1
|
||||
endif
|
||||
LIBS = $(GLIB_LIBS)
|
||||
unittest_LDADD = libmdbodbc.la ../libmdb/libmdb.la ../sql/libmdbsql.la
|
||||
|
@ -23,11 +23,11 @@
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
#ifdef UNIXODBC
|
||||
#include <odbcinstext.h>
|
||||
#else
|
||||
#if defined(HAVE_ODBCINST_H)
|
||||
#include <odbcinst.h>
|
||||
#endif
|
||||
#elif defined(HAVE_IODBCINST_H)
|
||||
#include <iodbcinst.h>
|
||||
#endif /* HAVE_ODBCINST_H */
|
||||
#include "connectparams.h"
|
||||
|
||||
|
||||
@ -93,7 +93,7 @@ void FreeConnectParams (ConnectParams* params)
|
||||
|
||||
gchar* GetConnectParam (ConnectParams* params, const gchar* paramName)
|
||||
{
|
||||
static __thread char tmp[FILENAME_MAX];
|
||||
static TLS char tmp[FILENAME_MAX];
|
||||
|
||||
/* use old servername */
|
||||
tmp[0] = '\0';
|
||||
@ -213,7 +213,7 @@ gchar* ExtractDSN (ConnectParams* params, const gchar* connectString)
|
||||
/*
|
||||
* Position ourselves to the beginning of "DSN"
|
||||
*/
|
||||
p = strstr (connectString, "DSN");
|
||||
p = strcasestr (connectString, "DSN");
|
||||
if (!p) return NULL;
|
||||
/*
|
||||
* Position ourselves to the "="
|
||||
@ -243,9 +243,9 @@ gchar* ExtractDBQ (ConnectParams* params, const gchar* connectString)
|
||||
if (!params)
|
||||
return NULL;
|
||||
/*
|
||||
* Position ourselves to the beginning of "DSN"
|
||||
* Position ourselves to the beginning of "DBQ"
|
||||
*/
|
||||
p = strstr (connectString, "DBQ");
|
||||
p = strcasestr (connectString, "DBQ");
|
||||
if (!p) return NULL;
|
||||
/*
|
||||
* Position ourselves to the "="
|
||||
@ -297,24 +297,4 @@ static void cleanup (gpointer key, gpointer value, gpointer user_data)
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
|
||||
#ifdef UNIXODBC
|
||||
|
||||
int
|
||||
ODBCINSTGetProperties(HODBCINSTPROPERTY hLastProperty)
|
||||
{
|
||||
hLastProperty->pNext = malloc(sizeof(ODBCINSTPROPERTY));
|
||||
hLastProperty = hLastProperty->pNext;
|
||||
memset(hLastProperty, 0, sizeof(ODBCINSTPROPERTY));
|
||||
hLastProperty->nPromptType = ODBCINST_PROMPTTYPE_FILENAME;
|
||||
strncpy(hLastProperty->szName, "Database", INI_MAX_PROPERTY_NAME);
|
||||
strncpy(hLastProperty->szValue, "", INI_MAX_PROPERTY_VALUE);
|
||||
hLastProperty->pszHelp = (char *) g_strdup("Filename and Path of MDB file to connect to.\n"
|
||||
"Use the full path to the database file.");
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
/** @}*/
|
38
src/odbc/getproperties.c
Normal file
38
src/odbc/getproperties.c
Normal file
@ -0,0 +1,38 @@
|
||||
/* MDB Tools - A library for reading MS Access database file
|
||||
* Copyright (C) 2000-2004 Brian Bruns
|
||||
*
|
||||
* portions based on FreeTDS, Copyright (C) 1998-1999 Brian Bruns
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <odbcinstext.h>
|
||||
|
||||
int
|
||||
ODBCINSTGetProperties(HODBCINSTPROPERTY hLastProperty)
|
||||
{
|
||||
hLastProperty->pNext = malloc(sizeof(ODBCINSTPROPERTY));
|
||||
hLastProperty = hLastProperty->pNext;
|
||||
memset(hLastProperty, 0, sizeof(ODBCINSTPROPERTY));
|
||||
hLastProperty->nPromptType = ODBCINST_PROMPTTYPE_FILENAME;
|
||||
strncpy(hLastProperty->szName, "Database", INI_MAX_PROPERTY_NAME);
|
||||
strncpy(hLastProperty->szValue, "", INI_MAX_PROPERTY_VALUE);
|
||||
hLastProperty->pszHelp = strdup("Filename and Path of MDB file to connect to.\n"
|
||||
"Use the full path to the database file.");
|
||||
|
||||
return 1;
|
||||
}
|
@ -21,9 +21,9 @@
|
||||
|
||||
#include <sql.h>
|
||||
#include <sqlext.h>
|
||||
#if defined(UNIXODBC)
|
||||
#if defined(HAVE_ODBCINST_H)
|
||||
# include <odbcinst.h>
|
||||
#elif defined(IODBC)
|
||||
#elif defined(HAVE_IODBCINST_H)
|
||||
# include <iodbcinst.h>
|
||||
#endif
|
||||
|
||||
@ -50,10 +50,7 @@ struct _hdbc {
|
||||
GPtrArray *statements;
|
||||
char lastError[256];
|
||||
char sqlState[6];
|
||||
#ifdef ENABLE_ODBC_W
|
||||
iconv_t iconv_in;
|
||||
iconv_t iconv_out;
|
||||
#endif
|
||||
mdb_locale_t locale;
|
||||
};
|
||||
struct _hstmt {
|
||||
MdbSQL *sql;
|
||||
@ -75,12 +72,16 @@ struct _hstmt {
|
||||
struct _sql_bind_info {
|
||||
int column_number;
|
||||
int column_bindtype; /* type/conversion required */
|
||||
int column_bindlen; /* size of varaddr buffer */
|
||||
int *column_lenbind; /* where to store length of varaddr used */
|
||||
SQLLEN column_bindlen; /* size of varaddr buffer */
|
||||
SQLLEN *column_lenbind; /* where to store length of varaddr used */
|
||||
char *varaddr;
|
||||
struct _sql_bind_info *next;
|
||||
};
|
||||
|
||||
size_t _mdb_odbc_ascii2unicode(struct _hdbc* dbc,
|
||||
const char *_in, size_t _in_len,
|
||||
SQLWCHAR *_out, size_t _out_count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
484
src/odbc/odbc.c
484
src/odbc/odbc.c
@ -16,11 +16,6 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
#define SQL_NOUNICODEMAP
|
||||
#define UNICODE
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
#include <sql.h>
|
||||
#include <sqlext.h>
|
||||
#include <string.h>
|
||||
@ -85,64 +80,6 @@ TypeInfo type_info[] = {
|
||||
#define NUM_TYPE_INFO_COLS 19
|
||||
#define MAX_TYPE_INFO 11
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
static void _init_iconv(struct _hdbc* dbc)
|
||||
{
|
||||
TRACE("_init_iconv");
|
||||
int endian = 1;
|
||||
const char* wcharset;
|
||||
if (sizeof(SQLWCHAR) == 2)
|
||||
if (*(char*)&endian == 1)
|
||||
wcharset = "UCS-2LE";
|
||||
else
|
||||
wcharset = "UCS-2BE";
|
||||
else if (sizeof(SQLWCHAR) == 4)
|
||||
if (*(char*)&endian == 1)
|
||||
wcharset = "UCS-4LE";
|
||||
else
|
||||
wcharset = "UCS-4BE";
|
||||
else
|
||||
fprintf(stderr, "Unsupported SQLWCHAR width %zd\n", sizeof(SQLWCHAR));
|
||||
|
||||
dbc->iconv_out = iconv_open(wcharset, "UTF-8");
|
||||
dbc->iconv_in = iconv_open("UTF-8", wcharset);
|
||||
}
|
||||
|
||||
static void _free_iconv(struct _hdbc *dbc)
|
||||
{
|
||||
TRACE("_free_iconv");
|
||||
if(dbc->iconv_out != (iconv_t)-1)iconv_close(dbc->iconv_out);
|
||||
if(dbc->iconv_in != (iconv_t)-1)iconv_close(dbc->iconv_in);
|
||||
}
|
||||
|
||||
static int unicode2ascii(struct _hdbc* dbc, char *_in, size_t *_lin, char *_out, size_t *_lout){
|
||||
char *in=_in, *out=_out;
|
||||
size_t lin=*_lin, lout=*_lout;
|
||||
int ret = iconv(dbc->iconv_in, &in, &lin, &out, &lout);
|
||||
*_lin -= lin;
|
||||
*_lout -= lout;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ascii2unicode(struct _hdbc* dbc, char *_in, size_t *_lin, char *_out, size_t *_lout){
|
||||
//fprintf(stderr,"ascii2unicode %08x %08x %08x %08x\n",_in,_lin,_out,_lout);
|
||||
char *in=_in, *out=_out;
|
||||
size_t lin=*_lin, lout=*_lout;
|
||||
//fprintf(stderr,"ascii2unicode %zd %zd\n",lin,lout);
|
||||
int ret = iconv(dbc->iconv_out, &in, &lin, &out, &lout);
|
||||
*_lin -= lin;
|
||||
*_lout -= lout;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlwlen(SQLWCHAR *p){
|
||||
int r=0;
|
||||
for(;*p;r++)
|
||||
p++;
|
||||
return r;
|
||||
}
|
||||
#endif // ENABLE_ODBC_W
|
||||
|
||||
static void LogHandleError(struct _hdbc* dbc, const char* format, ...)
|
||||
{
|
||||
va_list argp;
|
||||
@ -171,12 +108,35 @@ static SQLRETURN do_connect (
|
||||
// https://docs.microsoft.com/en-us/sql/relational-databases/native-client-odbc-date-time/datetime-data-type-conversions-odbc?view=sql-server-ver15
|
||||
mdb_set_date_fmt( dbc->sqlconn->mdb, "%F %H:%M:%S" );
|
||||
mdb_set_shortdate_fmt( dbc->sqlconn->mdb, "%F" );
|
||||
// Match formatting of REPID type values to MS Access ODBC driver
|
||||
mdb_set_repid_fmt( dbc->sqlconn->mdb, MDB_NOBRACES_4_2_2_2_6 );
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
else
|
||||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
size_t _mdb_odbc_ascii2unicode(struct _hdbc* dbc, const char *_in, size_t _in_len, SQLWCHAR *_out, size_t _out_count){
|
||||
wchar_t *w = malloc(_out_count * sizeof(wchar_t));
|
||||
size_t count = 0, i;
|
||||
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
|
||||
count = _mbstowcs_l(w, _in, _out_count, dbc->locale);
|
||||
#elif defined(HAVE_MBSTOWCS_L)
|
||||
count = mbstowcs_l(w, _in, _out_count, dbc->locale);
|
||||
#else
|
||||
locale_t oldlocale = uselocale(dbc->locale);
|
||||
count = mbstowcs(w, _in, _out_count);
|
||||
uselocale(oldlocale);
|
||||
#endif
|
||||
for (i=0; i<count; i++) {
|
||||
_out[i] = (SQLWCHAR)w[i];
|
||||
}
|
||||
free(w);
|
||||
if (count < _out_count)
|
||||
_out[count] = '\0';
|
||||
return count;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLDriverConnect(
|
||||
SQLHDBC hdbc,
|
||||
SQLHWND hwnd,
|
||||
@ -213,36 +173,6 @@ SQLRETURN SQL_API SQLDriverConnect(
|
||||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLDriverConnectW(
|
||||
SQLHDBC hdbc,
|
||||
SQLHWND hwnd,
|
||||
SQLWCHAR *szConnStrIn,
|
||||
SQLSMALLINT cbConnStrIn,
|
||||
SQLWCHAR *szConnStrOut,
|
||||
SQLSMALLINT cbConnStrOutMax,
|
||||
SQLSMALLINT *pcbConnStrOut,
|
||||
SQLUSMALLINT fDriverCompletion)
|
||||
{
|
||||
TRACE("SQLDriverConnectW");
|
||||
if(cbConnStrIn==SQL_NTS)cbConnStrIn=sqlwlen(szConnStrIn);
|
||||
{
|
||||
size_t l = cbConnStrIn*sizeof(SQLWCHAR), z = (cbConnStrIn+1)*3;
|
||||
SQLCHAR *tmp = malloc(z);
|
||||
SQLRETURN ret;
|
||||
unicode2ascii((struct _hdbc *)hdbc, (char*)szConnStrIn, &l, (char*)tmp, &z);
|
||||
tmp[z] = 0;
|
||||
ret = SQLDriverConnect(hdbc,hwnd,tmp,SQL_NTS,NULL,0,pcbConnStrOut,fDriverCompletion);
|
||||
free(tmp);
|
||||
if (szConnStrOut && cbConnStrOutMax>0)
|
||||
szConnStrOut[0] = 0;
|
||||
if (pcbConnStrOut)
|
||||
*pcbConnStrOut = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLBrowseConnect(
|
||||
SQLHDBC hdbc,
|
||||
SQLCHAR *szConnStrIn,
|
||||
@ -498,8 +428,10 @@ struct _hdbc* dbc;
|
||||
dbc->params = NewConnectParams ();
|
||||
dbc->statements = g_ptr_array_new();
|
||||
dbc->sqlconn = mdb_sql_init();
|
||||
#ifdef ENABLE_ODBC_W
|
||||
_init_iconv(dbc);
|
||||
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
|
||||
dbc->locale = _create_locale(LC_CTYPE, ".65001");
|
||||
#else
|
||||
dbc->locale = newlocale(LC_CTYPE_MASK, "C.UTF-8", NULL);
|
||||
#endif
|
||||
*phdbc=dbc;
|
||||
|
||||
@ -581,7 +513,7 @@ SQLRETURN SQL_API SQLBindCol(
|
||||
/* if this is a repeat */
|
||||
if (cur) {
|
||||
cur->column_bindtype = fCType;
|
||||
cur->column_lenbind = (int *)pcbValue;
|
||||
cur->column_lenbind = pcbValue;
|
||||
cur->column_bindlen = cbValueMax;
|
||||
cur->varaddr = (char *) rgbValue;
|
||||
} else {
|
||||
@ -590,7 +522,7 @@ SQLRETURN SQL_API SQLBindCol(
|
||||
newitem->column_number = icol;
|
||||
newitem->column_bindtype = fCType;
|
||||
newitem->column_bindlen = cbValueMax;
|
||||
newitem->column_lenbind = (int *)pcbValue;
|
||||
newitem->column_lenbind = pcbValue;
|
||||
newitem->varaddr = (char *) rgbValue;
|
||||
/* if there's no head yet */
|
||||
if (! stmt->bind_head) {
|
||||
@ -645,36 +577,6 @@ SQLRETURN SQL_API SQLConnect(
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLConnectW(
|
||||
SQLHDBC hdbc,
|
||||
SQLWCHAR *szDSN,
|
||||
SQLSMALLINT cbDSN,
|
||||
SQLWCHAR *szUID,
|
||||
SQLSMALLINT cbUID,
|
||||
SQLWCHAR *szAuthStr,
|
||||
SQLSMALLINT cbAuthStr)
|
||||
{
|
||||
TRACE("SQLConnectW");
|
||||
if(cbDSN==SQL_NTS)cbDSN=sqlwlen(szDSN);
|
||||
if(cbUID==SQL_NTS)cbUID=sqlwlen(szUID);
|
||||
if(cbAuthStr==SQL_NTS)cbAuthStr=sqlwlen(szAuthStr);
|
||||
{
|
||||
SQLCHAR *tmp1=calloc(cbDSN*4,1),*tmp2=calloc(cbUID*4,1),*tmp3=calloc(cbAuthStr*4,1);
|
||||
size_t l1=cbDSN*4,z1=cbDSN*2;
|
||||
size_t l2=cbUID*4,z2=cbUID*2;
|
||||
size_t l3=cbAuthStr*4,z3=cbAuthStr*2;
|
||||
SQLRETURN ret;
|
||||
unicode2ascii((struct _hdbc *)hdbc, (char*)szDSN, &z1, (char*)tmp1, &l1);
|
||||
unicode2ascii((struct _hdbc *)hdbc, (char*)szUID, &z2, (char*)tmp2, &l2);
|
||||
unicode2ascii((struct _hdbc *)hdbc, (char*)szAuthStr, &z3, (char*)tmp3, &l3);
|
||||
ret = SQLConnect(hdbc, tmp1, l1, tmp2, l2, tmp3, l3);
|
||||
free(tmp1),free(tmp2),free(tmp3);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLDescribeCol(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
@ -743,32 +645,6 @@ SQLRETURN SQL_API SQLDescribeCol(
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLDescribeColW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
SQLWCHAR *szColName,
|
||||
SQLSMALLINT cbColNameMax,
|
||||
SQLSMALLINT *pcbColName,
|
||||
SQLSMALLINT *pfSqlType,
|
||||
SQLULEN *pcbColDef, /* precision */
|
||||
SQLSMALLINT *pibScale,
|
||||
SQLSMALLINT *pfNullable)
|
||||
{
|
||||
TRACE("SQLDescribeColW");
|
||||
if(cbColNameMax==SQL_NTS)cbColNameMax=sqlwlen(szColName);
|
||||
{
|
||||
SQLCHAR *tmp=calloc(cbColNameMax*4,1);
|
||||
size_t l=cbColNameMax*4;
|
||||
SQLRETURN ret = SQLDescribeCol(hstmt, icol, tmp, cbColNameMax*4, (SQLSMALLINT*)&l, pfSqlType, pcbColDef, pibScale, pfNullable);
|
||||
ascii2unicode(((struct _hstmt*)hstmt)->hdbc, (char*)tmp, &l, (char*)szColName, (size_t*)pcbColName);
|
||||
*pcbColName/=sizeof(SQLWCHAR);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLColAttributes(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
@ -874,31 +750,6 @@ SQLRETURN SQL_API SQLColAttributes(
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLColAttributesW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
SQLUSMALLINT fDescType,
|
||||
SQLPOINTER rgbDesc,
|
||||
SQLSMALLINT cbDescMax,
|
||||
SQLSMALLINT *pcbDesc,
|
||||
SQLLEN *pfDesc)
|
||||
{
|
||||
TRACE("SQLColAttributesW");
|
||||
if (fDescType!=SQL_COLUMN_NAME && fDescType!=SQL_COLUMN_LABEL)
|
||||
return SQLColAttributes(hstmt,icol,fDescType,rgbDesc,cbDescMax,pcbDesc,pfDesc);
|
||||
else{
|
||||
SQLCHAR *tmp=calloc(cbDescMax*4,1);
|
||||
size_t l=cbDescMax*4;
|
||||
SQLRETURN ret=SQLColAttributes(hstmt,icol,fDescType,tmp,cbDescMax*4,(SQLSMALLINT*)&l,pfDesc);
|
||||
ascii2unicode(((struct _hstmt *)hstmt)->hdbc, (char*)tmp, &l, (char*)rgbDesc, (size_t*)pcbDesc);
|
||||
*pcbDesc/=sizeof(SQLWCHAR);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLDisconnect(
|
||||
SQLHDBC hdbc)
|
||||
{
|
||||
@ -958,39 +809,6 @@ SQLRETURN SQL_API SQLError(
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLErrorW(
|
||||
SQLHENV henv,
|
||||
SQLHDBC hdbc,
|
||||
SQLHSTMT hstmt,
|
||||
SQLWCHAR *szSqlState,
|
||||
SQLINTEGER *pfNativeError,
|
||||
SQLWCHAR *szErrorMsg,
|
||||
SQLSMALLINT cbErrorMsgMax,
|
||||
SQLSMALLINT *pcbErrorMsg)
|
||||
{
|
||||
SQLCHAR szSqlState8[6];
|
||||
SQLCHAR szErrorMsg8[3*cbErrorMsgMax+1];
|
||||
SQLSMALLINT pcbErrorMsg8;
|
||||
SQLRETURN result;
|
||||
|
||||
TRACE("SQLErrorW");
|
||||
|
||||
result = SQLError(henv, hdbc, hstmt, szSqlState8, pfNativeError, szErrorMsg8, 3*cbErrorMsgMax+1, &pcbErrorMsg8);
|
||||
if (result == SQL_SUCCESS) {
|
||||
struct _hdbc *dbc = hstmt ? ((struct _hstmt *)hstmt)->hdbc : hdbc;
|
||||
size_t lin=6, lout=6*sizeof(SQLWCHAR);
|
||||
ascii2unicode(dbc, (char*)szSqlState8, &lin, (char*)szSqlState, &lout);
|
||||
lin = pcbErrorMsg8;
|
||||
lout = cbErrorMsgMax;
|
||||
ascii2unicode(dbc, (char*)szErrorMsg8, &lin, (char*)szErrorMsg, &lout);
|
||||
if (pcbErrorMsg)
|
||||
*pcbErrorMsg = lout;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif // ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLExecute(SQLHSTMT hstmt)
|
||||
{
|
||||
struct _hstmt *stmt = (struct _hstmt *) hstmt;
|
||||
@ -1021,27 +839,6 @@ SQLRETURN SQL_API SQLExecDirect(
|
||||
return SQLExecute(hstmt);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLExecDirectW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLWCHAR *szSqlStr,
|
||||
SQLINTEGER cbSqlStr)
|
||||
{
|
||||
TRACE("SQLExecDirectW");
|
||||
if(cbSqlStr==SQL_NTS)cbSqlStr=sqlwlen(szSqlStr);
|
||||
{
|
||||
SQLCHAR *tmp=calloc(cbSqlStr*4,1);
|
||||
size_t l=cbSqlStr*4,z=cbSqlStr*2;
|
||||
SQLRETURN ret;
|
||||
unicode2ascii(((struct _hstmt *)hstmt)->hdbc, (char*)szSqlStr, &z, (char*)tmp, &l);
|
||||
ret = SQLExecDirect(hstmt, tmp, l);
|
||||
TRACE("SQLExecDirectW end");
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_ODBC_W
|
||||
|
||||
static void
|
||||
unbind_columns(struct _hstmt *stmt)
|
||||
{
|
||||
@ -1059,13 +856,13 @@ unbind_columns(struct _hstmt *stmt)
|
||||
stmt->bind_head = NULL;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLFetch(
|
||||
SQLRETURN SQLFetch(
|
||||
SQLHSTMT hstmt)
|
||||
{
|
||||
struct _hstmt *stmt = (struct _hstmt *) hstmt;
|
||||
struct _sql_bind_info *cur = stmt->bind_head;
|
||||
|
||||
TRACE("SQLFetch");
|
||||
|
||||
if ( stmt->sql->limit >= 0 && stmt->rows_affected == stmt->sql->limit ) {
|
||||
return SQL_NO_DATA_FOUND;
|
||||
}
|
||||
@ -1111,8 +908,10 @@ SQLRETURN SQL_API SQLFreeConnect(
|
||||
FreeConnectParams(dbc->params);
|
||||
g_ptr_array_free(dbc->statements, TRUE);
|
||||
mdb_sql_exit(dbc->sqlconn);
|
||||
#ifdef ENABLE_ODBC_W
|
||||
_free_iconv(dbc);
|
||||
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
|
||||
if (dbc->locale) _free_locale(dbc->locale);
|
||||
#else
|
||||
if (dbc->locale) freelocale(dbc->locale);
|
||||
#endif
|
||||
g_free(dbc);
|
||||
|
||||
@ -1382,31 +1181,6 @@ SQLRETURN SQL_API SQLColumns(
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLColumnsW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLWCHAR *szCatalogName,
|
||||
SQLSMALLINT cbCatalogName,
|
||||
SQLWCHAR *szSchemaName,
|
||||
SQLSMALLINT cbSchemaName,
|
||||
SQLWCHAR *szTableName,
|
||||
SQLSMALLINT cbTableName,
|
||||
SQLWCHAR *szColumnName,
|
||||
SQLSMALLINT cbColumnName)
|
||||
{
|
||||
if(cbTableName==SQL_NTS)cbTableName=sqlwlen(szTableName);
|
||||
{
|
||||
SQLCHAR *tmp=calloc(cbTableName*4,1);
|
||||
size_t l=cbTableName*4,z=cbTableName*2;
|
||||
SQLRETURN ret;
|
||||
unicode2ascii(((struct _hstmt* )hstmt)->hdbc, (char*)szTableName, &z, (char*)tmp, &l);
|
||||
ret = SQLColumns(hstmt, NULL, 0, NULL, 0, tmp, l, NULL, 0);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLGetConnectOption(
|
||||
SQLHDBC hdbc,
|
||||
SQLUSMALLINT fOption,
|
||||
@ -1465,9 +1239,21 @@ SQLRETURN SQL_API SQLGetData(
|
||||
|
||||
if (col->col_type == MDB_BOOL) {
|
||||
// bool cannot be null
|
||||
if (fCType == SQL_C_CHAR) {
|
||||
((SQLCHAR *)rgbValue)[0] = col->cur_value_len ? '0' : '1';
|
||||
((SQLCHAR *)rgbValue)[1] = '\0';
|
||||
if (pcbValue)
|
||||
*pcbValue = sizeof(SQLCHAR);
|
||||
} else if (fCType == SQL_C_WCHAR) {
|
||||
((SQLWCHAR *)rgbValue)[0] = col->cur_value_len ? '0' : '1';
|
||||
((SQLWCHAR *)rgbValue)[1] = '\0';
|
||||
if (pcbValue)
|
||||
*pcbValue = sizeof(SQLWCHAR);
|
||||
} else {
|
||||
*(BOOL*)rgbValue = col->cur_value_len ? 0 : 1;
|
||||
if (pcbValue)
|
||||
*pcbValue = 1;
|
||||
}
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
if (col->cur_value_len == 0) {
|
||||
@ -1496,7 +1282,7 @@ SQLRETURN SQL_API SQLGetData(
|
||||
found_bound_type:
|
||||
if (fCType==SQL_C_DEFAULT)
|
||||
fCType = _odbc_get_client_type(col);
|
||||
if (fCType == SQL_C_CHAR)
|
||||
if (fCType == SQL_C_CHAR || fCType == SQL_C_WCHAR)
|
||||
goto to_c_char;
|
||||
switch(col->col_type) {
|
||||
case MDB_BYTE:
|
||||
@ -1574,15 +1360,86 @@ SQLRETURN SQL_API SQLGetData(
|
||||
break;
|
||||
// case MDB_MONEY: TODO
|
||||
case MDB_FLOAT:
|
||||
switch (fCType) {
|
||||
case SQL_C_FLOAT:
|
||||
*(float*)rgbValue = mdb_get_single(mdb->pg_buf, col->cur_value_start);
|
||||
if (pcbValue)
|
||||
*pcbValue = sizeof(float);
|
||||
break;
|
||||
case SQL_C_DOUBLE:
|
||||
*(double*)rgbValue = (double)mdb_get_single(mdb->pg_buf, col->cur_value_start);
|
||||
if (pcbValue)
|
||||
*pcbValue = sizeof(double);
|
||||
break;
|
||||
case SQL_C_CHAR:
|
||||
case SQL_C_WCHAR:
|
||||
case SQL_C_STINYINT:
|
||||
case SQL_C_UTINYINT:
|
||||
case SQL_C_TINYINT:
|
||||
case SQL_C_SBIGINT:
|
||||
case SQL_C_UBIGINT:
|
||||
case SQL_C_SSHORT:
|
||||
case SQL_C_USHORT:
|
||||
case SQL_C_SHORT:
|
||||
case SQL_C_SLONG:
|
||||
case SQL_C_ULONG:
|
||||
case SQL_C_LONG:
|
||||
case SQL_C_NUMERIC:
|
||||
// case SQL_C_FLOAT:
|
||||
// case SQL_C_DOUBLE:
|
||||
case SQL_C_BIT:
|
||||
case SQL_C_BINARY:
|
||||
case SQL_C_INTERVAL_YEAR_TO_MONTH:
|
||||
case SQL_C_INTERVAL_DAY_TO_HOUR:
|
||||
case SQL_C_INTERVAL_DAY_TO_MINUTE:
|
||||
case SQL_C_INTERVAL_DAY_TO_SECOND:
|
||||
case SQL_C_INTERVAL_HOUR_TO_MINUTE:
|
||||
case SQL_C_INTERVAL_HOUR_TO_SECOND:
|
||||
strcpy(stmt->sqlState, "HYC00"); // Not implemented
|
||||
return SQL_ERROR;
|
||||
default:
|
||||
strcpy(stmt->sqlState, "07006"); // Not allowed
|
||||
return SQL_ERROR;
|
||||
}
|
||||
break;
|
||||
case MDB_DOUBLE:
|
||||
switch (fCType) {
|
||||
case SQL_C_DOUBLE:
|
||||
*(double*)rgbValue = mdb_get_double(mdb->pg_buf, col->cur_value_start);
|
||||
if (pcbValue)
|
||||
*pcbValue = sizeof(double);
|
||||
break;
|
||||
case SQL_C_CHAR:
|
||||
case SQL_C_WCHAR:
|
||||
case SQL_C_STINYINT:
|
||||
case SQL_C_UTINYINT:
|
||||
case SQL_C_TINYINT:
|
||||
case SQL_C_SBIGINT:
|
||||
case SQL_C_UBIGINT:
|
||||
case SQL_C_SSHORT:
|
||||
case SQL_C_USHORT:
|
||||
case SQL_C_SHORT:
|
||||
case SQL_C_SLONG:
|
||||
case SQL_C_ULONG:
|
||||
case SQL_C_LONG:
|
||||
case SQL_C_NUMERIC:
|
||||
case SQL_C_FLOAT:
|
||||
// case SQL_C_DOUBLE:
|
||||
case SQL_C_BIT:
|
||||
case SQL_C_BINARY:
|
||||
case SQL_C_INTERVAL_YEAR_TO_MONTH:
|
||||
case SQL_C_INTERVAL_DAY_TO_HOUR:
|
||||
case SQL_C_INTERVAL_DAY_TO_MINUTE:
|
||||
case SQL_C_INTERVAL_DAY_TO_SECOND:
|
||||
case SQL_C_INTERVAL_HOUR_TO_MINUTE:
|
||||
case SQL_C_INTERVAL_HOUR_TO_SECOND:
|
||||
strcpy(stmt->sqlState, "HYC00"); // Not implemented
|
||||
return SQL_ERROR;
|
||||
default:
|
||||
strcpy(stmt->sqlState, "07006"); // Not allowed
|
||||
return SQL_ERROR;
|
||||
}
|
||||
break;
|
||||
#if ODBCVER >= 0x0300
|
||||
// returns text if old odbc
|
||||
case MDB_DATETIME:
|
||||
@ -1656,7 +1513,7 @@ SQLRETURN SQL_API SQLGetData(
|
||||
free(stmt->ole_str);
|
||||
stmt->ole_str = NULL;
|
||||
break;
|
||||
default: /* FIXME here we assume fCType == SQL_C_CHAR */
|
||||
default: /* FIXME here we assume fCType == SQL_C_CHAR || fCType == SQL_C_WCHAR */
|
||||
to_c_char:
|
||||
{
|
||||
if (cbValueMax < 0) {
|
||||
@ -1664,6 +1521,7 @@ SQLRETURN SQL_API SQLGetData(
|
||||
return SQL_ERROR;
|
||||
}
|
||||
char *str = NULL;
|
||||
SQLWCHAR *wstr = NULL;
|
||||
if (col->col_type == MDB_NUMERIC) {
|
||||
str = mdb_numeric_to_string(mdb, col->cur_value_start,
|
||||
col->col_scale, col->col_prec);
|
||||
@ -1672,64 +1530,53 @@ SQLRETURN SQL_API SQLGetData(
|
||||
col->cur_value_start, col->col_type, col->cur_value_len);
|
||||
}
|
||||
size_t len = strlen(str);
|
||||
size_t charsize = 1;
|
||||
if (fCType == SQL_C_WCHAR) {
|
||||
wstr = calloc(len+1, charsize = sizeof(SQLWCHAR));
|
||||
len = _mdb_odbc_ascii2unicode(((struct _hstmt *)hstmt)->hdbc, str, len, wstr, len+1);
|
||||
}
|
||||
|
||||
if (stmt->pos >= len) {
|
||||
free(str);
|
||||
str = NULL;
|
||||
free(wstr); wstr = NULL;
|
||||
free(str); str = NULL;
|
||||
return SQL_NO_DATA;
|
||||
}
|
||||
if (pcbValue) {
|
||||
*pcbValue = len - stmt->pos;
|
||||
*pcbValue = (len - stmt->pos) * charsize;
|
||||
}
|
||||
if (cbValueMax == 0) {
|
||||
free(str);
|
||||
str = NULL;
|
||||
free(wstr); wstr = NULL;
|
||||
free(str); str = NULL;
|
||||
return SQL_SUCCESS_WITH_INFO;
|
||||
}
|
||||
|
||||
const int totalSizeRemaining = len - stmt->pos;
|
||||
const int partsRemain = cbValueMax - 1 < totalSizeRemaining;
|
||||
const int sizeToReadThisPart = partsRemain ? cbValueMax - 1 : totalSizeRemaining;
|
||||
memcpy(rgbValue, str + stmt->pos, sizeToReadThisPart);
|
||||
const int totalCharactersRemaining = len - stmt->pos;
|
||||
const int partsRemain = cbValueMax/charsize - 1 < totalCharactersRemaining;
|
||||
const int charactersToReadThisPart = partsRemain ? cbValueMax/charsize - 1 : totalCharactersRemaining;
|
||||
|
||||
((char *)rgbValue)[sizeToReadThisPart] = '\0';
|
||||
if (wstr) {
|
||||
memcpy(rgbValue, wstr + stmt->pos, charactersToReadThisPart * sizeof(SQLWCHAR));
|
||||
((SQLWCHAR *)rgbValue)[charactersToReadThisPart] = '\0';
|
||||
} else {
|
||||
memcpy(rgbValue, str + stmt->pos, charactersToReadThisPart);
|
||||
((SQLCHAR *)rgbValue)[charactersToReadThisPart] = '\0';
|
||||
}
|
||||
|
||||
free(wstr); wstr = NULL;
|
||||
free(str); str = NULL;
|
||||
|
||||
if (partsRemain) {
|
||||
stmt->pos += cbValueMax - 1;
|
||||
free(str); str = NULL;
|
||||
stmt->pos += charactersToReadThisPart;
|
||||
strcpy(stmt->sqlState, "01004"); // truncated
|
||||
return SQL_SUCCESS_WITH_INFO;
|
||||
}
|
||||
stmt->pos = len;
|
||||
free(str);
|
||||
str = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLGetDataW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
SQLSMALLINT fCType,
|
||||
SQLPOINTER rgbValue,
|
||||
SQLLEN cbValueMax,
|
||||
SQLLEN *pcbValue)
|
||||
{
|
||||
//todo: treat numbers correctly
|
||||
|
||||
SQLCHAR *tmp=calloc(cbValueMax*4,1);
|
||||
size_t l=cbValueMax*4;
|
||||
SQLRETURN ret = SQLGetData(hstmt, icol, fCType, tmp, cbValueMax*4, (SQLLEN*)&l);
|
||||
ascii2unicode(((struct _hstmt *)hstmt)->hdbc, (char*)tmp, &l, (char*)rgbValue, (size_t*)pcbValue);
|
||||
*pcbValue/=sizeof(SQLWCHAR);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
static void _set_func_exists(SQLUSMALLINT *pfExists, SQLUSMALLINT fFunction)
|
||||
{
|
||||
SQLUSMALLINT *mod;
|
||||
@ -1964,31 +1811,6 @@ SQLRETURN SQL_API SQLGetInfo(
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLGetInfoW(
|
||||
SQLHDBC hdbc,
|
||||
SQLUSMALLINT fInfoType,
|
||||
SQLPOINTER rgbInfoValue,
|
||||
SQLSMALLINT cbInfoValueMax,
|
||||
SQLSMALLINT *pcbInfoValue)
|
||||
{
|
||||
TRACE("SQLGetInfoW");
|
||||
|
||||
if(fInfoType==SQL_MAX_STATEMENT_LEN||fInfoType==SQL_SCHEMA_USAGE||fInfoType==SQL_CATALOG_LOCATION)
|
||||
return SQLGetInfo(hdbc,fInfoType,rgbInfoValue,cbInfoValueMax,pcbInfoValue);
|
||||
|
||||
SQLCHAR *tmp=calloc(cbInfoValueMax*4,1);
|
||||
size_t l=cbInfoValueMax*4;
|
||||
SQLRETURN ret = SQLGetInfo(hdbc, fInfoType, tmp, cbInfoValueMax*4,(SQLSMALLINT*)&l);
|
||||
size_t pcb=cbInfoValueMax;
|
||||
ascii2unicode((struct _hdbc *)hdbc, (char*)tmp, &l, (char*)rgbInfoValue, &pcb);
|
||||
pcb/=sizeof(SQLWCHAR);
|
||||
if(pcbInfoValue)*pcbInfoValue=pcb;
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLGetStmtOption(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT fOption,
|
||||
@ -2233,14 +2055,14 @@ SQLRETURN SQL_API SQLDataSources(
|
||||
|
||||
static int _odbc_fix_literals(struct _hstmt *stmt)
|
||||
{
|
||||
char tmp[4096],begin_tag[11];
|
||||
char tmp[4096];
|
||||
char *s, *d, *p;
|
||||
int i, quoted = 0, find_end = 0;
|
||||
char quote_char;
|
||||
char quote_char = '\0';
|
||||
|
||||
s=stmt->query;
|
||||
d=tmp;
|
||||
while (*s) {
|
||||
while (*s && d<tmp+sizeof(tmp)) {
|
||||
if (!quoted && (*s=='"' || *s=='\'')) {
|
||||
quoted = 1;
|
||||
quote_char = *s;
|
||||
@ -2255,9 +2077,7 @@ static int _odbc_fix_literals(struct _hstmt *stmt)
|
||||
/* garbage */
|
||||
*d++=*s++;
|
||||
} else {
|
||||
strncpy(begin_tag, s, i);
|
||||
begin_tag[i] = '\0';
|
||||
/* printf("begin tag %s\n", begin_tag); */
|
||||
/* printf("begin tag %.*s\n", i, s); */
|
||||
s += i;
|
||||
find_end = 1;
|
||||
}
|
||||
@ -2265,8 +2085,8 @@ static int _odbc_fix_literals(struct _hstmt *stmt)
|
||||
*d++=*s++;
|
||||
}
|
||||
}
|
||||
*d='\0';
|
||||
strcpy(stmt->query,tmp);
|
||||
|
||||
snprintf(stmt->query, sizeof(stmt->query), "%.*s", (int)(d-tmp), tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2373,7 +2193,7 @@ static const char * _odbc_get_client_type_name(MdbColumn *col)
|
||||
case MDB_COMPLEX:
|
||||
return "COMPLEX";
|
||||
default:
|
||||
// fprintf(stderr,"Unknown type %d\n",srv_type);
|
||||
fprintf(stderr,"Unknown type for column %s: %d\n",col->name,col->col_type);
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
|
265
src/odbc/odbcw.c
Normal file
265
src/odbc/odbcw.c
Normal file
@ -0,0 +1,265 @@
|
||||
/* MDB Tools - A library for reading MS Access database file
|
||||
* Copyright (C) 2000-2021 Brian Bruns and others
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* For a full list of functions that could be implemented, see:
|
||||
* https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/unicode-function-arguments?view=sql-server-ver15 */
|
||||
|
||||
#define SQL_NOUNICODEMAP
|
||||
#define UNICODE
|
||||
|
||||
#include <sql.h>
|
||||
#include <sqlext.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include "mdbodbc.h"
|
||||
|
||||
/** \addtogroup odbc
|
||||
* @{
|
||||
*/
|
||||
|
||||
//#define TRACE(x) fprintf(stderr,"Function %s\n", x);
|
||||
#define TRACE(x)
|
||||
|
||||
static size_t unicode2ascii(struct _hdbc* dbc, const SQLWCHAR *_in, size_t _in_count, SQLCHAR *_out, size_t _out_len){
|
||||
wchar_t *w = malloc((_in_count + 1) * sizeof(wchar_t));
|
||||
size_t i;
|
||||
size_t count = 0;
|
||||
for (i=0; i<_in_count; i++) {
|
||||
w[i] = _in[i]; // wchar_t might be larger than SQLWCHAR
|
||||
}
|
||||
w[_in_count] = '\0';
|
||||
|
||||
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
|
||||
count = _wcstombs_l((char *)_out, w, _out_len, dbc->locale);
|
||||
#elif defined(HAVE_WCSTOMBS_L)
|
||||
count = wcstombs_l((char *)_out, w, _out_len, dbc->locale);
|
||||
#else
|
||||
locale_t oldlocale = uselocale(dbc->locale);
|
||||
count = wcstombs((char *)_out, w, _out_len);
|
||||
uselocale(oldlocale);
|
||||
#endif
|
||||
free(w);
|
||||
if (count == (size_t)-1)
|
||||
return 0;
|
||||
|
||||
if (count < _out_len)
|
||||
_out[count] = '\0';
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int sqlwlen(SQLWCHAR *p){
|
||||
int r=0;
|
||||
for(;*p;r++)
|
||||
p++;
|
||||
return r;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLDriverConnectW(
|
||||
SQLHDBC hdbc,
|
||||
SQLHWND hwnd,
|
||||
SQLWCHAR *szConnStrIn,
|
||||
SQLSMALLINT cbConnStrIn,
|
||||
SQLWCHAR *szConnStrOut,
|
||||
SQLSMALLINT cbConnStrOutMax,
|
||||
SQLSMALLINT *pcbConnStrOut,
|
||||
SQLUSMALLINT fDriverCompletion)
|
||||
{
|
||||
TRACE("SQLDriverConnectW");
|
||||
if(cbConnStrIn==SQL_NTS)cbConnStrIn=sqlwlen(szConnStrIn);
|
||||
{
|
||||
size_t l = cbConnStrIn*4;
|
||||
SQLCHAR *tmp = malloc(l+1);
|
||||
SQLRETURN ret;
|
||||
l = unicode2ascii((struct _hdbc *)hdbc, szConnStrIn, cbConnStrIn, tmp, l);
|
||||
ret = SQLDriverConnect(hdbc,hwnd,tmp,SQL_NTS,NULL,0,pcbConnStrOut,fDriverCompletion);
|
||||
free(tmp);
|
||||
if (szConnStrOut && cbConnStrOutMax>0)
|
||||
szConnStrOut[0] = 0;
|
||||
if (pcbConnStrOut)
|
||||
*pcbConnStrOut = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLConnectW(
|
||||
SQLHDBC hdbc,
|
||||
SQLWCHAR *szDSN,
|
||||
SQLSMALLINT cbDSN,
|
||||
SQLWCHAR *szUID,
|
||||
SQLSMALLINT cbUID,
|
||||
SQLWCHAR *szAuthStr,
|
||||
SQLSMALLINT cbAuthStr)
|
||||
{
|
||||
TRACE("SQLConnectW");
|
||||
if(cbDSN==SQL_NTS)cbDSN=sqlwlen(szDSN);
|
||||
if(cbUID==SQL_NTS)cbUID=sqlwlen(szUID);
|
||||
if(cbAuthStr==SQL_NTS)cbAuthStr=sqlwlen(szAuthStr);
|
||||
{
|
||||
size_t l1=cbDSN*4;
|
||||
size_t l2=cbUID*4;
|
||||
size_t l3=cbAuthStr*4;
|
||||
SQLCHAR *tmp1=calloc(l1,1),*tmp2=calloc(l2,1),*tmp3=calloc(l3,1);
|
||||
SQLRETURN ret;
|
||||
l1 = unicode2ascii((struct _hdbc *)hdbc, szDSN, cbDSN, tmp1, l1);
|
||||
l2 = unicode2ascii((struct _hdbc *)hdbc, szUID, cbUID, tmp2, l2);
|
||||
l3 = unicode2ascii((struct _hdbc *)hdbc, szAuthStr, cbAuthStr, tmp3, l3);
|
||||
ret = SQLConnect(hdbc, tmp1, l1, tmp2, l2, tmp3, l3);
|
||||
free(tmp1),free(tmp2),free(tmp3);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLDescribeColW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
SQLWCHAR *szColName,
|
||||
SQLSMALLINT cbColNameMax,
|
||||
SQLSMALLINT *pcbColName,
|
||||
SQLSMALLINT *pfSqlType,
|
||||
SQLULEN *pcbColDef, /* precision */
|
||||
SQLSMALLINT *pibScale,
|
||||
SQLSMALLINT *pfNullable)
|
||||
{
|
||||
TRACE("SQLDescribeColW");
|
||||
if(cbColNameMax==SQL_NTS)cbColNameMax=sqlwlen(szColName);
|
||||
{
|
||||
size_t l=cbColNameMax*4+1;
|
||||
SQLCHAR *tmp=calloc(l,1);
|
||||
SQLRETURN ret = SQLDescribeCol(hstmt, icol, tmp, l, (SQLSMALLINT*)&l, pfSqlType, pcbColDef, pibScale, pfNullable);
|
||||
*pcbColName = _mdb_odbc_ascii2unicode(((struct _hstmt*)hstmt)->hdbc, (char*)tmp, l, szColName, cbColNameMax);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLColAttributesW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
SQLUSMALLINT fDescType,
|
||||
SQLPOINTER rgbDesc,
|
||||
SQLSMALLINT cbDescMax,
|
||||
SQLSMALLINT *pcbDesc,
|
||||
SQLLEN *pfDesc)
|
||||
{
|
||||
TRACE("SQLColAttributesW");
|
||||
if (fDescType!=SQL_COLUMN_NAME && fDescType!=SQL_COLUMN_LABEL)
|
||||
return SQLColAttributes(hstmt,icol,fDescType,rgbDesc,cbDescMax,pcbDesc,pfDesc);
|
||||
else{
|
||||
size_t l=cbDescMax*4+1;
|
||||
SQLCHAR *tmp=calloc(l,1);
|
||||
SQLRETURN ret=SQLColAttributes(hstmt,icol,fDescType,tmp,l,(SQLSMALLINT*)&l,pfDesc);
|
||||
*pcbDesc = _mdb_odbc_ascii2unicode(((struct _hstmt *)hstmt)->hdbc, (char*)tmp, l, (SQLWCHAR*)rgbDesc, cbDescMax);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLErrorW(
|
||||
SQLHENV henv,
|
||||
SQLHDBC hdbc,
|
||||
SQLHSTMT hstmt,
|
||||
SQLWCHAR *szSqlState,
|
||||
SQLINTEGER *pfNativeError,
|
||||
SQLWCHAR *szErrorMsg,
|
||||
SQLSMALLINT cbErrorMsgMax,
|
||||
SQLSMALLINT *pcbErrorMsg)
|
||||
{
|
||||
SQLCHAR szSqlState8[6];
|
||||
SQLCHAR szErrorMsg8[3*cbErrorMsgMax+1];
|
||||
SQLSMALLINT pcbErrorMsg8;
|
||||
SQLRETURN result;
|
||||
|
||||
TRACE("SQLErrorW");
|
||||
|
||||
result = SQLError(henv, hdbc, hstmt, szSqlState8, pfNativeError, szErrorMsg8, 3*cbErrorMsgMax+1, &pcbErrorMsg8);
|
||||
if (result == SQL_SUCCESS) {
|
||||
struct _hdbc *dbc = hstmt ? ((struct _hstmt *)hstmt)->hdbc : hdbc;
|
||||
size_t pcb;
|
||||
_mdb_odbc_ascii2unicode(dbc, (char*)szSqlState8, sizeof(szSqlState8), szSqlState, sizeof(szSqlState8));
|
||||
pcb = _mdb_odbc_ascii2unicode(dbc, (char*)szErrorMsg8, pcbErrorMsg8, szErrorMsg, cbErrorMsgMax);
|
||||
if (pcbErrorMsg) *pcbErrorMsg = pcb;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLExecDirectW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLWCHAR *szSqlStr,
|
||||
SQLINTEGER cbSqlStr)
|
||||
{
|
||||
TRACE("SQLExecDirectW");
|
||||
if(cbSqlStr==SQL_NTS)cbSqlStr=sqlwlen(szSqlStr);
|
||||
{
|
||||
size_t l=cbSqlStr*4;
|
||||
SQLCHAR *tmp=calloc(l,1);
|
||||
SQLRETURN ret;
|
||||
l = unicode2ascii(((struct _hstmt *)hstmt)->hdbc, szSqlStr, cbSqlStr, tmp, l);
|
||||
ret = SQLExecDirect(hstmt, tmp, l);
|
||||
TRACE("SQLExecDirectW end");
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLColumnsW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLWCHAR *szCatalogName,
|
||||
SQLSMALLINT cbCatalogName,
|
||||
SQLWCHAR *szSchemaName,
|
||||
SQLSMALLINT cbSchemaName,
|
||||
SQLWCHAR *szTableName,
|
||||
SQLSMALLINT cbTableName,
|
||||
SQLWCHAR *szColumnName,
|
||||
SQLSMALLINT cbColumnName)
|
||||
{
|
||||
if(cbTableName==SQL_NTS)cbTableName=sqlwlen(szTableName);
|
||||
{
|
||||
size_t l=cbTableName*4;
|
||||
SQLCHAR *tmp=calloc(l,1);
|
||||
SQLRETURN ret;
|
||||
l = unicode2ascii(((struct _hstmt* )hstmt)->hdbc, szTableName, cbTableName, tmp, l);
|
||||
ret = SQLColumns(hstmt, NULL, 0, NULL, 0, tmp, l, NULL, 0);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLGetInfoW(
|
||||
SQLHDBC hdbc,
|
||||
SQLUSMALLINT fInfoType,
|
||||
SQLPOINTER rgbInfoValue,
|
||||
SQLSMALLINT cbInfoValueMax,
|
||||
SQLSMALLINT *pcbInfoValue)
|
||||
{
|
||||
TRACE("SQLGetInfoW");
|
||||
|
||||
if(fInfoType==SQL_MAX_STATEMENT_LEN||fInfoType==SQL_SCHEMA_USAGE||fInfoType==SQL_CATALOG_LOCATION)
|
||||
return SQLGetInfo(hdbc,fInfoType,rgbInfoValue,cbInfoValueMax,pcbInfoValue);
|
||||
|
||||
size_t l=cbInfoValueMax*4+1;
|
||||
SQLCHAR *tmp=calloc(l,1);
|
||||
SQLRETURN ret = SQLGetInfo(hdbc, fInfoType, tmp, l, (SQLSMALLINT*)&l);
|
||||
size_t pcb = _mdb_odbc_ascii2unicode((struct _hdbc *)hdbc, (char*)tmp, l, (SQLWCHAR*)rgbInfoValue, cbInfoValueMax);
|
||||
if(pcbInfoValue)*pcbInfoValue=pcb;
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @}*/
|
@ -68,6 +68,7 @@ null { return NUL; }
|
||||
"=" { return EQ; }
|
||||
(<=) { return LTEQ; }
|
||||
(>=) { return GTEQ; }
|
||||
(<>) { return NEQ; }
|
||||
"<" { return LT; }
|
||||
">" { return GT; }
|
||||
like { return LIKE; }
|
||||
@ -112,7 +113,7 @@ strptime\( { return STRPTIME; }
|
||||
return STRING;
|
||||
}
|
||||
|
||||
(-?[0-9]+|(-?[0-9]*\.[0-9]+)(e[-+]?[0-9]+)?) {
|
||||
(-?[0-9]+|(-?[0-9]*\.[0-9]*)(e[-+]?[0-9]+)?) {
|
||||
yylval->name = g_strdup(yytext); return NUMBER;
|
||||
}
|
||||
~?(\/?[a-z0-9\.\-\_\!\~\'\(\)\%\xa0-\xff]+)+ {
|
||||
|
@ -17,9 +17,6 @@
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#ifndef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 700
|
||||
#endif
|
||||
#include "mdbsql.h"
|
||||
|
||||
#ifdef HAVE_STRPTIME
|
||||
@ -402,6 +399,7 @@ mdb_sql_eval_expr(MdbSQL *sql, char *const1, int op, char *const2)
|
||||
case MDB_LTEQ: compar = (value <= 0); break;
|
||||
case MDB_LIKE: compar = mdb_like_cmp(const1,const2); break;
|
||||
case MDB_ILIKE: compar = mdb_ilike_cmp(const1,const2); break;
|
||||
case MDB_NEQ: compar = (value ? 1 : 0); break;
|
||||
default: illop = 1;
|
||||
}
|
||||
} else if (const1[0]!='\'' && const2[0]!='\'') {
|
||||
@ -413,6 +411,7 @@ mdb_sql_eval_expr(MdbSQL *sql, char *const1, int op, char *const2)
|
||||
case MDB_GTEQ: compar = (val1 >= val2); break;
|
||||
case MDB_LT: compar = (val1 < val2); break;
|
||||
case MDB_LTEQ: compar = (val1 <= val2); break;
|
||||
case MDB_NEQ: compar = (val1 != val2); break;
|
||||
default: illop = 1;
|
||||
}
|
||||
} else {
|
||||
|
@ -63,7 +63,7 @@ typedef struct sql_context
|
||||
%token <name> IDENT NAME PATH STRING NUMBER OPENING CLOSING
|
||||
%token SELECT FROM WHERE CONNECT DISCONNECT TO LIST TABLES AND OR NOT LIMIT COUNT STRPTIME
|
||||
%token DESCRIBE TABLE TOP PERCENT
|
||||
%token LTEQ GTEQ LIKE ILIKE IS NUL
|
||||
%token LTEQ GTEQ NEQ LIKE ILIKE IS NUL
|
||||
|
||||
%type <name> database
|
||||
%type <name> constant
|
||||
@ -81,7 +81,7 @@ typedef struct sql_context
|
||||
%left OR
|
||||
%left AND
|
||||
%right NOT
|
||||
%left EQ LTEQ GTEQ LT GT LIKE ILIKE IS
|
||||
%left EQ LTEQ GTEQ NEQ LT GT LIKE ILIKE IS
|
||||
|
||||
%%
|
||||
|
||||
@ -192,6 +192,7 @@ operator:
|
||||
| LT { $$ = MDB_LT; }
|
||||
| LTEQ { $$ = MDB_LTEQ; }
|
||||
| GTEQ { $$ = MDB_GTEQ; }
|
||||
| NEQ { $$ = MDB_NEQ; }
|
||||
| LIKE { $$ = MDB_LIKE; }
|
||||
| ILIKE { $$ = MDB_ILIKE; }
|
||||
;
|
||||
|
@ -1,4 +1,7 @@
|
||||
if ENABLE_BASH_COMPLETION
|
||||
bashcompletiondir = $(BASH_COMPLETION_DIR)
|
||||
dist_bashcompletion_DATA = mdb-count mdb-export mdb-hexdump mdb-import mdb-json mdb-parsecsv mdb-prop mdb-queries mdb-schema mdb-sql mdb-tables mdb-ver
|
||||
dist_bashcompletion_DATA = mdb-count mdb-export mdb-hexdump mdb-import mdb-json mdb-parsecsv mdb-prop mdb-queries mdb-schema mdb-tables mdb-ver
|
||||
if SQL
|
||||
dist_bashcompletion_DATA += mdb-sql
|
||||
endif
|
||||
endif
|
||||
|
@ -35,17 +35,17 @@ char quote_text = 1;
|
||||
int count = 0;
|
||||
int started;
|
||||
|
||||
fputs("mdb-array is deprecated and will disappear in a future version of mdbtools.\n", stderr);
|
||||
fputs("Please drop us a line if you have any use of it.\n", stderr);
|
||||
fputs("See https://github.com/mdbtools/mdbtools/issues/197\n", stderr);
|
||||
fputs("\n", stderr);
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf (stderr, "Usage: %s <file> <table>\n", argv [0]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
fputs("mdb-array is deprecated and will disappear in a future version of mdbtools.\n", stderr);
|
||||
fputs("Please drop us a line if you have any use of it.\n", stderr);
|
||||
fputs("See https://github.com/mdbtools/mdbtools/issues/197\n", stderr);
|
||||
fputs("\n", stderr);
|
||||
|
||||
mdb = mdb_open (argv [1], MDB_NOFLAGS);
|
||||
if (!mdb)
|
||||
exit(1);
|
||||
|
@ -42,16 +42,16 @@ FILE *typesfile;
|
||||
FILE *headerfile;
|
||||
FILE *cfile;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf (stderr, "Usage: %s <file>\n",argv[0]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
fputs("mdb-header is deprecated and will disappear in a future version of mdbtools.\n", stderr);
|
||||
fputs("Please drop us a line if you have any use of it.\n", stderr);
|
||||
fputs("See https://github.com/mdbtools/mdbtools/issues/197\n", stderr);
|
||||
fputs("\n", stderr);
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf (stderr, "Usage: %s <file>\n",argv[0]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* open the database */
|
||||
|
||||
mdb = mdb_open (argv[1], MDB_NOFLAGS);
|
||||
@ -92,6 +92,11 @@ FILE *cfile;
|
||||
entry->object_name, entry->object_name);
|
||||
fprintf (cfile, "\tfprintf (stdout, \"**************** %s ****************\\n\");\n", entry->object_name);
|
||||
table = mdb_read_table (entry);
|
||||
if (!table) {
|
||||
fprintf(stderr, "Error: Table %s does not exist in this database.\n", entry->object_name);
|
||||
/* Don't bother clean up memory before exit */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* get the columns */
|
||||
mdb_read_columns (table);
|
||||
|
@ -53,17 +53,17 @@ main (int argc, char **argv)
|
||||
int lastcomma;
|
||||
int i;
|
||||
|
||||
fputs("mdb-parsecsv is deprecated and will disappear in a future version of mdbtools.\n", stderr);
|
||||
fputs("Please drop us a line if you have any use of it.\n", stderr);
|
||||
fputs("See https://github.com/mdbtools/mdbtools/issues/197\n", stderr);
|
||||
fputs("\n", stderr);
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf (stderr, "Usage: %s <file> (assumed extension .txt)\n",argv[0]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
fputs("mdb-parsecsv is deprecated and will disappear in a future version of mdbtools.\n", stderr);
|
||||
fputs("Please drop us a line if you have any use of it.\n", stderr);
|
||||
fputs("See https://github.com/mdbtools/mdbtools/issues/197\n", stderr);
|
||||
fputs("\n", stderr);
|
||||
|
||||
strcpy (txt_filename, argv [1]);
|
||||
txtfile = fopen (txt_filename, "r");
|
||||
if (!txtfile) {
|
||||
|
@ -97,9 +97,9 @@ main(int argc, char **argv)
|
||||
g_free(buf);
|
||||
mdb_free_tabledef(table);
|
||||
g_free(table_name);
|
||||
g_free(propColName);
|
||||
mdb_close(mdb);
|
||||
printf("Column %s not found in MSysObjects!\n", propColName);
|
||||
g_free(propColName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -304,7 +304,7 @@ find_sql_terminator(char *s)
|
||||
}
|
||||
|
||||
sp = &s[len-1];
|
||||
while (sp > s && isspace(*sp)) {
|
||||
while (sp > s && isspace((int)*sp)) {
|
||||
sp--;
|
||||
}
|
||||
|
||||
@ -322,7 +322,7 @@ main(int argc, char **argv)
|
||||
char prompt[20];
|
||||
int line = 0;
|
||||
char *mybuf;
|
||||
unsigned int bufsz;
|
||||
size_t bufsz;
|
||||
MdbSQL *sql;
|
||||
FILE *in = NULL, *out = NULL;
|
||||
char *filename_in=NULL, *filename_out=NULL;
|
||||
@ -408,7 +408,7 @@ main(int argc, char **argv)
|
||||
|
||||
/* give the buffer an initial size */
|
||||
bufsz = 4096;
|
||||
mybuf = g_malloc(bufsz);
|
||||
mybuf = malloc(bufsz);
|
||||
mybuf[0]='\0';
|
||||
|
||||
while (1) {
|
||||
@ -420,7 +420,7 @@ main(int argc, char **argv)
|
||||
|
||||
if (in) {
|
||||
s=calloc(bufsz, 1);
|
||||
if (!fgets(s, bufsz, in)) {
|
||||
if (!fgets(s, (int)bufsz, in)) {
|
||||
// Backwards compatibility with older MDBTools
|
||||
// Files read from the command line had an
|
||||
// implicit "go" at the end
|
||||
@ -464,7 +464,7 @@ main(int argc, char **argv)
|
||||
if (in) {
|
||||
fprintf(stderr, "Can not handle nested opens\n");
|
||||
} else {
|
||||
while (*fname && isspace(*fname))
|
||||
while (*fname && isspace((int)*fname))
|
||||
fname++;
|
||||
if (!(in = fopen(fname, "r"))) {
|
||||
fprintf(stderr,"Unable to open file %s\n", fname);
|
||||
@ -478,7 +478,7 @@ main(int argc, char **argv)
|
||||
|
||||
while (strlen(mybuf) + strlen(s) > bufsz) {
|
||||
bufsz *= 2;
|
||||
mybuf = (char *) g_realloc(mybuf, bufsz);
|
||||
mybuf = realloc(mybuf, bufsz);
|
||||
}
|
||||
#ifdef HAVE_READLINE_HISTORY
|
||||
/* don't record blank lines, or lines read from files
|
||||
@ -500,7 +500,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
mdb_sql_exit(sql);
|
||||
|
||||
g_free(mybuf);
|
||||
free(mybuf);
|
||||
if (s) free(s);
|
||||
if (out) fclose(out);
|
||||
if ((in) && (in != stdin)) fclose(in);
|
||||
|
143
test_script.sh
143
test_script.sh
@ -1,18 +1,131 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
# Simple test script; run after performing
|
||||
# git clone https://github.com/mdbtools/mdbtestdata.git test
|
||||
./src/util/mdb-json test/data/ASampleDatabase.accdb "Asset Items"
|
||||
./src/util/mdb-json test/data/nwind.mdb "Umsätze"
|
||||
./src/util/mdb-count test/data/ASampleDatabase.accdb "Asset Items"
|
||||
./src/util/mdb-count test/data/nwind.mdb "Umsätze"
|
||||
./src/util/mdb-prop test/data/ASampleDatabase.accdb "Asset Items"
|
||||
./src/util/mdb-prop test/data/nwind.mdb "Umsätze"
|
||||
./src/util/mdb-schema test/data/ASampleDatabase.accdb
|
||||
./src/util/mdb-schema test/data/nwind.mdb
|
||||
./src/util/mdb-schema test/data/nwind.mdb -T "Umsätze" postgres
|
||||
./src/util/mdb-tables test/data/ASampleDatabase.accdb
|
||||
./src/util/mdb-tables test/data/nwind.mdb
|
||||
./src/util/mdb-ver test/data/ASampleDatabase.accdb
|
||||
./src/util/mdb-ver test/data/nwind.mdb
|
||||
./src/util/mdb-queries test/data/ASampleDatabase.accdb qryCostsSummedByOwner
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
|
||||
LANG=C.UTF-8
|
||||
CDPATH= cd -- "$(dirname -- "$0")"
|
||||
|
||||
parseArgs() {
|
||||
MT_OUTPUT_KIND=verbose
|
||||
while :; do
|
||||
if test $# -lt 1; then
|
||||
break
|
||||
fi
|
||||
case "$1" in
|
||||
-q | --quiet)
|
||||
MT_OUTPUT_KIND=quiet
|
||||
;;
|
||||
-g | --github)
|
||||
MT_OUTPUT_KIND=github
|
||||
;;
|
||||
-h | --help)
|
||||
printf 'Syntax:\n%s [-q|--quiet|-g|--github] [-h|--help]\n' "$0"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
printf 'Unrecognized option: "%s"\n' "$1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
testCommand() {
|
||||
testCommand_name="$1"
|
||||
shift
|
||||
case $MT_OUTPUT_KIND in
|
||||
verbose)
|
||||
printf '# Running %s (%s)\n' "$testCommand_name" "$*"
|
||||
if "./src/util/$testCommand_name" "$@"; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
;;
|
||||
quiet)
|
||||
printf 'Testing %s (%s)... ' "$testCommand_name" "$*"
|
||||
if "./src/util/$testCommand_name" "$@" >/dev/null; then
|
||||
printf 'passed.\n'
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
;;
|
||||
github)
|
||||
testCommand_tempFile="$(mktemp)"
|
||||
printf 'Testing %s (%s)... ' "$testCommand_name" "$*"
|
||||
if "./src/util/$testCommand_name" "$@" 2>&1 >"$testCommand_tempFile"; then
|
||||
printf 'passed.\n'
|
||||
testCommand_rc=0
|
||||
else
|
||||
printf 'failed.\n'
|
||||
testCommand_rc=1
|
||||
fi
|
||||
echo '::group::Output'
|
||||
cat "$testCommand_tempFile"
|
||||
echo '::endgroup::'
|
||||
unlink "$testCommand_tempFile"
|
||||
return $testCommand_rc
|
||||
;;
|
||||
*)
|
||||
printf 'Unrecognized MT_OUTPUT_KIND (%s)\n' "$MT_OUTPUT_KIND"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
parseArgs "$@"
|
||||
|
||||
rc=0
|
||||
if ! testCommand mdb-json test/data/ASampleDatabase.accdb "Asset Items"; then
|
||||
rc=1
|
||||
fi
|
||||
if ! testCommand mdb-json test/data/nwind.mdb "Umsätze"; then
|
||||
rc=1
|
||||
fi
|
||||
if ! testCommand mdb-count test/data/ASampleDatabase.accdb "Asset Items"; then
|
||||
rc=1
|
||||
fi
|
||||
if ! testCommand mdb-count test/data/nwind.mdb "Umsätze"; then
|
||||
rc=1
|
||||
fi
|
||||
if ! testCommand mdb-prop test/data/ASampleDatabase.accdb "Asset Items"; then
|
||||
rc=1
|
||||
fi
|
||||
if ! testCommand mdb-prop test/data/nwind.mdb "Umsätze"; then
|
||||
rc=1
|
||||
fi
|
||||
if ! testCommand mdb-schema test/data/ASampleDatabase.accdb; then
|
||||
rc=1
|
||||
fi
|
||||
if ! testCommand mdb-schema test/data/nwind.mdb; then
|
||||
rc=1
|
||||
fi
|
||||
if ! testCommand mdb-schema test/data/nwind.mdb -T "Umsätze" postgres; then
|
||||
rc=1
|
||||
fi
|
||||
if ! testCommand mdb-tables test/data/ASampleDatabase.accdb; then
|
||||
rc=1
|
||||
fi
|
||||
if ! testCommand mdb-tables test/data/nwind.mdb; then
|
||||
rc=1
|
||||
fi
|
||||
if ! testCommand mdb-ver test/data/ASampleDatabase.accdb; then
|
||||
rc=1
|
||||
fi
|
||||
if ! testCommand mdb-ver test/data/nwind.mdb; then
|
||||
rc=1
|
||||
fi
|
||||
if ! testCommand mdb-queries test/data/ASampleDatabase.accdb qryCostsSummedByOwner; then
|
||||
rc=1
|
||||
fi
|
||||
|
||||
if [ $rc = 0 ]; then
|
||||
printf -- '\n%s passed.\n' "$0"
|
||||
else
|
||||
printf -- '\n%s failed!\n' "$0"
|
||||
fi
|
||||
exit $rc
|
||||
|
Loading…
Reference in New Issue
Block a user