mdb-export extention

Michael Maassen <[email protected]>
Newsgroups gmane.comp.db.mdb-tools.devel
Message-ID <Pine.LNX.4.44.0704051350340.29914-200000@hefr31.physik.uni-freiburg.de>
Hi,

appended is a version of mdb-export which

1) escapes non-printable chars if an escape char is given
   and no quoting is wanted: ex. -X '=' -Q

2) exports large OLE-columns, which requiers
   mdb_ole_read_next() (please have a look in ending the loop)

You can insert the patch in your dist if you like.

Regards,
Mic

Dr. Michael Maaßen                              Uni Freiburg
mailto:[email protected]           Physikalisches Institut
                                                Abt. Prof. Herten
Phone: + 49 - 761 - 203 - 5720                  Hermann-Herder-Str. 3
Fax:   + 49 - 761 - 203 - 5938                  79104 Freiburg

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

_______________________________________________
mdbtools-dev mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mdbtools-dev
mdb-cvs.c (text/x-csrc, 9.7 KB)
/* MDB Tools - A library for reading MS Access database file
 * Copyright (C) 2000 Brian Bruns
 *
 *
 * This library is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * add binary escapes by Michael Maassen <[email protected]>
 */

#include "mdbtools.h"

#ifdef DMALLOC
#include "dmalloc.h"
#endif

#undef MDB_BIND_SIZE
#define MDB_BIND_SIZE 20000000

#define is_text_type(x) (x==MDB_TEXT || x==MDB_MEMO || x==MDB_SDATETIME || x==MDB_OLE)
//#define is_text_type(x) (x==MDB_TEXT || x==MDB_MEMO || x==MDB_SDATETIME)

static char *sanitize_name(char *str, int sanitize);
static char *escapes(char *s);

char *delimiter = NULL;
char *row_delimiter = NULL;

void
print_col(gchar *col_val, int quote_text, int col_type, char *quote_char, char *escape_char)
{
        gchar *s;

        if (quote_text && is_text_type(col_type)) {
                fprintf(stdout,quote_char);
                for (s=col_val;*s;s++) {
                        if (strlen(quote_char)==1 && *s==quote_char[0]) {
                /* double the char if no escape char passed */
                                if (!escape_char) {
                                        fprintf(stdout,"%s%s",quote_char,quote_char);
                                } else {
                                        fprintf(stdout,"%s%s",escape_char,quote_char);
                                }
                        }
                        else fprintf(stdout,"%c",*s);
                }
                fprintf(stdout,quote_char);
        } else {
                fprintf(stdout,"%s",col_val);
        }
}

void
nprint_col(gchar *col_val, int len, int quote_text, int col_type, char *quote_char, char *escape_char)
{
        gchar *s;
	int i;
	if (len == -1) len = strlen(col_val);

        if (quote_text && is_text_type(col_type)) {
                fprintf(stdout,quote_char);
                for (s=col_val;*s;s++) {
                        if (strlen(quote_char)==1 && *s==quote_char[0]) {
                /* double the char if no escape char passed */
                                if (!escape_char) {
                                        fprintf(stdout,"%s%s",quote_char,quote_char);
                                } else {
                                        fprintf(stdout,"%s%s",escape_char,quote_char);
                                }
                        }
                        else fprintf(stdout,"%c",*s);
                }
                fprintf(stdout,quote_char);
        } else if (!quote_text && escape_char) { // no quoting, only escape to Hex
		for (i=0;i<len;i++) {
			s = col_val + i;
			if (!isprint(*s) || (*s ==  *escape_char) 
			    || (*s ==  *delimiter) || (*s ==  *row_delimiter) ) {
				fprintf(stdout,"%s%02x",escape_char,(unsigned char) *s);
			} else {
				fprintf(stdout,"%c",*s);
			}
		}
        } else {
                fprintf(stdout,"%s",col_val);
        }
}

int
main(int argc, char **argv)
{
	unsigned int j;
	MdbHandle *mdb;
	MdbTableDef *table;
	MdbColumn *col;
	char **bound_values;
	int  *bound_lens; 
	char *quote_char = NULL;
	char *escape_char = NULL;
	char header_row = 1;
	char quote_text = 1;
	char insert_statements = 0;
	char sanitize = 0;
	int  opt;

	while ((opt=getopt(argc, argv, "HQq:X:d:D:R:IS"))!=-1) {
		switch (opt) {
		case 'H':
			header_row = 0;
		break;
		case 'Q':
			quote_text = 0;
		break;
		case 'q':
			quote_char = (char *) g_strdup(optarg);
		break;
		case 'd':
			delimiter = escapes(optarg);
		break;
		case 'R':
			row_delimiter = escapes(optarg);
		break;
		case 'I':
			insert_statements = 1;
			header_row = 0;
		break;
		case 'S':
			sanitize = 1;
		break;
		case 'D':
			mdb_set_date_fmt(optarg);
		break;
		case 'X':
			escape_char = (char *) g_strdup(optarg);
		break;
		default:
		break;
		}
	}
	if (!quote_char) {
		quote_char = (char *) g_strdup("\"");
	}
	if (!delimiter) {
		delimiter = (char *) g_strdup(",");
	}
	if (!row_delimiter) {
		row_delimiter = (char *) g_strdup("\n");
	}
	
	/* 
	** optind is now the position of the first non-option arg, 
	** see getopt(3) 
	*/
	if (argc-optind < 2) {
		fprintf(stderr,"Usage: %s [options] <file> <table>\n",argv[0]);
		fprintf(stderr,"where options are:\n");
		fprintf(stderr,"  -H             supress header row\n");
		fprintf(stderr,"  -Q             don't wrap text-like fields in quotes\n");
		fprintf(stderr,"  -d <delimiter> specify a column delimiter\n");
		fprintf(stderr,"  -R <delimiter> specify a row delimiter\n");
		fprintf(stderr,"  -I             INSERT statements (instead of CSV)\n");
		fprintf(stderr,"  -D <format>    set the date format (see strftime(3) for details)\n");
		fprintf(stderr,"  -S             Sanitize names (replace spaces etc. with underscore)\n");
		fprintf(stderr,"  -q <char>      Use <char> to wrap text-like fields. Default is \".\n");
		fprintf(stderr,"  -X <char>      Use <char> to escape quoted characters within a field. Default is doubling.\n");
		g_free (delimiter);
		g_free (row_delimiter);
		g_free (quote_char);
		if (escape_char) g_free (escape_char);
		exit(1);
	}

	mdb_init();

	if (!(mdb = mdb_open(argv[optind], MDB_NOFLAGS))) {
		g_free (delimiter);
		g_free (row_delimiter);
		g_free (quote_char);
		if (escape_char) g_free (escape_char);
		mdb_exit();
		exit(1);
	}

	table = mdb_read_table_by_name(mdb, argv[argc-1], MDB_TABLE);
	if (!table) {
		fprintf(stderr, "Error: Table %s does not exist in this database.\n", argv[argc-1]);
		g_free (delimiter);
		g_free (row_delimiter);
		g_free (quote_char);
		if (escape_char) g_free (escape_char);
		mdb_close(mdb);
		mdb_exit();
		exit(1);
	}

	mdb_read_columns(table);
	mdb_rewind_table(table);
	
	bound_values = (char **) g_malloc(table->num_cols * sizeof(char *));
	bound_lens = (int *) g_malloc(table->num_cols * sizeof(int));
	for (j=0;j<table->num_cols;j++) {
		bound_values[j] = (char *) g_malloc0(MDB_BIND_SIZE);
		mdb_bind_column(table, j+1, bound_values[j], &bound_lens[j]);
	}
	if (header_row) {
		col=g_ptr_array_index(table->columns,0);
		fprintf(stdout,"%s",sanitize_name(col->name,sanitize));
		for (j=1;j<table->num_cols;j++) {
			col=g_ptr_array_index(table->columns,j);
			fprintf(stdout,delimiter);
			fprintf(stdout,"%s",sanitize_name(col->name,sanitize));
		}
		fprintf(stdout,"\n");
	}

	while(mdb_fetch_row(table)) {

		if (insert_statements) {
			fprintf(stdout, "INSERT INTO %s (",
				sanitize_name(argv[optind + 1],sanitize));
			for (j=0;j<table->num_cols;j++) {
				if (j>0) fprintf(stdout, ", ");
				col=g_ptr_array_index(table->columns,j);
				fprintf(stdout,"%s", sanitize_name(col->name,sanitize));
			} 
			fprintf(stdout, ") VALUES (");
		}

		for (j=0;j<table->num_cols;j++) {
			col=g_ptr_array_index(table->columns,j);
			if ((col->col_type == MDB_OLE)
			 && ((j==0) || (col->cur_value_len))) {
				//int len;
				// bound_lens[j]=mdb_ole_read(mdb, col, bound_values[j], MDB_BIND_SIZE);
				gchar kkd_ptr[MDB_MEMO_OVERHEAD];
				void *kkd_pg = g_malloc(200000);
				size_t len, pos;
				
				memcpy(kkd_ptr, bound_values[j], MDB_MEMO_OVERHEAD);
				//col = g_ptr_array_index(table->columns, col_num - 1);
				len = mdb_ole_read(mdb, col, kkd_ptr, MDB_BIND_SIZE);
				memcpy(kkd_pg, bound_values[j], len);
				bound_lens[j] = len;
				while ((len = mdb_ole_read_next(mdb, col, kkd_ptr))) {
					memcpy(kkd_pg + bound_lens[j], bound_values[j], len);
					bound_lens[j] += len;
					// FIXME: why 4076? how detect end?
					if (len < 4076) break;
				}
				memcpy(bound_values[j],kkd_pg,bound_lens[j]);
				g_free(kkd_pg);
			}
			if (j>0) {
				fprintf(stdout,delimiter);
			}
			if (insert_statements && !bound_lens[j]) {
				print_col("NULL",0,col->col_type, quote_char, escape_char);
			} else {
#if 0
				print_col(bound_values[j], 
					   quote_text, col->col_type, quote_char, escape_char);
#else
				nprint_col(bound_values[j], bound_lens[j],
					   quote_text, col->col_type, quote_char, escape_char);
#endif
			}
		}
		if (insert_statements) fprintf(stdout,")");
		fprintf(stdout, row_delimiter);
	}
	for (j=0;j<table->num_cols;j++) {
		g_free(bound_values[j]);
	}
	g_free(bound_values);
	g_free(bound_lens);
	mdb_free_tabledef(table);

	g_free (delimiter);
	g_free (row_delimiter);
	g_free (quote_char);
	if (escape_char) g_free (escape_char);
	mdb_close(mdb);
	mdb_exit();

	exit(0);
}

static char *sanitize_name(char *str, int sanitize)
{
	static char namebuf[256];
	char *p = namebuf;

	if (!sanitize)
		return str;
		
	while (*str) {
		*p = isalnum(*str) ? *str : '_';
		p++;
		str++;
	}
	
	*p = 0;
										
	return namebuf;
}

static char *escapes(char *s)
{
	char *d = (char *) g_strdup(s);
	char *t = d;
	unsigned char encode = 0;

	for (;*s; s++) {
		if (encode) {
			switch (*s) {
			case 'n': *t++='\n'; break;
			case 't': *t++='\t'; break;
			case 'r': *t++='\r'; break;
			default: *t++='\\'; *t++=*s; break;
			}	
			encode=0;
		} else if (*s=='\\') {
			encode=1;
		} else {
			*t++=*s;
		}
	}
	*t='\0';
	return d;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.