mirror of
https://github.com/mdbtools/mdbtools.git
synced 2025-06-28 15:39:02 +08:00
Compare commits
66 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 | ||
![]() |
05cb0449db |
81
.github/workflows/build.yml
vendored
81
.github/workflows/build.yml
vendored
@ -1,20 +1,25 @@
|
|||||||
name: build
|
name: build
|
||||||
on: [ push, pull_request ]
|
on: [ push, pull_request ]
|
||||||
|
env:
|
||||||
|
TEST_DATA_URL: https://github.com/mdbtools/mdbtestdata/archive/refs/heads/master.tar.gz
|
||||||
jobs:
|
jobs:
|
||||||
linux:
|
linux:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
compiler: [ clang, gcc, gcc-9, gcc-10 ]
|
compiler: [ clang, gcc, gcc-11, gcc-12 ]
|
||||||
iconv: [ enable-iconv, disable-iconv]
|
iconv: [ enable-iconv, disable-iconv]
|
||||||
glib: [ enable-glib, disable-glib ]
|
glib: [ enable-glib, disable-glib ]
|
||||||
steps:
|
steps:
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: sudo apt install gettext
|
run: sudo apt install gettext unixodbc gcc-11 gcc-12
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Fetch test data
|
- 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
|
- name: Autoconf
|
||||||
run: autoreconf -i -f
|
run: autoreconf -i -f
|
||||||
- name: Configure
|
- name: Configure
|
||||||
@ -24,7 +29,7 @@ jobs:
|
|||||||
- name: Make
|
- name: Make
|
||||||
run: make
|
run: make
|
||||||
- name: CLI tests
|
- name: CLI tests
|
||||||
run: bash -e -x ./test_script.sh
|
run: ./test_script.sh --github
|
||||||
- name: SQL tests
|
- name: SQL tests
|
||||||
run: bash -e -x ./test_sql.sh
|
run: bash -e -x ./test_sql.sh
|
||||||
- name: ODBC tests
|
- name: ODBC tests
|
||||||
@ -49,21 +54,24 @@ jobs:
|
|||||||
glib: [ enable-glib, disable-glib ]
|
glib: [ enable-glib, disable-glib ]
|
||||||
steps:
|
steps:
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
run: brew install bison gawk automake
|
run: brew install bison gawk automake libtool unixodbc
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Fetch test data
|
- 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
|
- name: Autoconf
|
||||||
run: autoreconf -i -f
|
run: autoreconf -i -f -I $(brew --prefix)/share/gettext/m4
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: ./configure --disable-silent-rules --${{ matrix.glib }} --${{ matrix.iconv }} --with-unixodbc=/usr/local/opt
|
run: ./configure --disable-silent-rules --${{ matrix.glib }} --${{ matrix.iconv }} --with-unixodbc=/opt/homebrew/opt/unixodbc
|
||||||
env:
|
env:
|
||||||
CC: ${{ matrix.compiler }}
|
CC: ${{ matrix.compiler }}
|
||||||
YACC: /usr/local/opt/bison/bin/bison
|
YACC: /opt/homebrew/opt/bison/bin/bison
|
||||||
- name: Make
|
- name: Make
|
||||||
run: make
|
run: make
|
||||||
- name: CLI tests
|
- name: CLI tests
|
||||||
run: bash -e -x ./test_script.sh
|
run: ./test_script.sh --github
|
||||||
- name: SQL tests
|
- name: SQL tests
|
||||||
run: bash -e -x ./test_sql.sh
|
run: bash -e -x ./test_sql.sh
|
||||||
- name: ODBC tests
|
- name: ODBC tests
|
||||||
@ -86,20 +94,23 @@ jobs:
|
|||||||
compiler: [ clang, gcc ]
|
compiler: [ clang, gcc ]
|
||||||
glib: [ enable-glib, disable-glib ]
|
glib: [ enable-glib, disable-glib ]
|
||||||
steps:
|
steps:
|
||||||
- name: Remove packages
|
|
||||||
run: brew unlink unixodbc
|
|
||||||
- name: Install packages
|
- 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
|
- uses: actions/checkout@v2
|
||||||
- name: Fetch test data
|
- 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
|
- name: Autoconf
|
||||||
run: autoreconf -i -f
|
run: autoreconf -i -f -I $(brew --prefix)/share/gettext/m4
|
||||||
- name: Configure
|
- 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:
|
env:
|
||||||
CC: ${{ matrix.compiler }}
|
CC: ${{ matrix.compiler }}
|
||||||
YACC: /usr/local/opt/bison/bin/bison
|
YACC: /opt/homebrew/opt/bison/bin/bison
|
||||||
- name: Make
|
- name: Make
|
||||||
run: make
|
run: make
|
||||||
- name: ODBC tests
|
- name: ODBC tests
|
||||||
@ -108,19 +119,37 @@ jobs:
|
|||||||
MDBPATH: test/data
|
MDBPATH: test/data
|
||||||
windows:
|
windows:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
env:
|
strategy:
|
||||||
MSYSTEM: MINGW64
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
iconv: [ enable-iconv, disable-iconv]
|
||||||
|
glib: [ enable-glib, disable-glib ]
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: msys2 {0}
|
||||||
steps:
|
steps:
|
||||||
|
- uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
update: true
|
||||||
|
install: >-
|
||||||
|
autotools
|
||||||
|
base-devel
|
||||||
|
gcc
|
||||||
|
git
|
||||||
|
glib2-devel
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Check out test data
|
- 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
|
- name: Autoconf
|
||||||
run: C:\msys64\usr\bin\bash -c -l 'cd "$GITHUB_WORKSPACE" && autoreconf -i -f'
|
run: autoreconf -i -f
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: C:\msys64\usr\bin\bash -c -l 'cd "$GITHUB_WORKSPACE" && ./configure'
|
run: ./configure --${{ matrix.glib }} --${{ matrix.iconv }}
|
||||||
- name: Make
|
- name: Make
|
||||||
run: C:\msys64\usr\bin\bash -c -l 'cd "$GITHUB_WORKSPACE" && make'
|
run: make
|
||||||
- name: Test
|
- 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
|
- 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
|
||||||
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -17,6 +17,7 @@ m4/
|
|||||||
config.log
|
config.log
|
||||||
config.status
|
config.status
|
||||||
configure
|
configure
|
||||||
|
/configure~
|
||||||
Makefile.in
|
Makefile.in
|
||||||
Makefile
|
Makefile
|
||||||
doc/*.1
|
doc/*.1
|
||||||
@ -26,6 +27,8 @@ include/mdbtools.h
|
|||||||
libmdb.pc
|
libmdb.pc
|
||||||
libmdbsql.pc
|
libmdbsql.pc
|
||||||
libtool
|
libtool
|
||||||
|
mdbtools-*.tar.gz
|
||||||
|
mdbtools-*.zip
|
||||||
src/extras/mdb-hexdump
|
src/extras/mdb-hexdump
|
||||||
src/odbc/unittest
|
src/odbc/unittest
|
||||||
src/sql/lexer.c
|
src/sql/lexer.c
|
||||||
@ -52,9 +55,10 @@ src/util/prkkd
|
|||||||
src/util/prole
|
src/util/prole
|
||||||
src/util/prtable
|
src/util/prtable
|
||||||
src/util/updrow
|
src/util/updrow
|
||||||
|
/test/
|
||||||
|
/.vscode/
|
||||||
## apidocs docs related
|
## apidocs docs related
|
||||||
public/
|
public/
|
||||||
.sass-cache/
|
.sass-cache/
|
||||||
|
*.css.map
|
||||||
temp-man-pages/
|
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)
|
if (row_id = 0)
|
||||||
offset_stop of memo = 2048(jet3) or 4096(jet4)
|
offset_stop of memo = 2048(jet3) or 4096(jet4)
|
||||||
else
|
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:
|
The length (partial if type 2) for the memo is:
|
||||||
|
96
NEWS
96
NEWS
@ -1,68 +1,62 @@
|
|||||||
Version 1.0.0 (Beta 4)
|
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:
|
Build:
|
||||||
|
* 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)
|
* 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
|
* 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
|
* Generating the configure script now requires autoconf 2.64 or later
|
||||||
|
|
||||||
ODBC:
|
Install:
|
||||||
* The Unicode driver (`libmdbodbcW.so`) no longer uses iconv #332 #333
|
* Install `libmdbodbc.so` and `libmdbodbcW.so` into ${libdir}/odbc #315
|
||||||
|
|
||||||
SQL:
|
|
||||||
* New `<>` (not equal) operator #329
|
|
||||||
|
|
||||||
Version 1.0.0 (Beta 3)
|
|
||||||
=============
|
|
||||||
|
|
||||||
Build:
|
|
||||||
* Fix warning with autoconf 2.70
|
|
||||||
* Rely on autoconf to define appropriate values of `_XOPEN_SOURCE` and friends
|
|
||||||
* Simplify configure script
|
|
||||||
|
|
||||||
libmdb:
|
|
||||||
* Restore previous `MdbHandle` struct layout
|
|
||||||
* Simplify `pkg-config --cflags`
|
|
||||||
|
|
||||||
libmdbsql:
|
|
||||||
* Provide correct `pkg-config --cflags`
|
|
||||||
|
|
||||||
ODBC:
|
|
||||||
* Format boolean values correctly as SQL_C_CHAR #327
|
|
||||||
|
|
||||||
mdb-schema:
|
|
||||||
* Fix incorrect treatment of CREATE TABLE and DROP TABLE #328 (Bug introduced in Beta 2)
|
|
||||||
|
|
||||||
Version 1.0.0 (Beta 2)
|
|
||||||
=============
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
SQL:
|
|
||||||
* New case-insensitive, Unicode-aware `ILIKE` operator #244
|
|
||||||
* Do not install `mdb-sql` if SQL support was not built #276
|
* Do not install `mdb-sql` if SQL support was not built #276
|
||||||
* Do not install `libmdbsql.pc` if SQL support was not built
|
* Do not install `libmdbsql.pc` if SQL support was not built
|
||||||
|
|
||||||
ODBC:
|
`pkg-config`:
|
||||||
* Install libmdbodbc.so and libmdbodbcW.so into ${libdir}/odbc #315
|
* 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
|
* Convert table names to lower case when exporting to PostgreSQL #322
|
||||||
* Use `CREATE IF NOT EXISTS` when exporting to PostgreSQL #321
|
* 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
|
* Deprecate tool
|
||||||
|
|
||||||
Version 0.9.4
|
Version 0.9.4
|
||||||
|
22
README.md
22
README.md
@ -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):
|
`configure` file (skip this step if you have downloaded a formal release):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ autoreconf -i -f
|
autoreconf -i -f
|
||||||
```
|
```
|
||||||
|
|
||||||
Then:
|
Then:
|
||||||
|
|
||||||
```bash
|
```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):
|
OR for a complete install (requires bison, flex, and unixODBC):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ ./configure --with-unixodbc=/usr/local
|
./configure --with-unixodbc=/usr/local
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, MDB Tools is linked against the copy of
|
By default, MDB Tools is linked against the copy of
|
||||||
@ -152,11 +159,10 @@ mutually exclusive.
|
|||||||
By default, the ODBC driver will be installed as /usr/local/lib/odbc/libmdbodbc.so,
|
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.
|
with a Unicode-capable driver at /usr/local/lib/odbc/libmdbodbcW.so.
|
||||||
|
|
||||||
A list of general options is available in the [INSTALL](./INSTALL) file, and
|
The command `configure --help` will give you the list of mdbtools specific options.
|
||||||
`configure --help` will give you the list of mdbtools specific options.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
Once MDB Tools has been compiled, libmdb.[so|a] will be in the src/libmdb
|
Once MDB Tools has been compiled, libmdb.[so|a] will be in the src/libmdb
|
||||||
@ -165,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:
|
You can then install (to /usr/local by default) by running the following as root:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ make install
|
make install
|
||||||
```
|
```
|
||||||
|
|
||||||
Some systems will also need the ld cache to be updated after installation;
|
Some systems will also need the ld cache to be updated after installation;
|
||||||
You can do that running:
|
You can do that running:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ ldconfig
|
ldconfig
|
||||||
```
|
```
|
||||||
|
|
||||||
## Hacking
|
## Hacking
|
||||||
|
32
TODO.md
32
TODO.md
@ -1,34 +1,4 @@
|
|||||||
TODO
|
TODO
|
||||||
----
|
----
|
||||||
|
|
||||||
### file format:
|
See the list of [open issues tagged "enhancement"](https://github.com/mdbtools/mdbtools/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement).
|
||||||
|
|
||||||
- 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
|
|
||||||
|
File diff suppressed because one or more lines are too long
@ -17,8 +17,10 @@ clone_folder: c:\projects\mdbtools
|
|||||||
|
|
||||||
skip_tags: true
|
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:
|
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 && 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 && autoreconf -i -f"
|
||||||
- C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && ./configure --disable-man --disable-silent-rules"
|
- C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && ./configure --disable-man --disable-silent-rules"
|
||||||
@ -26,4 +28,3 @@ build_script:
|
|||||||
|
|
||||||
test_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_script.sh"
|
||||||
- C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && ./test_sql.sh"
|
|
||||||
|
23
configure.ac
23
configure.ac
@ -1,5 +1,5 @@
|
|||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
AC_INIT([mdbtools],[1.0.0-beta4],[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_MACRO_DIR([m4])
|
||||||
AC_CONFIG_AUX_DIR([build-aux])
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
AC_CONFIG_SRCDIR(src/extras/mdb-dump.c)
|
AC_CONFIG_SRCDIR(src/extras/mdb-dump.c)
|
||||||
@ -7,11 +7,11 @@ AM_INIT_AUTOMAKE([foreign dist-zip])
|
|||||||
|
|
||||||
MDBTOOLS_VERSION_MAJOR=1
|
MDBTOOLS_VERSION_MAJOR=1
|
||||||
MDBTOOLS_VERSION_MINOR=0
|
MDBTOOLS_VERSION_MINOR=0
|
||||||
MDBTOOLS_VERSION_MICRO=0
|
MDBTOOLS_VERSION_MICRO=1
|
||||||
|
|
||||||
# Update these numbers with every release
|
# Update these numbers with every release
|
||||||
# See https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
# See https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||||
VERSION_INFO=4:0:1
|
VERSION_INFO=4:1:1
|
||||||
AC_SUBST(VERSION_INFO)
|
AC_SUBST(VERSION_INFO)
|
||||||
|
|
||||||
AM_MAINTAINER_MODE([enable])
|
AM_MAINTAINER_MODE([enable])
|
||||||
@ -83,10 +83,10 @@ AM_CONDITIONAL(SQL, test x$sql = xtrue)
|
|||||||
AC_SUBST(SQL)
|
AC_SUBST(SQL)
|
||||||
AC_SUBST(LFLAGS)
|
AC_SUBST(LFLAGS)
|
||||||
|
|
||||||
CFLAGS="$CFLAGS -Wall -Werror"
|
CFLAGS="$CFLAGS -Wall"
|
||||||
LOCALE_T=locale_t
|
LOCALE_T=locale_t
|
||||||
AS_CASE([$host],
|
AS_CASE([$host],
|
||||||
[*mingw*|*cygwin*], [LDFLAGS="$LDFLAGS -no-undefined" LOCALE_T=_locale_t], [])
|
[*mingw*], [LDFLAGS="$LDFLAGS -no-undefined" CFLAGS="$CFLAGS -D_spawnv=_spawnv"], [])
|
||||||
AC_SUBST(LOCALE_T)
|
AC_SUBST(LOCALE_T)
|
||||||
|
|
||||||
dnl See if iconv is present and wanted
|
dnl See if iconv is present and wanted
|
||||||
@ -153,7 +153,6 @@ if test "$with_iodbc"; then
|
|||||||
ODBC_CFLAGS=$(iodbc-config --prefix="$with_iodbc" --cflags)
|
ODBC_CFLAGS=$(iodbc-config --prefix="$with_iodbc" --cflags)
|
||||||
ODBC_LIBS=$(iodbc-config --prefix="$with_iodbc" --libs)
|
ODBC_LIBS=$(iodbc-config --prefix="$with_iodbc" --libs)
|
||||||
ODBC_LDFLAGS=""
|
ODBC_LDFLAGS=""
|
||||||
CFLAGS="$CFLAGS -DIODBC"
|
|
||||||
|
|
||||||
OLDLDFLAGS=$LDFLAGS
|
OLDLDFLAGS=$LDFLAGS
|
||||||
LDFLAGS="$LDFLAGS $ODBC_LIBS"
|
LDFLAGS="$LDFLAGS $ODBC_LIBS"
|
||||||
@ -168,8 +167,7 @@ AC_ARG_WITH(unixodbc,
|
|||||||
if test "$with_unixodbc"; then
|
if test "$with_unixodbc"; then
|
||||||
HAVE_ODBC=true
|
HAVE_ODBC=true
|
||||||
ODBC_CFLAGS="-I$with_unixodbc/include"
|
ODBC_CFLAGS="-I$with_unixodbc/include"
|
||||||
ODBC_LIBS="-L$with_unixodbc/$libdir"
|
ODBC_LIBS="-L$with_unixodbc/lib"
|
||||||
CFLAGS="$CFLAGS -DUNIXODBC"
|
|
||||||
|
|
||||||
dnl SIZEOF_LONG_INT and HAVE_LONG_LONG are required by some versions of unixODBC
|
dnl SIZEOF_LONG_INT and HAVE_LONG_LONG are required by some versions of unixODBC
|
||||||
dnl https://github.com/lurcher/unixODBC/issues/40
|
dnl https://github.com/lurcher/unixODBC/issues/40
|
||||||
@ -192,12 +190,18 @@ if test "$with_unixodbc"; then
|
|||||||
ODBC_LDFLAGS=""])
|
ODBC_LDFLAGS=""])
|
||||||
LDFLAGS=$OLDLDFLAGS
|
LDFLAGS=$OLDLDFLAGS
|
||||||
fi
|
fi
|
||||||
|
AM_CONDITIONAL([UNIXODBC], test "$with_unixodbc")
|
||||||
|
|
||||||
if test "x$HAVE_ODBC" = "xtrue"; then
|
if test "x$HAVE_ODBC" = "xtrue"; then
|
||||||
if test "x$sql" != "xtrue" ; then
|
if test "x$sql" != "xtrue" ; then
|
||||||
AC_MSG_ERROR([ODBC requires flex and bison for the SQL engine])
|
AC_MSG_ERROR([ODBC requires flex and bison for the SQL engine])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
OLDCFLAGS=$CFLAGS
|
||||||
|
CFLAGS="$CFLAGS $ODBC_CFLAGS"
|
||||||
|
AC_CHECK_HEADERS(odbcinst.h iodbcinst.h)
|
||||||
|
CFLAGS=$OLDCFLAGS
|
||||||
|
|
||||||
AC_SUBST(ODBC_CFLAGS)
|
AC_SUBST(ODBC_CFLAGS)
|
||||||
AC_SUBST(ODBC_LIBS)
|
AC_SUBST(ODBC_LIBS)
|
||||||
AC_SUBST(ODBC_LDFLAGS)
|
AC_SUBST(ODBC_LDFLAGS)
|
||||||
@ -222,10 +226,9 @@ AC_ARG_ENABLE(glib,
|
|||||||
|
|
||||||
if test "$enable_glib" = "yes"; then
|
if test "$enable_glib" = "yes"; then
|
||||||
GLIB_PACKAGE=glib-2.0
|
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
|
if test "x$HAVE_GLIB" = "xtrue"; then
|
||||||
GLIB_CFLAGS="$GLIB_CFLAGS -DHAVE_GLIB=1"
|
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)
|
AC_SUBST(GLIB_PACKAGE)
|
||||||
else
|
else
|
||||||
enable_glib=no
|
enable_glib=no
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
SHELL = /bin/sh
|
SHELL = /bin/sh
|
||||||
TXT2MAN = ./txt2man
|
TXT2MAN = $(srcdir)/txt2man
|
||||||
PRODUCT = MDBTools
|
PRODUCT = MDBTools
|
||||||
|
|
||||||
dist_man_MANS =
|
dist_man_MANS =
|
||||||
|
@ -9,7 +9,7 @@ SYNOPSIS
|
|||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
mdb-json is a utility program distributed with MDB Tools.
|
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
|
OPTIONS
|
||||||
-D, --date-format fmt Set the date format (see strftime(3) for details).
|
-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_malloc malloc
|
||||||
#define g_free free
|
#define g_free free
|
||||||
#define g_realloc realloc
|
#define g_realloc realloc
|
||||||
|
#define g_memdup2 g_memdup
|
||||||
|
|
||||||
#define G_STR_DELIMITERS "_-|> <."
|
#define G_STR_DELIMITERS "_-|> <."
|
||||||
|
|
||||||
|
@ -26,10 +26,6 @@
|
|||||||
* used within mdbtools so they won't be exported to calling programs.
|
* used within mdbtools so they won't be exported to calling programs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HAVE_G_MEMDUP2
|
|
||||||
#define g_memdup2 g_memdup
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,9 +21,6 @@
|
|||||||
#define MDBTOOLS_H_HAVE_ICONV_H @HAVE_ICONV_H@
|
#define MDBTOOLS_H_HAVE_ICONV_H @HAVE_ICONV_H@
|
||||||
#define MDBTOOLS_H_HAVE_XLOCALE_H @HAVE_XLOCALE_H@
|
#define MDBTOOLS_H_HAVE_XLOCALE_H @HAVE_XLOCALE_H@
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -48,6 +45,10 @@
|
|||||||
#include <io.h>
|
#include <io.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/** \addtogroup mdbtools
|
/** \addtogroup mdbtools
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
@ -67,6 +68,13 @@
|
|||||||
// M$VC see http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc
|
// M$VC see http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc
|
||||||
#define MDB_DEPRECATED(type, funcname) type __attribute__((deprecated)) funcname
|
#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;
|
typedef @LOCALE_T@ mdb_locale_t;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -158,6 +166,11 @@ enum {
|
|||||||
MDB_NO_MEMO = 0x0080, /* don't follow memo fields */
|
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 || \
|
#define mdb_is_logical_op(x) (x == MDB_OR || \
|
||||||
x == MDB_AND || \
|
x == MDB_AND || \
|
||||||
x == MDB_NOT )
|
x == MDB_NOT )
|
||||||
@ -300,6 +313,7 @@ typedef struct {
|
|||||||
size_t bind_size;
|
size_t bind_size;
|
||||||
char date_fmt[64];
|
char date_fmt[64];
|
||||||
char shortdate_fmt[64];
|
char shortdate_fmt[64];
|
||||||
|
MdbUuidFormat repid_fmt;
|
||||||
const char *boolean_false_value;
|
const char *boolean_false_value;
|
||||||
const char *boolean_true_value;
|
const char *boolean_true_value;
|
||||||
unsigned int num_catalog;
|
unsigned int num_catalog;
|
||||||
@ -530,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_data_dump(MdbTableDef *table);
|
||||||
void mdb_date_to_tm(double td, struct tm *t);
|
void mdb_date_to_tm(double td, struct tm *t);
|
||||||
void mdb_tm_to_date(struct tm *t, double *td);
|
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_bind_column(MdbTableDef *table, int col_num, void *bind_ptr, int *len_ptr);
|
||||||
int mdb_rewind_table(MdbTableDef *table);
|
int mdb_rewind_table(MdbTableDef *table);
|
||||||
int mdb_fetch_row(MdbTableDef *table);
|
int mdb_fetch_row(MdbTableDef *table);
|
||||||
@ -547,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_bind_size(MdbHandle *mdb, size_t bind_size);
|
||||||
void mdb_set_date_fmt(MdbHandle *mdb, const char *);
|
void mdb_set_date_fmt(MdbHandle *mdb, const char *);
|
||||||
void mdb_set_shortdate_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_words(MdbHandle *mdb);
|
||||||
void mdb_set_boolean_fmt_numbers(MdbHandle *mdb);
|
void mdb_set_boolean_fmt_numbers(MdbHandle *mdb);
|
||||||
int mdb_read_row(MdbTableDef *table, unsigned int row);
|
int mdb_read_row(MdbTableDef *table, unsigned int row);
|
||||||
|
@ -111,7 +111,7 @@ static const MdbBackendType mdb_mysql_types[] = {
|
|||||||
[MDB_LONGINT] = { .name = "int" },
|
[MDB_LONGINT] = { .name = "int" },
|
||||||
[MDB_MONEY] = { .name = "float" },
|
[MDB_MONEY] = { .name = "float" },
|
||||||
[MDB_FLOAT] = { .name = "float" },
|
[MDB_FLOAT] = { .name = "float" },
|
||||||
[MDB_DOUBLE] = { .name = "float" },
|
[MDB_DOUBLE] = { .name = "double" },
|
||||||
[MDB_DATETIME] = { .name = "datetime" },
|
[MDB_DATETIME] = { .name = "datetime" },
|
||||||
[MDB_BINARY] = { .name = "blob" },
|
[MDB_BINARY] = { .name = "blob" },
|
||||||
[MDB_TEXT] = { .name = "varchar", .needs_char_length = 1 },
|
[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);
|
const MdbBackendType *type = mdb_get_colbacktype(col);
|
||||||
if (!type) {
|
if (!type) {
|
||||||
// return NULL;
|
// return NULL;
|
||||||
static __thread char buf[16];
|
static TLS char buf[16];
|
||||||
snprintf(buf, sizeof(buf), "Unknown_%04x", col->col_type);
|
snprintf(buf, sizeof(buf), "Unknown_%04x", col->col_type);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
@ -401,7 +401,7 @@ void mdb_init_backends(MdbHandle *mdb)
|
|||||||
"COMMENT %s",
|
"COMMENT %s",
|
||||||
quote_schema_name_rquotes_merge);
|
quote_schema_name_rquotes_merge);
|
||||||
mdb_register_backend(mdb, "sqlite",
|
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,
|
mdb_sqlite_types, NULL, NULL,
|
||||||
"date('now')", "date('now')",
|
"date('now')", "date('now')",
|
||||||
"%Y-%m-%d %H:%M:%S",
|
"%Y-%m-%d %H:%M:%S",
|
||||||
@ -571,7 +571,47 @@ mdb_get_index_name(int backend, MdbTableDef *table, MdbIndex *idx)
|
|||||||
|
|
||||||
return index_name;
|
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
|
* mdb_print_indexes
|
||||||
* @output: Where to print the sql
|
* @output: Where to print the sql
|
||||||
@ -596,13 +636,16 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace)
|
|||||||
backend = MDB_BACKEND_MYSQL;
|
backend = MDB_BACKEND_MYSQL;
|
||||||
} else if (!strcmp(mdb->backend_name, "oracle")) {
|
} else if (!strcmp(mdb->backend_name, "oracle")) {
|
||||||
backend = MDB_BACKEND_ORACLE;
|
backend = MDB_BACKEND_ORACLE;
|
||||||
|
} else if (!strcmp(mdb->backend_name, "sqlite")) {
|
||||||
|
backend = MDB_BACKEND_SQLITE;
|
||||||
} else {
|
} else {
|
||||||
fprintf(outfile, "-- Indexes are not implemented for %s\n\n", mdb->backend_name);
|
fprintf(outfile, "-- Indexes are not implemented for %s\n\n", mdb->backend_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read indexes */
|
/* read indexes */
|
||||||
mdb_read_indices(table);
|
if (table->indices==NULL)
|
||||||
|
mdb_read_indices(table);
|
||||||
|
|
||||||
fprintf (outfile, "-- CREATE INDEXES ...\n");
|
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);
|
idx = g_ptr_array_index (table->indices, i);
|
||||||
if (idx->index_type==2)
|
if (idx->index_type==2)
|
||||||
continue;
|
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);
|
index_name = mdb_get_index_name(backend, table, idx);
|
||||||
switch (backend) {
|
switch (backend) {
|
||||||
@ -630,7 +676,10 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace)
|
|||||||
}
|
}
|
||||||
|
|
||||||
quoted_name = mdb_normalise_and_replace(mdb, "ed_name);
|
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) {
|
if (idx->index_type==1) {
|
||||||
switch (backend) {
|
switch (backend) {
|
||||||
case MDB_BACKEND_ORACLE:
|
case MDB_BACKEND_ORACLE:
|
||||||
@ -645,6 +694,7 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace)
|
|||||||
switch (backend) {
|
switch (backend) {
|
||||||
case MDB_BACKEND_ORACLE:
|
case MDB_BACKEND_ORACLE:
|
||||||
case MDB_BACKEND_POSTGRES:
|
case MDB_BACKEND_POSTGRES:
|
||||||
|
case MDB_BACKEND_SQLITE:
|
||||||
fprintf(outfile, "CREATE");
|
fprintf(outfile, "CREATE");
|
||||||
if (idx->flags & MDB_IDX_UNIQUE)
|
if (idx->flags & MDB_IDX_UNIQUE)
|
||||||
fprintf (outfile, " UNIQUE");
|
fprintf (outfile, " UNIQUE");
|
||||||
@ -872,6 +922,10 @@ generate_table_schema(FILE *outfile, MdbCatalogEntry *entry, char *dbnamespace,
|
|||||||
fprintf (outfile, " (\n");
|
fprintf (outfile, " (\n");
|
||||||
|
|
||||||
table = mdb_read_table (entry);
|
table = mdb_read_table (entry);
|
||||||
|
if (!table) {
|
||||||
|
fprintf(stderr, "Error: Table %s does not exist\n", entry->object_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* get the columns */
|
/* get the columns */
|
||||||
mdb_read_columns(table);
|
mdb_read_columns(table);
|
||||||
@ -964,6 +1018,11 @@ generate_table_schema(FILE *outfile, MdbCatalogEntry *entry, char *dbnamespace,
|
|||||||
fputs("\n", outfile);
|
fputs("\n", outfile);
|
||||||
} /* for */
|
} /* 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);
|
fputs(")", outfile);
|
||||||
if (mdb->default_backend->per_table_comment_statement && export_options & MDB_SHEXP_COMMENTS) {
|
if (mdb->default_backend->per_table_comment_statement && export_options & MDB_SHEXP_COMMENTS) {
|
||||||
prop_value = mdb_table_get_prop(table, "Description");
|
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);
|
entry = g_ptr_array_index(mdb->catalog,i);
|
||||||
if (obj_type==MDB_ANY || entry->object_type==obj_type) {
|
if (obj_type==MDB_ANY || entry->object_type==obj_type) {
|
||||||
printf("Type: %-12s Name: %-48s Page: %06lx\n",
|
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->object_name,
|
||||||
entry->table_pg);
|
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);
|
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)
|
void mdb_set_boolean_fmt_numbers(MdbHandle *mdb)
|
||||||
{
|
{
|
||||||
mdb->boolean_false_value = boolean_false_number;
|
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)
|
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;
|
const unsigned char *kkd = (const unsigned char *)buf;
|
||||||
return g_strdup_printf("{%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" "-" "%02X%02X" "-" "%02X%02X%02X%02X%02X%02X",
|
||||||
kkd[pos+3], kkd[pos+2], kkd[pos+1], kkd[pos], // little-endian
|
kkd[pos+3], kkd[pos+2], kkd[pos+1], kkd[pos], // little-endian
|
||||||
kkd[pos+5], kkd[pos+4], // little-endian
|
kkd[pos+5], kkd[pos+4], // little-endian
|
||||||
kkd[pos+7], kkd[pos+6], // little-endian
|
kkd[pos+7], kkd[pos+6], // little-endian
|
||||||
kkd[pos+8], kkd[pos+9], // big-endian
|
kkd[pos+8], kkd[pos+9], // big-endian
|
||||||
|
|
||||||
kkd[pos+10], kkd[pos+11],
|
kkd[pos+10], kkd[pos+11],
|
||||||
kkd[pos+12], kkd[pos+13],
|
kkd[pos+12], kkd[pos+13],
|
||||||
kkd[pos+14], kkd[pos+15]); // big-endian
|
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) {
|
switch (datatype) {
|
||||||
case MDB_BYTE:
|
case MDB_BYTE:
|
||||||
text = g_strdup_printf("%hhd", mdb_get_byte(buf, start));
|
text = g_strdup_printf("%hhu", mdb_get_byte(buf, start));
|
||||||
break;
|
break;
|
||||||
case MDB_INT:
|
case MDB_INT:
|
||||||
text = g_strdup_printf("%hd",
|
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);
|
text = mdb_money_to_string(mdb, start);
|
||||||
break;
|
break;
|
||||||
case MDB_REPID:
|
case MDB_REPID:
|
||||||
text = mdb_uuid_to_string(buf, start);
|
text = mdb_uuid_to_string_fmt(buf, start, mdb->repid_fmt);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* shouldn't happen. bools are handled specially
|
/* shouldn't happen. bools are handled specially
|
||||||
|
@ -255,7 +255,8 @@ gchar *g_locale_to_utf8(const gchar *opsysstring, size_t len,
|
|||||||
mbstowcs(utf16, opsysstring, wlen+1);
|
mbstowcs(utf16, opsysstring, wlen+1);
|
||||||
gchar *utf8 = malloc(3*len+1);
|
gchar *utf8 = malloc(3*len+1);
|
||||||
gchar *dst = utf8;
|
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
|
// u >= 0x10000 requires surrogate pairs, ignore
|
||||||
dst += g_unichar_to_utf8(utf16[i], dst);
|
dst += g_unichar_to_utf8(utf16[i], dst);
|
||||||
}
|
}
|
||||||
@ -332,7 +333,8 @@ void g_hash_table_insert(GHashTable *table, void *key, void *value) {
|
|||||||
|
|
||||||
gboolean g_hash_table_remove(GHashTable *table, gconstpointer key) {
|
gboolean g_hash_table_remove(GHashTable *table, gconstpointer key) {
|
||||||
int found = 0;
|
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);
|
MyNode *node = g_ptr_array_index(table->array, i);
|
||||||
if (found) {
|
if (found) {
|
||||||
table->array->pdata[i-1] = table->array->pdata[i];
|
table->array->pdata[i-1] = table->array->pdata[i];
|
||||||
@ -398,7 +400,8 @@ void g_ptr_array_add(GPtrArray *array, void *entry) {
|
|||||||
|
|
||||||
gboolean g_ptr_array_remove(GPtrArray *array, gpointer data) {
|
gboolean g_ptr_array_remove(GPtrArray *array, gpointer data) {
|
||||||
int found = 0;
|
int found = 0;
|
||||||
for (guint i=0; i<array->len; i++) {
|
guint i;
|
||||||
|
for (i=0; i<array->len; i++) {
|
||||||
if (found) {
|
if (found) {
|
||||||
array->pdata[i-1] = array->pdata[i];
|
array->pdata[i-1] = array->pdata[i];
|
||||||
} else if (!found && array->pdata[i] == data) {
|
} 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_shortdate_fmt(mdb, "%x");
|
||||||
mdb_set_bind_size(mdb, MDB_BIND_SIZE);
|
mdb_set_bind_size(mdb, MDB_BIND_SIZE);
|
||||||
mdb_set_boolean_fmt_numbers(mdb);
|
mdb_set_boolean_fmt_numbers(mdb);
|
||||||
|
mdb_set_repid_fmt(mdb, MDB_BRACES_4_2_2_8);
|
||||||
#ifdef HAVE_ICONV
|
#ifdef HAVE_ICONV
|
||||||
mdb->iconv_in = (iconv_t)-1;
|
mdb->iconv_in = (iconv_t)-1;
|
||||||
mdb->iconv_out = (iconv_t)-1;
|
mdb->iconv_out = (iconv_t)-1;
|
||||||
@ -315,10 +316,11 @@ MdbHandle *mdb_clone_handle(MdbHandle *mdb)
|
|||||||
mdb_iconv_init(newmdb);
|
mdb_iconv_init(newmdb);
|
||||||
mdb_set_default_backend(newmdb, mdb->backend_name);
|
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
|
// the backend's default formats, so we need to explicitly copy them here
|
||||||
mdb_set_date_fmt(newmdb, mdb->date_fmt);
|
mdb_set_date_fmt(newmdb, mdb->date_fmt);
|
||||||
mdb_set_shortdate_fmt(newmdb, mdb->shortdate_fmt);
|
mdb_set_shortdate_fmt(newmdb, mdb->shortdate_fmt);
|
||||||
|
mdb_set_repid_fmt(newmdb, mdb->repid_fmt);
|
||||||
|
|
||||||
if (mdb->f) {
|
if (mdb->f) {
|
||||||
mdb->f->refs++;
|
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)
|
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] = {
|
unsigned char tmp_key[4] = {
|
||||||
tmp_key_i & 0xFF, (tmp_key_i >> 8) & 0xFF,
|
tmp_key_i & 0xFF, (tmp_key_i >> 8) & 0xFF,
|
||||||
(tmp_key_i >> 16) & 0xFF, (tmp_key_i >> 24) & 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)
|
int mdb_get_int16(void *buf, int offset)
|
||||||
{
|
{
|
||||||
unsigned char *u8_buf = (unsigned char *)buf + 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)
|
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)
|
long mdb_get_int32_msb(void *buf, int offset)
|
||||||
{
|
{
|
||||||
unsigned char *u8_buf = (unsigned char *)buf + 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)
|
long mdb_get_int32(void *buf, int offset)
|
||||||
{
|
{
|
||||||
unsigned char *u8_buf = (unsigned char *)buf + 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)
|
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)
|
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;
|
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;
|
return f.f;
|
||||||
}
|
}
|
||||||
float mdb_pg_get_single(MdbHandle *mdb, int offset)
|
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)
|
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;
|
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) +
|
d.g = ((uint64_t)u8_buf[0] << 0) +
|
||||||
((guint64)u8_buf[4] << 32) + ((guint64)u8_buf[5] << 40) +
|
((uint64_t)u8_buf[1] << 8) +
|
||||||
((guint64)u8_buf[6] << 48) + ((guint64)u8_buf[7] << 56);
|
((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;
|
return d.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
double mdb_pg_get_double(MdbHandle *mdb, int offset)
|
double mdb_pg_get_double(MdbHandle *mdb, int offset)
|
||||||
{
|
{
|
||||||
if (offset <0 || offset+8 > mdb->fmt->pg_size) return -1;
|
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);
|
return mdb_get_double(mdb->pg_buf, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
mdb_set_pos(MdbHandle *mdb, int pos)
|
mdb_set_pos(MdbHandle *mdb, int pos)
|
||||||
{
|
{
|
||||||
|
@ -275,6 +275,8 @@ static const char *mdb_iconv_name_from_code_page(int code_page) {
|
|||||||
case 860: jet3_iconv_code="IBM860"; break;
|
case 860: jet3_iconv_code="IBM860"; break;
|
||||||
case 861: jet3_iconv_code="IBM861"; break;
|
case 861: jet3_iconv_code="IBM861"; break;
|
||||||
case 862: jet3_iconv_code="IBM862"; 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 865: jet3_iconv_code="IBM865"; break;
|
||||||
case 866: jet3_iconv_code="IBM866"; break;
|
case 866: jet3_iconv_code="IBM866"; break;
|
||||||
case 869: jet3_iconv_code="IBM869"; 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);
|
//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);
|
tmpbuf = g_malloc(idx2_sz);
|
||||||
for (i=0;i<table->num_idxs;i++) {
|
for (i=0;i<table->num_idxs;i++) {
|
||||||
if (!read_pg_if_n(mdb, tmpbuf, &cur_pos, idx2_sz)) {
|
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);
|
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)
|
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);
|
//fprintf(stderr, "num_idxs:%d num_real_idxs:%d\n", table->num_idxs, table->num_real_idxs);
|
||||||
g_free(tmpbuf);
|
g_free(tmpbuf);
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
|
|
||||||
#define DEBUG 1
|
#define DEBUG 1
|
||||||
|
|
||||||
static __thread unsigned long opts;
|
static TLS unsigned long opts;
|
||||||
static __thread int optset;
|
static TLS int optset;
|
||||||
|
|
||||||
static void load_options(void);
|
static void load_options(void);
|
||||||
|
|
||||||
|
@ -78,25 +78,26 @@ int rc;
|
|||||||
}
|
}
|
||||||
int mdb_test_int(MdbSargNode *node, gint32 i)
|
int mdb_test_int(MdbSargNode *node, gint32 i)
|
||||||
{
|
{
|
||||||
|
gint32 val = node->val_type == MDB_INT ? node->value.i : node->value.d;
|
||||||
switch (node->op) {
|
switch (node->op) {
|
||||||
case MDB_EQUAL:
|
case MDB_EQUAL:
|
||||||
//fprintf(stderr, "comparing %ld and %ld\n", i, node->value.i);
|
//fprintf(stderr, "comparing %ld and %ld\n", i, node->value.i);
|
||||||
if (node->value.i == i) return 1;
|
if (val == i) return 1;
|
||||||
break;
|
break;
|
||||||
case MDB_GT:
|
case MDB_GT:
|
||||||
if (node->value.i < i) return 1;
|
if (val < i) return 1;
|
||||||
break;
|
break;
|
||||||
case MDB_LT:
|
case MDB_LT:
|
||||||
if (node->value.i > i) return 1;
|
if (val > i) return 1;
|
||||||
break;
|
break;
|
||||||
case MDB_GTEQ:
|
case MDB_GTEQ:
|
||||||
if (node->value.i <= i) return 1;
|
if (val <= i) return 1;
|
||||||
break;
|
break;
|
||||||
case MDB_LTEQ:
|
case MDB_LTEQ:
|
||||||
if (node->value.i >= i) return 1;
|
if (val >= i) return 1;
|
||||||
break;
|
break;
|
||||||
case MDB_NEQ:
|
case MDB_NEQ:
|
||||||
if (node->value.i != i) return 1;
|
if (val != i) return 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_int() for operator %d\n",node->op);
|
fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_int() for operator %d\n",node->op);
|
||||||
@ -244,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));
|
ret = mdb_test_int(node, (gint32)mdb_get_int32(field->value, 0));
|
||||||
break;
|
break;
|
||||||
case MDB_FLOAT:
|
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;
|
break;
|
||||||
case MDB_DOUBLE:
|
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;
|
break;
|
||||||
case MDB_TEXT:
|
case MDB_TEXT:
|
||||||
mdb_unicode2ascii(mdb, field->value, field->siz, tmpbuf, sizeof(tmpbuf));
|
mdb_unicode2ascii(mdb, field->value, field->siz, tmpbuf, sizeof(tmpbuf));
|
||||||
ret = mdb_test_string(node, tmpbuf);
|
ret = mdb_test_string(node, tmpbuf);
|
||||||
break;
|
break;
|
||||||
case MDB_MEMO:
|
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));
|
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);
|
//printf("%s\n",val);
|
||||||
ret = mdb_test_string(node, val);
|
ret = mdb_test_string(node, val);
|
||||||
|
@ -92,6 +92,12 @@ MdbTableDef *mdb_read_table(MdbCatalogEntry *entry)
|
|||||||
mdb_free_tabledef(table);
|
mdb_free_tabledef(table);
|
||||||
return NULL;
|
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);
|
table->usage_map = g_memdup2((char*)buf + row_start, table->map_sz);
|
||||||
if (mdb_get_option(MDB_DEBUG_USAGE))
|
if (mdb_get_option(MDB_DEBUG_USAGE))
|
||||||
mdb_buffer_dump(buf, row_start, table->map_sz);
|
mdb_buffer_dump(buf, row_start, table->map_sz);
|
||||||
@ -355,6 +361,9 @@ unsigned int i, bitn;
|
|||||||
guint32 pgnum;
|
guint32 pgnum;
|
||||||
|
|
||||||
table = mdb_read_table(entry);
|
table = mdb_read_table(entry);
|
||||||
|
if (!table)
|
||||||
|
return;
|
||||||
|
|
||||||
fprintf(stdout,"definition page = %lu\n",entry->table_pg);
|
fprintf(stdout,"definition page = %lu\n",entry->table_pg);
|
||||||
fprintf(stdout,"number of datarows = %d\n",table->num_rows);
|
fprintf(stdout,"number of datarows = %d\n",table->num_rows);
|
||||||
fprintf(stdout,"number of columns = %d\n",table->num_cols);
|
fprintf(stdout,"number of columns = %d\n",table->num_cols);
|
||||||
|
@ -5,6 +5,9 @@ lib_LTLIBRARIES = libmdbodbc.la
|
|||||||
libdir=@libdir@/odbc
|
libdir=@libdir@/odbc
|
||||||
AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(ODBC_CFLAGS)
|
AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(ODBC_CFLAGS)
|
||||||
libmdbodbc_la_SOURCES = odbc.c connectparams.c
|
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_LIBADD = ../libmdb/libmdb.la ../sql/libmdbsql.la $(ODBC_LIBS)
|
||||||
libmdbodbc_la_LDFLAGS = -avoid-version -export-symbols-regex '^(SQL|ODBCINST)' $(ODBC_LDFLAGS)
|
libmdbodbc_la_LDFLAGS = -avoid-version -export-symbols-regex '^(SQL|ODBCINST)' $(ODBC_LDFLAGS)
|
||||||
lib_LTLIBRARIES += libmdbodbcW.la
|
lib_LTLIBRARIES += libmdbodbcW.la
|
||||||
|
@ -23,11 +23,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#ifdef UNIXODBC
|
#if defined(HAVE_ODBCINST_H)
|
||||||
#include <odbcinstext.h>
|
|
||||||
#else
|
|
||||||
#include <odbcinst.h>
|
#include <odbcinst.h>
|
||||||
#endif
|
#elif defined(HAVE_IODBCINST_H)
|
||||||
|
#include <iodbcinst.h>
|
||||||
|
#endif /* HAVE_ODBCINST_H */
|
||||||
#include "connectparams.h"
|
#include "connectparams.h"
|
||||||
|
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ void FreeConnectParams (ConnectParams* params)
|
|||||||
|
|
||||||
gchar* GetConnectParam (ConnectParams* params, const gchar* paramName)
|
gchar* GetConnectParam (ConnectParams* params, const gchar* paramName)
|
||||||
{
|
{
|
||||||
static __thread char tmp[FILENAME_MAX];
|
static TLS char tmp[FILENAME_MAX];
|
||||||
|
|
||||||
/* use old servername */
|
/* use old servername */
|
||||||
tmp[0] = '\0';
|
tmp[0] = '\0';
|
||||||
@ -213,7 +213,7 @@ gchar* ExtractDSN (ConnectParams* params, const gchar* connectString)
|
|||||||
/*
|
/*
|
||||||
* Position ourselves to the beginning of "DSN"
|
* Position ourselves to the beginning of "DSN"
|
||||||
*/
|
*/
|
||||||
p = strstr (connectString, "DSN");
|
p = strcasestr (connectString, "DSN");
|
||||||
if (!p) return NULL;
|
if (!p) return NULL;
|
||||||
/*
|
/*
|
||||||
* Position ourselves to the "="
|
* Position ourselves to the "="
|
||||||
@ -243,9 +243,9 @@ gchar* ExtractDBQ (ConnectParams* params, const gchar* connectString)
|
|||||||
if (!params)
|
if (!params)
|
||||||
return NULL;
|
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;
|
if (!p) return NULL;
|
||||||
/*
|
/*
|
||||||
* Position ourselves to the "="
|
* Position ourselves to the "="
|
||||||
@ -297,24 +297,4 @@ static void cleanup (gpointer key, gpointer value, gpointer user_data)
|
|||||||
g_free (value);
|
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 <sql.h>
|
||||||
#include <sqlext.h>
|
#include <sqlext.h>
|
||||||
#if defined(UNIXODBC)
|
#if defined(HAVE_ODBCINST_H)
|
||||||
# include <odbcinst.h>
|
# include <odbcinst.h>
|
||||||
#elif defined(IODBC)
|
#elif defined(HAVE_IODBCINST_H)
|
||||||
# include <iodbcinst.h>
|
# include <iodbcinst.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -72,12 +72,16 @@ struct _hstmt {
|
|||||||
struct _sql_bind_info {
|
struct _sql_bind_info {
|
||||||
int column_number;
|
int column_number;
|
||||||
int column_bindtype; /* type/conversion required */
|
int column_bindtype; /* type/conversion required */
|
||||||
int column_bindlen; /* size of varaddr buffer */
|
SQLLEN column_bindlen; /* size of varaddr buffer */
|
||||||
int *column_lenbind; /* where to store length of varaddr used */
|
SQLLEN *column_lenbind; /* where to store length of varaddr used */
|
||||||
char *varaddr;
|
char *varaddr;
|
||||||
struct _sql_bind_info *next;
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
185
src/odbc/odbc.c
185
src/odbc/odbc.c
@ -108,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
|
// 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_date_fmt( dbc->sqlconn->mdb, "%F %H:%M:%S" );
|
||||||
mdb_set_shortdate_fmt( dbc->sqlconn->mdb, "%F" );
|
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;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return SQL_ERROR;
|
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(
|
SQLRETURN SQL_API SQLDriverConnect(
|
||||||
SQLHDBC hdbc,
|
SQLHDBC hdbc,
|
||||||
SQLHWND hwnd,
|
SQLHWND hwnd,
|
||||||
@ -490,7 +513,7 @@ SQLRETURN SQL_API SQLBindCol(
|
|||||||
/* if this is a repeat */
|
/* if this is a repeat */
|
||||||
if (cur) {
|
if (cur) {
|
||||||
cur->column_bindtype = fCType;
|
cur->column_bindtype = fCType;
|
||||||
cur->column_lenbind = (int *)pcbValue;
|
cur->column_lenbind = pcbValue;
|
||||||
cur->column_bindlen = cbValueMax;
|
cur->column_bindlen = cbValueMax;
|
||||||
cur->varaddr = (char *) rgbValue;
|
cur->varaddr = (char *) rgbValue;
|
||||||
} else {
|
} else {
|
||||||
@ -499,7 +522,7 @@ SQLRETURN SQL_API SQLBindCol(
|
|||||||
newitem->column_number = icol;
|
newitem->column_number = icol;
|
||||||
newitem->column_bindtype = fCType;
|
newitem->column_bindtype = fCType;
|
||||||
newitem->column_bindlen = cbValueMax;
|
newitem->column_bindlen = cbValueMax;
|
||||||
newitem->column_lenbind = (int *)pcbValue;
|
newitem->column_lenbind = pcbValue;
|
||||||
newitem->varaddr = (char *) rgbValue;
|
newitem->varaddr = (char *) rgbValue;
|
||||||
/* if there's no head yet */
|
/* if there's no head yet */
|
||||||
if (! stmt->bind_head) {
|
if (! stmt->bind_head) {
|
||||||
@ -833,13 +856,13 @@ unbind_columns(struct _hstmt *stmt)
|
|||||||
stmt->bind_head = NULL;
|
stmt->bind_head = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLRETURN SQL_API SQLFetch(
|
SQLRETURN SQLFetch(
|
||||||
SQLHSTMT hstmt)
|
SQLHSTMT hstmt)
|
||||||
{
|
{
|
||||||
struct _hstmt *stmt = (struct _hstmt *) hstmt;
|
struct _hstmt *stmt = (struct _hstmt *) hstmt;
|
||||||
struct _sql_bind_info *cur = stmt->bind_head;
|
struct _sql_bind_info *cur = stmt->bind_head;
|
||||||
|
|
||||||
TRACE("SQLFetch");
|
TRACE("SQLFetch");
|
||||||
|
|
||||||
if ( stmt->sql->limit >= 0 && stmt->rows_affected == stmt->sql->limit ) {
|
if ( stmt->sql->limit >= 0 && stmt->rows_affected == stmt->sql->limit ) {
|
||||||
return SQL_NO_DATA_FOUND;
|
return SQL_NO_DATA_FOUND;
|
||||||
}
|
}
|
||||||
@ -1217,13 +1240,15 @@ SQLRETURN SQL_API SQLGetData(
|
|||||||
if (col->col_type == MDB_BOOL) {
|
if (col->col_type == MDB_BOOL) {
|
||||||
// bool cannot be null
|
// bool cannot be null
|
||||||
if (fCType == SQL_C_CHAR) {
|
if (fCType == SQL_C_CHAR) {
|
||||||
if ( col->cur_value_len )
|
((SQLCHAR *)rgbValue)[0] = col->cur_value_len ? '0' : '1';
|
||||||
((char *)rgbValue)[0] = '0';
|
((SQLCHAR *)rgbValue)[1] = '\0';
|
||||||
else
|
|
||||||
((char *)rgbValue)[0] = '1';
|
|
||||||
((char *)rgbValue)[1] = '\0';
|
|
||||||
if (pcbValue)
|
if (pcbValue)
|
||||||
*pcbValue = sizeof(SQLCHAR);
|
*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 {
|
} else {
|
||||||
*(BOOL*)rgbValue = col->cur_value_len ? 0 : 1;
|
*(BOOL*)rgbValue = col->cur_value_len ? 0 : 1;
|
||||||
if (pcbValue)
|
if (pcbValue)
|
||||||
@ -1257,7 +1282,7 @@ SQLRETURN SQL_API SQLGetData(
|
|||||||
found_bound_type:
|
found_bound_type:
|
||||||
if (fCType==SQL_C_DEFAULT)
|
if (fCType==SQL_C_DEFAULT)
|
||||||
fCType = _odbc_get_client_type(col);
|
fCType = _odbc_get_client_type(col);
|
||||||
if (fCType == SQL_C_CHAR)
|
if (fCType == SQL_C_CHAR || fCType == SQL_C_WCHAR)
|
||||||
goto to_c_char;
|
goto to_c_char;
|
||||||
switch(col->col_type) {
|
switch(col->col_type) {
|
||||||
case MDB_BYTE:
|
case MDB_BYTE:
|
||||||
@ -1335,14 +1360,85 @@ SQLRETURN SQL_API SQLGetData(
|
|||||||
break;
|
break;
|
||||||
// case MDB_MONEY: TODO
|
// case MDB_MONEY: TODO
|
||||||
case MDB_FLOAT:
|
case MDB_FLOAT:
|
||||||
*(float*)rgbValue = mdb_get_single(mdb->pg_buf, col->cur_value_start);
|
switch (fCType) {
|
||||||
if (pcbValue)
|
case SQL_C_FLOAT:
|
||||||
*pcbValue = sizeof(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;
|
break;
|
||||||
case MDB_DOUBLE:
|
case MDB_DOUBLE:
|
||||||
*(double*)rgbValue = mdb_get_double(mdb->pg_buf, col->cur_value_start);
|
switch (fCType) {
|
||||||
if (pcbValue)
|
case SQL_C_DOUBLE:
|
||||||
*pcbValue = sizeof(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;
|
break;
|
||||||
#if ODBCVER >= 0x0300
|
#if ODBCVER >= 0x0300
|
||||||
// returns text if old odbc
|
// returns text if old odbc
|
||||||
@ -1417,7 +1513,7 @@ SQLRETURN SQL_API SQLGetData(
|
|||||||
free(stmt->ole_str);
|
free(stmt->ole_str);
|
||||||
stmt->ole_str = NULL;
|
stmt->ole_str = NULL;
|
||||||
break;
|
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:
|
to_c_char:
|
||||||
{
|
{
|
||||||
if (cbValueMax < 0) {
|
if (cbValueMax < 0) {
|
||||||
@ -1425,6 +1521,7 @@ SQLRETURN SQL_API SQLGetData(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
char *str = NULL;
|
char *str = NULL;
|
||||||
|
SQLWCHAR *wstr = NULL;
|
||||||
if (col->col_type == MDB_NUMERIC) {
|
if (col->col_type == MDB_NUMERIC) {
|
||||||
str = mdb_numeric_to_string(mdb, col->cur_value_start,
|
str = mdb_numeric_to_string(mdb, col->cur_value_start,
|
||||||
col->col_scale, col->col_prec);
|
col->col_scale, col->col_prec);
|
||||||
@ -1433,37 +1530,47 @@ SQLRETURN SQL_API SQLGetData(
|
|||||||
col->cur_value_start, col->col_type, col->cur_value_len);
|
col->cur_value_start, col->col_type, col->cur_value_len);
|
||||||
}
|
}
|
||||||
size_t len = strlen(str);
|
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) {
|
if (stmt->pos >= len) {
|
||||||
free(str);
|
free(wstr); wstr = NULL;
|
||||||
str = NULL;
|
free(str); str = NULL;
|
||||||
return SQL_NO_DATA;
|
return SQL_NO_DATA;
|
||||||
}
|
}
|
||||||
if (pcbValue) {
|
if (pcbValue) {
|
||||||
*pcbValue = len - stmt->pos;
|
*pcbValue = (len - stmt->pos) * charsize;
|
||||||
}
|
}
|
||||||
if (cbValueMax == 0) {
|
if (cbValueMax == 0) {
|
||||||
free(str);
|
free(wstr); wstr = NULL;
|
||||||
str = NULL;
|
free(str); str = NULL;
|
||||||
return SQL_SUCCESS_WITH_INFO;
|
return SQL_SUCCESS_WITH_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int totalSizeRemaining = len - stmt->pos;
|
const int totalCharactersRemaining = len - stmt->pos;
|
||||||
const int partsRemain = cbValueMax - 1 < totalSizeRemaining;
|
const int partsRemain = cbValueMax/charsize - 1 < totalCharactersRemaining;
|
||||||
const int sizeToReadThisPart = partsRemain ? cbValueMax - 1 : totalSizeRemaining;
|
const int charactersToReadThisPart = partsRemain ? cbValueMax/charsize - 1 : totalCharactersRemaining;
|
||||||
memcpy(rgbValue, str + stmt->pos, sizeToReadThisPart);
|
|
||||||
|
|
||||||
((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) {
|
if (partsRemain) {
|
||||||
stmt->pos += cbValueMax - 1;
|
stmt->pos += charactersToReadThisPart;
|
||||||
free(str); str = NULL;
|
|
||||||
strcpy(stmt->sqlState, "01004"); // truncated
|
strcpy(stmt->sqlState, "01004"); // truncated
|
||||||
return SQL_SUCCESS_WITH_INFO;
|
return SQL_SUCCESS_WITH_INFO;
|
||||||
}
|
}
|
||||||
stmt->pos = len;
|
stmt->pos = len;
|
||||||
free(str);
|
|
||||||
str = NULL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1948,14 +2055,14 @@ SQLRETURN SQL_API SQLDataSources(
|
|||||||
|
|
||||||
static int _odbc_fix_literals(struct _hstmt *stmt)
|
static int _odbc_fix_literals(struct _hstmt *stmt)
|
||||||
{
|
{
|
||||||
char tmp[4096],begin_tag[11];
|
char tmp[4096];
|
||||||
char *s, *d, *p;
|
char *s, *d, *p;
|
||||||
int i, quoted = 0, find_end = 0;
|
int i, quoted = 0, find_end = 0;
|
||||||
char quote_char;
|
char quote_char = '\0';
|
||||||
|
|
||||||
s=stmt->query;
|
s=stmt->query;
|
||||||
d=tmp;
|
d=tmp;
|
||||||
while (*s) {
|
while (*s && d<tmp+sizeof(tmp)) {
|
||||||
if (!quoted && (*s=='"' || *s=='\'')) {
|
if (!quoted && (*s=='"' || *s=='\'')) {
|
||||||
quoted = 1;
|
quoted = 1;
|
||||||
quote_char = *s;
|
quote_char = *s;
|
||||||
@ -1970,9 +2077,7 @@ static int _odbc_fix_literals(struct _hstmt *stmt)
|
|||||||
/* garbage */
|
/* garbage */
|
||||||
*d++=*s++;
|
*d++=*s++;
|
||||||
} else {
|
} else {
|
||||||
strncpy(begin_tag, s, i);
|
/* printf("begin tag %.*s\n", i, s); */
|
||||||
begin_tag[i] = '\0';
|
|
||||||
/* printf("begin tag %s\n", begin_tag); */
|
|
||||||
s += i;
|
s += i;
|
||||||
find_end = 1;
|
find_end = 1;
|
||||||
}
|
}
|
||||||
@ -1980,8 +2085,8 @@ static int _odbc_fix_literals(struct _hstmt *stmt)
|
|||||||
*d++=*s++;
|
*d++=*s++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*d='\0';
|
|
||||||
strcpy(stmt->query,tmp);
|
snprintf(stmt->query, sizeof(stmt->query), "%.*s", (int)(d-tmp), tmp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2088,7 +2193,7 @@ static const char * _odbc_get_client_type_name(MdbColumn *col)
|
|||||||
case MDB_COMPLEX:
|
case MDB_COMPLEX:
|
||||||
return "COMPLEX";
|
return "COMPLEX";
|
||||||
default:
|
default:
|
||||||
// fprintf(stderr,"Unknown type %d\n",srv_type);
|
fprintf(stderr,"Unknown type for column %s: %d\n",col->name,col->col_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* 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 SQL_NOUNICODEMAP
|
||||||
#define UNICODE
|
#define UNICODE
|
||||||
|
|
||||||
@ -61,27 +64,6 @@ static size_t unicode2ascii(struct _hdbc* dbc, const SQLWCHAR *_in, size_t _in_c
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sqlwlen(SQLWCHAR *p){
|
static int sqlwlen(SQLWCHAR *p){
|
||||||
int r=0;
|
int r=0;
|
||||||
for(;*p;r++)
|
for(;*p;r++)
|
||||||
@ -161,7 +143,7 @@ SQLRETURN SQL_API SQLDescribeColW(
|
|||||||
size_t l=cbColNameMax*4+1;
|
size_t l=cbColNameMax*4+1;
|
||||||
SQLCHAR *tmp=calloc(l,1);
|
SQLCHAR *tmp=calloc(l,1);
|
||||||
SQLRETURN ret = SQLDescribeCol(hstmt, icol, tmp, l, (SQLSMALLINT*)&l, pfSqlType, pcbColDef, pibScale, pfNullable);
|
SQLRETURN ret = SQLDescribeCol(hstmt, icol, tmp, l, (SQLSMALLINT*)&l, pfSqlType, pcbColDef, pibScale, pfNullable);
|
||||||
*pcbColName = ascii2unicode(((struct _hstmt*)hstmt)->hdbc, (char*)tmp, l, szColName, cbColNameMax);
|
*pcbColName = _mdb_odbc_ascii2unicode(((struct _hstmt*)hstmt)->hdbc, (char*)tmp, l, szColName, cbColNameMax);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -183,7 +165,7 @@ SQLRETURN SQL_API SQLColAttributesW(
|
|||||||
size_t l=cbDescMax*4+1;
|
size_t l=cbDescMax*4+1;
|
||||||
SQLCHAR *tmp=calloc(l,1);
|
SQLCHAR *tmp=calloc(l,1);
|
||||||
SQLRETURN ret=SQLColAttributes(hstmt,icol,fDescType,tmp,l,(SQLSMALLINT*)&l,pfDesc);
|
SQLRETURN ret=SQLColAttributes(hstmt,icol,fDescType,tmp,l,(SQLSMALLINT*)&l,pfDesc);
|
||||||
*pcbDesc = ascii2unicode(((struct _hstmt *)hstmt)->hdbc, (char*)tmp, l, (SQLWCHAR*)rgbDesc, cbDescMax);
|
*pcbDesc = _mdb_odbc_ascii2unicode(((struct _hstmt *)hstmt)->hdbc, (char*)tmp, l, (SQLWCHAR*)rgbDesc, cbDescMax);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -210,8 +192,8 @@ SQLRETURN SQL_API SQLErrorW(
|
|||||||
if (result == SQL_SUCCESS) {
|
if (result == SQL_SUCCESS) {
|
||||||
struct _hdbc *dbc = hstmt ? ((struct _hstmt *)hstmt)->hdbc : hdbc;
|
struct _hdbc *dbc = hstmt ? ((struct _hstmt *)hstmt)->hdbc : hdbc;
|
||||||
size_t pcb;
|
size_t pcb;
|
||||||
ascii2unicode(dbc, (char*)szSqlState8, sizeof(szSqlState8), szSqlState, sizeof(szSqlState8));
|
_mdb_odbc_ascii2unicode(dbc, (char*)szSqlState8, sizeof(szSqlState8), szSqlState, sizeof(szSqlState8));
|
||||||
pcb = ascii2unicode(dbc, (char*)szErrorMsg8, pcbErrorMsg8, szErrorMsg, cbErrorMsgMax);
|
pcb = _mdb_odbc_ascii2unicode(dbc, (char*)szErrorMsg8, pcbErrorMsg8, szErrorMsg, cbErrorMsgMax);
|
||||||
if (pcbErrorMsg) *pcbErrorMsg = pcb;
|
if (pcbErrorMsg) *pcbErrorMsg = pcb;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -259,24 +241,6 @@ SQLRETURN SQL_API SQLColumnsW(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLRETURN SQL_API SQLGetDataW(
|
|
||||||
SQLHSTMT hstmt,
|
|
||||||
SQLUSMALLINT icol,
|
|
||||||
SQLSMALLINT fCType,
|
|
||||||
SQLPOINTER rgbValue,
|
|
||||||
SQLLEN cbValueMax,
|
|
||||||
SQLLEN *pcbValue)
|
|
||||||
{
|
|
||||||
//todo: treat numbers correctly
|
|
||||||
|
|
||||||
size_t l=cbValueMax*4+1;
|
|
||||||
SQLCHAR *tmp=calloc(l,1);
|
|
||||||
SQLRETURN ret = SQLGetData(hstmt, icol, fCType, tmp, l, (SQLLEN*)&l);
|
|
||||||
*pcbValue = ascii2unicode(((struct _hstmt *)hstmt)->hdbc, (char*)tmp, l, (SQLWCHAR*)rgbValue, cbValueMax);
|
|
||||||
free(tmp);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
SQLRETURN SQL_API SQLGetInfoW(
|
SQLRETURN SQL_API SQLGetInfoW(
|
||||||
SQLHDBC hdbc,
|
SQLHDBC hdbc,
|
||||||
SQLUSMALLINT fInfoType,
|
SQLUSMALLINT fInfoType,
|
||||||
@ -292,7 +256,7 @@ SQLRETURN SQL_API SQLGetInfoW(
|
|||||||
size_t l=cbInfoValueMax*4+1;
|
size_t l=cbInfoValueMax*4+1;
|
||||||
SQLCHAR *tmp=calloc(l,1);
|
SQLCHAR *tmp=calloc(l,1);
|
||||||
SQLRETURN ret = SQLGetInfo(hdbc, fInfoType, tmp, l, (SQLSMALLINT*)&l);
|
SQLRETURN ret = SQLGetInfo(hdbc, fInfoType, tmp, l, (SQLSMALLINT*)&l);
|
||||||
size_t pcb = ascii2unicode((struct _hdbc *)hdbc, (char*)tmp, l, (SQLWCHAR*)rgbInfoValue, cbInfoValueMax);
|
size_t pcb = _mdb_odbc_ascii2unicode((struct _hdbc *)hdbc, (char*)tmp, l, (SQLWCHAR*)rgbInfoValue, cbInfoValueMax);
|
||||||
if(pcbInfoValue)*pcbInfoValue=pcb;
|
if(pcbInfoValue)*pcbInfoValue=pcb;
|
||||||
free(tmp);
|
free(tmp);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -113,7 +113,7 @@ strptime\( { return STRPTIME; }
|
|||||||
return STRING;
|
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;
|
yylval->name = g_strdup(yytext); return NUMBER;
|
||||||
}
|
}
|
||||||
~?(\/?[a-z0-9\.\-\_\!\~\'\(\)\%\xa0-\xff]+)+ {
|
~?(\/?[a-z0-9\.\-\_\!\~\'\(\)\%\xa0-\xff]+)+ {
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
if ENABLE_BASH_COMPLETION
|
if ENABLE_BASH_COMPLETION
|
||||||
bashcompletiondir = $(BASH_COMPLETION_DIR)
|
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
|
endif
|
||||||
|
@ -35,17 +35,17 @@ char quote_text = 1;
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
int started;
|
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)
|
if (argc < 3)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Usage: %s <file> <table>\n", argv [0]);
|
fprintf (stderr, "Usage: %s <file> <table>\n", argv [0]);
|
||||||
exit (1);
|
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);
|
mdb = mdb_open (argv [1], MDB_NOFLAGS);
|
||||||
if (!mdb)
|
if (!mdb)
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -42,16 +42,16 @@ FILE *typesfile;
|
|||||||
FILE *headerfile;
|
FILE *headerfile;
|
||||||
FILE *cfile;
|
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("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("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("See https://github.com/mdbtools/mdbtools/issues/197\n", stderr);
|
||||||
fputs("\n", stderr);
|
fputs("\n", stderr);
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
fprintf (stderr, "Usage: %s <file>\n",argv[0]);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
/* open the database */
|
/* open the database */
|
||||||
|
|
||||||
mdb = mdb_open (argv[1], MDB_NOFLAGS);
|
mdb = mdb_open (argv[1], MDB_NOFLAGS);
|
||||||
@ -92,6 +92,11 @@ FILE *cfile;
|
|||||||
entry->object_name, entry->object_name);
|
entry->object_name, entry->object_name);
|
||||||
fprintf (cfile, "\tfprintf (stdout, \"**************** %s ****************\\n\");\n", entry->object_name);
|
fprintf (cfile, "\tfprintf (stdout, \"**************** %s ****************\\n\");\n", entry->object_name);
|
||||||
table = mdb_read_table (entry);
|
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 */
|
/* get the columns */
|
||||||
mdb_read_columns (table);
|
mdb_read_columns (table);
|
||||||
|
@ -53,17 +53,17 @@ main (int argc, char **argv)
|
|||||||
int lastcomma;
|
int lastcomma;
|
||||||
int i;
|
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)
|
if (argc < 2)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Usage: %s <file> (assumed extension .txt)\n",argv[0]);
|
fprintf (stderr, "Usage: %s <file> (assumed extension .txt)\n",argv[0]);
|
||||||
exit (1);
|
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]);
|
strcpy (txt_filename, argv [1]);
|
||||||
txtfile = fopen (txt_filename, "r");
|
txtfile = fopen (txt_filename, "r");
|
||||||
if (!txtfile) {
|
if (!txtfile) {
|
||||||
|
@ -97,9 +97,9 @@ main(int argc, char **argv)
|
|||||||
g_free(buf);
|
g_free(buf);
|
||||||
mdb_free_tabledef(table);
|
mdb_free_tabledef(table);
|
||||||
g_free(table_name);
|
g_free(table_name);
|
||||||
g_free(propColName);
|
|
||||||
mdb_close(mdb);
|
mdb_close(mdb);
|
||||||
printf("Column %s not found in MSysObjects!\n", propColName);
|
printf("Column %s not found in MSysObjects!\n", propColName);
|
||||||
|
g_free(propColName);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +304,7 @@ find_sql_terminator(char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sp = &s[len-1];
|
sp = &s[len-1];
|
||||||
while (sp > s && isspace(*sp)) {
|
while (sp > s && isspace((int)*sp)) {
|
||||||
sp--;
|
sp--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,7 +322,7 @@ main(int argc, char **argv)
|
|||||||
char prompt[20];
|
char prompt[20];
|
||||||
int line = 0;
|
int line = 0;
|
||||||
char *mybuf;
|
char *mybuf;
|
||||||
unsigned int bufsz;
|
size_t bufsz;
|
||||||
MdbSQL *sql;
|
MdbSQL *sql;
|
||||||
FILE *in = NULL, *out = NULL;
|
FILE *in = NULL, *out = NULL;
|
||||||
char *filename_in=NULL, *filename_out=NULL;
|
char *filename_in=NULL, *filename_out=NULL;
|
||||||
@ -408,7 +408,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
/* give the buffer an initial size */
|
/* give the buffer an initial size */
|
||||||
bufsz = 4096;
|
bufsz = 4096;
|
||||||
mybuf = g_malloc(bufsz);
|
mybuf = malloc(bufsz);
|
||||||
mybuf[0]='\0';
|
mybuf[0]='\0';
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -420,7 +420,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
if (in) {
|
if (in) {
|
||||||
s=calloc(bufsz, 1);
|
s=calloc(bufsz, 1);
|
||||||
if (!fgets(s, bufsz, in)) {
|
if (!fgets(s, (int)bufsz, in)) {
|
||||||
// Backwards compatibility with older MDBTools
|
// Backwards compatibility with older MDBTools
|
||||||
// Files read from the command line had an
|
// Files read from the command line had an
|
||||||
// implicit "go" at the end
|
// implicit "go" at the end
|
||||||
@ -464,7 +464,7 @@ main(int argc, char **argv)
|
|||||||
if (in) {
|
if (in) {
|
||||||
fprintf(stderr, "Can not handle nested opens\n");
|
fprintf(stderr, "Can not handle nested opens\n");
|
||||||
} else {
|
} else {
|
||||||
while (*fname && isspace(*fname))
|
while (*fname && isspace((int)*fname))
|
||||||
fname++;
|
fname++;
|
||||||
if (!(in = fopen(fname, "r"))) {
|
if (!(in = fopen(fname, "r"))) {
|
||||||
fprintf(stderr,"Unable to open file %s\n", fname);
|
fprintf(stderr,"Unable to open file %s\n", fname);
|
||||||
@ -478,7 +478,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
while (strlen(mybuf) + strlen(s) > bufsz) {
|
while (strlen(mybuf) + strlen(s) > bufsz) {
|
||||||
bufsz *= 2;
|
bufsz *= 2;
|
||||||
mybuf = (char *) g_realloc(mybuf, bufsz);
|
mybuf = realloc(mybuf, bufsz);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_READLINE_HISTORY
|
#ifdef HAVE_READLINE_HISTORY
|
||||||
/* don't record blank lines, or lines read from files
|
/* don't record blank lines, or lines read from files
|
||||||
@ -500,7 +500,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
mdb_sql_exit(sql);
|
mdb_sql_exit(sql);
|
||||||
|
|
||||||
g_free(mybuf);
|
free(mybuf);
|
||||||
if (s) free(s);
|
if (s) free(s);
|
||||||
if (out) fclose(out);
|
if (out) fclose(out);
|
||||||
if ((in) && (in != stdin)) fclose(in);
|
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
|
# Simple test script; run after performing
|
||||||
# git clone https://github.com/mdbtools/mdbtestdata.git test
|
# 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"
|
set -o errexit
|
||||||
./src/util/mdb-count test/data/ASampleDatabase.accdb "Asset Items"
|
set -o nounset
|
||||||
./src/util/mdb-count test/data/nwind.mdb "Umsätze"
|
|
||||||
./src/util/mdb-prop test/data/ASampleDatabase.accdb "Asset Items"
|
LANG=C.UTF-8
|
||||||
./src/util/mdb-prop test/data/nwind.mdb "Umsätze"
|
CDPATH= cd -- "$(dirname -- "$0")"
|
||||||
./src/util/mdb-schema test/data/ASampleDatabase.accdb
|
|
||||||
./src/util/mdb-schema test/data/nwind.mdb
|
parseArgs() {
|
||||||
./src/util/mdb-schema test/data/nwind.mdb -T "Umsätze" postgres
|
MT_OUTPUT_KIND=verbose
|
||||||
./src/util/mdb-tables test/data/ASampleDatabase.accdb
|
while :; do
|
||||||
./src/util/mdb-tables test/data/nwind.mdb
|
if test $# -lt 1; then
|
||||||
./src/util/mdb-ver test/data/ASampleDatabase.accdb
|
break
|
||||||
./src/util/mdb-ver test/data/nwind.mdb
|
fi
|
||||||
./src/util/mdb-queries test/data/ASampleDatabase.accdb qryCostsSummedByOwner
|
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