public UpdatableResultSetView(SystemTransaction transaction, IMutableTable backedTable, Expression[] project, IRowCursor select) { this.transaction = transaction; this.backedTable = backedTable; this.project = project; originalSelect = select; currentSelect = select; this.select = null; }
public SystemColumnsTable(SystemTransaction transaction, long id) { this.transaction = transaction; this.id = id; columns = new ColumnCollection(this); SetupColumns(); }
public IQueryContext CreateContext() { lock (syncObject) { // Create a new transaction if there isn't already one open. if (transaction == null) { transaction = session.CreateTransaction(username); } // The query container table QueryContainerTable queryContainer = new QueryContainerTable(transaction, null); // Return a query container interface return new EmbeddedQueryContext(queryContainer, transaction, syncObject); } }
public IQueryContext Execute(IQueryContext context) { // Synchronize over this object to enforce the single thread per session // rule. Note that this does not prevent other sessions from interacting // with the database concurrently. lock (syncObject) { // Create a new transaction if there isn't already one open. if (transaction == null) transaction = session.CreateTransaction(username); // Only row count of 1 currently supported, if (context.RowCount != 1) throw new ArgumentException("Incorrect query context"); EmbeddedQueryContext result_i = (EmbeddedQueryContext)context; QueryContainerTable table = (QueryContainerTable) result_i.BackedTable; Query query = table.Query; // Execute the query and return the result return ExecuteQuery(query); } }
private void AddColumnIndex(SystemTransaction transaction, SystemTable schemaTable, string indexName, string column) { throw new NotImplementedException(); }
public QueryPlanner(SystemTransaction transaction) { this.transaction = transaction; random = new Random(); simpleProcessor = new QueryProcessor(transaction); }
private void Add3ColumnIndex(SystemTransaction transaction, SystemTable table, string indexName, string column1, string column2, string column3) { throw new NotImplementedException(); }
internal QueryProcessor(SystemTransaction transaction) { this.transaction = transaction; tableStack = new List<ITable>(); rowIdStack = new List<RowId>(); }
internal void CopyIndexFrom(SystemTransaction transaction, long indexId) { // Get the index name IndexName indexName = GetIndexName(indexId); // We get the index as a SystemTableIndex SystemIndexSetDataSource indexSource = transaction.GetIndex(indexId); // Check if an object with this name exists in this transaction, if (IndexExists(indexName.TableName, indexName.Name)) { // It does exist, so generate an error throw new ApplicationException("Index copy failed, index '" + indexName + "' already exists"); } // Copy the index to this transaction indexSource.CopyEntirelyTo(this); // Update the index id, AddIndex(indexId, indexName.TableName, indexName.Name, user.Name, indexSource.Collation); }
internal static void CompleteRowUpdate(SystemTransaction transaction, IMutableTable table, TableName tableName, RowId beforeRowid, RowId afterRowid) { IIndexSetDataSource[] ids = transaction.GetTableIndexes(tableName); foreach (IIndexSetDataSource i in ids) { i.Remove(beforeRowid); i.Insert(afterRowid); } // TODO: check for constraint violations table.Commit(); }
public SqlInterpreter(ISessionContext context, SystemTransaction transaction) { this.context = context; this.transaction = transaction; }
private IQueryContext ExecuteQuery(Query query) { lock (syncObject) { // Make the statement interpreter SqlInterpreter interpreter = new SqlInterpreter(this, transaction); // Execute the query ITable resultSet = interpreter.ExecQuery(query); // Was the last command a transactional operation (commit or rollback)? if (interpreter.HasSpecialCommand) { if (interpreter.SpecialCommand.Equals("set_schema")) { string schemaName = SqlInterpreter.GetStaticString(interpreter.SpecialCommandArgument); transaction.ChangeSchema(schemaName); resultSet = SqlInterpreter.DMLResult(1); } else { try { // Commit it (if it's a commit op) and dispose if (interpreter.SpecialCommand.Equals("commit")) session.CommitTransaction(transaction); } finally { // We must ensure that dispose is always called regardless SystemTransaction to_dispose = transaction; transaction = null; session.DisposeTransaction(to_dispose); } int result = (transaction == null) ? 0 : 1; resultSet = SqlInterpreter.DMLResult(result); } } // Map the result table into a form the JDBC driver wants return new EmbeddedQueryContext(resultSet, transaction, syncObject); } }
public EmbeddedQueryContext(ITable backedTable, SystemTransaction transaction, object syncObject) { this.syncObject = syncObject; isClosed = false; this.backedTable = backedTable; // Determine the updatability of the result set notNotUpdatableReason = null; // If the result set is a mutable table data source object, if (backedTable is IMutableTable) { updatableView = new UpdatableResultSetView(transaction, (IMutableTable) backedTable, null, backedTable.GetRowCursor()); } else { // Can we map this to a native table? TableName nativeTableName = QueryProcessor.GetNativeTableName(backedTable); // If we can, if (nativeTableName != null) { // The top table must be an operation table and must have all // FETCHVAR operations, if (backedTable is ExpressionTable) { ExpressionTable expressionTable = (ExpressionTable)backedTable; Expression[] projectionExps = expressionTable.Expressions; foreach (Expression op in projectionExps) { if (QueryProcessor.GetAsVariableRef(op) == null) { notNotUpdatableReason = "Not updatable, result set contains functional " + "projections. Please simplify the select terms."; break; } } // Otherwise, if it all looks ok, set the updatable table if (notNotUpdatableReason == null) { SystemTable nativeTableSource = transaction.GetTable(nativeTableName); updatableView = new UpdatableResultSetView(transaction, nativeTableSource, projectionExps, backedTable.GetRowCursor()); } } else { notNotUpdatableReason = "This result set is not updatable."; } } else { notNotUpdatableReason = "Not updatable, result set does not source " + "to a native table."; } // If we didn't create an updatable view, we create one with null values // and use if for iterator caching only if (updatableView == null) { updatableView = new UpdatableResultSetView(null, null, null, backedTable.GetRowCursor()); } } }
public QueryOptimizer(SystemTransaction transaction) { this.transaction = transaction; }
public IQueryContext Execute(Query query) { // Synchronize over this object to enforce the single thread per session // rule. Note that this does not prevent other sessions from interacting // with the database concurrently. lock (syncObject) { // Create a new transaction if there isn't already one open. if (transaction == null) transaction = session.CreateTransaction(username); // Execute the query and return the result return ExecuteQuery(query); } }
public void PerformSample(SystemTransaction transaction) { // Translate into tables and column names ITable tableSource = transaction.GetTable(var.TableName); // DOn't bother unless the table has 64 or more values if (tableSource.RowCount < (DivisionPointCount * 2)) { sampleCount = 0; totalSize = 0; return; } // The number of elements in total totalSize = tableSource.RowCount; // The actual number of samples, sampleCount = (int)System.Math.Min(tableSource.RowCount / 2, MaxSampleCount); String col_name = var.Name; int colId = tableSource.Columns.IndexOf(var.Name); // Work out the size long size = tableSource.RowCount; // The sample point difference double sampleDiff = (double)size / sampleCount; // The index of the tables used in sampling IIndex<RowId> sampleIndex = transaction.CreateTemporaryIndex<RowId>(sampleCount); // Create a RowIndexCollation for this SqlType type; type = tableSource.Columns[colId].Type; IndexCollation collation = new IndexCollation(type, col_name); // Create the collation object, CollationIndexResolver resolver = new CollationIndexResolver(tableSource, collation); // The row cursor IRowCursor rowCursor = tableSource.GetRowCursor(); RowId[] sampleRowset = new RowId[sampleCount]; // First read in the row_ids we are sampling, { // The current sample point double p = 0; // The number read, int samplesRead = 0; // Make a sorted sample index of the dataset while (samplesRead < sampleCount) { long pos = ((long)p) - 1; pos = System.Math.Min(pos, tableSource.RowCount - 2); rowCursor.MoveTo(pos); if (!rowCursor.MoveNext()) throw new SystemException(); RowId rowId = rowCursor.Current; sampleRowset[samplesRead] = rowId; // Should this be Math.random(sample_diff * 2) for random distribution // of the samples? p += sampleDiff; ++samplesRead; } } // Now read the samples, { int samplePoint = 0; foreach (RowId rowId in sampleRowset) { // Hint ahead the samples we are picking, if ((samplePoint % 24) == 0) { for (int i = samplePoint; i < samplePoint + 24 && i < sampleRowset.Length; ++i) { tableSource.PrefetchValue(-1, sampleRowset[i]); } } // Pick the sample and sort it, SqlObject[] sample = new SqlObject[] { tableSource.GetValue(colId, rowId) }; sampleIndex.Insert(sample, rowId, resolver); ++samplePoint; } } // Now extract the interesting sample points from the sorted set IIndexCursor<RowId> samplesCursor = sampleIndex.GetCursor(); long sampleIndexSize = sampleIndex.Count; double divisionDiff = sampleIndexSize / (DivisionPointCount - 1); for (int i = 0; i < DivisionPointCount; ++i) { long samplePoint = (long)(divisionDiff * i); if (samplePoint >= sampleIndexSize) { samplePoint = sampleIndexSize - 1; } samplesCursor.Position = samplePoint - 1; if (!samplesCursor.MoveNext()) throw new SystemException(); RowId rowId = samplesCursor.Current; divisionPoints[i] = tableSource.GetValue(colId, rowId); } // Clear the temporary index sampleIndex.Clear(); }
internal void CopyTableFrom(SystemTransaction transaction, long tableId) { // We get the table as a TSTableDataSource SystemTable tableSource = transaction.GetTable(tableId); // Check if an object with this name exists in this transaction, TableName tableName = tableSource.Name; if (TableExists(tableName)) // It does exist, so generate an error throw new ApplicationException("Table copy failed, table '" + tableName + "' already exists"); // Copy the table to this transaction tableSource.CopyTo(this); // Update the directory id, AddObject(tableId, tableName, user.Name); }
public QueryCostModel(SystemTransaction transaction) { this.transaction = transaction; processor = new QueryProcessor(transaction); }
private long AddColumnSet(SystemTransaction transaction, string[] columns) { throw new NotImplementedException(); }
public QueryContainerTable(SystemTransaction transaction, Query query) { this.transaction = transaction; parameters = new List<SqlObject>(); if (query != null) { queryString = query.Text; foreach (QueryParameter parameter in query.Parameters) parameters.Add(parameter.Value); } columns = new ColumnCollection(this); columns.Add("#QUERY", SqlType.String, true); }
private void AddForeignConstraint(SystemTransaction transaction, TableName srcTableName, long srcColSet, TableName refTableName, long refColSet) { throw new NotImplementedException(); }
internal void StartTransaction(SystemTransaction tnx) { if (!verified) { tnx.VerifyUser(this); verified = true; } verified = true; sessionStarted = DateTime.Now; sessionCommands = new List<Query>(); transaction = tnx; }
internal static void SetInsertRowToDefault(SystemTransaction transaction, TableName table_name, IMutableTable table, RowId rowid) { // Get all column defaults on the table IList<object> table_defaults = transaction.QueryTableDefaults(table_name); int sz = table_defaults.Count / 2; // Exit quickly if there's no default values if (sz == 0) return; // Create a query processor QueryProcessor processor = new QueryProcessor(transaction); // For each default value, TableRow row = table.GetRow(rowid); for (int i = 0; i < sz; ++i) { string colName = (string)table_defaults[i * 2]; Expression colDefault = (Expression)table_defaults[(i * 2) + 1]; // Execute the default value expression ITable defaultResult = processor.Execute(colDefault); // Turn it into a TObject SqlObject val = defaultResult.GetValue(0, new RowId(0)); // The col num of the column name int colIndex = table.Columns.IndexOf(colName); if (colIndex < 0) throw new ApplicationException("Column '" + colName + "' not found for DEFAULT value"); // And insert it row.SetValue(colIndex, val); } }
internal void EndTransaction() { transaction = null; sessionCommands.Clear(); sessionCommands = null; sessionStarted = DateTime.MinValue; verified = false; }
private static IRowCursor QueryAllMatches(SystemTransaction transaction, TableName tableName, SystemTable table, IList<string> columns, SqlObject val) { // Try and find an index on these columns SystemIndexSetDataSource indexSet = transaction.FindIndexOn(tableName, columns); // If index found if (indexSet != null) // Query the index and find all matches return indexSet.Select(SelectableRange.Is(val)); // Otherwise no index, so scan the table for matches // Make an Expression for the operation; // (column1, column2, ...columnn) = val Expression compExp; int sz = columns.Count; if (sz > 1) { FunctionExpression cfunExp = new FunctionExpression("composite_fetch"); for (int i = 0; i < sz; ++i) { Expression varRef = new FetchVariableExpression(new Variable(tableName, columns[i])); cfunExp.Parameters.Add(varRef); } compExp = cfunExp; } else if (sz == 1) { compExp = new FetchVariableExpression(new Variable(tableName, columns[0])); } else { throw new ApplicationException("Invalid columns list size"); } // Equality test FunctionExpression funExp = new FunctionExpression("@is_sql"); funExp.Parameters.Add(compExp); funExp.Parameters.Add(new FetchStaticExpression(val)); // Create a query processor and perform the scan operation QueryProcessor processor = new QueryProcessor(transaction); ITable result = processor.FilterByScan(table, funExp); // Return the row cursor return result.GetRowCursor(); }
public void CommitTransaction(SystemTransaction transaction) { // If the transaction has had no changes, we return immediately if (!transaction.HasChanges) return; // The transaction we are working on through this commit process, SystemTransaction workingTransaction; // If the given transaction is of the same commit version as the current, // then the working transaction is the given transaction lock (commitSyncRoot) { // The list table ids we updated List<long> modifiedTables = new List<long>(); // If the given transaction is of the same commit version, then the // working version is the given. If there hasn't been a commit since // the given transaction was created then no transaction merge is // necessary. if (transaction.CommitVersion == currentCommitVersion) { workingTransaction = transaction; // We make sure we update the 'modified_tables' list with the set of // unique tables that were changed List<long> alteredTableIds = transaction.AlteredTables; alteredTableIds.Sort(); int sz = alteredTableIds.Count; long lastTableId = -1; // This goes through the altered table list provided by the // transaction and creates a unique set of tables that were // altered. for (int i = 0; i < sz; ++i) { long table_id = alteredTableIds[i]; if (table_id != lastTableId) { modifiedTables.Add(table_id); lastTableId = table_id; } } } // Otherwise we must create a new working transaction else { // ----------------- // Transaction MERGE // ----------------- // This condition occurs when a transaction has been committed after // the given transaction was created, and we need to move any updates // from the committing transaction to the latest update. workingTransaction = new SystemTransaction(this, db.CreateTransaction(), currentCommitVersion, transaction.User.Verified()); // SystemTable merges, // First of all replay the general database updates as described in // the journal (table and index creation/drops etc). TransactionJournal tranJournal = transaction.Journal; IEnumerator<JournalEntry> i = tranJournal.GetEnumerator(); // The list of tables created in this transaction List<long> tablesCreated = new List<long>(); while (i.MoveNext()) { JournalEntry entry = i.Current; JournalCommandCode command = entry.Code; long ident = entry.TableId; // Table commands, if (command == JournalCommandCode.TableCreate) { // Copy the created table from the original transaction to the // working transaction. // We check the table exists in the transaction. If it doesn't // it means the table was dropped. if (transaction.TableExists(ident)) { // Get the name of the object TableName tname = transaction.GetObjectName(ident); if (workingTransaction.TableExists(tname)) { // Create fails, the table name exists in the current // transaction throw new CommitException("CREATE TABLE '" + tname + "' failed: table with name exists in " + "current transaction"); } // Otherwise copy the table workingTransaction.CopyTableFrom(transaction, ident); tablesCreated.Add(ident); } } // When the table is structurally changed (columns, added/removed, // etc) else if (command == JournalCommandCode.TableAlter) { long tableId = ident; // If this table was created by this transaction, then we don't // need to worry, we have the most recent version of the table // structure. // Otherwise, the table was altered during the transaction, so // we need to copy the most recent version if it hasn't changed. if (!tablesCreated.Contains(tableId)) { // Check it exists in the current // If it doesn't it means it was dropped if (transaction.TableExists(tableId)) { // Check the table exists if (!workingTransaction.TableExists(tableId)) { throw new CommitException("ALTER TABLE '" + transaction.GetObjectName(tableId) + "' failed: table does not exist in the " + "current transaction"); } // Check the version of the table we are dropping is the same // version and exists. long ver1 = transaction.GetTableVersion(tableId); long ver2 = workingTransaction.GetTableVersion(tableId); // If the versions are different, some modification has happened // to the table so we generate an error if (ver1 != ver2) throw new CommitException("ALTER TABLE '" + transaction.GetObjectName(tableId) + "' failed: Table was modified by a concurrent transaction"); // Okay, we can now copy the table. We drop the existing table // and copy the new one over. workingTransaction.DropTable(tableId); workingTransaction.CopyTableFrom(transaction, tableId); } } } else if (command == JournalCommandCode.TableDrop) { long table_id = ident; // Check the table exists if (!workingTransaction.TableExists(table_id)) { throw new CommitException("DROP TABLE '" + transaction.GetObjectName(table_id) + "' failed: Table does not exist in the current transaction"); } // Check the version of the table we are dropping is the same // version and exists. long ver1 = transaction.GetTableVersion(table_id); long ver2 = workingTransaction.GetTableVersion(table_id); // If the versions are different, some modification has happened // to the table so we generate an error if (ver1 != ver2) { throw new CommitException("DROP TABLE '" + transaction.GetObjectName(table_id) + "' failed: Table was modified by a concurrent transaction"); } // Drop the table workingTransaction.DropTable(table_id); } // Index commands, else if (command == JournalCommandCode.IndexAdd) { long indexId = ident; // The name of the table of the index TableName indexTname = transaction.GetIndexName(indexId).TableName; // If the above returns null, it means the index no longer // exists so we skip if (indexTname != null) { // If the table doesn't exist in the working transaction, if (!workingTransaction.TableExists(indexTname)) throw new CommitException("CREATE INDEX on '" + indexTname + "' failed: table does not exist in the current transaction"); // Get the table id long tableId = workingTransaction.GetTableId(indexTname); // NOTE: This check ensures the index we copy from the transaction // we are committing is correct and up to date. We should, // perhaps, rewrite this to rebuild the index if there were // concurrent modifications to the table. // If the versions of the table we are creating the index on is // different then we fail, long ver1 = transaction.GetTableVersion(tableId); long ver2 = workingTransaction.GetTableVersion(tableId); // If the versions are different, some modification has happened // to the table so we generate an error if (ver1 != ver2) { throw new CommitException("CREATE INDEX on '" + indexTname + "' failed: Table was modified by " + "a concurrent transaction"); } // Copy the created index, workingTransaction.CopyIndexFrom(transaction, ident); } } else if (command == JournalCommandCode.IndexDelete) { long indexId = ident; // Drop the index. This fails if the index doesn't exist in the // current version. Note that this will succeed if there were // modifications to the table by a concurrent transaction. workingTransaction.DropIndex(indexId); } // Otherwise unrecognized else { throw new ApplicationException("Unknown journal entry: " + command); } } // Now replay the table level operations, // The list of all tables changed during the lifespan of the // transaction, List<long> alteredTableIds = transaction.AlteredTables; alteredTableIds.Sort(); long lastTableId = -1; int sz = alteredTableIds.Count; // For each table id that was altered, for (int n = 0; n < sz; ++n) { long tableId = alteredTableIds[n]; if (tableId != lastTableId) { // The SystemTable object SystemTable currentTable = workingTransaction.GetTable(tableId); // If the table no longer exists we ignore the journal and go to // the next table. We assume the table drop has not broken // database integrity if we have reached this part. if (currentTable != null) { // Add this to the list of tables we updated modifiedTables.Add(tableId); // The table name TableName tableName = currentTable.Name; // The indexes on this table SystemIndexSetDataSource[] indexes = workingTransaction.GetTableIndexes(tableName); // The table from which we are merging in entries, SystemTable toMerge = transaction.GetTable(tableId); // Get the journal for this table id, TransactionJournal journal = toMerge.Journal; // Replay the operations in the journal, IEnumerator<JournalEntry> ti = journal.GetEnumerator(); while (ti.MoveNext()) { JournalEntry entry = ti.Current; JournalCommandCode command = entry.Code; RowId ident = entry.RowId; if (command == JournalCommandCode.RowAdd) { currentTable.CopyRowIdFrom(toMerge, ident); // Update the indexes foreach (IIndexSetDataSource idx in indexes) { idx.Insert(ident); } } else if (command == JournalCommandCode.RowRemove) { // This will commit exception if the row no longer exists. currentTable.RemoveRowId(ident); // Update the indexes foreach (IIndexSetDataSource idx in indexes) { idx.Remove(ident); } } else if (command == JournalCommandCode.ColumnAdd) { // Can be ignored, this is handled by a structural change // entry in the transaction log, and copying the table over // from the lower version transaction. } else if (command == JournalCommandCode.ColumnRemove) { // Can be ignored, this is handled by a structural change // entry in the transaction log, and copying the table over // from the lower version transaction. } } } lastTableId = tableId; } } // We have now successfully replayed all the operations on the working // transaction. The following artifacts may now be in the database; // 1) Unique constraints may be violated // 2) Referential integrity may be violated // 3) Check constraints need to be checked again if they contain // nested query functions. } // Go through the list of updated tables and increment the commit // version on each of them foreach (long modifiedTableId in modifiedTables) { workingTransaction.IncrementTableVersion(modifiedTableId); } // Check any deferred constraints on the working_transaction // TODO: all the table/index merge functionality here... try { // And commit the working transaction db.CommitTransaction(workingTransaction.State); // Increment the commit version number ++currentCommitVersion; } catch (Exception e) { throw new CommitException("The database state failed to commit the transaction changes: " + e.Message, e); } } }
internal QueryProcessor(QueryProcessor src) { transaction = src.transaction; tableStack = new List<ITable>(src.tableStack); rowIdStack = new List<RowId>(src.rowIdStack); }
public void DisposeTransaction(SystemTransaction transaction) { ITransactionState transactionState = transaction.State; transaction.MarkAsDisposed(); db.DisposeTransaction(transactionState); }
public SystemIndexSetDataSource(SystemTransaction transaction, ITableIndex index) { this.transaction = transaction; this.index = index; }
public ColumnsSystemTable(SystemTransaction transaction, long tableId) : base(new TableName(SystemTableNames.SystemSchema, "Columns")) { this.transaction = transaction; this.tableId = tableId; }