/// <summary> /// Executes an SQL statement and return the results. /// </summary> /// <param name="statement">The SQL statement to execute.</param> /// <param name="channel">The channel to use.</param> /// <returns>The Result object.</returns> public Result Execute(string statement, Channel channel) { if (TracingHelper.TraceEnabled) { TracingHelper.Write(statement); } Tokenizer c = new Tokenizer(statement); Parser p = new Parser(this, c, channel); Result rResult = new Result(); string newStatement = string.Empty; int updateCount = 0; try { if (_log != null && _log.cCache != null) { _log.cCache.CleanUp(); } if (TracingHelper.AssertEnabled) { TracingHelper.Assert(!channel.IsNestedTransaction); } TracingHelper.Check(channel != null, TracingHelper.ACCESS_IS_DENIED); TracingHelper.Check(!_shutDown, TracingHelper.DATABASE_IS_SHUTDOWN); while (true) { int begin = c.Position; bool script = false; string sToken = c.GetString(); if( sToken.Equals("") ) break; switch(sToken) { case "SELECT": rResult = p.ProcessSelect(); break; case "INSERT": rResult = p.ProcessInsert(); break; case "UPDATE": rResult = p.ProcessUpdate(); break; case "DELETE": rResult = p.ProcessDelete(); break; case "ALTER": rResult=p.ProcessAlter(); break; case "CREATE": rResult = ProcessCreate(c, channel); script = true; break; case "DROP": rResult = ProcessDrop(c, channel); script = true; break; case "GRANT": rResult = ProcessGrantOrRevoke(c, channel, true); script = true; break; case "REVOKE": rResult = ProcessGrantOrRevoke(c, channel, false); script = true; break; case "CONNECT": rResult = ProcessConnect(c, channel); break; case "DISCONNECT": rResult = ProcessDisconnect(c, channel); break; case "SET": rResult = ProcessSet(c, channel); script = true; break; case "SCRIPT": rResult = ProcessScript(c, channel); break; case "COMMIT": rResult = ProcessCommit(c, channel); script = true; break; case "ROLLBACK": rResult = ProcessRollback(c, channel); script = true; break; case "SHUTDOWN": rResult = ProcessShutdown(c, channel); break; case "CHECKPOINT": rResult = ProcessCheckpoint(channel); break; case "CALL": rResult = p.ProcessCall(); break; case "SHOW": rResult = ProcessShow(c,channel); break; case "DECLARE": rResult = p.ProcessDeclare(); script = true; break; case ";": continue; default: throw TracingHelper.Error(TracingHelper.UnexpectedToken, sToken); } if( rResult != null && rResult.UpdateCount > updateCount ) updateCount = rResult.UpdateCount; if (script && _log != null) { int end = c.Position; _log.Write(channel, c.GetPart(begin, end)); } } } catch (Exception e) { rResult = new Result(TracingHelper.GetMessage(e) + " in statement [" + statement + "]"); } if( rResult != null && rResult.UpdateCount < updateCount ) rResult.SetUpdateCount( updateCount ); return rResult; }
/// <summary> /// Process ALTER TABLE statements. /// /// ALTER TABLE tableName ADD COLUMN columnName columnType; /// ALTER TABLE tableName DELETE COLUMN columnName; /// </summary> /// <remarks> /// The only change I've made to Sergio's original code was /// changing the insert's to call insertNoCheck to bypass the trigger /// mechanism that is a part of hsqldb 1.60 and beyond. - Mark Tutt /// </remarks> /// <returns></returns> public Result ProcessAlter() { tTokenizer.GetThis ("TABLE"); string token = tTokenizer.GetString (); cChannel.CheckReadWrite (); // cChannel.check(token,Access.ALTER); --> Accessul nu-l inca controleaza... string tName = token; string swap = tName + "SWAP"; // nimicirea swapului... dDatabase.Execute ("DROP TABLE " + swap, cChannel); Table initialTable = dDatabase.GetTable (token, cChannel); int count = 0; token = tTokenizer.GetString (); if (token.Equals ("ADD")) { token = tTokenizer.GetString (); if (token.Equals ("COLUMN")) { Table swapTable = new Table (dDatabase, true, swap, initialTable.IsCached); // copiem coloanele (fara date) din tabelul initial in swap for (int i = 0; i < initialTable.ColumnCount; i++) { Column aColumn = initialTable.GetColumn (i); swapTable.AddColumn (aColumn); } // end Of copiem coloanele... // aflam daca are PrimaryKey & o cream... string cName = tTokenizer.GetString (); string cType = tTokenizer.GetString (); ColumnType iType = Column.GetColumnType (cType); string sToken = cType; // int primarykeycolumn = -1; bool identity = false; int column = initialTable.ColumnCount + 1; // !-- // stolen from CREATE TABLE... string sColumn = cName; if (iType == ColumnType.VarChar && dDatabase.IsIgnoreCase) { iType = ColumnType.VarCharIgnoreCase; } sToken = tTokenizer.GetString (); if (iType == ColumnType.DbDouble && sToken.Equals ("PRECISION")) { sToken = tTokenizer.GetString (); } if (sToken.Equals ("(")) { // overread length do { sToken = tTokenizer.GetString (); } while (!sToken.Equals (")")); sToken = tTokenizer.GetString (); } // !-- bool nullable = true; if (sToken.Equals ("NULL")) { sToken = tTokenizer.GetString (); } else if (sToken.Equals ("NOT")) { tTokenizer.GetThis ("NULL"); nullable = false; sToken = tTokenizer.GetString (); } /* * if(sToken.Equals("IDENTITY")) { * identity=true; * Trace.check(primarykeycolumn==-1,Trace.SECOND_PRIMARY_KEY,sColumn); * sToken=tTokenizer.getstring(); * primarykeycolumn=column; * } * * if(sToken.Equals("PRIMARY")) { * tTokenizer.getThis("KEY"); * Trace.check(identity || primarykeycolumn==-1, * Trace.SECOND_PRIMARY_KEY,sColumn); * primarykeycolumn=column; * //sToken=tTokenizer.getstring(); * } * //end of STOLEN... */ swapTable.AddColumn (cName, iType, nullable, identity); // under construction... if (initialTable.ColumnCount < initialTable.InternalColumnCount) { swapTable.CreatePrimaryKey (); } else { swapTable.CreatePrimaryKey (initialTable.PrimaryIndex.Columns [0]); } // endof PrimaryKey... // sa ne farimam cu indicii... ;-(( Index idx = null; while (true) { idx = initialTable.GetNextIndex (idx); if (idx == null) { break; } if (idx == initialTable.PrimaryIndex) { continue; } swapTable.CreateIndex (idx); } // end of Index... cChannel.Commit (); dDatabase.LinkTable (swapTable); Tokenizer tmpTokenizer = new Tokenizer ("SELECT * FROM " + tName); Parser pp = new Parser (dDatabase, tmpTokenizer, cChannel); string ff = tmpTokenizer.GetString (); if (!initialTable.IsEmpty) { Record n = ((Result)pp.ProcessSelect ()).Root; do { object[] row = swapTable.NewRow; object[] row1 = n.Data; for (int i = 0; i < initialTable.ColumnCount; i++) { row [i] = row1 [i]; } swapTable.InsertNoCheck (row, cChannel); n = n.Next; } while (n != null); } dDatabase.Execute ("DROP TABLE " + tName, cChannel); // cream tabelul vechi cu proprietatile celui nou... initialTable = new Table (dDatabase, true, tName, swapTable.IsCached); for (int i = 0; i < swapTable.ColumnCount; i++) { Column aColumn = swapTable.GetColumn (i); initialTable.AddColumn (aColumn); } if (swapTable.ColumnCount < swapTable.InternalColumnCount) { initialTable.CreatePrimaryKey (); } else { initialTable.CreatePrimaryKey (swapTable.PrimaryIndex.Columns [0]); } // endof PrimaryKey... // sa ne farimam cu indicii... ;-(( idx = null; while (true) { idx = swapTable.GetNextIndex (idx); if (idx == null) { break; } if (idx == swapTable.PrimaryIndex) { continue; } initialTable.CreateIndex (idx); } // end of Index... cChannel.Commit (); dDatabase.LinkTable (initialTable); // end of cream... // copiem datele din swap in tabel... tmpTokenizer = new Tokenizer ("SELECT * FROM " + swap); pp = new Parser (dDatabase, tmpTokenizer, cChannel); ff = tmpTokenizer.GetString (); if (!swapTable.IsEmpty) { Record n = ((Result)pp.ProcessSelect ()).Root; do { object[] row = initialTable.NewRow; object[] row1 = n.Data; for (int i = 0; i < swapTable.ColumnCount; i++) { row [i] = row1 [i]; } initialTable.InsertNoCheck (row, cChannel); n = n.Next; } while (n != null); // end of copiem... } dDatabase.Execute ("DROP TABLE " + swap, cChannel); count = 4; } else { throw TracingHelper.Error (TracingHelper.UnexpectedToken, token); } } else if (token.Equals ("DELETE")) { token = tTokenizer.GetString (); if (token.Equals ("COLUMN")) { Table swapTable = new Table (dDatabase, true, swap, initialTable.IsCached); string cName = tTokenizer.GetString (); int undesired = initialTable.GetColumnNumber (cName); for (int i = 0; i < initialTable.ColumnCount; i++) { Column aColumn = initialTable.GetColumn (i); if (i != undesired) { swapTable.AddColumn (aColumn); } } int pKey = -1; // !-- if (initialTable.ColumnCount < initialTable.InternalColumnCount) { swapTable.CreatePrimaryKey (); } else { int[] cols = initialTable.PrimaryIndex.Columns; pKey = cols [0]; if ((cols [0] > undesired) || (cols [0] + cols.Length < undesired)) { if (undesired < initialTable.PrimaryIndex.Columns [0]) { // reindexarea... for (int i = 0; i < cols.Length; i++) { cols [i]--; } // endOf reindexarea... } // MT: This initially wouldn't compile, missing the array index on cols[] swapTable.CreatePrimaryKey (cols [0]); } else { swapTable.CreatePrimaryKey (); } } // endof PrimaryKey... // sa ne farimam cu indicii... ;-(( Index idx = null; while (true) { idx = initialTable.GetNextIndex (idx); if (idx == null) { break; } if (idx == initialTable.PrimaryIndex) { continue; } bool flag = true; int[] cols = idx.Columns; for (int i = 0; i < cols.Length; i++) { if (cols [i] == undesired) { flag = false; } } if (flag) { Index tIdx; for (int i = 0; i < cols.Length; i++) { if (cols [i] > undesired) { cols [i]--; } } tIdx = new Index (idx.Name, idx.Columns, idx.ColumnType, idx.IsUnique); swapTable.CreateIndex (tIdx); } } // !-- cChannel.Commit (); dDatabase.LinkTable (swapTable); Tokenizer tmpTokenizer = new Tokenizer ("SELECT * FROM " + tName); Parser pp = new Parser (dDatabase, tmpTokenizer, cChannel); string ff = tmpTokenizer.GetString (); if (!initialTable.IsEmpty) { Record n = ((Result)pp.ProcessSelect ()).Root; do { object[] row = swapTable.NewRow; object[] row1 = n.Data; int j = 0; for (int i = 0; i < initialTable.ColumnCount; i++) { if (i != undesired) { row [j] = row1 [i]; j++; } } swapTable.InsertNoCheck (row, cChannel); n = n.Next; } while (n != null); } dDatabase.Execute ("DROP TABLE " + tName, cChannel); // cream tabelul vechi cu proprietatile celui nou... initialTable = new Table (dDatabase, true, tName, swapTable.IsCached); for (int i = 0; i < swapTable.ColumnCount; i++) { Column aColumn = swapTable.GetColumn (i); initialTable.AddColumn (aColumn); } // !-- if (swapTable.ColumnCount < swapTable.InternalColumnCount) { initialTable.CreatePrimaryKey (); } else { initialTable.CreatePrimaryKey (swapTable.PrimaryIndex.Columns [0]); } // endof PrimaryKey... // sa ne farimam cu indicii... ;-(( idx = null; while (true) { idx = swapTable.GetNextIndex (idx); if (idx == null) { break; } if (idx == swapTable.PrimaryIndex) { continue; } initialTable.CreateIndex (idx); } // end of Index... // !-- cChannel.Commit (); dDatabase.LinkTable (initialTable); // end of cream... // copiem datele din swap in tabel... tmpTokenizer = new Tokenizer ("SELECT * FROM " + swap); pp = new Parser (dDatabase, tmpTokenizer, cChannel); ff = tmpTokenizer.GetString (); if (!swapTable.IsEmpty) { Record n = ((Result)pp.ProcessSelect ()).Root; do { object[] row = initialTable.NewRow; object[] row1 = n.Data; for (int i = 0; i < swapTable.ColumnCount; i++) { row [i] = row1 [i]; } initialTable.InsertNoCheck (row, cChannel); n = n.Next; } while (n != null); // end of copiem... } dDatabase.Execute ("DROP TABLE " + swap, cChannel); count = 3; } else { throw TracingHelper.Error (TracingHelper.UnexpectedToken, token); } count = 3; } Result r = new Result (); r.SetUpdateCount (count); return r; }
private Result ProcessSet(Tokenizer tokenizer, Channel channel) { string sToken = tokenizer.GetString(); switch(sToken) { case "PASSWORD": channel.CheckReadWrite(); channel.SetPassword(tokenizer.GetStringToken()); break; case "READONLY": channel.Commit(); channel.SetReadOnly(ProcessTrueOrFalse(tokenizer)); break; case "LOGSIZE": { channel.CheckAdmin(); int i = Int32.Parse(tokenizer.GetString()); if (_log != null) { _log.SetLogSize(i); } } break; case "IGNORECASE": channel.CheckAdmin(); _ignoreCase = ProcessTrueOrFalse(tokenizer); break; case "MAXROWS": { int i = Int32.Parse(tokenizer.GetString()); channel.MaxRows = i; break; } case "AUTOCOMMIT": channel.SetAutoCommit(ProcessTrueOrFalse(tokenizer)); break; case "TABLE": { channel.CheckReadWrite(); channel.CheckAdmin(); Table t = GetTable(tokenizer.GetString(), channel); tokenizer.GetThis("INDEX"); tokenizer.GetString(); t.IndexRoots = (string)tokenizer.Value; } break; case "REFERENCIAL_INTEGRITY": case "REFERENTIAL_INTEGRITY": channel.CheckAdmin(); _referentialIntegrity = ProcessTrueOrFalse(tokenizer); break; case "WRITE_DELAY": { channel.CheckAdmin(); bool delay = ProcessTrueOrFalse(tokenizer); if (_log != null) { _log.SetWriteDelay(delay); } } break; default: if( tokenizer.TokenType == TokenType.VARIABLE ) { Parser p = new Parser(this, tokenizer, channel); p.ProcessSet( sToken ); break; } throw TracingHelper.Error(TracingHelper.UnexpectedToken, sToken); } return new Result(); }