 |
|
 |
Hello Daniel,
Thanks a lot for your "An easy to use wrapper for SQLite3" on Code Project.
I observed one critical issue with this wrapper. The function QuerySQL or QuerySQL2 returns Table or TablePtr. But if I just delete pTable does not free up complete memory allocated by your "row" s. There is always a big memory leakage after every Query, even after using delete for Table pointer.
Moreover QuerySQL return an object which is locally created in function on Stack memory. When function is out of its scope that memory on stack is no more usable for application.
I just wanted to check, if you have any update concerning above errors. I will be more than happy if you have any
Thanks, Vijay Chavan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
you use the function strncpy_s which is a Microsoft Visual Studio 2005/.NET Framework 2.0 function.
Regards Andrew
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
why do you use m_pStreamHeader an instance of the parent class? Does the inheritance not the job?
Greetings from Germany
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Man, you must be referring to the Server/Client implementation...
Anyway, if you will look deep into the code (maybe debug it?), you'll see what it is used for. In short - it implements another stream management class for handling the header of a packet. Over the time I will add more detailed comments on the code, right now anything in the code could change, because I have yet to implement encryption and compression.
----- Daniel Cohen Gindi danielgindi (at) gmail dot com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I spent a long time looking for SQLite wrappers over the net and I like yours a lot. But it is difficult for a newcomer to SQLite to step into SQLite and then into wrapper. So basic samples in the article would save a great time. Just a remark in case your decide to update the article, thanks a lot for your classes.
Yarp http://www.senosoft.com/
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
 |
Hey!
This article is not intended for someone who have just learned that there is something called "c++", first you have to learn some about for,while,if,;,++,--... Hey! I'm just kidding!
Now seriously: The classes that I've written here, does not require any samples to be written, and it does not even require great knowledge in c++. All you have to do, is add the classes to your project, add the SQLite library (found at www.sqlite.org) as source code or as a .lib, And start using it! The code is self explanatory! I mean, do you not understand word like "Open Database" or "Execute SQL"? You simply supply the filename, and it opens the database... You give it an SQL, it executes it... If SQL examples is what you need - then this is not the right article. If you need to know how to include the .lib of sqlite in your project, this is also basics and not for this article.
I assume that if a developer is looking for an embedded SQL engine, he is already an experienced programmer, and knows more than he has to know to understand my code.
Cheers!
----- Daniel Cohen Gindi danielgindi (at) gmail dot com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Hehe.. I'm no joking! Just got to find the time to write the actual article, the code already exists...
----- Daniel Cohen Gindi danielgindi (at) gmail dot com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Wow, really looking forward to see your implementation. Have been using SQLite for a while but still thinking about the best way to implement client server architecture for it.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
 |
One of the most important thing that I have added is more safe code.
It means that if you have something like this: SQLite::Database * pDatabase=0;
if (pDatabase->IsOpen()) { . . }
Then IsOpen() will first check if pDatabase is valid, and return false. (Just like CWnd::GetSafeHwnd)
There are some more functions that are "safe" now, like Table::GoFirst...
There's a JoinTable function now to join the rows of two tables, and there's a () operator for the TablePtr class, so you can use pTablePtr()... instead of pTablePtr->m_pTable...
----- Daniel Cohen Gindi danielgindi (at) gmail dot com
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
 |
Thank you Daniel,
For what it is worth, I added the following just to make this consistent with some of the other wrappers (e.g. ADO ) that I was using. bool Database::BeginTransaction() ///< As the name says { if (!IsOpen()) {m_iLastError=SQLITE_ERROR; return false;} return ExecuteSQL(_T("BEGIN TRANSACTION")); } bool Database::CommitTransaction() ///< As the name says { if (!IsOpen()) {m_iLastError=SQLITE_ERROR; return false;} return ExecuteSQL(_T("COMMIT TRANSACTION")); } bool Database::RollbackTransaction() ///< As the name says { if (!IsOpen()) {m_iLastError=SQLITE_ERROR; return false;} return ExecuteSQL(_T("ROLLBACK TRANSACTION")); }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi! Thanks! Personally I'm not using BEGIN/COMIT/ROLLBACK very much, because SQLite has some other advanced methods of controlling those things, and advanced configuration (per SQL statement) what to do in case of failure... you can see sqlite.org for details of their special additions to SQL...
Anyway, I'll add this in my code, and upload it soon. (I'll update the documentation later on, when there's another serious update...
----- Daniel Cohen Gindi danielgindi (at) gmail dot com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
You don't use transactions with SQLite???? You're probably happy with 60 inserts per second performance, do you?
gnk
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Yep! I do not normally have to do more than that! my SELECTs are pretty complicated though...
----- Daniel Cohen Gindi danielgindi (at) gmail dot com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi!
I've looked at the transaction sqls you have added, but the function themselves aren't right, because ExecuteSQL does not return boolean, it returns the error, so you should return ExecuteSQL(...)==SQLITE_OK and not just ExecuteSQL(...) And you should also update m_iLastError...
Look at the code that I've uploaded...
Daniel
----- Daniel Cohen Gindi danielgindi (at) gmail dot com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
First, in your .h file, your inline declaration of GetLastError() is misspelled -- it is listed as int GerLastError(){ return m_iLastError; }; which won't cause any compiler complaints, but it conflicts with your documentation.
Second, I note that you have a method (Table* QuerySQL2(LPCTSTR strSQL);) which leaves it up to the programmer to free the pointer memory. I come from the "I create it, I free it; you create it, you free it" school of thought. If everybody adhered to that principle it would make memory management issues much simpler. I think it would be much cleaner if you assigned the pointer to a member var before returning it, then check the var's null state in your destructor and free the memory if necessary. It would make your code cleaner and more user friendly, and it would adhere to fairly widely practiced programming standards of memory management.
Just fyi... I haven't run the code in an app yet, but it looks good on paper. I will vote for your article, once I have tested the code.. but it is logically structure very well. I like what you have done with this -- powerful simplicity. Nice Job!
In business, if two people always agree, one of them is unnecessary.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi! Thanks for your notes!
The truth is I did have 3 minor bugs in the first version I released here, then some hours later I fixed it, and added the BLOB support.
I apologize for the mis-spelling, I spend more time on coding than writing the documentation... I also already wrote here that the real documentation is in the code 
About your suggestion for that "pointer management" technique: From what you are saying I understand that you want a class like "TablePtr" that will contain a member pointing to a Table class, Then the destructor will free it. Correct me if I'm wrong... Anyway I will soon take care of it and post an update, and at the same time I'll fix the misspelling...
BTW, regarding your other post, as far as I know, you do not have to use MFC to support TCHAR, and so the classes are not only for MFC... Again, correct me if I'm wrong...
----- Daniel Cohen Gindi danielgindi (at) gmail dot com
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
 |
Hi, I have just uploaded an update with the last changes: TablePtr wrapper for Table*, and fix for the "GerLastError"
----- Daniel Cohen Gindi danielgindi (at) gmail dot com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Daniel Cohen Gindi wrote: From what you are saying I understand that you want a class like "TablePtr" that will contain a member pointing to a Table class, Then the destructor will free it. I don't think that's necessary.. your Database class is creating/returning the pointer and it already has a constructor/destructor function. It could handle freeing the memory allocation as well. But, yes, however you do it I think it's better coding practice to be responsible for freeing any resources you allocate.. so if the Database class allocates the resource, then it should be freed in that class as well. That may seem picky, but remember people who aren't familiar with your code will be trying to read it and use it.
Daniel Cohen Gindi wrote: BTW, regarding your other post, as far as I know, you do not have to use MFC to support TCHAR, and so the classes are not only for MFC... No, of course not... I didn't say they were ONLY for MFC. What I said was that it was MFC compatible. You can pass a CString directly to any function accepting an LPCTSTR (const char*) and MFC will automatically make the conversion and you don't have to worry about data loss, buffer overruns, etc. It's not quite so tidy with char* and char** -- now you're dealing with pointers, buffers and copying data, etc., or you have to type-cast to a non-const data type or pass a CString.buffer() address (both of which can have undesirable results should the data be modified) My point was if someone is coding in MFC why use a wrapper that isn't MFC compatible? Wrappers relying on standard strings and character pointers should be left to non-MFC apps.
There are still plenty of situations where MFC isn't a viable choice, and you don't want your code tied to it... but when you are using MFC you may as well take advantage of it's simplicity... your class allows for that... many of the others available don't. So to an MFC coder your class's MFC compatibility is one good reason to use it over the other 27 available wrappers - that was my point.
In business, if two people always agree, one of them is unnecessary.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Looks good but SQLite web page lists 27 C++ wrappers.
Why did you write your own and how is it better than the existing ones?
Dave Cross
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
 |
Truth is I did'nt know that there were C++ wrappers already, And anyway I always prefer my own code, which I can trust the most - And understand the best, So in case I find a bug, or have to add code, I change it with no effort at all.
I apologize for making you 'confused' :-P Anyway, if anyone finds it useful, that was worth uploading to the web!
----- Daniel Cohen Gindi danielgindi (at) gmail dot com
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
 |
Dave, if you looked at all 27 classes you will note that they aren't all free, many of the free ones aren't very good, some aren't even supported anymore, and there is only ONE decent MFC wrapper -- and it isn't even supported anymore.
The whole point of a wrapper class is to substantially REDUCE the amount of coding necessary to achieve a result. If a wrapper class only changes the function name/data type you are using, or only eliminates 1 or 2 lines of code, but leaves you to still handle errors, handle data management on queries, etc.. then it really isn't wrapping much code.
While I haven't used the code in question here, and it may or may not be full of bugs, etc.. there are a few things I like about the logic of the class compared to the other wrappers available. 1) is it's simplicity. It doesn't wrap EVERYTHING that sqlite3 is capable of, but if you are developing an end-user app, more than likely basic read/write functions and error-handling are all you will need the vast majority of the time, so why add unnecessary/unused code to your app? 2) It is an MFC class -- because of his use of the LPCTSTR data type you can pass your C-Strings directly without first converting to a pointer or a memory buffer. When programming in MFC I like to let Windows handle memory management as much as possible. Just fill your app with pointers galore and then try to debug an invalid pointer and you will understand. 3) Finally, I love that he puts the query results in a table class. All you do is execute a query with one line of code and you now have results that you can manage anyway you like.. you can populate a list, you could export to a CSV or text file, you can fill form fields if you wish to use an old-school MFC type RECORD BASED interface -- you could even write the results to another database table. It does all the work for you, but still leaves you with enough flexibility to manage your data and display the results any way you like.
For a "simple" wrapper class, this is very well thought out. If the code works as good as promised, I will give a 5 for this project.
For those of you who don't want MFC, there are plenty of other choices... If you are doing a web-based app, stick with MySQL - the point of sqLite is it's "embeddability" - it's purpose is desktop/distributed apps. And some of us who still provide custom desktop solutions for the Windows platform, still use MFC. Thanks dude, you've simplified my life.
In business, if two people always agree, one of them is unnecessary.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
 |
Thanks, thats exactly the sort of precis that I was hoping for from the author. Not knowing SQLlite, but being intrigued by the first few line I read, I wanted to know if it would be worth my while investigating further. Your praise, combined with what I read on the SQLlite web page, encorage me to dig deeper and consider this as an alternative to SQL Server for my next DB project. Many a time I knowingly choose a sub-optimal solution because it's 'what I know' and good authors explain why this old dog should spend valuable time learning new tricks.
Dave Cross
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |