Compare commits

...

87 Commits

Author SHA1 Message Date
Evan Miller
c6486ce68c Update GCC
Some checks failed
build / linux (clang, enable-glib, disable-iconv) (push) Has been cancelled
build / linux (clang, enable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc, disable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc, disable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc, enable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc, enable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc-11, disable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc-11, disable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc-11, enable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc-11, enable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc-12, disable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc-12, disable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc-12, enable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc-12, enable-glib, enable-iconv) (push) Has been cancelled
build / macos (clang, disable-glib, disable-iconv) (push) Has been cancelled
build / macos (clang, disable-glib, enable-iconv) (push) Has been cancelled
build / macos (clang, enable-glib, disable-iconv) (push) Has been cancelled
build / macos (clang, enable-glib, enable-iconv) (push) Has been cancelled
build / macos (gcc, disable-glib, disable-iconv) (push) Has been cancelled
build / macos (gcc, disable-glib, enable-iconv) (push) Has been cancelled
build / macos (gcc, enable-glib, disable-iconv) (push) Has been cancelled
build / macos (gcc, enable-glib, enable-iconv) (push) Has been cancelled
build / macos-iodbc (clang, disable-glib) (push) Has been cancelled
build / macos-iodbc (clang, enable-glib) (push) Has been cancelled
build / macos-iodbc (gcc, disable-glib) (push) Has been cancelled
build / macos-iodbc (gcc, enable-glib) (push) Has been cancelled
build / windows (disable-glib, disable-iconv) (push) Has been cancelled
build / windows (disable-glib, enable-iconv) (push) Has been cancelled
build / windows (enable-glib, disable-iconv) (push) Has been cancelled
build / windows (enable-glib, enable-iconv) (push) Has been cancelled
2025-05-23 07:58:16 -04:00
Evan Miller
11607108be CI fixes 2025-05-23 07:47:15 -04:00
Trương Chương Dương
6ed4188994
Fix error when ccompile by mingw32 and remove the $ from example shell script (#448)
Some checks failed
build / linux (clang, enable-glib, disable-iconv) (push) Has been cancelled
build / linux (clang, enable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc, disable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc, disable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc, enable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc, enable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc-10, disable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc-10, disable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc-10, enable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc-10, enable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc-9, disable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc-9, disable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc-9, enable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc-9, enable-glib, enable-iconv) (push) Has been cancelled
build / macos (clang, disable-glib, disable-iconv) (push) Has been cancelled
build / macos (clang, disable-glib, enable-iconv) (push) Has been cancelled
build / macos (clang, enable-glib, disable-iconv) (push) Has been cancelled
build / macos (clang, enable-glib, enable-iconv) (push) Has been cancelled
build / macos (gcc, disable-glib, disable-iconv) (push) Has been cancelled
build / macos (gcc, disable-glib, enable-iconv) (push) Has been cancelled
build / macos (gcc, enable-glib, disable-iconv) (push) Has been cancelled
build / macos (gcc, enable-glib, enable-iconv) (push) Has been cancelled
build / macos-iodbc (clang, disable-glib) (push) Has been cancelled
build / macos-iodbc (clang, enable-glib) (push) Has been cancelled
build / macos-iodbc (gcc, disable-glib) (push) Has been cancelled
build / macos-iodbc (gcc, enable-glib) (push) Has been cancelled
build / windows (disable-glib, disable-iconv) (push) Has been cancelled
build / windows (disable-glib, enable-iconv) (push) Has been cancelled
build / windows (enable-glib, disable-iconv) (push) Has been cancelled
build / windows (enable-glib, enable-iconv) (push) Has been cancelled
* Fix build error with mingw32

* Remove $ from shell example

---------

Co-authored-by: hacrot3000 <hacrot3000@gmail.com>
2025-05-20 09:00:20 -04:00
Evan Miller
b81b1c9271 Version 1.0.1
Some checks failed
build / linux (clang, enable-glib, disable-iconv) (push) Has been cancelled
build / linux (clang, enable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc, disable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc, disable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc, enable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc, enable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc-10, disable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc-10, disable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc-10, enable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc-10, enable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc-9, disable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc-9, disable-glib, enable-iconv) (push) Has been cancelled
build / linux (gcc-9, enable-glib, disable-iconv) (push) Has been cancelled
build / linux (gcc-9, enable-glib, enable-iconv) (push) Has been cancelled
build / macos (clang, disable-glib, disable-iconv) (push) Has been cancelled
build / macos (clang, disable-glib, enable-iconv) (push) Has been cancelled
build / macos (clang, enable-glib, disable-iconv) (push) Has been cancelled
build / macos (clang, enable-glib, enable-iconv) (push) Has been cancelled
build / macos (gcc, disable-glib, disable-iconv) (push) Has been cancelled
build / macos (gcc, disable-glib, enable-iconv) (push) Has been cancelled
build / macos (gcc, enable-glib, disable-iconv) (push) Has been cancelled
build / macos (gcc, enable-glib, enable-iconv) (push) Has been cancelled
build / macos-iodbc (clang, disable-glib) (push) Has been cancelled
build / macos-iodbc (clang, enable-glib) (push) Has been cancelled
build / macos-iodbc (gcc, disable-glib) (push) Has been cancelled
build / macos-iodbc (gcc, enable-glib) (push) Has been cancelled
build / windows (disable-glib, disable-iconv) (push) Has been cancelled
build / windows (disable-glib, enable-iconv) (push) Has been cancelled
build / windows (enable-glib, disable-iconv) (push) Has been cancelled
build / windows (enable-glib, enable-iconv) (push) Has been cancelled
2024-12-26 07:28:56 -05:00
Evan Miller
c5d4d1d4ee Fix txt2man path 2024-12-26 07:27:34 -05:00
Evan Miller
7625bfaebf Build fixes 2024-12-26 06:33:37 -05:00
Yuhang Ji
4c4ff13237
Update HACKING.md (#439)
Add the missing `& offset_mask` to `offset_stop of memo`
2024-07-04 10:19:57 -04:00
Evan Miller
2b2ef525c8 Fix another brew path on macos CI 2024-05-14 16:09:10 -04:00
Evan Miller
3a954c00d4 Fix brew paths on macos CI 2024-05-14 16:01:41 -04:00
Evan Miller
98d17badc6 Install unixodbc on macos CI 2024-05-14 14:24:51 -04:00
Evan Miller
997f4ec846 Install libtool on macos CI 2024-05-14 14:20:16 -04:00
bstoeger
f517db5df0
Move includes out of extern "C" block (#435)
"mbdtools.h" couldn't be included from C++ files, because the "glib.h"
include is in the extern "C" block. The latter includes C++ headers
for C++ source files, which define templates. These don't work with
extern "C" linkage and the compilation falls apart with numerous
errors.

To fix this problem, move the includes out of the extern "C" block.
2024-05-13 09:12:45 -04:00
Akkana Peck
7e057e3197
Fix a minor error in the mdb-json man page (#427) 2024-02-17 13:18:12 -05:00
Michele Locati
bb83142d47
Make test_script.sh less verbose (configurable) (#424) 2023-10-10 08:18:52 -04:00
Benjamin Holstein
bf77523c1d
Add support for SQLGetData converting floating point types (#422) 2023-10-06 18:31:26 -04:00
Michele Locati
c423097326
Fix invalid byte sequence error when running test_script.sh in some cases (#423)
This fixes the following error that may occur:
argument parsing failed: Invalid byte sequence in conversion input
2023-10-06 17:00:07 -04:00
Evan Miller
57d9e7a65e
Fix iodbc path on macos GH action (#421) 2023-09-10 14:16:02 -04:00
Elio Blanca
6640f9c707
fix use after free (#419) 2023-09-03 20:54:22 -04:00
Mladen Milinkovic
328249a628
Fixed truncating 64bit (SQL_NULL_DATA) values (#416) 2023-07-06 06:47:10 -04:00
Cédric Luthi
0d67eb4c73
Fix ODBC_LIBS for unixODBC (#415)
Using `$libdir` doesn't work and produces an error when configuring with ` ./configure --with-unixodbc=$(brew --prefix)`

> configure:21209: gcc -o conftest -g -O2 -Wall -Werror   -L/opt/homebrew/${exec_prefix}/lib conftest.c -lodbcinst   >&5
> ld: warning: directory not found for option '-L/opt/homebrew/${exec_prefix}/lib'
> ld: library not found for -lodbcinst
> clang: error: linker command failed with exit code 1 (use -v to see invocation)

Note that `warning: directory not found for option '-L/.../${exec_prefix}/lib'` is always emitted but if unixodbc is installed in `/usr/local/lib` linking would still work.
2023-07-04 14:56:41 -04:00
Cédric Luthi
633d1c091f
Make DSN and DBQ extraction from connection string case insensitive (#414) 2023-07-03 15:34:02 -04:00
drf5n
1097a48b80
Update README.md to remove INSTALL reference (#407)
Per https://github.com/mdbtools/mdbtools/issues/406#issuecomment-1463541923
2023-05-17 07:10:43 -04:00
Evan Miller
d9025dbf22 Two more code pages 2023-04-27 20:36:22 -04:00
Marco Manfredini
0e77b68e76
Add index and primary key output to the sqlite schema writer backend. (#402) 2023-02-02 05:36:22 -05:00
Evan Miller
9aa68a6ba1 Fix macos-iodbc CI build 2023-02-02 05:35:21 -05:00
Evan Miller
f7ae5e3f3c
Require glib2 2.68 or later (for g_memdup2) (#400) 2022-12-17 07:08:44 -05:00
Evan Miller
f14fbea093 Fix C89 errors 2022-12-17 05:41:45 -05:00
Evan Miller
d54f7b669f update gitignore 2022-12-17 05:36:26 -05:00
Evan Miller
0b96ecaff1
Fix windows GH action (#399) 2022-12-17 05:33:40 -05:00
Evan Miller
9e1ec2a588
Merge pull request #394 from h3xx/fix-bash-completion
Fix wrongly installed mdb-sql completion script
2022-08-26 08:26:57 -04:00
Dan Church
ff544c0b76
Fix wrongly installed mdb-sql completion script
Gate it behind the same conditional that the `mdb-sql` program is gated
behind.
2022-08-24 16:34:11 -05:00
Evan Miller
ab5beff0fa
Merge pull request #381 from schaanie17/dev
Changed mapping of MDB_DOUBLE for MySQL from float to double
2022-03-08 12:14:46 -08:00
Jan Langer
22af793623 Changed mapping of MDB_DOUBLE for MySQL from float to double 2022-03-08 19:18:08 +01:00
Evan Miller
ff085816b2
Merge pull request #377 from jwrdegoede/oss-fuzz-35972-null-ptr-deref-fix
Always check mdb_read_table() return value
2022-01-25 10:46:43 -05:00
Hans de Goede
03391fc913 Always check mdb_read_table() return value
A couple of places were missing NULL return value checks for
mdb_read_table()'s return value. Add these.

This fixes a NULL pointer deref while running ./test_script.sh
on the test mdb file from oss-fuzz/35972 .

Note this does NOT fix the original problem reported in oss-fuzz/35972
which reports a "Dynamic-stack-buffer-overflow WRITE 16" issue,
which I've been unable to reproduce.
2022-01-25 16:35:28 +01:00
Evan Miller
2da65ffdb3
Merge pull request #376 from jwrdegoede/oss-fuzz-36187-null-ptr-deref-fix
Fix null-ptr deref when table->map_sz is 0
2022-01-25 10:24:14 -05:00
Hans de Goede
4febc7b5c6 Fix null-ptr deref when table->map_sz is 0
The oss-fuzz/36187 attached
clusterfuzz-testcase-minimized-fuzz_mdb-4756071066501120
has a table with a map_sz of 0 and the g_memdup2 call returns NULL for
this, while mdb_map_find_next unconditionally derefs table->usage_map
to read the first byte which contains the map-type.

This leads to a NULL-ptr deref (at least with -fsanitize=address builds),
fix this by rejecting tables with a map_sz of 0.

Note this does NOT fix the original problem reported in oss-fuzz/36187
which reports a "Dynamic-stack-buffer-overflow WRITE 16" issue, which
I've been unable to reproduce.
2022-01-25 15:10:38 +01:00
pedromorgan@gmail.com
bcad261464 remove *.css.map 2021-11-24 10:41:48 -05:00
Evan Miller
ab9e4088a9 Merge branch 'dev' 2021-10-24 09:17:04 -04:00
Evan Miller
1f88aac676 Version 1.0.0 2021-10-24 09:05:19 -04:00
Evan Miller
c3df30837e Fix appveyor build 2021-09-30 09:59:16 -04:00
Christian Ehrhardt
22c379a611 Fix gcc-11 error "directive argument is null"
mdbtools triggered
In function ‘printf’,
    inlined from ‘mdb_dump_catalog’ at catalog.c:195:4:
/usr/include/powerpc64le-linux-gnu/bits/stdio2.h:112:10:
error: ‘%-12s’ directive argument is null [-Werror=format-overflow=]
  112 |   return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ());

This is due to mdb_get_objtype_string potentially returning NULL
which isn't allowed anymore as it would cause a segfault on the latter
print.

Fixes: #352

Signed-off-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
2021-09-30 08:19:53 -04:00
Evan Miller
5946750058 Version 1.0.0, Beta 7 2021-09-29 15:53:46 -04:00
Evan Miller
5ddad8660b Clarify some bit-shifting casts 2021-09-29 09:20:24 -04:00
Evan Miller
6de0227a36 Fix export of byte field values >127
Regression introduced in v0.9.3-beta1. Fixes #350
2021-09-29 09:16:22 -04:00
Evan Miller
b0a1f00113 Version 1.0.0, Beta 6 2021-09-12 16:00:21 -04:00
Evan Miller
77ee311eec Rearrange some ODBC code
Move unixODBC specific code to its own source file, and support old
iODBC installations that have only iodbinst.h.
2021-09-08 11:07:17 -04:00
Evan Miller
c04a3fb9a7 Merge branch 'dev' of github.com:mdbtools/mdbtools into dev 2021-09-08 10:58:30 -04:00
Evan Miller
ee5834d239 Print deprecation warnings before usage info 2021-09-08 10:50:28 -04:00
Evan Miller
f0d435ecdb Use TLS macro for cross-platform thread-local storage 2021-09-08 09:09:03 -04:00
Evan Miller
c137d64d13 Improved bounds checking 2021-09-08 06:41:58 -04:00
Evan Miller
4369721363 ODBC: Support SQL_C_WCHAR target type. Fixes #347
Also remove SQLFetchW and SQLGetDataW since they are not documented
in any other ODBC drivers.
2021-09-08 06:15:59 -04:00
Evan Miller
30d55a87ef Version 1.0.0, Beta 5 2021-09-06 15:22:23 -04:00
Evan Miller
a0e72c5dfa Implement SQLFetchW
Fixes #347
2021-09-06 15:09:46 -04:00
Evan Miller
16b2970931
Merge pull request #344 from nyalldawson/repid_odbc_str2
Customizable UUID format with mdb_uuid_to_string_fmt()
2021-08-30 09:17:25 -04:00
Nyall Dawson
98ef4a1663 [odbc] Ensure repid field formatting matching Microsoft Access ODBC
driver formatting of these fields (i.e. without surrounding {} braces)
2021-08-30 09:34:29 +10:00
Evan Miller
92dc91bfe8
Merge pull request #343 from nyalldawson/fix_index_read_errors
Fix accidental reads of non-index data as indices
2021-08-29 07:20:27 -04:00
Evan Miller
9b57c3ff66
Merge pull request #342 from nyalldawson/fix_double_conversion
Fix incorrect conversion of double values
2021-08-29 07:14:36 -04:00
Nyall Dawson
d94796d79b Fix accidental reads of non-index data as indices
Follow up be2a287f5c - it's hard to be sure from the commit message,
but I suspect the intention here was to reduce the number of indices
read in that particular situation, instead of allowing replacing
the number of real indices read direct from the table definition
with a larger number.

In any case, omitting a possible index definition which exists
is a safer approach then trying to read an index from non-index data.

Fixes #335
2021-08-29 16:22:34 +10:00
Nyall Dawson
dccc88b722 Fix incorrect conversion of double values
Fixes #339
2021-08-29 15:31:00 +10:00
Nyall Dawson
4c61f2d49b Handle sql queries where a double constant value has a trailing .
with no extra digits, e.g. "my_double_col" = 123.
2021-08-26 23:54:06 -04:00
Nyall Dawson
036f9b95c6 Handle sql queries where a double column is compared to an int
eg "my_double_column" = 123
2021-08-26 23:54:06 -04:00
Nyall Dawson
f4ca6b9e57 Handle sql queries where an integer column is compared to a double value
(e.g. "my_int_column" = 123.0)
2021-08-26 23:54:06 -04:00
Nyall Dawson
f557e6525b Better error output 2021-08-26 23:49:11 -04:00
Nyall Dawson
fa336fd325 Handle sql queries using REP_ID columns 2021-08-26 20:17:39 -04:00
Evan Miller
2aea0e2e41 Version 1.0.0, Beta 4 2021-08-25 08:49:57 -04:00
Evan Miller
6faf1b8615
Merge pull request #333 from mdbtools/odbc-sans-iconv
Remove iconv from ODBC Unicode driver
2021-08-25 08:34:48 -04:00
Evan Miller
ddd1be91a8 iconv fixes 2021-08-24 19:36:34 -04:00
Evan Miller
41d2a797ab Check for mbstowcs_l separately 2021-08-24 15:15:34 -04:00
Evan Miller
0164b4df1a Move Unicode ODBC functions to separate file (remove ODBC's iconv)
Use wcstombs and friends to perform Unicode conversion inside the ODBC
driver. Functionality should be identical as before, except that
installations without iconv will now be able to compile and install the
Unicode (libmdbodbcW) driver.

iconv remains present in the main libmdb library.
2021-08-23 13:39:39 -04:00
Evan Miller
00d597b6d3 Simplify header 2021-08-22 21:33:33 -04:00
Evan Miller
d3eea5f38e Simplify some locale_t code 2021-08-22 12:20:13 -04:00
Evan Miller
d1369407c5 --disable-iconv configure option 2021-08-22 11:36:31 -04:00
Evan Miller
0346f00735 Report iconv support at end of configure 2021-08-22 07:38:20 -04:00
Nyall Dawson
fadd536e2e
Add support for <> SQL operator (#329) 2021-08-22 00:28:29 -04:00
Evan Miller
6a15f6b1e6 Fix issue number in NEWS file 2021-08-20 08:34:31 -04:00
Evan Miller
f9c11b52cf Version 1.0.0, Beta 3 2021-08-20 08:29:13 -04:00
Evan Miller
49ee8272ab Remove _GNU_SOURCE (rely on AC_USE_SYSTEM_EXTENSIONS) 2021-08-20 08:23:24 -04:00
Evan Miller
f71924dab6 Use AC_USE_SYSTEM_EXTENSIONS
Defining _XOPEN_SOURCE explicitly in the source file leads to all kinds
of cross-platform headaches, plus incompatibilities between
configure-time capabilities and compile-time features. Let autoconf sort
out how to expose the largest number of functions in a way that is
consistent between configuration and compilation.
2021-08-20 08:06:19 -04:00
Evan Miller
89c7aa27b4 Fix create/drop incorrect argument order
Fixes #328
2021-08-20 08:03:44 -04:00
Evan Miller
148eed1546 Fix pkg-config Cflags
Previously we needed the cflags to include the original HAVE_ICONV value
so that MdbHandle looked the same to client applications as it did to
the compiled library. Now we use a .in file for the header so that these
definitions are not necessary when the client is compiling.
2021-08-20 07:24:40 -04:00
Evan Miller
3ad1669b2e Restore previous MdbHandle struct layout 2021-08-20 07:20:50 -04:00
Nyall Dawson
05d1b373d5
[odbc] Format boolean values correctly as SQL_C_CHAR (#327)
When a boolean column value is requested as a SQL_C_CHAR value,
correctly return a "1" or "0" string value
2021-08-19 21:21:46 -04:00
Evan Miller
45dcdbc5a6 Fix AC_PROG_LEX warning with autoconf 2.70 2021-08-19 18:23:37 -04:00
Evan Miller
0f0ecb0202 Clean up configure.ac 2021-08-19 18:23:20 -04:00
Evan Miller
00e4437a17 Git-ignore generated header 2021-08-19 08:11:30 -04:00
Evan Miller
05cb0449db Version 0.9.4, final 2021-08-04 16:52:37 -04:00
43 changed files with 1107 additions and 683 deletions

View File

@ -1,29 +1,35 @@
name: build
on: [ push, pull_request ]
env:
TEST_DATA_URL: https://github.com/mdbtools/mdbtestdata/archive/refs/heads/master.tar.gz
jobs:
linux:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
compiler: [ clang, gcc, gcc-9, gcc-10 ]
compiler: [ clang, gcc, gcc-11, gcc-12 ]
iconv: [ enable-iconv, disable-iconv]
glib: [ enable-glib, disable-glib ]
steps:
- name: Install packages
run: sudo apt install gettext
run: sudo apt install gettext unixodbc gcc-11 gcc-12
- uses: actions/checkout@v2
- name: Fetch test data
run: git clone https://github.com/mdbtools/mdbtestdata.git test
run: |
rm -rf test
mkdir test
curl -sSLf "$TEST_DATA_URL" | tar xz --strip-components=1 -C test
- name: Autoconf
run: autoreconf -i -f
- name: Configure
run: ./configure --disable-silent-rules --${{ matrix.glib }} --with-unixodbc=/usr
run: ./configure --disable-silent-rules --${{ matrix.glib }} --${{ matrix.iconv }} --with-unixodbc=/usr
env:
CC: ${{ matrix.compiler }}
- name: Make
run: make
- name: CLI tests
run: bash -e -x ./test_script.sh
run: ./test_script.sh --github
- name: SQL tests
run: bash -e -x ./test_sql.sh
- name: ODBC tests
@ -44,24 +50,28 @@ jobs:
fail-fast: false
matrix:
compiler: [ clang, gcc ]
iconv: [ enable-iconv, disable-iconv]
glib: [ enable-glib, disable-glib ]
steps:
- name: Install packages
run: brew install bison gawk automake
run: brew install bison gawk automake libtool unixodbc
- uses: actions/checkout@v2
- name: Fetch test data
run: git clone https://github.com/mdbtools/mdbtestdata.git test
run: |
rm -rf test
mkdir test
curl -sSLf "$TEST_DATA_URL" | tar xz --strip-components=1 -C test
- name: Autoconf
run: autoreconf -i -f
run: autoreconf -i -f -I $(brew --prefix)/share/gettext/m4
- name: Configure
run: ./configure --disable-silent-rules --${{ matrix.glib }} --with-unixodbc=/usr/local/opt
run: ./configure --disable-silent-rules --${{ matrix.glib }} --${{ matrix.iconv }} --with-unixodbc=/opt/homebrew/opt/unixodbc
env:
CC: ${{ matrix.compiler }}
YACC: /usr/local/opt/bison/bin/bison
YACC: /opt/homebrew/opt/bison/bin/bison
- name: Make
run: make
- name: CLI tests
run: bash -e -x ./test_script.sh
run: ./test_script.sh --github
- name: SQL tests
run: bash -e -x ./test_sql.sh
- name: ODBC tests
@ -84,20 +94,23 @@ jobs:
compiler: [ clang, gcc ]
glib: [ enable-glib, disable-glib ]
steps:
- name: Remove packages
run: brew unlink unixodbc
- name: Install packages
run: brew install libiodbc bison gawk automake
run: brew install bison gawk automake libtool libiodbc
- name: Add path
run: echo /opt/homebrew/opt/libiodbc/bin >> $GITHUB_PATH
- uses: actions/checkout@v2
- name: Fetch test data
run: git clone https://github.com/mdbtools/mdbtestdata.git test
run: |
rm -rf test
mkdir test
curl -sSLf "$TEST_DATA_URL" | tar xz --strip-components=1 -C test
- name: Autoconf
run: autoreconf -i -f
run: autoreconf -i -f -I $(brew --prefix)/share/gettext/m4
- name: Configure
run: ./configure --disable-silent-rules --${{ matrix.glib }} --with-iodbc=/usr/local/opt
run: ./configure --disable-silent-rules --${{ matrix.glib }} --with-iodbc=/opt/homebrew/opt/libiodbc
env:
CC: ${{ matrix.compiler }}
YACC: /usr/local/opt/bison/bin/bison
YACC: /opt/homebrew/opt/bison/bin/bison
- name: Make
run: make
- name: ODBC tests
@ -106,19 +119,37 @@ jobs:
MDBPATH: test/data
windows:
runs-on: windows-latest
env:
MSYSTEM: MINGW64
strategy:
fail-fast: false
matrix:
iconv: [ enable-iconv, disable-iconv]
glib: [ enable-glib, disable-glib ]
defaults:
run:
shell: msys2 {0}
steps:
- uses: msys2/setup-msys2@v2
with:
update: true
install: >-
autotools
base-devel
gcc
git
glib2-devel
- uses: actions/checkout@v2
- name: Check out test data
run: git clone https://github.com/mdbtools/mdbtestdata.git test
- name: Fetch test data
run: |
rm -rf test
mkdir test
curl -sSLf "$TEST_DATA_URL" | tar xz --strip-components=1 -C test
- name: Autoconf
run: C:\msys64\usr\bin\bash -c -l 'cd "$GITHUB_WORKSPACE" && autoreconf -i -f'
run: autoreconf -i -f
- name: Configure
run: C:\msys64\usr\bin\bash -c -l 'cd "$GITHUB_WORKSPACE" && ./configure'
run: ./configure --${{ matrix.glib }} --${{ matrix.iconv }}
- name: Make
run: C:\msys64\usr\bin\bash -c -l 'cd "$GITHUB_WORKSPACE" && make'
run: make
- name: Test
run: C:\msys64\usr\bin\bash -c -l 'cd "$GITHUB_WORKSPACE" && bash -e -x ./test_script.sh'
run: ./test_script.sh --github
- name: SQL Test
run: C:\msys64\usr\bin\bash -c -l 'cd "$GITHUB_WORKSPACE" && bash -e -x ./test_sql.sh'
run: bash -e -x ./test_sql.sh

9
.gitignore vendored
View File

@ -17,14 +17,18 @@ m4/
config.log
config.status
configure
/configure~
Makefile.in
Makefile
doc/*.1
INSTALL
include/mdbver.h
include/mdbtools.h
libmdb.pc
libmdbsql.pc
libtool
mdbtools-*.tar.gz
mdbtools-*.zip
src/extras/mdb-hexdump
src/odbc/unittest
src/sql/lexer.c
@ -51,9 +55,10 @@ src/util/prkkd
src/util/prole
src/util/prtable
src/util/updrow
/test/
/.vscode/
## apidocs docs related
public/
.sass-cache/
*.css.map
temp-man-pages/

View File

@ -259,7 +259,7 @@ offset_start of memo = (int16*) LVAL_page[offset_num_rows + (row_id * 2) + 2]
if (row_id = 0)
offset_stop of memo = 2048(jet3) or 4096(jet4)
else
offset_stop of memo = (int16*) LVAL_page[offset_num_row + (row_id * 2)]
offset_stop of memo = (int16*) LVAL_page[offset_num_row + (row_id * 2)] & offset_mask // offset_mask = 0x1fff
```
The length (partial if type 2) for the memo is:

65
NEWS
View File

@ -1,33 +1,62 @@
Version 1.0.0 (Beta 2)
Version 1.0.0
=============
MDB Tools 1.0 includes a number of new features compared to the 0.9 series. The
most significant change is that mdbtools.h is now generated at build time, and
its internal HAVE_ macros have been removed. This means that it is now safe for
clients to compile against mdbtools.h without needing to provide the same
HAVE_ICONV and HAVE_GLIB flags that were present when the library was first
compiled. For most users, MDB Tools 1.0 will be ABI and API compatible with the
0.9 series but see the notes in the "Install" section below.
The SQL engine has two new operators: ILIKE (case-insensitive pattern matching)
and <> (not equals).
Changes since 0.9.4:
Build:
* Ensure compiler supports thread-local storage
libmdb:
* Copy date formats when cloning handles #326
* Restore previous `mdb_register_backend` API
* Restore previous `MdbBackend` struct layout
Version 1.0.0 (Beta 1)
=============
libmdb:
* Generate platform-specific `mdbtools.h` at configure-time #316
* Ensure compiler supports thread-local storage
* Fix `AC_PROG_LEX` warning with autoconf 2.70
* Rely on autoconf to define appropriate values of `_XOPEN_SOURCE` and friends
* New `--disable-iconv` configure option (falls back to `wcstombs` where possible)
* Fix a build error when `./configure` detected iconv, but thought it was not working
* Generating the configure script now requires autoconf 2.64 or later
SQL:
* New case-insensitive, Unicode-aware `ILIKE` operator #244
Install:
* Install `libmdbodbc.so` and `libmdbodbcW.so` into ${libdir}/odbc #315
* Do not install `mdb-sql` if SQL support was not built #276
* Do not install `libmdbsql.pc` if SQL support was not built
ODBC:
* Install libmdbodbc.so and libmdbodbcW.so into ${libdir}/odbc #315
`pkg-config`:
* Simplify `--cflags` for libmdb
* Provide correct `--cflags` for libmdbsql
mdb-export:
libmdb:
* Copy date formats when cloning handles #326
* Fix incorrect reading of double values #339 #342
* Fix accidental reads of non-index data #335 #343
* New `mdb_set_repid_fmt()` for setting the format of Rep IDs (UUIDs) #344
SQL:
* New case-insensitive, Unicode-aware `ILIKE` operator #244
* New `<>` (not equal) operator #329
* Improved support for comparing floating-point values to integers
* Improved support for floating point literals with no fractional digits (e.g. "3.")
* Add support for querying Rep IDs
ODBC:
* Format boolean values correctly as `SQL_C_CHAR` #327
* Add support for the `SQL_C_WCHAR` (UTF-16) return type #347 #348
* The Unicode driver (`libmdbodbcW.so`) no longer uses iconv #332 #333
* Add support for older iODBC installations lacking `odbcinst.h`
`mdb-export`:
* Convert table names to lower case when exporting to PostgreSQL #322
* Use `CREATE IF NOT EXISTS` when exporting to PostgreSQL #321
* Fix issue where byte columns with values > 127 were exported as negative numbers (regression introduced in v0.9.3-beta1) #350
mdb-hexdump:
`mdb-hexdump`:
* Deprecate tool
Version 0.9.4

View File

@ -74,7 +74,7 @@ First, you must have reasonably current installations of:
* [libtool](https://www.gnu.org/software/libtool/)
* [automake](https://www.gnu.org/software/automake/)
* [autoconf](https://www.gnu.org/software/autoconf/) (version >= 2.58)
* [autoconf](https://www.gnu.org/software/autoconf/) (version >= 2.64)
If you want to build the SQL engine, you'll need
[bison](https://www.gnu.org/software/bison/) (version >= 3.0) or
@ -116,19 +116,26 @@ If you have cloned the Git repository, you will first need to generate the
`configure` file (skip this step if you have downloaded a formal release):
```bash
$ autoreconf -i -f
autoreconf -i -f
```
Then:
```bash
$ ./configure
./configure
```
OR with mingw32 (--disable-shared --enable-static are optional as you knew):
```bash
./configure --host=x86_64-w64-mingw32 --disable-shared --enable-static
```
OR for a complete install (requires bison, flex, and unixODBC):
```bash
$ ./configure --with-unixodbc=/usr/local
./configure --with-unixodbc=/usr/local
```
By default, MDB Tools is linked against the copy of
@ -149,11 +156,13 @@ mutually exclusive.
causes the iODBC driver to be built.
```
A list of general options is available in the [INSTALL](./INSTALL) file, and
`configure --help` will give you the list of mdbtools specific options.
By default, the ODBC driver will be installed as /usr/local/lib/odbc/libmdbodbc.so,
with a Unicode-capable driver at /usr/local/lib/odbc/libmdbodbcW.so.
The command `configure --help` will give you the list of mdbtools specific options.
```bash
$ make
make
```
Once MDB Tools has been compiled, libmdb.[so|a] will be in the src/libmdb
@ -162,14 +171,14 @@ directory and the utility programs will be in the src/util directory.
You can then install (to /usr/local by default) by running the following as root:
```bash
$ make install
make install
```
Some systems will also need the ld cache to be updated after installation;
You can do that running:
```bash
$ ldconfig
ldconfig
```
## Hacking

32
TODO.md
View File

@ -1,34 +1,4 @@
TODO
----
### file format:
- export VBA script
- re-examine KKD records for form design (OLE streams?)
- write support (understood, not coded)
### libmdb:
- Complete the list of datatypes
- Straighten out which functions in libmdb are meant to be used and which
ones should be static.
- Create an API reference for libmdb (maybe some man pages).
- Sargs need to support all datatypes
- Add support for index scanning when using sargs (partial)
- write support
### utils:
- need program to unpack VBA script to file (see prole)
- Access forms to glade converter ?
- need --version flag (done using -M flag on mdb-ver)
### SQL Engine:
- Joins
- insert/updates
- bogus column name in where clause not caught
### ODBC:
- many unimplemented funtions
See the list of [open issues tagged "enhancement"](https://github.com/mdbtools/mdbtools/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement).

File diff suppressed because one or more lines are too long

View File

@ -17,8 +17,10 @@ clone_folder: c:\projects\mdbtools
skip_tags: true
# Installing packages leads to the error:
# Can't locate threads.pm in @INC (you may need to install the threads module)
# So disable the SQL tests on this platform for now
build_script:
- C:\cygwin64\setup-x86_64.exe -q -P bison -P flex -P libiconv-devel
- C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && git clone https://github.com/mdbtools/mdbtestdata.git test"
- C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && autoreconf -i -f"
- C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && ./configure --disable-man --disable-silent-rules"
@ -26,4 +28,3 @@ build_script:
test_script:
- C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && ./test_script.sh"
- C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && ./test_sql.sh"

View File

@ -1,5 +1,5 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT([mdbtools],[1.0.0-beta2],[https://github.com/mdbtools/mdbtools/issues],[],[https://github.com/mdbtools/mdbtools])
AC_INIT([mdbtools],[1.0.1],[https://github.com/mdbtools/mdbtools/issues],[],[https://github.com/mdbtools/mdbtools])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_SRCDIR(src/extras/mdb-dump.c)
@ -7,17 +7,18 @@ AM_INIT_AUTOMAKE([foreign dist-zip])
MDBTOOLS_VERSION_MAJOR=1
MDBTOOLS_VERSION_MINOR=0
MDBTOOLS_VERSION_MICRO=0
MDBTOOLS_VERSION_MICRO=1
# Update these numbers with every release
# See https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
VERSION_INFO=4:0:0
VERSION_INFO=4:1:1
AC_SUBST(VERSION_INFO)
AC_SUBST(MDBTOOLS_CFLAGS)
AM_MAINTAINER_MODE([enable])
AM_SILENT_RULES([yes])
AC_USE_SYSTEM_EXTENSIONS
AC_PROG_CC(gcc)
AC_PROG_CXX
AX_TLS([FOO=bar], AC_MSG_ERROR([$CC does not support thread-local storage. A newer compiler is required.]))
@ -25,7 +26,7 @@ dnl Checks for programs.
AC_PROG_MAKE_SET
m4_pattern_allow([AM_PROG_AR], [AM_PROG_AR])
LT_INIT([win32-dll])
AC_PROG_LEX
AC_PROG_LEX([noyywrap])
AC_PROG_YACC
dnl Checks for header files.
@ -37,13 +38,8 @@ AC_CHECK_DECLS([program_invocation_short_name], [], [], [[
dnl Checks for library functions.
VL_LIB_READLINE
AC_CHECK_FUNCS(strptime fmemopen gmtime_r reallocf wcstombs_l vasprintf vasnprintf)
AC_CHECK_FUNCS(strptime fmemopen gmtime_r reallocf wcstombs_l mbstowcs_l vasprintf vasnprintf)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_SIZE_T
AM_ICONV
AM_GCC_ATTRIBUTE_ALIAS
dnl Enable large files on 32-bit systems
@ -87,13 +83,31 @@ AM_CONDITIONAL(SQL, test x$sql = xtrue)
AC_SUBST(SQL)
AC_SUBST(LFLAGS)
CFLAGS="$CFLAGS -Wall -Werror"
CFLAGS="$CFLAGS -Wall"
LOCALE_T=locale_t
AS_CASE([$host],
[*mingw*|*cygwin*], [LDFLAGS="$LDFLAGS -no-undefined"], [])
[*mingw*], [LDFLAGS="$LDFLAGS -no-undefined" CFLAGS="$CFLAGS -D_spawnv=_spawnv"], [])
AC_SUBST(LOCALE_T)
dnl See if iconv is present and wanted
AC_ARG_ENABLE(iconv,
AS_HELP_STRING([--disable-iconv], [do not use iconv for character conversions (use locale.h where possible)]),
[enable_iconv=$enableval], [enable_iconv=yes])
HAVE_ICONV_H=0
if test "$enable_iconv" = "yes"; then
AM_ICONV
# Use the "working iconv" test instead of the "iconv" ($am_cv_func_iconv) test
# so that our HAVE_ICONV_H substitution variable has the same value as the HAVE_ICONV
# C macro
if test "$am_func_iconv" = "yes"; then
HAVE_ICONV_H=1
fi
fi
AC_SUBST(HAVE_ICONV_H)
dnl Fuzz testing
AC_ARG_ENABLE([fuzz-testing], AS_HELP_STRING([--enable-fuzz-testing], ["Enable fuzz testing (requires Clang 6 or later)"]), [
AC_ARG_ENABLE([fuzz-testing], AS_HELP_STRING([--enable-fuzz-testing], [enable fuzz testing (requires Clang 6 or later)]), [
AC_MSG_CHECKING([whether $CC accepts -fsanitize=fuzzer])
tmp_saved_flags=$[]_AC_LANG_PREFIX[]FLAGS
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS -fsanitize=fuzzer"
@ -139,7 +153,6 @@ if test "$with_iodbc"; then
ODBC_CFLAGS=$(iodbc-config --prefix="$with_iodbc" --cflags)
ODBC_LIBS=$(iodbc-config --prefix="$with_iodbc" --libs)
ODBC_LDFLAGS=""
CFLAGS="$CFLAGS -DIODBC"
OLDLDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS $ODBC_LIBS"
@ -154,8 +167,7 @@ AC_ARG_WITH(unixodbc,
if test "$with_unixodbc"; then
HAVE_ODBC=true
ODBC_CFLAGS="-I$with_unixodbc/include"
ODBC_LIBS="-L$with_unixodbc/$libdir"
CFLAGS="$CFLAGS -DUNIXODBC"
ODBC_LIBS="-L$with_unixodbc/lib"
dnl SIZEOF_LONG_INT and HAVE_LONG_LONG are required by some versions of unixODBC
dnl https://github.com/lurcher/unixODBC/issues/40
@ -178,21 +190,24 @@ if test "$with_unixodbc"; then
ODBC_LDFLAGS=""])
LDFLAGS=$OLDLDFLAGS
fi
AM_CONDITIONAL([UNIXODBC], test "$with_unixodbc")
if test "x$HAVE_ODBC" = "xtrue"; then
if test "x$sql" != "xtrue" ; then
AC_MSG_ERROR([ODBC requires flex and bison for the SQL engine])
fi
OLDCFLAGS=$CFLAGS
CFLAGS="$CFLAGS $ODBC_CFLAGS"
AC_CHECK_HEADERS(odbcinst.h iodbcinst.h)
CFLAGS=$OLDCFLAGS
AC_SUBST(ODBC_CFLAGS)
AC_SUBST(ODBC_LIBS)
AC_SUBST(ODBC_LDFLAGS)
OPTDIRS="$OPTDIRS odbc"
fi
dnl Conditionally build odbc wide version
AM_CONDITIONAL(ICONV, test "$am_cv_func_iconv" = "yes")
dnl Testing presence of pkg-config
AC_MSG_CHECKING([pkg-config m4 macros])
if test m4_ifdef([PKG_CHECK_MODULES], [yes], [no]) = yes; then
@ -211,10 +226,9 @@ AC_ARG_ENABLE(glib,
if test "$enable_glib" = "yes"; then
GLIB_PACKAGE=glib-2.0
PKG_CHECK_MODULES([GLIB], [$GLIB_PACKAGE], HAVE_GLIB=true, HAVE_GLIB=false)
PKG_CHECK_MODULES([GLIB], [$GLIB_PACKAGE >= 2.68], HAVE_GLIB=true, HAVE_GLIB=false)
if test "x$HAVE_GLIB" = "xtrue"; then
GLIB_CFLAGS="$GLIB_CFLAGS -DHAVE_GLIB=1"
AC_CHECK_LIB($GLIB_PACKAGE, g_memdup2, [GLIB_CFLAGS="$GLIB_CFLAGS -DHAVE_G_MEMDUP2=1"])
AC_SUBST(GLIB_PACKAGE)
else
enable_glib=no
@ -223,22 +237,12 @@ fi
AM_CONDITIONAL(FAKE_GLIB, test "x$enable_glib" != "xyes")
dnl Set up substitution variables
if test "$am_cv_func_iconv" = "yes"; then
ICONV_INCLUDE_HEADER=iconv.h
ICONV_TYPE=iconv_t
else
ICONV_INCLUDE_HEADER=stdbool.h
ICONV_TYPE=[void *]
fi
AC_SUBST(ICONV_INCLUDE_HEADER)
AC_SUBST(ICONV_TYPE)
if test "$ac_cv_header_xlocale_h" = "yes"; then
XLOCALE_INCLUDE_HEADER=xlocale.h
HAVE_XLOCALE_H=1
else
XLOCALE_INCLUDE_HEADER=stdbool.h
HAVE_XLOCALE_H=0
fi
AC_SUBST(XLOCALE_INCLUDE_HEADER)
AC_SUBST(HAVE_XLOCALE_H)
if test "$enable_glib" = "yes"; then
GLIB_INCLUDE_HEADER=glib.h
@ -319,6 +323,8 @@ if test x$HAVE_ODBC = xtrue; then summary=${bold_green}enabled; else summary=${b
AC_MSG_NOTICE([ ODBC : ${summary}${reset}])
if test x$enable_glib = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
AC_MSG_NOTICE([ GLib : ${summary}${reset}])
if test x$enable_iconv = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
AC_MSG_NOTICE([ iconv : ${summary}${reset}])
if test x$enable_man = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
AC_MSG_NOTICE([ man pages : ${summary}${reset}])
if test "x$with_bash_completion_dir" != "xno"; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi

View File

@ -1,5 +1,5 @@
SHELL = /bin/sh
TXT2MAN = ./txt2man
TXT2MAN = $(srcdir)/txt2man
PRODUCT = MDBTools
dist_man_MANS =

View File

@ -9,7 +9,7 @@ SYNOPSIS
DESCRIPTION
mdb-json is a utility program distributed with MDB Tools.
It produces a CSV (comma separated value) output for the given table. Such output is suitable for importation into databases or spreadsheets.
It produces JSON output for the given table. Such output is suitable for parsing in a variety of languages.
OPTIONS
-D, --date-format fmt Set the date format (see strftime(3) for details).

View File

@ -117,6 +117,7 @@ typedef struct GOptionContext {
#define g_malloc malloc
#define g_free free
#define g_realloc realloc
#define g_memdup2 g_memdup
#define G_STR_DELIMITERS "_-|> <."

View File

@ -26,10 +26,6 @@
* used within mdbtools so they won't be exported to calling programs.
*/
#ifndef HAVE_G_MEMDUP2
#define g_memdup2 g_memdup
#endif
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -18,9 +18,9 @@
#ifndef _mdbtools_h_
#define _mdbtools_h_
#ifdef __cplusplus
extern "C" {
#endif
#define MDBTOOLS_H_HAVE_ICONV_H @HAVE_ICONV_H@
#define MDBTOOLS_H_HAVE_XLOCALE_H @HAVE_XLOCALE_H@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
@ -31,14 +31,24 @@
#include <ctype.h>
#include <string.h>
#include <locale.h>
#include <@ICONV_INCLUDE_HEADER@>
#include <@XLOCALE_INCLUDE_HEADER@>
#include <@GLIB_INCLUDE_HEADER@>
#if MDBTOOLS_H_HAVE_ICONV_H
#include <iconv.h>
#endif
#if MDBTOOLS_H_HAVE_XLOCALE_H
#include <xlocale.h>
#endif
#ifdef _WIN32
#include <io.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** \addtogroup mdbtools
* @{
*/
@ -58,6 +68,15 @@
// M$VC see http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc
#define MDB_DEPRECATED(type, funcname) type __attribute__((deprecated)) funcname
#ifdef __MINGW32__
#include <stdlib.h>
#ifndef locale_t
typedef _locale_t locale_t;
#endif
#endif
typedef @LOCALE_T@ mdb_locale_t;
enum {
MDB_PAGE_DB = 0,
MDB_PAGE_DATA,
@ -122,6 +141,7 @@ enum {
MDB_ISNULL,
MDB_NOTNULL,
MDB_ILIKE,
MDB_NEQ,
};
typedef enum {
@ -146,6 +166,11 @@ enum {
MDB_NO_MEMO = 0x0080, /* don't follow memo fields */
};
typedef enum {
MDB_BRACES_4_2_2_8, /* "{XXXX-XX-XX-XXXXXXXX}" format */
MDB_NOBRACES_4_2_2_2_6, /* "XXXX-XX-XX-XX-XXXXXX" format (matches MS Access ODBC driver) */
} MdbUuidFormat;
#define mdb_is_logical_op(x) (x == MDB_OR || \
x == MDB_AND || \
x == MDB_NOT )
@ -155,6 +180,7 @@ enum {
x == MDB_LT || \
x == MDB_GTEQ || \
x == MDB_LTEQ || \
x == MDB_NEQ || \
x == MDB_LIKE || \
x == MDB_ILIKE || \
x == MDB_ISNULL || \
@ -287,6 +313,7 @@ typedef struct {
size_t bind_size;
char date_fmt[64];
char shortdate_fmt[64];
MdbUuidFormat repid_fmt;
const char *boolean_false_value;
const char *boolean_true_value;
unsigned int num_catalog;
@ -299,12 +326,11 @@ typedef struct {
char *relationships_values[5];
MdbStatistics *stats;
GHashTable *backends;
@ICONV_TYPE@ iconv_in;
@ICONV_TYPE@ iconv_out;
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
_locale_t locale;
#if MDBTOOLS_H_HAVE_ICONV_H
iconv_t iconv_in;
iconv_t iconv_out;
#else
locale_t locale;
mdb_locale_t locale;
#endif
} MdbHandle;
@ -518,7 +544,8 @@ int mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr,
void mdb_data_dump(MdbTableDef *table);
void mdb_date_to_tm(double td, struct tm *t);
void mdb_tm_to_date(struct tm *t, double *td);
char *mdb_uuid_to_string(const void *buf, int start);
char *mdb_uuid_to_string(const void *buf, int start); /* Uses default MDB_BRACES_4_2_2_8 format */
char *mdb_uuid_to_string_fmt(const void *buf, int start, MdbUuidFormat format);
int mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr, int *len_ptr);
int mdb_rewind_table(MdbTableDef *table);
int mdb_fetch_row(MdbTableDef *table);
@ -535,6 +562,7 @@ void* mdb_ole_read_full(MdbHandle *mdb, MdbColumn *col, size_t *size);
void mdb_set_bind_size(MdbHandle *mdb, size_t bind_size);
void mdb_set_date_fmt(MdbHandle *mdb, const char *);
void mdb_set_shortdate_fmt(MdbHandle *mdb, const char *);
void mdb_set_repid_fmt(MdbHandle *mdb, MdbUuidFormat format);
void mdb_set_boolean_fmt_words(MdbHandle *mdb);
void mdb_set_boolean_fmt_numbers(MdbHandle *mdb);
int mdb_read_row(MdbTableDef *table, unsigned int row);

View File

@ -12,4 +12,4 @@ Description: core MDB file support library
Requires: @GLIB_PACKAGE@
Version: @VERSION@
Libs: -L${libdir} -lmdb
Cflags: @MDBTOOLS_CFLAGS@
Cflags: -I${includedir}

View File

@ -12,5 +12,4 @@ Description: libmdb based SQL engine
Requires: libmdb
Version: @VERSION@
Libs: -L${libdir} -lmdbsql
Cflags:
Cflags: -I${includedir}

View File

@ -1,11 +1,18 @@
# iconv.m4 serial 19 (gettext-0.18.2)
dnl Copyright (C) 2000-2002, 2007-2014, 2016 Free Software Foundation, Inc.
# iconv.m4 serial 24
dnl Copyright (C) 2000-2002, 2007-2014, 2016-2021 Free Software Foundation,
dnl Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl From Bruno Haible.
AC_PREREQ([2.64])
dnl Note: AM_ICONV is documented in the GNU gettext manual
dnl <https://www.gnu.org/software/gettext/manual/html_node/AM_005fICONV.html>.
dnl Don't make changes that are incompatible with that documentation!
AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
[
dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
@ -85,8 +92,9 @@ AC_DEFUN([AM_ICONV_LINK],
#endif
]],
[[int result = 0;
/* Test against AIX 5.1 bug: Failures are not distinguishable from successful
returns. */
/* Test against AIX 5.1...7.2 bug: Failures are not distinguishable from
successful returns. This is even documented in
<https://www.ibm.com/support/knowledgecenter/ssw_aix_72/i_bostechref/iconv.html> */
{
iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
if (cd_utf8_to_88591 != (iconv_t)(-1))
@ -167,15 +175,27 @@ AC_DEFUN([AM_ICONV_LINK],
#endif
/* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
provided. */
if (/* Try standardized names. */
iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
{
/* Try standardized names. */
iconv_t cd1 = iconv_open ("UTF-8", "EUC-JP");
/* Try IRIX, OSF/1 names. */
&& iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
iconv_t cd2 = iconv_open ("UTF-8", "eucJP");
/* Try AIX names. */
&& iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
iconv_t cd3 = iconv_open ("UTF-8", "IBM-eucJP");
/* Try HP-UX names. */
&& iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
iconv_t cd4 = iconv_open ("utf8", "eucJP");
if (cd1 == (iconv_t)(-1) && cd2 == (iconv_t)(-1)
&& cd3 == (iconv_t)(-1) && cd4 == (iconv_t)(-1))
result |= 16;
if (cd1 != (iconv_t)(-1))
iconv_close (cd1);
if (cd2 != (iconv_t)(-1))
iconv_close (cd2);
if (cd3 != (iconv_t)(-1))
iconv_close (cd3);
if (cd4 != (iconv_t)(-1))
iconv_close (cd4);
}
return result;
]])],
[am_cv_func_iconv_works=yes], ,
@ -212,8 +232,7 @@ AC_DEFUN([AM_ICONV_LINK],
AC_SUBST([LTLIBICONV])
])
dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to
dnl avoid warnings like
dnl Define AM_ICONV using AC_DEFUN_ONCE, in order to avoid warnings like
dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required".
dnl This is tricky because of the way 'aclocal' is implemented:
dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN.
@ -221,22 +240,13 @@ dnl Otherwise aclocal's initial scan pass would miss the macro definition.
dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions.
dnl Otherwise aclocal would emit many "Use of uninitialized value $1"
dnl warnings.
m4_define([gl_iconv_AC_DEFUN],
m4_version_prereq([2.64],
[[AC_DEFUN_ONCE(
[$1], [$2])]],
[m4_ifdef([gl_00GNULIB],
[[AC_DEFUN_ONCE(
[$1], [$2])]],
[[AC_DEFUN(
[$1], [$2])]])]))
gl_iconv_AC_DEFUN([AM_ICONV],
AC_DEFUN_ONCE([AM_ICONV],
[
AM_ICONV_LINK
if test "$am_cv_func_iconv" = yes; then
AC_MSG_CHECKING([for iconv declaration])
AC_CACHE_VAL([am_cv_proto_iconv], [
AC_COMPILE_IFELSE(
AC_CACHE_CHECK([whether iconv is compatible with its POSIX signature],
[gl_cv_iconv_nonconst],
[AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[
#include <stdlib.h>
@ -245,27 +255,29 @@ extern
#ifdef __cplusplus
"C"
#endif
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus)
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
#else
size_t iconv();
#endif
]],
[[]])],
[am_cv_proto_iconv_arg1=""],
[am_cv_proto_iconv_arg1="const"])
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
AC_MSG_RESULT([
$am_cv_proto_iconv])
AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1],
[gl_cv_iconv_nonconst=yes],
[gl_cv_iconv_nonconst=no])
])
else
dnl When compiling GNU libiconv on a system that does not have iconv yet,
dnl pick the POSIX compliant declaration without 'const'.
gl_cv_iconv_nonconst=yes
fi
if test $gl_cv_iconv_nonconst = yes; then
iconv_arg1=""
else
iconv_arg1="const"
fi
AC_DEFINE_UNQUOTED([ICONV_CONST], [$iconv_arg1],
[Define as const if the declaration of iconv() needs const.])
dnl Also substitute ICONV_CONST in the gnulib generated <iconv.h>.
m4_ifdef([gl_ICONV_H_DEFAULTS],
[AC_REQUIRE([gl_ICONV_H_DEFAULTS])
if test -n "$am_cv_proto_iconv_arg1"; then
if test $gl_cv_iconv_nonconst != yes; then
ICONV_CONST="const"
fi
])
fi
])

View File

@ -111,7 +111,7 @@ static const MdbBackendType mdb_mysql_types[] = {
[MDB_LONGINT] = { .name = "int" },
[MDB_MONEY] = { .name = "float" },
[MDB_FLOAT] = { .name = "float" },
[MDB_DOUBLE] = { .name = "float" },
[MDB_DOUBLE] = { .name = "double" },
[MDB_DATETIME] = { .name = "datetime" },
[MDB_BINARY] = { .name = "blob" },
[MDB_TEXT] = { .name = "varchar", .needs_char_length = 1 },
@ -294,7 +294,7 @@ mdb_get_colbacktype_string(const MdbColumn *col)
const MdbBackendType *type = mdb_get_colbacktype(col);
if (!type) {
// return NULL;
static __thread char buf[16];
static TLS char buf[16];
snprintf(buf, sizeof(buf), "Unknown_%04x", col->col_type);
return buf;
}
@ -401,7 +401,7 @@ void mdb_init_backends(MdbHandle *mdb)
"COMMENT %s",
quote_schema_name_rquotes_merge);
mdb_register_backend(mdb, "sqlite",
MDB_SHEXP_DROPTABLE|MDB_SHEXP_DEFVALUES|MDB_SHEXP_BULK_INSERT,
MDB_SHEXP_DROPTABLE|MDB_SHEXP_DEFVALUES|MDB_SHEXP_BULK_INSERT|MDB_SHEXP_INDEXES|MDB_SHEXP_CST_NOTNULL,
mdb_sqlite_types, NULL, NULL,
"date('now')", "date('now')",
"%Y-%m-%d %H:%M:%S",
@ -471,8 +471,8 @@ void mdb_register_backend(MdbHandle *mdb, char *backend_name, guint32 capabiliti
short_now, long_now,
date_fmt, shortdate_fmt,
charset_statement,
drop_statement,
"CREATE TABLE %s\n",
drop_statement,
constraint_not_empty_statement,
column_comment_statement,
per_column_comment_statement,
@ -571,7 +571,47 @@ mdb_get_index_name(int backend, MdbTableDef *table, MdbIndex *idx)
return index_name;
}
/**
* mdb_print_pk - print primary key constraint
* @output: Where to print the sql
* @table: Table to process
*/
static void
mdb_print_pk_if_sqlite(FILE *outfile, MdbTableDef *table)
{
unsigned int i, j;
MdbHandle *mdb = table->entry->mdb;
MdbIndex *idx;
MdbColumn *col;
char *quoted_name;
// this is only necessary for sqlite
if (strcmp(mdb->backend_name, "sqlite") != 0)
return;
if (table->indices==NULL)
mdb_read_indices(table);
for (i = 0; i < table->num_idxs; i++) {
idx = g_ptr_array_index(table->indices, i);
if (idx->index_type == 1) {
fprintf(outfile, "\t, PRIMARY KEY (");
for (j = 0; j < idx->num_keys; j++) {
if (j)
fprintf(outfile, ", ");
col = g_ptr_array_index(table->columns, idx->key_col_num[j] - 1);
quoted_name = mdb->default_backend->quote_schema_name(NULL, col->name);
quoted_name = mdb_normalise_and_replace(mdb, &quoted_name);
fprintf(outfile, "%s", quoted_name);
if (idx->index_type != 1 && idx->key_col_order[j])
/* no DESC for primary keys */
fprintf(outfile, " DESC");
g_free(quoted_name);
}
fprintf(outfile, ")\n");
}
}
}
/**
* mdb_print_indexes
* @output: Where to print the sql
@ -596,12 +636,15 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace)
backend = MDB_BACKEND_MYSQL;
} else if (!strcmp(mdb->backend_name, "oracle")) {
backend = MDB_BACKEND_ORACLE;
} else if (!strcmp(mdb->backend_name, "sqlite")) {
backend = MDB_BACKEND_SQLITE;
} else {
fprintf(outfile, "-- Indexes are not implemented for %s\n\n", mdb->backend_name);
return;
}
/* read indexes */
if (table->indices==NULL)
mdb_read_indices(table);
fprintf (outfile, "-- CREATE INDEXES ...\n");
@ -613,6 +656,9 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace)
idx = g_ptr_array_index (table->indices, i);
if (idx->index_type==2)
continue;
/* Sqlite3 primary keys have to be issued as a table constraint */
if (idx->index_type == 1 && backend == MDB_BACKEND_SQLITE)
continue;
index_name = mdb_get_index_name(backend, table, idx);
switch (backend) {
@ -630,7 +676,10 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace)
}
quoted_name = mdb_normalise_and_replace(mdb, &quoted_name);
if (idx->num_keys == 0) {
fprintf(outfile, "-- WARNING: found no keys for index %s - ignored\n", quoted_name);
continue;
}
if (idx->index_type==1) {
switch (backend) {
case MDB_BACKEND_ORACLE:
@ -645,6 +694,7 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace)
switch (backend) {
case MDB_BACKEND_ORACLE:
case MDB_BACKEND_POSTGRES:
case MDB_BACKEND_SQLITE:
fprintf(outfile, "CREATE");
if (idx->flags & MDB_IDX_UNIQUE)
fprintf (outfile, " UNIQUE");
@ -872,6 +922,10 @@ generate_table_schema(FILE *outfile, MdbCatalogEntry *entry, char *dbnamespace,
fprintf (outfile, " (\n");
table = mdb_read_table (entry);
if (!table) {
fprintf(stderr, "Error: Table %s does not exist\n", entry->object_name);
return;
}
/* get the columns */
mdb_read_columns(table);
@ -964,6 +1018,11 @@ generate_table_schema(FILE *outfile, MdbCatalogEntry *entry, char *dbnamespace,
fputs("\n", outfile);
} /* for */
if (export_options & MDB_SHEXP_INDEXES) {
// sqlite does not support ALTER TABLE PRIMARY KEY, so we need to place it directly into CREATE TABLE
mdb_print_pk_if_sqlite(outfile, table);
}
fputs(")", outfile);
if (mdb->default_backend->per_table_comment_statement && export_options & MDB_SHEXP_COMMENTS) {
prop_value = mdb_table_get_prop(table, "Description");

View File

@ -193,7 +193,7 @@ mdb_dump_catalog(MdbHandle *mdb, int obj_type)
entry = g_ptr_array_index(mdb->catalog,i);
if (obj_type==MDB_ANY || entry->object_type==obj_type) {
printf("Type: %-12s Name: %-48s Page: %06lx\n",
mdb_get_objtype_string(entry->object_type),
mdb_get_objtype_string(entry->object_type) ?: "Unknown",
entry->object_name,
entry->table_pg);
}

View File

@ -68,6 +68,11 @@ void mdb_set_shortdate_fmt(MdbHandle *mdb, const char *fmt)
snprintf(mdb->shortdate_fmt, sizeof(mdb->shortdate_fmt), "%s", fmt);
}
void mdb_set_repid_fmt(MdbHandle *mdb, MdbUuidFormat format)
{
mdb->repid_fmt = format;
}
void mdb_set_boolean_fmt_numbers(MdbHandle *mdb)
{
mdb->boolean_false_value = boolean_false_number;
@ -946,15 +951,20 @@ mdb_date_to_string(MdbHandle *mdb, const char *fmt, void *buf, int start)
}
char *mdb_uuid_to_string(const void *buf, int pos)
{
return mdb_uuid_to_string_fmt(buf,pos,MDB_BRACES_4_2_2_8);
}
char *mdb_uuid_to_string_fmt(const void *buf, int pos, MdbUuidFormat format)
{
const unsigned char *kkd = (const unsigned char *)buf;
return g_strdup_printf("{%02X%02X%02X%02X" "-" "%02X%02X" "-" "%02X%02X"
"-" "%02X%02X" "%02X%02X%02X%02X%02X%02X}",
return g_strdup_printf(format == MDB_BRACES_4_2_2_8
? "{%02X%02X%02X%02X" "-" "%02X%02X" "-" "%02X%02X" "-" "%02X%02X%02X%02X%02X%02X%02X%02X}"
: "%02X%02X%02X%02X" "-" "%02X%02X" "-" "%02X%02X" "-" "%02X%02X" "-" "%02X%02X%02X%02X%02X%02X",
kkd[pos+3], kkd[pos+2], kkd[pos+1], kkd[pos], // little-endian
kkd[pos+5], kkd[pos+4], // little-endian
kkd[pos+7], kkd[pos+6], // little-endian
kkd[pos+8], kkd[pos+9], // big-endian
kkd[pos+10], kkd[pos+11],
kkd[pos+12], kkd[pos+13],
kkd[pos+14], kkd[pos+15]); // big-endian
@ -999,7 +1009,7 @@ char *mdb_col_to_string(MdbHandle *mdb, void *buf, int start, int datatype, int
switch (datatype) {
case MDB_BYTE:
text = g_strdup_printf("%hhd", mdb_get_byte(buf, start));
text = g_strdup_printf("%hhu", mdb_get_byte(buf, start));
break;
case MDB_INT:
text = g_strdup_printf("%hd",
@ -1046,7 +1056,7 @@ char *mdb_col_to_string(MdbHandle *mdb, void *buf, int start, int datatype, int
text = mdb_money_to_string(mdb, start);
break;
case MDB_REPID:
text = mdb_uuid_to_string(buf, start);
text = mdb_uuid_to_string_fmt(buf, start, mdb->repid_fmt);
break;
default:
/* shouldn't happen. bools are handled specially

View File

@ -18,7 +18,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define _GNU_SOURCE
#include "mdbfakeglib.h"
#include <stddef.h>
@ -256,7 +255,8 @@ gchar *g_locale_to_utf8(const gchar *opsysstring, size_t len,
mbstowcs(utf16, opsysstring, wlen+1);
gchar *utf8 = malloc(3*len+1);
gchar *dst = utf8;
for (size_t i=0; i<len; i++) {
size_t i;
for (i=0; i<len; i++) {
// u >= 0x10000 requires surrogate pairs, ignore
dst += g_unichar_to_utf8(utf16[i], dst);
}
@ -333,7 +333,8 @@ void g_hash_table_insert(GHashTable *table, void *key, void *value) {
gboolean g_hash_table_remove(GHashTable *table, gconstpointer key) {
int found = 0;
for (guint i=0; i<table->array->len; i++) {
guint i;
for (i=0; i<table->array->len; i++) {
MyNode *node = g_ptr_array_index(table->array, i);
if (found) {
table->array->pdata[i-1] = table->array->pdata[i];
@ -399,7 +400,8 @@ void g_ptr_array_add(GPtrArray *array, void *entry) {
gboolean g_ptr_array_remove(GPtrArray *array, gpointer data) {
int found = 0;
for (guint i=0; i<array->len; i++) {
guint i;
for (i=0; i<array->len; i++) {
if (found) {
array->pdata[i-1] = array->pdata[i];
} else if (!found && array->pdata[i] == data) {

View File

@ -130,6 +130,7 @@ static MdbHandle *mdb_handle_from_stream(FILE *stream, MdbFileFlags flags) {
mdb_set_shortdate_fmt(mdb, "%x");
mdb_set_bind_size(mdb, MDB_BIND_SIZE);
mdb_set_boolean_fmt_numbers(mdb);
mdb_set_repid_fmt(mdb, MDB_BRACES_4_2_2_8);
#ifdef HAVE_ICONV
mdb->iconv_in = (iconv_t)-1;
mdb->iconv_out = (iconv_t)-1;
@ -315,10 +316,11 @@ MdbHandle *mdb_clone_handle(MdbHandle *mdb)
mdb_iconv_init(newmdb);
mdb_set_default_backend(newmdb, mdb->backend_name);
// date formats for the source handle may have been changed from
// formats for the source handle may have been changed from
// the backend's default formats, so we need to explicitly copy them here
mdb_set_date_fmt(newmdb, mdb->date_fmt);
mdb_set_shortdate_fmt(newmdb, mdb->shortdate_fmt);
mdb_set_repid_fmt(newmdb, mdb->repid_fmt);
if (mdb->f) {
mdb->f->refs++;
@ -379,7 +381,7 @@ static ssize_t _mdb_read_pg(MdbHandle *mdb, void *pg_buf, unsigned long pg)
*/
if (pg != 0 && mdb->f->db_key != 0)
{
guint32 tmp_key_i = mdb->f->db_key ^ pg;
uint32_t tmp_key_i = mdb->f->db_key ^ pg;
unsigned char tmp_key[4] = {
tmp_key_i & 0xFF, (tmp_key_i >> 8) & 0xFF,
(tmp_key_i >> 16) & 0xFF, (tmp_key_i >> 24) & 0xFF };
@ -412,7 +414,7 @@ unsigned char mdb_pg_get_byte(MdbHandle *mdb, int offset)
int mdb_get_int16(void *buf, int offset)
{
unsigned char *u8_buf = (unsigned char *)buf + offset;
return u8_buf[0] + (u8_buf[1] << 8);
return ((uint32_t)u8_buf[0] << 0) + ((uint32_t)u8_buf[1] << 8);
}
int mdb_pg_get_int16(MdbHandle *mdb, int offset)
{
@ -424,12 +426,20 @@ int mdb_pg_get_int16(MdbHandle *mdb, int offset)
long mdb_get_int32_msb(void *buf, int offset)
{
unsigned char *u8_buf = (unsigned char *)buf + offset;
return (u8_buf[0] << 24) + (u8_buf[1] << 16) + (u8_buf[2] << 8) + u8_buf[3];
return
((uint32_t)u8_buf[0] << 24) +
((uint32_t)u8_buf[1] << 16) +
((uint32_t)u8_buf[2] << 8) +
((uint32_t)u8_buf[3] << 0);
}
long mdb_get_int32(void *buf, int offset)
{
unsigned char *u8_buf = (unsigned char *)buf + offset;
return u8_buf[0] + (u8_buf[1] << 8) + (u8_buf[2] << 16) + (u8_buf[3] << 24);
return
((uint32_t)u8_buf[0] << 0) +
((uint32_t)u8_buf[1] << 8) +
((uint32_t)u8_buf[2] << 16) +
((uint32_t)u8_buf[3] << 24);
}
long mdb_pg_get_int32(MdbHandle *mdb, int offset)
{
@ -440,9 +450,12 @@ long mdb_pg_get_int32(MdbHandle *mdb, int offset)
float mdb_get_single(void *buf, int offset)
{
union {guint32 g; float f;} f;
union {uint32_t g; float f;} f;
unsigned char *u8_buf = (unsigned char *)buf + offset;
f.g = u8_buf[0] + (u8_buf[1] << 8) + (u8_buf[2] << 16) + (u8_buf[3] << 24);
f.g = ((uint32_t)u8_buf[0] << 0) +
((uint32_t)u8_buf[1] << 8) +
((uint32_t)u8_buf[2] << 16) +
((uint32_t)u8_buf[3] << 24);
return f.f;
}
float mdb_pg_get_single(MdbHandle *mdb, int offset)
@ -454,13 +467,19 @@ float mdb_pg_get_single(MdbHandle *mdb, int offset)
double mdb_get_double(void *buf, int offset)
{
union {guint64 g; double d;} d;
union {uint64_t g; double d;} d;
unsigned char *u8_buf = (unsigned char *)buf + offset;
d.g = u8_buf[0] + (u8_buf[1] << 8) + (u8_buf[2] << 16) + (u8_buf[3] << 24) +
((guint64)u8_buf[4] << 32) + ((guint64)u8_buf[5] << 40) +
((guint64)u8_buf[6] << 48) + ((guint64)u8_buf[7] << 56);
d.g = ((uint64_t)u8_buf[0] << 0) +
((uint64_t)u8_buf[1] << 8) +
((uint64_t)u8_buf[2] << 16) +
((uint64_t)u8_buf[3] << 24) +
((uint64_t)u8_buf[4] << 32) +
((uint64_t)u8_buf[5] << 40) +
((uint64_t)u8_buf[6] << 48) +
((uint64_t)u8_buf[7] << 56);
return d.d;
}
double mdb_pg_get_double(MdbHandle *mdb, int offset)
{
if (offset <0 || offset+8 > mdb->fmt->pg_size) return -1;
@ -468,7 +487,6 @@ double mdb_pg_get_double(MdbHandle *mdb, int offset)
return mdb_get_double(mdb->pg_buf, offset);
}
int
mdb_set_pos(MdbHandle *mdb, int pos)
{

View File

@ -88,15 +88,7 @@ static size_t latin1_to_utf8_without_iconv(const char *in_ptr, size_t len_in, ch
return out - dest;
}
static size_t decompressed_to_utf8_without_iconv(MdbHandle *mdb, const char *in_ptr, size_t len_in, char *dest, size_t dlen) {
if (IS_JET3(mdb)) {
if (mdb->f->code_page == 1252) {
return latin1_to_utf8_without_iconv(in_ptr, len_in, dest, dlen);
}
int count = 0;
snprintf(dest, dlen, "%.*s%n", (int)len_in, in_ptr, &count);
return count;
}
static size_t unicode2ascii_locale(mdb_locale_t locale, const char *in_ptr, size_t len_in, char *dest, size_t dlen) {
size_t i;
size_t count = 0;
size_t len_out = dlen - 1;
@ -109,11 +101,11 @@ static size_t decompressed_to_utf8_without_iconv(MdbHandle *mdb, const char *in_
w[len_in/2] = '\0';
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
count = _wcstombs_l(dest, w, len_out, mdb->locale);
count = _wcstombs_l(dest, w, len_out, locale);
#elif defined(HAVE_WCSTOMBS_L)
count = wcstombs_l(dest, w, len_out, mdb->locale);
count = wcstombs_l(dest, w, len_out, locale);
#else
locale_t oldlocale = uselocale(mdb->locale);
locale_t oldlocale = uselocale(locale);
count = wcstombs(dest, w, len_out);
uselocale(oldlocale);
#endif
@ -124,6 +116,18 @@ static size_t decompressed_to_utf8_without_iconv(MdbHandle *mdb, const char *in_
dest[count] = '\0';
return count;
}
static size_t decompressed_to_utf8_without_iconv(MdbHandle *mdb, const char *in_ptr, size_t len_in, char *dest, size_t dlen) {
if (IS_JET3(mdb)) {
if (mdb->f->code_page == 1252) {
return latin1_to_utf8_without_iconv(in_ptr, len_in, dest, dlen);
}
int count = 0;
snprintf(dest, dlen, "%.*s%n", (int)len_in, in_ptr, &count);
return count;
}
return unicode2ascii_locale(mdb->locale, in_ptr, len_in, dest, dlen);
}
#endif
/*
@ -271,6 +275,8 @@ static const char *mdb_iconv_name_from_code_page(int code_page) {
case 860: jet3_iconv_code="IBM860"; break;
case 861: jet3_iconv_code="IBM861"; break;
case 862: jet3_iconv_code="IBM862"; break;
case 863: jet3_iconv_code="IBM863"; break;
case 864: jet3_iconv_code="IBM864"; break;
case 865: jet3_iconv_code="IBM865"; break;
case 866: jet3_iconv_code="IBM866"; break;
case 869: jet3_iconv_code="IBM869"; break;

View File

@ -236,7 +236,7 @@ mdb_read_indices(MdbTableDef *table)
*/
//fprintf(stderr, "num_idxs:%d num_real_idxs:%d\n", table->num_idxs, table->num_real_idxs);
table->num_real_idxs = 0;
unsigned int num_idxs_type_other_than_2 = 0;
tmpbuf = g_malloc(idx2_sz);
for (i=0;i<table->num_idxs;i++) {
if (!read_pg_if_n(mdb, tmpbuf, &cur_pos, idx2_sz)) {
@ -264,8 +264,11 @@ mdb_read_indices(MdbTableDef *table)
fprintf(stderr, "idx #%d: %d %d %d %d %d/%d\n", i, idx_marker, rel_idx_type, rel_idx_number, rel_idx_page, update_action_flags, delete_action_flags);
}*/
if (pidx->index_type!=2)
table->num_real_idxs++;
num_idxs_type_other_than_2++;
}
if (num_idxs_type_other_than_2<table->num_real_idxs)
table->num_real_idxs=num_idxs_type_other_than_2;
//fprintf(stderr, "num_idxs:%d num_real_idxs:%d\n", table->num_idxs, table->num_real_idxs);
g_free(tmpbuf);

View File

@ -24,8 +24,8 @@
#define DEBUG 1
static __thread unsigned long opts;
static __thread int optset;
static TLS unsigned long opts;
static TLS int optset;
static void load_options(void);

View File

@ -67,6 +67,9 @@ int rc;
case MDB_LTEQ:
if (rc>=0) return 1;
break;
case MDB_NEQ:
if (rc!=0) return 1;
break;
default:
fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_string() for operator %d\n",node->op);
break;
@ -75,22 +78,26 @@ int rc;
}
int mdb_test_int(MdbSargNode *node, gint32 i)
{
gint32 val = node->val_type == MDB_INT ? node->value.i : node->value.d;
switch (node->op) {
case MDB_EQUAL:
//fprintf(stderr, "comparing %ld and %ld\n", i, node->value.i);
if (node->value.i == i) return 1;
if (val == i) return 1;
break;
case MDB_GT:
if (node->value.i < i) return 1;
if (val < i) return 1;
break;
case MDB_LT:
if (node->value.i > i) return 1;
if (val > i) return 1;
break;
case MDB_GTEQ:
if (node->value.i <= i) return 1;
if (val <= i) return 1;
break;
case MDB_LTEQ:
if (node->value.i >= i) return 1;
if (val >= i) return 1;
break;
case MDB_NEQ:
if (val != i) return 1;
break;
default:
fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_int() for operator %d\n",node->op);
@ -129,6 +136,9 @@ int mdb_test_double(int op, double vd, double d)
case MDB_LTEQ:
ret = (vd >= d);
break;
case MDB_NEQ:
ret = (vd != d);
break;
default:
fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_double() for operator %d\n",op);
break;
@ -235,16 +245,17 @@ mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNode *node, MdbField *field
ret = mdb_test_int(node, (gint32)mdb_get_int32(field->value, 0));
break;
case MDB_FLOAT:
ret = mdb_test_double(node->op, node->value.d, mdb_get_single(field->value, 0));
ret = mdb_test_double(node->op, node->val_type == MDB_INT ? node->value.i : node->value.d, mdb_get_single(field->value, 0));
break;
case MDB_DOUBLE:
ret = mdb_test_double(node->op, node->value.d, mdb_get_double(field->value, 0));
ret = mdb_test_double(node->op, node->val_type == MDB_INT ? node->value.i : node->value.d, mdb_get_double(field->value, 0));
break;
case MDB_TEXT:
mdb_unicode2ascii(mdb, field->value, field->siz, tmpbuf, sizeof(tmpbuf));
ret = mdb_test_string(node, tmpbuf);
break;
case MDB_MEMO:
case MDB_REPID:
val = mdb_col_to_string(mdb, mdb->pg_buf, field->start, col->col_type, (gint32)mdb_get_int32(field->value, 0));
//printf("%s\n",val);
ret = mdb_test_string(node, val);

View File

@ -92,6 +92,12 @@ MdbTableDef *mdb_read_table(MdbCatalogEntry *entry)
mdb_free_tabledef(table);
return NULL;
}
/* First byte of usage_map is the map-type and must always be present */
if (table->map_sz < 1) {
fprintf(stderr, "mdb_read_table: invalid map-size: %zu\n", table->map_sz);
mdb_free_tabledef(table);
return NULL;
}
table->usage_map = g_memdup2((char*)buf + row_start, table->map_sz);
if (mdb_get_option(MDB_DEBUG_USAGE))
mdb_buffer_dump(buf, row_start, table->map_sz);
@ -355,6 +361,9 @@ unsigned int i, bitn;
guint32 pgnum;
table = mdb_read_table(entry);
if (!table)
return;
fprintf(stdout,"definition page = %lu\n",entry->table_pg);
fprintf(stdout,"number of datarows = %d\n",table->num_rows);
fprintf(stdout,"number of columns = %d\n",table->num_cols);

View File

@ -5,14 +5,14 @@ lib_LTLIBRARIES = libmdbodbc.la
libdir=@libdir@/odbc
AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(ODBC_CFLAGS)
libmdbodbc_la_SOURCES = odbc.c connectparams.c
if UNIXODBC
libmdbodbc_la_SOURCES += getproperties.c
endif
libmdbodbc_la_LIBADD = ../libmdb/libmdb.la ../sql/libmdbsql.la $(ODBC_LIBS)
libmdbodbc_la_LDFLAGS = -avoid-version -export-symbols-regex '^(SQL|ODBCINST)' $(ODBC_LDFLAGS)
if ICONV
lib_LTLIBRARIES += libmdbodbcW.la
libmdbodbcW_la_SOURCES = $(libmdbodbc_la_SOURCES)
libmdbodbcW_la_LIBADD = $(libmdbodbc_la_LIBADD) @LIBICONV@
libmdbodbcW_la_SOURCES = $(libmdbodbc_la_SOURCES) odbcw.c
libmdbodbcW_la_LIBADD = $(libmdbodbc_la_LIBADD)
libmdbodbcW_la_LDFLAGS = $(libmdbodbc_la_LDFLAGS)
libmdbodbcW_la_CFLAGS = $(AM_CFLAGS) -D ENABLE_ODBC_W=1
endif
LIBS = $(GLIB_LIBS)
unittest_LDADD = libmdbodbc.la ../libmdb/libmdb.la ../sql/libmdbsql.la

View File

@ -23,11 +23,11 @@
#include <string.h>
#include <sys/stat.h>
#include <ctype.h>
#ifdef UNIXODBC
#include <odbcinstext.h>
#else
#if defined(HAVE_ODBCINST_H)
#include <odbcinst.h>
#endif
#elif defined(HAVE_IODBCINST_H)
#include <iodbcinst.h>
#endif /* HAVE_ODBCINST_H */
#include "connectparams.h"
@ -93,7 +93,7 @@ void FreeConnectParams (ConnectParams* params)
gchar* GetConnectParam (ConnectParams* params, const gchar* paramName)
{
static __thread char tmp[FILENAME_MAX];
static TLS char tmp[FILENAME_MAX];
/* use old servername */
tmp[0] = '\0';
@ -213,7 +213,7 @@ gchar* ExtractDSN (ConnectParams* params, const gchar* connectString)
/*
* Position ourselves to the beginning of "DSN"
*/
p = strstr (connectString, "DSN");
p = strcasestr (connectString, "DSN");
if (!p) return NULL;
/*
* Position ourselves to the "="
@ -243,9 +243,9 @@ gchar* ExtractDBQ (ConnectParams* params, const gchar* connectString)
if (!params)
return NULL;
/*
* Position ourselves to the beginning of "DSN"
* Position ourselves to the beginning of "DBQ"
*/
p = strstr (connectString, "DBQ");
p = strcasestr (connectString, "DBQ");
if (!p) return NULL;
/*
* Position ourselves to the "="
@ -297,24 +297,4 @@ static void cleanup (gpointer key, gpointer value, gpointer user_data)
g_free (value);
}
#ifdef UNIXODBC
int
ODBCINSTGetProperties(HODBCINSTPROPERTY hLastProperty)
{
hLastProperty->pNext = malloc(sizeof(ODBCINSTPROPERTY));
hLastProperty = hLastProperty->pNext;
memset(hLastProperty, 0, sizeof(ODBCINSTPROPERTY));
hLastProperty->nPromptType = ODBCINST_PROMPTTYPE_FILENAME;
strncpy(hLastProperty->szName, "Database", INI_MAX_PROPERTY_NAME);
strncpy(hLastProperty->szValue, "", INI_MAX_PROPERTY_VALUE);
hLastProperty->pszHelp = (char *) g_strdup("Filename and Path of MDB file to connect to.\n"
"Use the full path to the database file.");
return 1;
}
#endif
/** @}*/

38
src/odbc/getproperties.c Normal file
View 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;
}

View File

@ -21,9 +21,9 @@
#include <sql.h>
#include <sqlext.h>
#if defined(UNIXODBC)
#if defined(HAVE_ODBCINST_H)
# include <odbcinst.h>
#elif defined(IODBC)
#elif defined(HAVE_IODBCINST_H)
# include <iodbcinst.h>
#endif
@ -50,10 +50,7 @@ struct _hdbc {
GPtrArray *statements;
char lastError[256];
char sqlState[6];
#ifdef ENABLE_ODBC_W
iconv_t iconv_in;
iconv_t iconv_out;
#endif
mdb_locale_t locale;
};
struct _hstmt {
MdbSQL *sql;
@ -75,12 +72,16 @@ struct _hstmt {
struct _sql_bind_info {
int column_number;
int column_bindtype; /* type/conversion required */
int column_bindlen; /* size of varaddr buffer */
int *column_lenbind; /* where to store length of varaddr used */
SQLLEN column_bindlen; /* size of varaddr buffer */
SQLLEN *column_lenbind; /* where to store length of varaddr used */
char *varaddr;
struct _sql_bind_info *next;
};
size_t _mdb_odbc_ascii2unicode(struct _hdbc* dbc,
const char *_in, size_t _in_len,
SQLWCHAR *_out, size_t _out_count);
#ifdef __cplusplus
}
#endif

View File

@ -16,11 +16,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef ENABLE_ODBC_W
#define SQL_NOUNICODEMAP
#define UNICODE
#endif //ENABLE_ODBC_W
#include <sql.h>
#include <sqlext.h>
#include <string.h>
@ -85,64 +80,6 @@ TypeInfo type_info[] = {
#define NUM_TYPE_INFO_COLS 19
#define MAX_TYPE_INFO 11
#ifdef ENABLE_ODBC_W
static void _init_iconv(struct _hdbc* dbc)
{
TRACE("_init_iconv");
int endian = 1;
const char* wcharset;
if (sizeof(SQLWCHAR) == 2)
if (*(char*)&endian == 1)
wcharset = "UCS-2LE";
else
wcharset = "UCS-2BE";
else if (sizeof(SQLWCHAR) == 4)
if (*(char*)&endian == 1)
wcharset = "UCS-4LE";
else
wcharset = "UCS-4BE";
else
fprintf(stderr, "Unsupported SQLWCHAR width %zd\n", sizeof(SQLWCHAR));
dbc->iconv_out = iconv_open(wcharset, "UTF-8");
dbc->iconv_in = iconv_open("UTF-8", wcharset);
}
static void _free_iconv(struct _hdbc *dbc)
{
TRACE("_free_iconv");
if(dbc->iconv_out != (iconv_t)-1)iconv_close(dbc->iconv_out);
if(dbc->iconv_in != (iconv_t)-1)iconv_close(dbc->iconv_in);
}
static int unicode2ascii(struct _hdbc* dbc, char *_in, size_t *_lin, char *_out, size_t *_lout){
char *in=_in, *out=_out;
size_t lin=*_lin, lout=*_lout;
int ret = iconv(dbc->iconv_in, &in, &lin, &out, &lout);
*_lin -= lin;
*_lout -= lout;
return ret;
}
static int ascii2unicode(struct _hdbc* dbc, char *_in, size_t *_lin, char *_out, size_t *_lout){
//fprintf(stderr,"ascii2unicode %08x %08x %08x %08x\n",_in,_lin,_out,_lout);
char *in=_in, *out=_out;
size_t lin=*_lin, lout=*_lout;
//fprintf(stderr,"ascii2unicode %zd %zd\n",lin,lout);
int ret = iconv(dbc->iconv_out, &in, &lin, &out, &lout);
*_lin -= lin;
*_lout -= lout;
return ret;
}
static int sqlwlen(SQLWCHAR *p){
int r=0;
for(;*p;r++)
p++;
return r;
}
#endif // ENABLE_ODBC_W
static void LogHandleError(struct _hdbc* dbc, const char* format, ...)
{
va_list argp;
@ -171,12 +108,35 @@ static SQLRETURN do_connect (
// https://docs.microsoft.com/en-us/sql/relational-databases/native-client-odbc-date-time/datetime-data-type-conversions-odbc?view=sql-server-ver15
mdb_set_date_fmt( dbc->sqlconn->mdb, "%F %H:%M:%S" );
mdb_set_shortdate_fmt( dbc->sqlconn->mdb, "%F" );
// Match formatting of REPID type values to MS Access ODBC driver
mdb_set_repid_fmt( dbc->sqlconn->mdb, MDB_NOBRACES_4_2_2_2_6 );
return SQL_SUCCESS;
}
else
return SQL_ERROR;
}
size_t _mdb_odbc_ascii2unicode(struct _hdbc* dbc, const char *_in, size_t _in_len, SQLWCHAR *_out, size_t _out_count){
wchar_t *w = malloc(_out_count * sizeof(wchar_t));
size_t count = 0, i;
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
count = _mbstowcs_l(w, _in, _out_count, dbc->locale);
#elif defined(HAVE_MBSTOWCS_L)
count = mbstowcs_l(w, _in, _out_count, dbc->locale);
#else
locale_t oldlocale = uselocale(dbc->locale);
count = mbstowcs(w, _in, _out_count);
uselocale(oldlocale);
#endif
for (i=0; i<count; i++) {
_out[i] = (SQLWCHAR)w[i];
}
free(w);
if (count < _out_count)
_out[count] = '\0';
return count;
}
SQLRETURN SQL_API SQLDriverConnect(
SQLHDBC hdbc,
SQLHWND hwnd,
@ -213,36 +173,6 @@ SQLRETURN SQL_API SQLDriverConnect(
return SQL_ERROR;
}
#ifdef ENABLE_ODBC_W
SQLRETURN SQL_API SQLDriverConnectW(
SQLHDBC hdbc,
SQLHWND hwnd,
SQLWCHAR *szConnStrIn,
SQLSMALLINT cbConnStrIn,
SQLWCHAR *szConnStrOut,
SQLSMALLINT cbConnStrOutMax,
SQLSMALLINT *pcbConnStrOut,
SQLUSMALLINT fDriverCompletion)
{
TRACE("SQLDriverConnectW");
if(cbConnStrIn==SQL_NTS)cbConnStrIn=sqlwlen(szConnStrIn);
{
size_t l = cbConnStrIn*sizeof(SQLWCHAR), z = (cbConnStrIn+1)*3;
SQLCHAR *tmp = malloc(z);
SQLRETURN ret;
unicode2ascii((struct _hdbc *)hdbc, (char*)szConnStrIn, &l, (char*)tmp, &z);
tmp[z] = 0;
ret = SQLDriverConnect(hdbc,hwnd,tmp,SQL_NTS,NULL,0,pcbConnStrOut,fDriverCompletion);
free(tmp);
if (szConnStrOut && cbConnStrOutMax>0)
szConnStrOut[0] = 0;
if (pcbConnStrOut)
*pcbConnStrOut = 0;
return ret;
}
}
#endif // ENABLE_ODBC_W
SQLRETURN SQL_API SQLBrowseConnect(
SQLHDBC hdbc,
SQLCHAR *szConnStrIn,
@ -498,8 +428,10 @@ struct _hdbc* dbc;
dbc->params = NewConnectParams ();
dbc->statements = g_ptr_array_new();
dbc->sqlconn = mdb_sql_init();
#ifdef ENABLE_ODBC_W
_init_iconv(dbc);
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
dbc->locale = _create_locale(LC_CTYPE, ".65001");
#else
dbc->locale = newlocale(LC_CTYPE_MASK, "C.UTF-8", NULL);
#endif
*phdbc=dbc;
@ -581,7 +513,7 @@ SQLRETURN SQL_API SQLBindCol(
/* if this is a repeat */
if (cur) {
cur->column_bindtype = fCType;
cur->column_lenbind = (int *)pcbValue;
cur->column_lenbind = pcbValue;
cur->column_bindlen = cbValueMax;
cur->varaddr = (char *) rgbValue;
} else {
@ -590,7 +522,7 @@ SQLRETURN SQL_API SQLBindCol(
newitem->column_number = icol;
newitem->column_bindtype = fCType;
newitem->column_bindlen = cbValueMax;
newitem->column_lenbind = (int *)pcbValue;
newitem->column_lenbind = pcbValue;
newitem->varaddr = (char *) rgbValue;
/* if there's no head yet */
if (! stmt->bind_head) {
@ -645,36 +577,6 @@ SQLRETURN SQL_API SQLConnect(
return ret;
}
#ifdef ENABLE_ODBC_W
SQLRETURN SQL_API SQLConnectW(
SQLHDBC hdbc,
SQLWCHAR *szDSN,
SQLSMALLINT cbDSN,
SQLWCHAR *szUID,
SQLSMALLINT cbUID,
SQLWCHAR *szAuthStr,
SQLSMALLINT cbAuthStr)
{
TRACE("SQLConnectW");
if(cbDSN==SQL_NTS)cbDSN=sqlwlen(szDSN);
if(cbUID==SQL_NTS)cbUID=sqlwlen(szUID);
if(cbAuthStr==SQL_NTS)cbAuthStr=sqlwlen(szAuthStr);
{
SQLCHAR *tmp1=calloc(cbDSN*4,1),*tmp2=calloc(cbUID*4,1),*tmp3=calloc(cbAuthStr*4,1);
size_t l1=cbDSN*4,z1=cbDSN*2;
size_t l2=cbUID*4,z2=cbUID*2;
size_t l3=cbAuthStr*4,z3=cbAuthStr*2;
SQLRETURN ret;
unicode2ascii((struct _hdbc *)hdbc, (char*)szDSN, &z1, (char*)tmp1, &l1);
unicode2ascii((struct _hdbc *)hdbc, (char*)szUID, &z2, (char*)tmp2, &l2);
unicode2ascii((struct _hdbc *)hdbc, (char*)szAuthStr, &z3, (char*)tmp3, &l3);
ret = SQLConnect(hdbc, tmp1, l1, tmp2, l2, tmp3, l3);
free(tmp1),free(tmp2),free(tmp3);
return ret;
}
}
#endif //ENABLE_ODBC_W
SQLRETURN SQL_API SQLDescribeCol(
SQLHSTMT hstmt,
SQLUSMALLINT icol,
@ -743,32 +645,6 @@ SQLRETURN SQL_API SQLDescribeCol(
return ret;
}
#ifdef ENABLE_ODBC_W
SQLRETURN SQL_API SQLDescribeColW(
SQLHSTMT hstmt,
SQLUSMALLINT icol,
SQLWCHAR *szColName,
SQLSMALLINT cbColNameMax,
SQLSMALLINT *pcbColName,
SQLSMALLINT *pfSqlType,
SQLULEN *pcbColDef, /* precision */
SQLSMALLINT *pibScale,
SQLSMALLINT *pfNullable)
{
TRACE("SQLDescribeColW");
if(cbColNameMax==SQL_NTS)cbColNameMax=sqlwlen(szColName);
{
SQLCHAR *tmp=calloc(cbColNameMax*4,1);
size_t l=cbColNameMax*4;
SQLRETURN ret = SQLDescribeCol(hstmt, icol, tmp, cbColNameMax*4, (SQLSMALLINT*)&l, pfSqlType, pcbColDef, pibScale, pfNullable);
ascii2unicode(((struct _hstmt*)hstmt)->hdbc, (char*)tmp, &l, (char*)szColName, (size_t*)pcbColName);
*pcbColName/=sizeof(SQLWCHAR);
free(tmp);
return ret;
}
}
#endif //ENABLE_ODBC_W
SQLRETURN SQL_API SQLColAttributes(
SQLHSTMT hstmt,
SQLUSMALLINT icol,
@ -874,31 +750,6 @@ SQLRETURN SQL_API SQLColAttributes(
return ret;
}
#ifdef ENABLE_ODBC_W
SQLRETURN SQL_API SQLColAttributesW(
SQLHSTMT hstmt,
SQLUSMALLINT icol,
SQLUSMALLINT fDescType,
SQLPOINTER rgbDesc,
SQLSMALLINT cbDescMax,
SQLSMALLINT *pcbDesc,
SQLLEN *pfDesc)
{
TRACE("SQLColAttributesW");
if (fDescType!=SQL_COLUMN_NAME && fDescType!=SQL_COLUMN_LABEL)
return SQLColAttributes(hstmt,icol,fDescType,rgbDesc,cbDescMax,pcbDesc,pfDesc);
else{
SQLCHAR *tmp=calloc(cbDescMax*4,1);
size_t l=cbDescMax*4;
SQLRETURN ret=SQLColAttributes(hstmt,icol,fDescType,tmp,cbDescMax*4,(SQLSMALLINT*)&l,pfDesc);
ascii2unicode(((struct _hstmt *)hstmt)->hdbc, (char*)tmp, &l, (char*)rgbDesc, (size_t*)pcbDesc);
*pcbDesc/=sizeof(SQLWCHAR);
free(tmp);
return ret;
}
}
#endif //ENABLE_ODBC_W
SQLRETURN SQL_API SQLDisconnect(
SQLHDBC hdbc)
{
@ -958,39 +809,6 @@ SQLRETURN SQL_API SQLError(
return result;
}
#ifdef ENABLE_ODBC_W
SQLRETURN SQL_API SQLErrorW(
SQLHENV henv,
SQLHDBC hdbc,
SQLHSTMT hstmt,
SQLWCHAR *szSqlState,
SQLINTEGER *pfNativeError,
SQLWCHAR *szErrorMsg,
SQLSMALLINT cbErrorMsgMax,
SQLSMALLINT *pcbErrorMsg)
{
SQLCHAR szSqlState8[6];
SQLCHAR szErrorMsg8[3*cbErrorMsgMax+1];
SQLSMALLINT pcbErrorMsg8;
SQLRETURN result;
TRACE("SQLErrorW");
result = SQLError(henv, hdbc, hstmt, szSqlState8, pfNativeError, szErrorMsg8, 3*cbErrorMsgMax+1, &pcbErrorMsg8);
if (result == SQL_SUCCESS) {
struct _hdbc *dbc = hstmt ? ((struct _hstmt *)hstmt)->hdbc : hdbc;
size_t lin=6, lout=6*sizeof(SQLWCHAR);
ascii2unicode(dbc, (char*)szSqlState8, &lin, (char*)szSqlState, &lout);
lin = pcbErrorMsg8;
lout = cbErrorMsgMax;
ascii2unicode(dbc, (char*)szErrorMsg8, &lin, (char*)szErrorMsg, &lout);
if (pcbErrorMsg)
*pcbErrorMsg = lout;
}
return result;
}
#endif // ENABLE_ODBC_W
SQLRETURN SQL_API SQLExecute(SQLHSTMT hstmt)
{
struct _hstmt *stmt = (struct _hstmt *) hstmt;
@ -1021,27 +839,6 @@ SQLRETURN SQL_API SQLExecDirect(
return SQLExecute(hstmt);
}
#ifdef ENABLE_ODBC_W
SQLRETURN SQL_API SQLExecDirectW(
SQLHSTMT hstmt,
SQLWCHAR *szSqlStr,
SQLINTEGER cbSqlStr)
{
TRACE("SQLExecDirectW");
if(cbSqlStr==SQL_NTS)cbSqlStr=sqlwlen(szSqlStr);
{
SQLCHAR *tmp=calloc(cbSqlStr*4,1);
size_t l=cbSqlStr*4,z=cbSqlStr*2;
SQLRETURN ret;
unicode2ascii(((struct _hstmt *)hstmt)->hdbc, (char*)szSqlStr, &z, (char*)tmp, &l);
ret = SQLExecDirect(hstmt, tmp, l);
TRACE("SQLExecDirectW end");
free(tmp);
return ret;
}
}
#endif // ENABLE_ODBC_W
static void
unbind_columns(struct _hstmt *stmt)
{
@ -1059,13 +856,13 @@ unbind_columns(struct _hstmt *stmt)
stmt->bind_head = NULL;
}
SQLRETURN SQL_API SQLFetch(
SQLRETURN SQLFetch(
SQLHSTMT hstmt)
{
struct _hstmt *stmt = (struct _hstmt *) hstmt;
struct _sql_bind_info *cur = stmt->bind_head;
TRACE("SQLFetch");
if ( stmt->sql->limit >= 0 && stmt->rows_affected == stmt->sql->limit ) {
return SQL_NO_DATA_FOUND;
}
@ -1111,8 +908,10 @@ SQLRETURN SQL_API SQLFreeConnect(
FreeConnectParams(dbc->params);
g_ptr_array_free(dbc->statements, TRUE);
mdb_sql_exit(dbc->sqlconn);
#ifdef ENABLE_ODBC_W
_free_iconv(dbc);
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
if (dbc->locale) _free_locale(dbc->locale);
#else
if (dbc->locale) freelocale(dbc->locale);
#endif
g_free(dbc);
@ -1382,31 +1181,6 @@ SQLRETURN SQL_API SQLColumns(
return SQL_SUCCESS;
}
#ifdef ENABLE_ODBC_W
SQLRETURN SQL_API SQLColumnsW(
SQLHSTMT hstmt,
SQLWCHAR *szCatalogName,
SQLSMALLINT cbCatalogName,
SQLWCHAR *szSchemaName,
SQLSMALLINT cbSchemaName,
SQLWCHAR *szTableName,
SQLSMALLINT cbTableName,
SQLWCHAR *szColumnName,
SQLSMALLINT cbColumnName)
{
if(cbTableName==SQL_NTS)cbTableName=sqlwlen(szTableName);
{
SQLCHAR *tmp=calloc(cbTableName*4,1);
size_t l=cbTableName*4,z=cbTableName*2;
SQLRETURN ret;
unicode2ascii(((struct _hstmt* )hstmt)->hdbc, (char*)szTableName, &z, (char*)tmp, &l);
ret = SQLColumns(hstmt, NULL, 0, NULL, 0, tmp, l, NULL, 0);
free(tmp);
return ret;
}
}
#endif //ENABLE_ODBC_W
SQLRETURN SQL_API SQLGetConnectOption(
SQLHDBC hdbc,
SQLUSMALLINT fOption,
@ -1465,9 +1239,21 @@ SQLRETURN SQL_API SQLGetData(
if (col->col_type == MDB_BOOL) {
// bool cannot be null
if (fCType == SQL_C_CHAR) {
((SQLCHAR *)rgbValue)[0] = col->cur_value_len ? '0' : '1';
((SQLCHAR *)rgbValue)[1] = '\0';
if (pcbValue)
*pcbValue = sizeof(SQLCHAR);
} else if (fCType == SQL_C_WCHAR) {
((SQLWCHAR *)rgbValue)[0] = col->cur_value_len ? '0' : '1';
((SQLWCHAR *)rgbValue)[1] = '\0';
if (pcbValue)
*pcbValue = sizeof(SQLWCHAR);
} else {
*(BOOL*)rgbValue = col->cur_value_len ? 0 : 1;
if (pcbValue)
*pcbValue = 1;
}
return SQL_SUCCESS;
}
if (col->cur_value_len == 0) {
@ -1496,7 +1282,7 @@ SQLRETURN SQL_API SQLGetData(
found_bound_type:
if (fCType==SQL_C_DEFAULT)
fCType = _odbc_get_client_type(col);
if (fCType == SQL_C_CHAR)
if (fCType == SQL_C_CHAR || fCType == SQL_C_WCHAR)
goto to_c_char;
switch(col->col_type) {
case MDB_BYTE:
@ -1574,15 +1360,86 @@ SQLRETURN SQL_API SQLGetData(
break;
// case MDB_MONEY: TODO
case MDB_FLOAT:
switch (fCType) {
case SQL_C_FLOAT:
*(float*)rgbValue = mdb_get_single(mdb->pg_buf, col->cur_value_start);
if (pcbValue)
*pcbValue = sizeof(float);
break;
case SQL_C_DOUBLE:
*(double*)rgbValue = (double)mdb_get_single(mdb->pg_buf, col->cur_value_start);
if (pcbValue)
*pcbValue = sizeof(double);
break;
case SQL_C_CHAR:
case SQL_C_WCHAR:
case SQL_C_STINYINT:
case SQL_C_UTINYINT:
case SQL_C_TINYINT:
case SQL_C_SBIGINT:
case SQL_C_UBIGINT:
case SQL_C_SSHORT:
case SQL_C_USHORT:
case SQL_C_SHORT:
case SQL_C_SLONG:
case SQL_C_ULONG:
case SQL_C_LONG:
case SQL_C_NUMERIC:
// case SQL_C_FLOAT:
// case SQL_C_DOUBLE:
case SQL_C_BIT:
case SQL_C_BINARY:
case SQL_C_INTERVAL_YEAR_TO_MONTH:
case SQL_C_INTERVAL_DAY_TO_HOUR:
case SQL_C_INTERVAL_DAY_TO_MINUTE:
case SQL_C_INTERVAL_DAY_TO_SECOND:
case SQL_C_INTERVAL_HOUR_TO_MINUTE:
case SQL_C_INTERVAL_HOUR_TO_SECOND:
strcpy(stmt->sqlState, "HYC00"); // Not implemented
return SQL_ERROR;
default:
strcpy(stmt->sqlState, "07006"); // Not allowed
return SQL_ERROR;
}
break;
case MDB_DOUBLE:
switch (fCType) {
case SQL_C_DOUBLE:
*(double*)rgbValue = mdb_get_double(mdb->pg_buf, col->cur_value_start);
if (pcbValue)
*pcbValue = sizeof(double);
break;
case SQL_C_CHAR:
case SQL_C_WCHAR:
case SQL_C_STINYINT:
case SQL_C_UTINYINT:
case SQL_C_TINYINT:
case SQL_C_SBIGINT:
case SQL_C_UBIGINT:
case SQL_C_SSHORT:
case SQL_C_USHORT:
case SQL_C_SHORT:
case SQL_C_SLONG:
case SQL_C_ULONG:
case SQL_C_LONG:
case SQL_C_NUMERIC:
case SQL_C_FLOAT:
// case SQL_C_DOUBLE:
case SQL_C_BIT:
case SQL_C_BINARY:
case SQL_C_INTERVAL_YEAR_TO_MONTH:
case SQL_C_INTERVAL_DAY_TO_HOUR:
case SQL_C_INTERVAL_DAY_TO_MINUTE:
case SQL_C_INTERVAL_DAY_TO_SECOND:
case SQL_C_INTERVAL_HOUR_TO_MINUTE:
case SQL_C_INTERVAL_HOUR_TO_SECOND:
strcpy(stmt->sqlState, "HYC00"); // Not implemented
return SQL_ERROR;
default:
strcpy(stmt->sqlState, "07006"); // Not allowed
return SQL_ERROR;
}
break;
#if ODBCVER >= 0x0300
// returns text if old odbc
case MDB_DATETIME:
@ -1656,7 +1513,7 @@ SQLRETURN SQL_API SQLGetData(
free(stmt->ole_str);
stmt->ole_str = NULL;
break;
default: /* FIXME here we assume fCType == SQL_C_CHAR */
default: /* FIXME here we assume fCType == SQL_C_CHAR || fCType == SQL_C_WCHAR */
to_c_char:
{
if (cbValueMax < 0) {
@ -1664,6 +1521,7 @@ SQLRETURN SQL_API SQLGetData(
return SQL_ERROR;
}
char *str = NULL;
SQLWCHAR *wstr = NULL;
if (col->col_type == MDB_NUMERIC) {
str = mdb_numeric_to_string(mdb, col->cur_value_start,
col->col_scale, col->col_prec);
@ -1672,64 +1530,53 @@ SQLRETURN SQL_API SQLGetData(
col->cur_value_start, col->col_type, col->cur_value_len);
}
size_t len = strlen(str);
size_t charsize = 1;
if (fCType == SQL_C_WCHAR) {
wstr = calloc(len+1, charsize = sizeof(SQLWCHAR));
len = _mdb_odbc_ascii2unicode(((struct _hstmt *)hstmt)->hdbc, str, len, wstr, len+1);
}
if (stmt->pos >= len) {
free(str);
str = NULL;
free(wstr); wstr = NULL;
free(str); str = NULL;
return SQL_NO_DATA;
}
if (pcbValue) {
*pcbValue = len - stmt->pos;
*pcbValue = (len - stmt->pos) * charsize;
}
if (cbValueMax == 0) {
free(str);
str = NULL;
free(wstr); wstr = NULL;
free(str); str = NULL;
return SQL_SUCCESS_WITH_INFO;
}
const int totalSizeRemaining = len - stmt->pos;
const int partsRemain = cbValueMax - 1 < totalSizeRemaining;
const int sizeToReadThisPart = partsRemain ? cbValueMax - 1 : totalSizeRemaining;
memcpy(rgbValue, str + stmt->pos, sizeToReadThisPart);
const int totalCharactersRemaining = len - stmt->pos;
const int partsRemain = cbValueMax/charsize - 1 < totalCharactersRemaining;
const int charactersToReadThisPart = partsRemain ? cbValueMax/charsize - 1 : totalCharactersRemaining;
((char *)rgbValue)[sizeToReadThisPart] = '\0';
if (wstr) {
memcpy(rgbValue, wstr + stmt->pos, charactersToReadThisPart * sizeof(SQLWCHAR));
((SQLWCHAR *)rgbValue)[charactersToReadThisPart] = '\0';
} else {
memcpy(rgbValue, str + stmt->pos, charactersToReadThisPart);
((SQLCHAR *)rgbValue)[charactersToReadThisPart] = '\0';
}
free(wstr); wstr = NULL;
free(str); str = NULL;
if (partsRemain) {
stmt->pos += cbValueMax - 1;
free(str); str = NULL;
stmt->pos += charactersToReadThisPart;
strcpy(stmt->sqlState, "01004"); // truncated
return SQL_SUCCESS_WITH_INFO;
}
stmt->pos = len;
free(str);
str = NULL;
break;
}
}
return SQL_SUCCESS;
}
#ifdef ENABLE_ODBC_W
SQLRETURN SQL_API SQLGetDataW(
SQLHSTMT hstmt,
SQLUSMALLINT icol,
SQLSMALLINT fCType,
SQLPOINTER rgbValue,
SQLLEN cbValueMax,
SQLLEN *pcbValue)
{
//todo: treat numbers correctly
SQLCHAR *tmp=calloc(cbValueMax*4,1);
size_t l=cbValueMax*4;
SQLRETURN ret = SQLGetData(hstmt, icol, fCType, tmp, cbValueMax*4, (SQLLEN*)&l);
ascii2unicode(((struct _hstmt *)hstmt)->hdbc, (char*)tmp, &l, (char*)rgbValue, (size_t*)pcbValue);
*pcbValue/=sizeof(SQLWCHAR);
free(tmp);
return ret;
}
#endif //ENABLE_ODBC_W
static void _set_func_exists(SQLUSMALLINT *pfExists, SQLUSMALLINT fFunction)
{
SQLUSMALLINT *mod;
@ -1964,31 +1811,6 @@ SQLRETURN SQL_API SQLGetInfo(
return SQL_SUCCESS;
}
#ifdef ENABLE_ODBC_W
SQLRETURN SQL_API SQLGetInfoW(
SQLHDBC hdbc,
SQLUSMALLINT fInfoType,
SQLPOINTER rgbInfoValue,
SQLSMALLINT cbInfoValueMax,
SQLSMALLINT *pcbInfoValue)
{
TRACE("SQLGetInfoW");
if(fInfoType==SQL_MAX_STATEMENT_LEN||fInfoType==SQL_SCHEMA_USAGE||fInfoType==SQL_CATALOG_LOCATION)
return SQLGetInfo(hdbc,fInfoType,rgbInfoValue,cbInfoValueMax,pcbInfoValue);
SQLCHAR *tmp=calloc(cbInfoValueMax*4,1);
size_t l=cbInfoValueMax*4;
SQLRETURN ret = SQLGetInfo(hdbc, fInfoType, tmp, cbInfoValueMax*4,(SQLSMALLINT*)&l);
size_t pcb=cbInfoValueMax;
ascii2unicode((struct _hdbc *)hdbc, (char*)tmp, &l, (char*)rgbInfoValue, &pcb);
pcb/=sizeof(SQLWCHAR);
if(pcbInfoValue)*pcbInfoValue=pcb;
free(tmp);
return ret;
}
#endif //ENABLE_ODBC_W
SQLRETURN SQL_API SQLGetStmtOption(
SQLHSTMT hstmt,
SQLUSMALLINT fOption,
@ -2233,14 +2055,14 @@ SQLRETURN SQL_API SQLDataSources(
static int _odbc_fix_literals(struct _hstmt *stmt)
{
char tmp[4096],begin_tag[11];
char tmp[4096];
char *s, *d, *p;
int i, quoted = 0, find_end = 0;
char quote_char;
char quote_char = '\0';
s=stmt->query;
d=tmp;
while (*s) {
while (*s && d<tmp+sizeof(tmp)) {
if (!quoted && (*s=='"' || *s=='\'')) {
quoted = 1;
quote_char = *s;
@ -2255,9 +2077,7 @@ static int _odbc_fix_literals(struct _hstmt *stmt)
/* garbage */
*d++=*s++;
} else {
strncpy(begin_tag, s, i);
begin_tag[i] = '\0';
/* printf("begin tag %s\n", begin_tag); */
/* printf("begin tag %.*s\n", i, s); */
s += i;
find_end = 1;
}
@ -2265,8 +2085,8 @@ static int _odbc_fix_literals(struct _hstmt *stmt)
*d++=*s++;
}
}
*d='\0';
strcpy(stmt->query,tmp);
snprintf(stmt->query, sizeof(stmt->query), "%.*s", (int)(d-tmp), tmp);
return 0;
}
@ -2373,7 +2193,7 @@ static const char * _odbc_get_client_type_name(MdbColumn *col)
case MDB_COMPLEX:
return "COMPLEX";
default:
// fprintf(stderr,"Unknown type %d\n",srv_type);
fprintf(stderr,"Unknown type for column %s: %d\n",col->name,col->col_type);
break;
}
return NULL;

265
src/odbc/odbcw.c Normal file
View File

@ -0,0 +1,265 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000-2021 Brian Bruns and others
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* For a full list of functions that could be implemented, see:
* https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/unicode-function-arguments?view=sql-server-ver15 */
#define SQL_NOUNICODEMAP
#define UNICODE
#include <sql.h>
#include <sqlext.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include "mdbodbc.h"
/** \addtogroup odbc
* @{
*/
//#define TRACE(x) fprintf(stderr,"Function %s\n", x);
#define TRACE(x)
static size_t unicode2ascii(struct _hdbc* dbc, const SQLWCHAR *_in, size_t _in_count, SQLCHAR *_out, size_t _out_len){
wchar_t *w = malloc((_in_count + 1) * sizeof(wchar_t));
size_t i;
size_t count = 0;
for (i=0; i<_in_count; i++) {
w[i] = _in[i]; // wchar_t might be larger than SQLWCHAR
}
w[_in_count] = '\0';
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
count = _wcstombs_l((char *)_out, w, _out_len, dbc->locale);
#elif defined(HAVE_WCSTOMBS_L)
count = wcstombs_l((char *)_out, w, _out_len, dbc->locale);
#else
locale_t oldlocale = uselocale(dbc->locale);
count = wcstombs((char *)_out, w, _out_len);
uselocale(oldlocale);
#endif
free(w);
if (count == (size_t)-1)
return 0;
if (count < _out_len)
_out[count] = '\0';
return count;
}
static int sqlwlen(SQLWCHAR *p){
int r=0;
for(;*p;r++)
p++;
return r;
}
SQLRETURN SQL_API SQLDriverConnectW(
SQLHDBC hdbc,
SQLHWND hwnd,
SQLWCHAR *szConnStrIn,
SQLSMALLINT cbConnStrIn,
SQLWCHAR *szConnStrOut,
SQLSMALLINT cbConnStrOutMax,
SQLSMALLINT *pcbConnStrOut,
SQLUSMALLINT fDriverCompletion)
{
TRACE("SQLDriverConnectW");
if(cbConnStrIn==SQL_NTS)cbConnStrIn=sqlwlen(szConnStrIn);
{
size_t l = cbConnStrIn*4;
SQLCHAR *tmp = malloc(l+1);
SQLRETURN ret;
l = unicode2ascii((struct _hdbc *)hdbc, szConnStrIn, cbConnStrIn, tmp, l);
ret = SQLDriverConnect(hdbc,hwnd,tmp,SQL_NTS,NULL,0,pcbConnStrOut,fDriverCompletion);
free(tmp);
if (szConnStrOut && cbConnStrOutMax>0)
szConnStrOut[0] = 0;
if (pcbConnStrOut)
*pcbConnStrOut = 0;
return ret;
}
}
SQLRETURN SQL_API SQLConnectW(
SQLHDBC hdbc,
SQLWCHAR *szDSN,
SQLSMALLINT cbDSN,
SQLWCHAR *szUID,
SQLSMALLINT cbUID,
SQLWCHAR *szAuthStr,
SQLSMALLINT cbAuthStr)
{
TRACE("SQLConnectW");
if(cbDSN==SQL_NTS)cbDSN=sqlwlen(szDSN);
if(cbUID==SQL_NTS)cbUID=sqlwlen(szUID);
if(cbAuthStr==SQL_NTS)cbAuthStr=sqlwlen(szAuthStr);
{
size_t l1=cbDSN*4;
size_t l2=cbUID*4;
size_t l3=cbAuthStr*4;
SQLCHAR *tmp1=calloc(l1,1),*tmp2=calloc(l2,1),*tmp3=calloc(l3,1);
SQLRETURN ret;
l1 = unicode2ascii((struct _hdbc *)hdbc, szDSN, cbDSN, tmp1, l1);
l2 = unicode2ascii((struct _hdbc *)hdbc, szUID, cbUID, tmp2, l2);
l3 = unicode2ascii((struct _hdbc *)hdbc, szAuthStr, cbAuthStr, tmp3, l3);
ret = SQLConnect(hdbc, tmp1, l1, tmp2, l2, tmp3, l3);
free(tmp1),free(tmp2),free(tmp3);
return ret;
}
}
SQLRETURN SQL_API SQLDescribeColW(
SQLHSTMT hstmt,
SQLUSMALLINT icol,
SQLWCHAR *szColName,
SQLSMALLINT cbColNameMax,
SQLSMALLINT *pcbColName,
SQLSMALLINT *pfSqlType,
SQLULEN *pcbColDef, /* precision */
SQLSMALLINT *pibScale,
SQLSMALLINT *pfNullable)
{
TRACE("SQLDescribeColW");
if(cbColNameMax==SQL_NTS)cbColNameMax=sqlwlen(szColName);
{
size_t l=cbColNameMax*4+1;
SQLCHAR *tmp=calloc(l,1);
SQLRETURN ret = SQLDescribeCol(hstmt, icol, tmp, l, (SQLSMALLINT*)&l, pfSqlType, pcbColDef, pibScale, pfNullable);
*pcbColName = _mdb_odbc_ascii2unicode(((struct _hstmt*)hstmt)->hdbc, (char*)tmp, l, szColName, cbColNameMax);
free(tmp);
return ret;
}
}
SQLRETURN SQL_API SQLColAttributesW(
SQLHSTMT hstmt,
SQLUSMALLINT icol,
SQLUSMALLINT fDescType,
SQLPOINTER rgbDesc,
SQLSMALLINT cbDescMax,
SQLSMALLINT *pcbDesc,
SQLLEN *pfDesc)
{
TRACE("SQLColAttributesW");
if (fDescType!=SQL_COLUMN_NAME && fDescType!=SQL_COLUMN_LABEL)
return SQLColAttributes(hstmt,icol,fDescType,rgbDesc,cbDescMax,pcbDesc,pfDesc);
else{
size_t l=cbDescMax*4+1;
SQLCHAR *tmp=calloc(l,1);
SQLRETURN ret=SQLColAttributes(hstmt,icol,fDescType,tmp,l,(SQLSMALLINT*)&l,pfDesc);
*pcbDesc = _mdb_odbc_ascii2unicode(((struct _hstmt *)hstmt)->hdbc, (char*)tmp, l, (SQLWCHAR*)rgbDesc, cbDescMax);
free(tmp);
return ret;
}
}
SQLRETURN SQL_API SQLErrorW(
SQLHENV henv,
SQLHDBC hdbc,
SQLHSTMT hstmt,
SQLWCHAR *szSqlState,
SQLINTEGER *pfNativeError,
SQLWCHAR *szErrorMsg,
SQLSMALLINT cbErrorMsgMax,
SQLSMALLINT *pcbErrorMsg)
{
SQLCHAR szSqlState8[6];
SQLCHAR szErrorMsg8[3*cbErrorMsgMax+1];
SQLSMALLINT pcbErrorMsg8;
SQLRETURN result;
TRACE("SQLErrorW");
result = SQLError(henv, hdbc, hstmt, szSqlState8, pfNativeError, szErrorMsg8, 3*cbErrorMsgMax+1, &pcbErrorMsg8);
if (result == SQL_SUCCESS) {
struct _hdbc *dbc = hstmt ? ((struct _hstmt *)hstmt)->hdbc : hdbc;
size_t pcb;
_mdb_odbc_ascii2unicode(dbc, (char*)szSqlState8, sizeof(szSqlState8), szSqlState, sizeof(szSqlState8));
pcb = _mdb_odbc_ascii2unicode(dbc, (char*)szErrorMsg8, pcbErrorMsg8, szErrorMsg, cbErrorMsgMax);
if (pcbErrorMsg) *pcbErrorMsg = pcb;
}
return result;
}
SQLRETURN SQL_API SQLExecDirectW(
SQLHSTMT hstmt,
SQLWCHAR *szSqlStr,
SQLINTEGER cbSqlStr)
{
TRACE("SQLExecDirectW");
if(cbSqlStr==SQL_NTS)cbSqlStr=sqlwlen(szSqlStr);
{
size_t l=cbSqlStr*4;
SQLCHAR *tmp=calloc(l,1);
SQLRETURN ret;
l = unicode2ascii(((struct _hstmt *)hstmt)->hdbc, szSqlStr, cbSqlStr, tmp, l);
ret = SQLExecDirect(hstmt, tmp, l);
TRACE("SQLExecDirectW end");
free(tmp);
return ret;
}
}
SQLRETURN SQL_API SQLColumnsW(
SQLHSTMT hstmt,
SQLWCHAR *szCatalogName,
SQLSMALLINT cbCatalogName,
SQLWCHAR *szSchemaName,
SQLSMALLINT cbSchemaName,
SQLWCHAR *szTableName,
SQLSMALLINT cbTableName,
SQLWCHAR *szColumnName,
SQLSMALLINT cbColumnName)
{
if(cbTableName==SQL_NTS)cbTableName=sqlwlen(szTableName);
{
size_t l=cbTableName*4;
SQLCHAR *tmp=calloc(l,1);
SQLRETURN ret;
l = unicode2ascii(((struct _hstmt* )hstmt)->hdbc, szTableName, cbTableName, tmp, l);
ret = SQLColumns(hstmt, NULL, 0, NULL, 0, tmp, l, NULL, 0);
free(tmp);
return ret;
}
}
SQLRETURN SQL_API SQLGetInfoW(
SQLHDBC hdbc,
SQLUSMALLINT fInfoType,
SQLPOINTER rgbInfoValue,
SQLSMALLINT cbInfoValueMax,
SQLSMALLINT *pcbInfoValue)
{
TRACE("SQLGetInfoW");
if(fInfoType==SQL_MAX_STATEMENT_LEN||fInfoType==SQL_SCHEMA_USAGE||fInfoType==SQL_CATALOG_LOCATION)
return SQLGetInfo(hdbc,fInfoType,rgbInfoValue,cbInfoValueMax,pcbInfoValue);
size_t l=cbInfoValueMax*4+1;
SQLCHAR *tmp=calloc(l,1);
SQLRETURN ret = SQLGetInfo(hdbc, fInfoType, tmp, l, (SQLSMALLINT*)&l);
size_t pcb = _mdb_odbc_ascii2unicode((struct _hdbc *)hdbc, (char*)tmp, l, (SQLWCHAR*)rgbInfoValue, cbInfoValueMax);
if(pcbInfoValue)*pcbInfoValue=pcb;
free(tmp);
return ret;
}
/** @}*/

View File

@ -68,6 +68,7 @@ null { return NUL; }
"=" { return EQ; }
(<=) { return LTEQ; }
(>=) { return GTEQ; }
(<>) { return NEQ; }
"<" { return LT; }
">" { return GT; }
like { return LIKE; }
@ -112,7 +113,7 @@ strptime\( { return STRPTIME; }
return STRING;
}
(-?[0-9]+|(-?[0-9]*\.[0-9]+)(e[-+]?[0-9]+)?) {
(-?[0-9]+|(-?[0-9]*\.[0-9]*)(e[-+]?[0-9]+)?) {
yylval->name = g_strdup(yytext); return NUMBER;
}
~?(\/?[a-z0-9\.\-\_\!\~\'\(\)\%\xa0-\xff]+)+ {

View File

@ -17,9 +17,6 @@
*/
#include <stdarg.h>
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 700
#endif
#include "mdbsql.h"
#ifdef HAVE_STRPTIME
@ -402,6 +399,7 @@ mdb_sql_eval_expr(MdbSQL *sql, char *const1, int op, char *const2)
case MDB_LTEQ: compar = (value <= 0); break;
case MDB_LIKE: compar = mdb_like_cmp(const1,const2); break;
case MDB_ILIKE: compar = mdb_ilike_cmp(const1,const2); break;
case MDB_NEQ: compar = (value ? 1 : 0); break;
default: illop = 1;
}
} else if (const1[0]!='\'' && const2[0]!='\'') {
@ -413,6 +411,7 @@ mdb_sql_eval_expr(MdbSQL *sql, char *const1, int op, char *const2)
case MDB_GTEQ: compar = (val1 >= val2); break;
case MDB_LT: compar = (val1 < val2); break;
case MDB_LTEQ: compar = (val1 <= val2); break;
case MDB_NEQ: compar = (val1 != val2); break;
default: illop = 1;
}
} else {

View File

@ -63,7 +63,7 @@ typedef struct sql_context
%token <name> IDENT NAME PATH STRING NUMBER OPENING CLOSING
%token SELECT FROM WHERE CONNECT DISCONNECT TO LIST TABLES AND OR NOT LIMIT COUNT STRPTIME
%token DESCRIBE TABLE TOP PERCENT
%token LTEQ GTEQ LIKE ILIKE IS NUL
%token LTEQ GTEQ NEQ LIKE ILIKE IS NUL
%type <name> database
%type <name> constant
@ -81,7 +81,7 @@ typedef struct sql_context
%left OR
%left AND
%right NOT
%left EQ LTEQ GTEQ LT GT LIKE ILIKE IS
%left EQ LTEQ GTEQ NEQ LT GT LIKE ILIKE IS
%%
@ -192,6 +192,7 @@ operator:
| LT { $$ = MDB_LT; }
| LTEQ { $$ = MDB_LTEQ; }
| GTEQ { $$ = MDB_GTEQ; }
| NEQ { $$ = MDB_NEQ; }
| LIKE { $$ = MDB_LIKE; }
| ILIKE { $$ = MDB_ILIKE; }
;

View File

@ -1,4 +1,7 @@
if ENABLE_BASH_COMPLETION
bashcompletiondir = $(BASH_COMPLETION_DIR)
dist_bashcompletion_DATA = mdb-count mdb-export mdb-hexdump mdb-import mdb-json mdb-parsecsv mdb-prop mdb-queries mdb-schema mdb-sql mdb-tables mdb-ver
dist_bashcompletion_DATA = mdb-count mdb-export mdb-hexdump mdb-import mdb-json mdb-parsecsv mdb-prop mdb-queries mdb-schema mdb-tables mdb-ver
if SQL
dist_bashcompletion_DATA += mdb-sql
endif
endif

View File

@ -35,17 +35,17 @@ char quote_text = 1;
int count = 0;
int started;
fputs("mdb-array is deprecated and will disappear in a future version of mdbtools.\n", stderr);
fputs("Please drop us a line if you have any use of it.\n", stderr);
fputs("See https://github.com/mdbtools/mdbtools/issues/197\n", stderr);
fputs("\n", stderr);
if (argc < 3)
{
fprintf (stderr, "Usage: %s <file> <table>\n", argv [0]);
exit (1);
}
fputs("mdb-array is deprecated and will disappear in a future version of mdbtools.\n", stderr);
fputs("Please drop us a line if you have any use of it.\n", stderr);
fputs("See https://github.com/mdbtools/mdbtools/issues/197\n", stderr);
fputs("\n", stderr);
mdb = mdb_open (argv [1], MDB_NOFLAGS);
if (!mdb)
exit(1);

View File

@ -42,16 +42,16 @@ FILE *typesfile;
FILE *headerfile;
FILE *cfile;
if (argc < 2) {
fprintf (stderr, "Usage: %s <file>\n",argv[0]);
exit (1);
}
fputs("mdb-header is deprecated and will disappear in a future version of mdbtools.\n", stderr);
fputs("Please drop us a line if you have any use of it.\n", stderr);
fputs("See https://github.com/mdbtools/mdbtools/issues/197\n", stderr);
fputs("\n", stderr);
if (argc < 2) {
fprintf (stderr, "Usage: %s <file>\n",argv[0]);
exit (1);
}
/* open the database */
mdb = mdb_open (argv[1], MDB_NOFLAGS);
@ -92,6 +92,11 @@ FILE *cfile;
entry->object_name, entry->object_name);
fprintf (cfile, "\tfprintf (stdout, \"**************** %s ****************\\n\");\n", entry->object_name);
table = mdb_read_table (entry);
if (!table) {
fprintf(stderr, "Error: Table %s does not exist in this database.\n", entry->object_name);
/* Don't bother clean up memory before exit */
exit(1);
}
/* get the columns */
mdb_read_columns (table);

View File

@ -53,17 +53,17 @@ main (int argc, char **argv)
int lastcomma;
int i;
fputs("mdb-parsecsv is deprecated and will disappear in a future version of mdbtools.\n", stderr);
fputs("Please drop us a line if you have any use of it.\n", stderr);
fputs("See https://github.com/mdbtools/mdbtools/issues/197\n", stderr);
fputs("\n", stderr);
if (argc < 2)
{
fprintf (stderr, "Usage: %s <file> (assumed extension .txt)\n",argv[0]);
exit (1);
}
fputs("mdb-parsecsv is deprecated and will disappear in a future version of mdbtools.\n", stderr);
fputs("Please drop us a line if you have any use of it.\n", stderr);
fputs("See https://github.com/mdbtools/mdbtools/issues/197\n", stderr);
fputs("\n", stderr);
strcpy (txt_filename, argv [1]);
txtfile = fopen (txt_filename, "r");
if (!txtfile) {

View File

@ -97,9 +97,9 @@ main(int argc, char **argv)
g_free(buf);
mdb_free_tabledef(table);
g_free(table_name);
g_free(propColName);
mdb_close(mdb);
printf("Column %s not found in MSysObjects!\n", propColName);
g_free(propColName);
return 1;
}

View File

@ -304,7 +304,7 @@ find_sql_terminator(char *s)
}
sp = &s[len-1];
while (sp > s && isspace(*sp)) {
while (sp > s && isspace((int)*sp)) {
sp--;
}
@ -322,7 +322,7 @@ main(int argc, char **argv)
char prompt[20];
int line = 0;
char *mybuf;
unsigned int bufsz;
size_t bufsz;
MdbSQL *sql;
FILE *in = NULL, *out = NULL;
char *filename_in=NULL, *filename_out=NULL;
@ -408,7 +408,7 @@ main(int argc, char **argv)
/* give the buffer an initial size */
bufsz = 4096;
mybuf = g_malloc(bufsz);
mybuf = malloc(bufsz);
mybuf[0]='\0';
while (1) {
@ -420,7 +420,7 @@ main(int argc, char **argv)
if (in) {
s=calloc(bufsz, 1);
if (!fgets(s, bufsz, in)) {
if (!fgets(s, (int)bufsz, in)) {
// Backwards compatibility with older MDBTools
// Files read from the command line had an
// implicit "go" at the end
@ -464,7 +464,7 @@ main(int argc, char **argv)
if (in) {
fprintf(stderr, "Can not handle nested opens\n");
} else {
while (*fname && isspace(*fname))
while (*fname && isspace((int)*fname))
fname++;
if (!(in = fopen(fname, "r"))) {
fprintf(stderr,"Unable to open file %s\n", fname);
@ -478,7 +478,7 @@ main(int argc, char **argv)
while (strlen(mybuf) + strlen(s) > bufsz) {
bufsz *= 2;
mybuf = (char *) g_realloc(mybuf, bufsz);
mybuf = realloc(mybuf, bufsz);
}
#ifdef HAVE_READLINE_HISTORY
/* don't record blank lines, or lines read from files
@ -500,7 +500,7 @@ main(int argc, char **argv)
}
mdb_sql_exit(sql);
g_free(mybuf);
free(mybuf);
if (s) free(s);
if (out) fclose(out);
if ((in) && (in != stdin)) fclose(in);

View File

@ -1,18 +1,131 @@
#!/bin/bash
#!/bin/sh
# Simple test script; run after performing
# git clone https://github.com/mdbtools/mdbtestdata.git test
./src/util/mdb-json test/data/ASampleDatabase.accdb "Asset Items"
./src/util/mdb-json test/data/nwind.mdb "Umsätze"
./src/util/mdb-count test/data/ASampleDatabase.accdb "Asset Items"
./src/util/mdb-count test/data/nwind.mdb "Umsätze"
./src/util/mdb-prop test/data/ASampleDatabase.accdb "Asset Items"
./src/util/mdb-prop test/data/nwind.mdb "Umsätze"
./src/util/mdb-schema test/data/ASampleDatabase.accdb
./src/util/mdb-schema test/data/nwind.mdb
./src/util/mdb-schema test/data/nwind.mdb -T "Umsätze" postgres
./src/util/mdb-tables test/data/ASampleDatabase.accdb
./src/util/mdb-tables test/data/nwind.mdb
./src/util/mdb-ver test/data/ASampleDatabase.accdb
./src/util/mdb-ver test/data/nwind.mdb
./src/util/mdb-queries test/data/ASampleDatabase.accdb qryCostsSummedByOwner
set -o errexit
set -o nounset
LANG=C.UTF-8
CDPATH= cd -- "$(dirname -- "$0")"
parseArgs() {
MT_OUTPUT_KIND=verbose
while :; do
if test $# -lt 1; then
break
fi
case "$1" in
-q | --quiet)
MT_OUTPUT_KIND=quiet
;;
-g | --github)
MT_OUTPUT_KIND=github
;;
-h | --help)
printf 'Syntax:\n%s [-q|--quiet|-g|--github] [-h|--help]\n' "$0"
exit 0
;;
*)
printf 'Unrecognized option: "%s"\n' "$1"
exit 1
;;
esac
shift
done
}
testCommand() {
testCommand_name="$1"
shift
case $MT_OUTPUT_KIND in
verbose)
printf '# Running %s (%s)\n' "$testCommand_name" "$*"
if "./src/util/$testCommand_name" "$@"; then
return 0
fi
return 1
;;
quiet)
printf 'Testing %s (%s)... ' "$testCommand_name" "$*"
if "./src/util/$testCommand_name" "$@" >/dev/null; then
printf 'passed.\n'
return 0
fi
return 1
;;
github)
testCommand_tempFile="$(mktemp)"
printf 'Testing %s (%s)... ' "$testCommand_name" "$*"
if "./src/util/$testCommand_name" "$@" 2>&1 >"$testCommand_tempFile"; then
printf 'passed.\n'
testCommand_rc=0
else
printf 'failed.\n'
testCommand_rc=1
fi
echo '::group::Output'
cat "$testCommand_tempFile"
echo '::endgroup::'
unlink "$testCommand_tempFile"
return $testCommand_rc
;;
*)
printf 'Unrecognized MT_OUTPUT_KIND (%s)\n' "$MT_OUTPUT_KIND"
exit 1
;;
esac
}
parseArgs "$@"
rc=0
if ! testCommand mdb-json test/data/ASampleDatabase.accdb "Asset Items"; then
rc=1
fi
if ! testCommand mdb-json test/data/nwind.mdb "Umsätze"; then
rc=1
fi
if ! testCommand mdb-count test/data/ASampleDatabase.accdb "Asset Items"; then
rc=1
fi
if ! testCommand mdb-count test/data/nwind.mdb "Umsätze"; then
rc=1
fi
if ! testCommand mdb-prop test/data/ASampleDatabase.accdb "Asset Items"; then
rc=1
fi
if ! testCommand mdb-prop test/data/nwind.mdb "Umsätze"; then
rc=1
fi
if ! testCommand mdb-schema test/data/ASampleDatabase.accdb; then
rc=1
fi
if ! testCommand mdb-schema test/data/nwind.mdb; then
rc=1
fi
if ! testCommand mdb-schema test/data/nwind.mdb -T "Umsätze" postgres; then
rc=1
fi
if ! testCommand mdb-tables test/data/ASampleDatabase.accdb; then
rc=1
fi
if ! testCommand mdb-tables test/data/nwind.mdb; then
rc=1
fi
if ! testCommand mdb-ver test/data/ASampleDatabase.accdb; then
rc=1
fi
if ! testCommand mdb-ver test/data/nwind.mdb; then
rc=1
fi
if ! testCommand mdb-queries test/data/ASampleDatabase.accdb qryCostsSummedByOwner; then
rc=1
fi
if [ $rc = 0 ]; then
printf -- '\n%s passed.\n' "$0"
else
printf -- '\n%s failed!\n' "$0"
fi
exit $rc