How to compact an Access database using the ODBC .accdb driver - c++

Am trying to determine how to compact an Access database using the .accdb ODBC driver. Note that I'm aware of how to accomplish this using the old .mdb driver, essentially something like this:
const TCHAR *Driver = TEXT("Microsoft Access Driver (*.mdb)");
TCHAR *DatabasePath = GetRegDBPath() ;
_stprintf_s(Attr, sizeof(Attr)/sizeof(TCHAR), TEXT("COMPACT_DB=%s%s %s%s General"), DatabasePath,
DBName,
DatabasePath,
DBName ) ;
Ret = SQLConfigDataSource(hPar,
ODBC_ADD_DSN,
Driver,
Attr);
However substituting the Driver string with Microsoft Access Driver (.mdb, .accdb), the call fails and calling *SQLInstallerError *to obtain error information comes back with (the rather unhelpful) message: Driver's ConfigDSN, ConfigDriver, or ConfigTranslator failed.
I've tried varations on the above syntax, using a different output database path, omitting the General parameter, all yield the same result.
This link suggests it can't be done but I'm sceptical because it's possible to do it from the ODBC Administrator Panel. Additionally looking through the ACEODBC.DLL for string content shows the presence of the COMPACT_DB strings:
jon#monolith:~/temp$ strings -t x -e l ACEODBC.DLL | grep -i compact
395f0 COMPACT_DB
39978 COMPACT_DB=%s
All suggests it should be possibe if I knew what the correct syntax is.

As far as I know, no, ODBC was never able to compact a access database.
your posted code does a printf (simple outputs some text), and that certainly would not and does not do a compact database. the next line of code "might" C + R the datbase, but that code is not posted.
eg:
SQLConfigDataSource
And I suppose it also possible that the TEXT() method used in above might have some code, but then again, you have to provide what that TEXT() method does then.
From what I can find?
You have to create a "com" object instance of the Access database engine (JET for mdb files, and ACE for accDB files).

Related

Inserting UNICODE into Oracle from C/C++ shows garbage in DB

I have the below sample program...
int main(void)
{
char insertQuery[] = "INSERT INTO ABCD_TABLE VALUES('987','31-AUG-16','19-JAN-17','901',
'31-DEC-12','1',\'\',\'\',\'\',\'\',\'\',\'\',\'ÜÜcreate02_de,ää\')";
connectToSQLServer();
executeINSERTQuery(insertQuery);
return 0;
}
When I run the program, the query is inserted successfully into the DB but the ÜÜ is shown as garbage.
When I run the same query manually in Toad, it is inserted proprly and the ÜÜ is shown properly in Toda.
"INSERT INTO ABCD_TABLE VALUES('987','31-AUG-16','19-JAN-17','901','31-DEC-12','1','','','','','','','ÜÜcreate02_de,ää')";
What might be the issue?
Please do let me know if you guys need the code sample of connectToSQLServer() and executeINSERTQuery(insertQuery). I will provide.
You have set NLS_LANG variable to ALL32UTF8. Also there is a way how to do it on OCI level, see: OCIEnvNlsCreate and Database Globalization Support Guide.
By doing this you till tell the OCI driver that everything you store in buffers is in UTF8 charset, and everything withdrawn from from database also must be in UTF8.
PS: note that some OCI api functions do distinguish number of bytes and number of characters. So for example you must not use OCILobRead/OCILobWrite to manipulate CLOBS. You must use extended versions OCILobRead2/OCILobWrite2.

Using "rundll32.exe" to access SpeechUX.dll

Good Day,
I have searched the Internet tirelessly trying to find an example of how to start Windows Speech Training from with in my VB.Net Speech Recognition Application.
I have found a couple examples, which I can not get working to save my life.
One such example is on the Visual Studios Fourms:
HERE
this particular example users the "Process.Start" call to try and start the Speech Training Session. However this does not work for me. Here is the exmaple from that thread:
Process.Start("rundll32.exe", "C:\Windows\system32\speech\speechux\SpeechUX.dll, RunWizard UserTraining")
What happens is I get and error that says:
There was a problem starting
C:\Windows\system32\speech\speechux\SpeechUX.dll
The specified module could not be found
So I tried creating a shortcut (.lnk) file and thought I could access the DLL this way. My short cut kind of does the same thing. In the short cut I call the "rundll32.exe" with parameters:
C:\Windows\System32\rundll32.exe "C:\Windows\system32\speech\speechux\SpeechUX.dll" RunWizard UserTraining
Then in my VB.Net application I use the "Process.Start" and try to run the shortcut.
This also gives me the same error. However the shortcut itself will start the SPeech Training session. Weird?!?
So, I then took it one step further, to see if it has something to do with my VB.Net Application and the "Process.Start" Call.
I created a VBScript, and using "Wscript.Shell" I point to the Shortcut.
Running the VBScript calls the Shortcut and low and behold the Speech Training starts!
Great! But...
when I try to run the VBscript from my VB.net Application, I get that error again.
What the heck is going on here?
Your problem likely is that your program is compiled as 32-bit and your OS is 64-bit, and thus, when you try to access "C:\Windows\System32\Speech\SpeechUX\SpeechUX.dll" from your program, you're really accessing "C:\Windows\SysWOW64\Speech\SpeechUX\SpeechUX.dll" which, as rundll32.exe is reporting doesn't exist.
Compile your program as 64-bit instead or try the pseudo directory %SystemRoot%\sysnative.
Also, instead of rundll32.exe, you may want to just run SpeechUXWiz.exe with an argument.
Eg.
private Process StartSpeechMicrophoneTraining()
{
Process process = new Process();
process.StartInfo.FileName = System.IO.Path.Combine(Environment.SystemDirectory, "speech\\speechux\\SpeechUXWiz.exe");
process.StartInfo.Arguments = "MicTraining";
process.Start();
return process;
}
private Process StartSpeechUserTraining()
{
Process process = new Process();
process.StartInfo.FileName = System.IO.Path.Combine(Environment.SystemDirectory, "speech\\speechux\\SpeechUXWiz.exe");
process.StartInfo.Arguments = "UserTraining";
process.Start();
return process;
}
Hope that helps.
Read more about Windows 32-bit on Windows 64-bit at http://en.wikipedia.org/wiki/WoW64
or your problem specifically at http://en.wikipedia.org/wiki/WoW64#Registry_and_file_system
If you are using a 64bit OS and want to access system32 folder you must use the directory alias name, which is "sysnative".
"C:\windows\sysnative" will allow you access to system32 folder and all it's contents.
Honestly, who decided this at Microsoft is just silly!!

vimrc to detect remote connection

At the moment I have to hard code the names of servers on my vimrc in order to either make it different on the remote machine. This is done by conditional statement using hostname() function in vim. I want to make the conditional to be based on the status of remote connection and not on the hostname. So...
The first possible solution I found was using the following bash command in system():
cat /proc/$PPID/status | head -1 | cut -f2
This does not work because I use GNU screen and this will not detect my connection status properly.
The second possible solution I am exploring right now is using who am i This reliably shows whether or not remote connection has been made from which client, but I have trouble getting it working with system()
if substitute(system('who am i'), "theclient", ????, "") == ""
...
How could I get ???? to extract my client name somehow??
Even if the second solution works, allowing me to use .vimrc for many different remote machines, it is still tied to one client. I want the conditional to work in all remote session, regardless of the client name. So I am wondering, is this possible?
The following line allows me to create a variable that detects the remote connection status:
let g:remoteSession = ($STY == "")
Now you can surround the lines that you want to be ignored in the remote connection via:
if g:remoteSession
...
endif
On a side note, I do not know how expensive it is look up the environment variable compared to the global variable, but I am guessing the difference is negligible. The system call in an environment like cygwin where fork() is inefficient, it is worth doing the optimization.
Instead of adding conditional logic to a shared ~/.vimrc, you could alternatively source system-local settings. I use the following:
" Source system-specific .vimrc first.
if filereadable(expand('~/local/.vimrc'))
source ~/local/.vimrc
endif
" Stop sourcing if inclusion guard exists.
if exists('g:loaded_vimrc')
finish
endif
" Common settings of .vimrc here...
I find this more scalable than trying to maintain an ever-changing list of hostnames in a central location.

How can I get the native C API connection structure from MySQL Connector/C++?

I'm using the MySQL Connector/C++ to communicate with a MySQL server from a C++ program. For some reason (see below for the background), I need at some point the native C API connection structure. How do I get it from the Connector/C++ classes?
Background:
I want to load a huge amount of data (up to 2-3 billion tuples) from the client's main memory into the server. Therefore, I want to try the LOAD DATA INFILE statement. To avoid to write the whole data to a text file first, I want to define my own local infile handler, which reads the data directly from the main memory.
However, the Connector/C++ comes with no method to set user-defined local infile handlers, but the native C API does. The corresponding C function mysql_set_local_infile_handler() needs a native connection handler (the structure MYSQL) as input parameter. So how do I get this handler from the Connector/C++? Or is there any better way to set the local infile handler in a Connector/C++ environment?
You want sql::mysql::NativeAPI::MySQL_NativeConnectionWrapper::mysql, but it is a private member that is not returned by any method. Therefore, to access the structure, you will have to fork the Connector/C++ source and compile your own connector.
If that's the path you take, you might prefer to provide access to mysql_set_local_infile_handler() from within Connector/C++.
There is another way to work it around via the help of c++ command "system".
1) set the mysql environment in my.cnf: local-infile=1. You can find this file here: how to know mysql my.cnf location. Or just add option mysql --local-infile [other options] in the shell command line mentioned below.
2) In your c++ code, instead of using stmt->execute(...) from c++ connector, using
system("mysql -u username --database=dbname --password=pw -e \"LOAD DATA LOCAL INFILE filename INTO TABLE tablename FIELD TERMINATED BY ',' LINES TERMINATED BY '\n' (column1, column2, column3);\"");
The char array could also be manipulated in the program. Though it seems "low-tech", it does get work done in my project.

Interop exception with VC++ and MySQL C++ Connector

I am helping a friend with his bachelor thesis project. It is a program that calculates bending moments for various materials. One of the extra requirements that the client desires is database functionality to store and retrieve various pieces of data being used in the program.
The program is a forms application written in managed C++. I jumped on board to help with writing the database functionality. I am using MySQL Server 5.5 and the MySQL Connector/C++ to bridge the program and the database. Everything has been going pretty well and all the functionality we need works just fine, but only in debug. As soon as we put the program into release mode there is undefined behavior occurring at runtime. Below is the function that is used to open a connection to the database:
try
{
m_driver = get_driver_instance();
m_conn = m_driver->connect(m_dbHost, m_dbUser, m_dbPwd);
m_conn->setSchema(m_dbSchema);
}
catch(sql::SQLException &e)
{
int a = e.getErrorCode();
MessageBoxA(NULL, e.what(), "DB Error", MB_OK);
}
The values passed into the connect function are all std::string. In debug mode the connection is made with no issues. In release mode an exception is caught after the connect function is called, and displays the message "Unknown MySQL Server Host '####' (0)" where the #### is always some garbage text. I also notice that in the output window another exception is being thrown, this one is the type System.Runtime.InteropServices.SEHException.
I have been doing some research and have seen numerous cases of this exception on many forums (and here on stack exchange) but no one seems to be having this issue with the MySQL connector. My assumption is that the memory is being corrupted because the program is mixed mode, with the main program code being written in Managed C++ and my database helper code being in native C++ (as required by the connector).
Is there something I can change in my code to try and fix this issue to that the strings aren't being corrupted at run time. I have tried many different hacks to try and solve the problem but nothing has worked.
Thanks,
Tom
Update: I am now seeing this error in debug mode. I added code to retrieve values from the database and populate some text boxes on the form. The code is as follows:
// Populate the form with material details
String^ selectedMaterial = (String^)(comboBox1->SelectedItem);
string selectedMaterial_ = "";
MarshalString(selectedMaterial, selectedMaterial_);
sql::ResultSet* results = dbHelper.GetData("matname", selectedMaterial_);
if (results->rowsCount() == 1)
{
// Outdim
string outdim_ = "";
outdim_ = results->getString("outdim");
String^ outdim = gcnew String(outdim_.c_str());
textBox1->Text = outdim;
}
else
{
// !!!! Duplicate materials in list
}
When it tries to read outdim from the result set the SEHException is thrown, and the only other piece of information given is that it was thrown in an external component.
Update 2: I ran Application Verifier against the debug executable and then launched the program from VS2010. However the form window never loads so somewhere along the line the program must be getting halted. Strangely there is absolutely no information in the log files in Application Verifier. I also tried with the release version and I didnt get any useful information from that either.