Introduction
.NET! C #! If you have not been inundated with the marketing of Microsoft's new initiatives, you've been living in your cube without a web connection for quite a while. Like a lot of developers, I had installed the .NET SDK And the Beta 1 of Visual Studio .Net and Played with it. However, Since ITS Release Was So Far Out in The Future and I Had Deadlines To Meet, I Soon Went Back to Working Weth The Things My Customers Needed Now.
But the press coverage continued. One evening our Vice President of New Technologies noticed me carrying out a book on COM on the way out, and asked something like 'COM ? Why are not you studying .NET and C #?'
OK, I Knew What Management Was Thinking About, It Couldn't Hurt To Give This Thing Another Look ...
Being the masochist that I am, I generally learn a new language or technology by jumping in over my head and figuring it out when I've got motivation, like a looming deadline. Since I'm not likely to see any customers asking for. NET Work Prior To It's Release, I needed to come up with something on my oow.
I recently started a project on SourceForge, the HSQL Database Engine which is continuing the development of a Java SQL engine project that had been dropped by the original developer. From what I saw and read, C # was a lot like Java, so why not port It? there................
This is The Story of That Little Adventure.
Porting Issues
There are enough differences between Java and C # to give you a bit of a headache when porting anything significant. I believe that Microsoft's Java User Migration Path (JUMP) will be a success at converting 80-90% of Java code, but the rest of it is going to be sticky. Doing it manually was a somewhat painful process.Syntax differences are minor at best. The compiler thankfully complained about these and stopped, so I spent a little over a day making these changes, without being distracted by the next STEP.
Then came the majority of the porting effort. If my memory serves me right, the first time there were no syntax problems the complier reported over 3000 library / API errors. Almost all of these were due to differences between the Java API and the .NET API.
Rather Than Go Into All of them, I'll Elaborate ON A FEW.
In Java, the StringBuffer class is used for building a string to eliminate the overhead of creating multiple String objects when building a complex string. .NET has an equivalent class, StringBuilder. The methods are almost identical, with the exception of the first character of The Methods Are Uppercase, so stringBuffer.Append Becomes StringBuilder.Append.
.
These kinds of differences are pervasive throughout the .NET API. Most of the JAVA API objects are represented, but have slight differences that could be resolved by a smart parser that understood both languages. Without something like JUMP, or at least a comparative guide available I had to do a lot of reading to find the classes I needed.
The bad part:. C # and .NET do not support the loading of a class at runtime based on it's name This forced me to drop support for triggers from the C # version of the database engine, as this was central to their design Additionally,. many of the SQL operators were implemented using this technique in the Java version, so the C # version currently does not support as many SQL options as the Java version. If someone was motivated, they could probably add support for them in the C # version in a Couple of days.update
Thanks to Rossen Blagoev, Who Pointed Out That Is Possible To Load a class by name in c #, using the Activator Class.
Activator.createInstance (Type.gettype ("MyClass"));
I'll have to play with it, but I think the Activator and MethodInfo classes will be required to do what I need to, and I think for C # the parser will have to be changed slightly, since it needs to know the Assembly if the Class to be loading is not in the executing assembly.
Here Is The Java Version of A Result Object's Constructor
Result (byte b []) throws SQLException {ByteArrayInputStream bin = new ByteArrayInputStream (b); DataInputStream in = new DataInputStream (bin); try {iMode = in.readInt (); if (iMode == ERROR) {throw Trace.getError (In.Readutf ());} else if (imode == updateCount) {iUpdatecount = in.readint ();} else if (imode == data) {intl = in.readint (); preparedata (l); IColumnCount = L; for (int i = 0; i Public results (byte [] b) {membratestream bin = new memoryStream (b); binaryreader din = new binaryreader (bin); try {immode = din.readint32 (); if (imode == error) {throw TRACE.GETERROR DIN.ReadString ());} else if (imode == updatecount) {iUpdatecount = din.readint32 ();} else if (imode == data) {INT L = DIN.READINT32 (); preparedata (L); icolumncount = L; for (int i = 0; i SQL ENGINE ARCHITECTURE Each database connection uses a different Channel object. The Channel has a link to a User object and a list of Transaction objects. (A Transaction object is a single row insert or delete in a table) The result from a database operation is a Result object (this * May * Contain Record Objects if the query Was a successful select operation) . How A Statement is Processed The Database creates a Tokenizer that breaks the statement into tokens. If it's a INSERT, UPDATE, DELETE or SELECT, a Parser is created (all other statements are processed by the Database class directly) The Parser creates a Select object if it's a SELECT. This Select Contains One or More TableFilter Objects (A Conditional Cursor Over A Table), Expression Objects and Possibly Another Select (if it's a union) How the data is store The Index is an AVL tree. Each Index contains a root Node that is 'null' if the table is empty. Each node may have a parent node and a left and / or right child. Each node is linked to a Row object (the Row Contains the data.) The data is contained in an Array of Objects. Transaction Handling The Channel keeps track of the uncommitted transactions. Each Transaction object contains a reference to the 'old' data. Statements that may fail (for example UPDATES) start a nested transaction, but more nesting is not built in. Also, since SharpHSQL was not designed as a multi-user database, other Channel's can read the uncommitted transaction objects, ie a two-phase commit protocol is not used. A rollback is done by un-doing (re-inserting or deleting) the changes in reverse order. This also means that we have implemented UPDATES as a combination of DELETE and INSERT operations, which is why updates are slower than inserts.More specific information about the internal architecture of the engine can be found at the HSQL Database Engine project page on SourceForge. How to use the sharphsql classes The SharpHSQL class in the sample project contains basic examples of executing queries and accessing their results. It implements a simple command line SQL engine that you can type queries into and display the results. EXAMPLE // Create An In Memory Database By Creating With the name "." // this has no logging or ost database ("."); // the "sa" user is created by Default with no password, So we can connect // Using this userchannel mychannel = db.connect ("sa", "); all queries return a result ObjectResult Rs; // We need a string to enter out queriesstring query ="; // while the Query is not the quit commandwhile (! query.tolower (). Equals ("quit") {// Write a little prompt out to the console console.write ("sql>"); // read a line of text Query = Console.readline (); // is it quit command? If (! Query.tolower (). Equals ("quit)) {// no, execute it usding our channel Object = db.execute (Query, MyChannel); // if there is an error if (rs.Serror! = null) {// print the error message out to the console console.writeline (} else {// write out some statistics Console.Write (RS.Getsize () "Rows Returned," RS.IupdateCount "Rows Affected./N/N"); // if We Had Records Returned IF (rs.root! = Null) {// Get the first one record r = rs.root; // Get the column count from the result Object int column_count = rs.getColumnCount (); for (int x = 0; x } Console.write ("/ n"); while (r! = Null) {for (int x = 0; x