public NuoDbDataReader(NuoDbConnection connection, int handle, EncodedDataStream dataStream, NuoDbCommand statement, bool readColumnNames) { this.connection = connection; this.handle = handle; this.pendingRows = dataStream; this.statement = statement; if (this.handle != -1) this.connection.InternalConnection.RegisterResultSet(this.handle); this.numberColumns = this.pendingRows != null ? this.pendingRows.getInt() : 0; this.values = new Value[numberColumns]; if (readColumnNames) { this.columnNames = new string[numberColumns]; for (int n = 0; n < numberColumns; ++n) { columnNames[n] = dataStream.getString(); } } else { //RemPreparedStatement ps = (RemPreparedStatement)statement; //columnNames = ps.columnNames; } }
public override DataTable GetSchemaTable() { if (metadata != null) return metadata; #if DEBUG System.Diagnostics.Trace.WriteLine("NuoDbDataReader.GetSchemaTable(" + statement.CommandText + ")"); #endif EncodedDataStream dataStream = new EncodedDataStream(); dataStream.startMessage(Protocol.GetMetaData); dataStream.encodeInt(handle); connection.InternalConnection.sendAndReceive(dataStream); int numberColumns = dataStream.getInt(); metadata = new DataTable("SchemaTable"); // Info on the schema of this table is at http://msdn.microsoft.com/en-us/library/system.data.odbc.odbcdatareader.getschematable.aspx // The zero-based ordinal of the column. This column cannot contain a null value. metadata.Columns.Add("ColumnOrdinal", typeof(int)); // The name of the column; this might not be unique. If the column name cannot be determined, a null value is returned. // This name always reflects the most recent naming of the column in the current view or command text. metadata.Columns.Add("ColumnName", typeof(string)); // The maximum possible length of a value in the column. For columns that use a fixed-length data type, this is the size of the data type. metadata.Columns.Add("ColumnSize", typeof(int)); // If DbType is a numeric data type, this is the maximum precision of the column. The precision depends on the // definition of the column. If DbType is not a numeric data type, do not use the data in this column. // If the underlying ODBC driver returns a precision value for a non-numeric data type, this value is used in the schema table. metadata.Columns.Add("NumericPrecision", typeof(int)); // If DbType is Decimal, the number of digits to the right of the decimal point. Otherwise, this is a null value. // If the underlying ODBC driver returns a precision value for a non-numeric data type, this value is used in the schema table. metadata.Columns.Add("NumericScale", typeof(int)); // The name of the catalog in the data store that contains the column. NULL if the base catalog name cannot be determined. // The default for this column is a null value. metadata.Columns.Add("BaseCatalogName", typeof(string)); // The name of the schema in the data source that contains the column. NULL if the base catalog name cannot be determined. // The default for this column is a null value. metadata.Columns.Add("BaseSchemaName", typeof(string)); // The name of the table or view in the data store that contains the column. A null value if the base table name cannot be determined. // The default of this column is a null value. metadata.Columns.Add("BaseTableName", typeof(string)); // The name of the column in the data store. This might be different from the column name returned in the ColumnName column if an alias was used. // A null value if the base column name cannot be determined or if the rowset column is derived, but not identical to, a column in the data store. // The default for this column is a null value. metadata.Columns.Add("BaseColumnName", typeof(string)); // Maps to the common language runtime type of DbType. metadata.Columns.Add("DataType", typeof(Type)); // The underlying driver type. metadata.Columns.Add("ProviderType", typeof(int)); // true if the column contains a Binary Long Object (BLOB) that contains very long data. The definition of very long data is driver-specific. metadata.Columns.Add("IsLong", typeof(bool)); // true if the column assigns values to new rows in fixed increments; otherwise false. The default for this column is false. metadata.Columns.Add("IsAutoIncrement", typeof(bool)); // true if the column cannot be modified; otherwise false. metadata.Columns.Add("IsReadOnly", typeof(bool)); // true: No two rows in the base table (the table returned in BaseTableName) can have the same value in this column. // IsUnique is guaranteed to be true if the column represents a key by itself or if there is a constraint of type UNIQUE that applies only to this column. // false: The column can contain duplicate values in the base table. The default for this column is false. metadata.Columns.Add("IsUnique", typeof(bool)); // true: The column is one of a set of columns in the rowset that, taken together, uniquely identify the row. // The set of columns with IsKey set to true must uniquely identify a row in the rowset. There is no requirement that this set of columns is a minimal set of columns. This set of columns may be generated from a base table primary key, a unique constraint, or a unique index. // false: The column is not required to uniquely identify the row. metadata.Columns.Add("IsKey", typeof(bool)); // Set if the column contains a persistent row identifier that cannot be written to, and has no meaningful value except to identity the row. metadata.Columns.Add("IsRowVersion", typeof(bool)); // true if the consumer can set the column to a null value or if the driver cannot determine whether the consumer can set the column to a null value. // Otherwise, false. A column may contain null values, even if it cannot be set to a null value. metadata.Columns.Add("AllowDBNull", typeof(bool)); // The SQLDataReader also returns these columns: // Returns a string representing the data type of the specified column. metadata.Columns.Add("DataTypeName", typeof(string)); // true: The column is an identity column. // false: The column is not an identity column. metadata.Columns.Add("IsIdentity", typeof(bool)); // true: The column is an expression column. // false: The column is not an expression column. metadata.Columns.Add("IsExpression", typeof(bool)); metadata.BeginLoadData(); for (int n = 0; n < numberColumns; ++n) { DataRow row = metadata.NewRow(); row["ColumnOrdinal"] = n; // data fields must be read in this exact order! row["BaseCatalogName"] = dataStream.getString(); row["BaseSchemaName"] = dataStream.getString(); row["BaseTableName"] = dataStream.getString(); row["BaseColumnName"] = dataStream.getString(); row["ColumnName"] = dataStream.getString(); string collationSequence = dataStream.getString(); row["DataTypeName"] = dataStream.getString(); row["ProviderType"] = NuoDbConnectionInternal.mapJavaSqlToDbType(dataStream.getInt()); row["ColumnSize"] = dataStream.getInt(); row["NumericPrecision"] = dataStream.getInt(); row["NumericScale"] = dataStream.getInt(); if (((DbType)row["ProviderType"] == DbType.Int16 || (DbType)row["ProviderType"] == DbType.Int32 || (DbType)row["ProviderType"] == DbType.Int64) && (int)row["NumericScale"] != 0) { row["ProviderType"] = DbType.Decimal; } row["DataType"] = Type.GetType(NuoDbConnectionInternal.mapNuoDbToNetType((string)row["DataTypeName"], (int)row["NumericPrecision"], (int)row["NumericScale"])); int flags = dataStream.getInt(); const int rsmdSearchable = (1 << 1); const int rsmdAutoIncrement = (1 << 2); const int rsmdCaseSensitive = (1 << 3); const int rsmdCurrency = (1 << 4); const int rsmdDefinitelyWritable = (1 << 5); const int rsmdWritable = (1 << 6); const int rsmdReadOnly = (1 << 7); const int rsmdSigned = (1 << 8); const int rsmdNullable = (1 << 9); row["IsAutoIncrement"] = (flags & rsmdAutoIncrement) != 0; row["IsReadOnly"] = (flags & rsmdReadOnly) != 0; row["AllowDBNull"] = (flags & rsmdNullable) != 0; // for the moment, set the column to be a normal one; later we will look for primary indexes row["IsKey"] = row["IsIdentity"] = row["IsUnique"] = false; row["IsLong"] = row["IsRowVersion"] = row["IsExpression"] = false; metadata.Rows.Add(row); #if DEBUG System.Diagnostics.Trace.WriteLine("-> " + row["ColumnName"] + ", " + row["DataTypeName"] + "(" + row["NumericPrecision"] + "," + row["NumericScale"] + ") " + row["DataType"]); #endif } metadata.EndLoadData(); // fill in the IsPrimary column Dictionary<string, DataTable> schemas = new Dictionary<string, DataTable>(); foreach (DataRow row in metadata.Rows) { string key = row["BaseSchemaName"] + "|" + row["BaseTableName"]; DataTable indexInfo = null; if (!schemas.ContainsKey(key)) { indexInfo = connection.GetSchema("IndexColumns", new string[] { null, (string)row["BaseSchemaName"], (string)row["BaseTableName"] }); schemas.Add(key, indexInfo); } else indexInfo = schemas[key]; DataRow[] rows = indexInfo.Select(String.Format("INDEXCOLUMN_NAME = '{0}' AND INDEXCOLUMN_ISPRIMARY = true", row["BaseColumnName"])); if (rows != null && rows.Length > 0) { row.BeginEdit(); row["IsKey"] = row["IsIdentity"] = true; row.EndEdit(); } } return metadata; }
private void doOpen(string hostName) { string databaseName = parsedConnectionString.Database; int index = hostName.IndexOf(':'); int port = PORT; if (index != -1) { try { port = Int32.Parse(hostName.Substring(index + 1)); } catch (FormatException e) { throw new ArgumentException("Invalid port number in connection string", "ConnectionString", e); } hostName = hostName.Substring(0, index); } dataStream = new EncodedDataStream(); authenticating = false; try { StringDictionary properties = new StringDictionary(); Tag tag = new Tag("Connection"); tag.addAttribute("Service", "SQL2"); tag.addAttribute("Database", databaseName); if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.ServerKey)) { tag.addAttribute("Server", parsedConnectionString.Server); properties["Server"] = parsedConnectionString.Server; } string userName = null; if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.UserKey)) { properties["User"] = userName = parsedConnectionString.User; tag.addAttribute("User", userName); } string password = null; if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.PasswordKey)) { password = parsedConnectionString.Password; } string cipher = DEFAULT_CIPHER; if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.SchemaKey)) { tag.addAttribute("Schema", parsedConnectionString.Schema); properties["Schema"] = parsedConnectionString.Schema; } // see comment below ... for now these are the only two types that // we can support in the client code if ((!cipher.Equals("RC4")) && (!cipher.Equals("None"))) throw new NuoDbSqlException("Unknown cipher: " + cipher); tag.addAttribute("Cipher", cipher); string xml = tag.ToString(); CryptoSocket brokerSocket = new CryptoSocket(hostName, port); inputStream = brokerSocket.InputStream; outputStream = brokerSocket.OutputStream; dataStream.write(xml); dataStream.send(outputStream); dataStream.getMessage(inputStream); string response = dataStream.readString(); brokerSocket.Close(); Tag responseTag = new Tag(); responseTag.parse(response); if (responseTag.Name.Equals("Error")) { throw new NuoDbSqlException(responseTag.getAttribute("text", "error text not found")); } serverAddress = responseTag.getAttribute("Address", null); serverPort = responseTag.getIntAttribute("Port", 0); if (serverAddress == null || serverPort == 0) { throw new NuoDbSqlException("no NuoDB nodes are available for database \"" + databaseName + "\""); } socket = new CryptoSocket(serverAddress, serverPort); //socket.TcpNoDelay = true; inputStream = socket.InputStream; outputStream = socket.OutputStream; dataStream.reset(); dataStream.write(xml); dataStream.send(outputStream); RemotePassword remotePassword = new RemotePassword(); string userKey = remotePassword.genClientKey(); dataStream.startMessage(Protocol.OpenDatabase); dataStream.encodeInt(Protocol.PROTOCOL_VERSION); dataStream.encodeString(databaseName); getProcessConnection(databaseName); string dbUUId = processConnection.DatabaseUUId.ToString(); // see if the app set the TimeZone. If so, it will be sent to the server // so set the local TZ to be the same. If not, send the current default // TZ to the server. (Of course, this affects this connection only) /* String timeZone = properties.getProperty(TIMEZONE_NAME); if (timeZone == null) { // Save the default at the time the connection was opened TimeZone tz = TimeZone.getDefault(); sqlContext.setTimeZone(tz); sqlContext.setTimeZoneId(tz.getID()); properties.setProperty(TIMEZONE_NAME, tz.getID()); } else { TimeZone tz = TimeZone.getTimeZone(timeZone); sqlContext.setTimeZone(tz); sqlContext.setTimeZoneId(tz.getID()); } */ int count = properties.Count + 1 + ((dbUUId == null) ? 0 : 1); // Add LastCommitInfo and DatabaseUUId dataStream.encodeInt(count); foreach (DictionaryEntry property in properties) { string name = (string)property.Key; string value = (string)property.Value; dataStream.encodeString(name); dataStream.encodeString(value); } // LastCommitInfo and DatabaseUUId are sent as properties. This avoids sending another // message and keeps them from being protocol version sensitive string lastCommitParam = getProcessConnection(databaseName).getLastCommitInfo(); dataStream.encodeString("LastCommitInfo"); dataStream.encodeString(lastCommitParam); if (dbUUId != null) { dataStream.encodeString("DatabaseUUId"); dataStream.encodeString(dbUUId); } // This would have been the last commit txn id if that scheme was ever fully // implemented but it wasn't and this is now obsolete. keep it for compatibility with older servers dataStream.encodeLong(0); dataStream.encodeString(userKey); sendAndReceive(dataStream); protocolVersion = dataStream.getInt(); string serverKey = dataStream.getString(); string salt = dataStream.getString(); dataStream.ProtocolVersion = protocolVersion; if (protocolVersion >= Protocol.PROTOCOL_VERSION5) { processConnection.DatabaseUUId = dataStream.getUUId(); } string upperUserName = userName.ToUpper(); byte[] key = remotePassword.computeSessionKey(upperUserName, password, salt, serverKey); // NOTE: unlike the C++ implementation we only support RC4 in .NET // and it's a hard-coded class (instead of the factory interface // on the C++ CryptoSocket) so there's no checking to see which // cipher was requested here inputStream.encrypt(new CipherRC4(key)); outputStream.encrypt(new CipherRC4(key)); dataStream.startMessage(Protocol.Authentication); dataStream.encodeString("Success!"); authenticating = true; sendAndReceive(dataStream); // if the caller requested a cipher of None and we got here then the // server accpeted it and expects us to disable crypto now if (cipher.Equals("None")) { inputStream.encrypt(null); outputStream.encrypt(null); } } catch (NuoDbSqlException e) { #if DEBUG System.Diagnostics.Trace.WriteLine("NuoDBConnection::doOpen(): exception " + e.ToString()); #endif if (authenticating) { throw new NuoDbSqlException("Authentication failed for database \"" + databaseName + "\"", e); } throw e; } catch (IOException exception) { #if DEBUG System.Diagnostics.Trace.WriteLine("NuoDBConnection::doOpen(): exception " + exception.ToString()); #endif if (socket != null && socket.Connected) { try { socket.Close(); socket = null; } catch (IOException) { // just ignore } } throw new NuoDbSqlException(exception.ToString()); } catch (XmlException exception) { #if DEBUG System.Diagnostics.Trace.WriteLine("NuoDBConnection::doOpen(): exception " + exception.ToString()); #endif if (socket != null && socket.Connected) { try { socket.Close(); socket = null; } catch (IOException) { // just ignore } } throw new NuoDbSqlException(exception.ToString()); } }
internal void sendAndReceive(EncodedDataStream stream) { try { lock (this) { stream.send(outputStream); stream.getMessage(inputStream); int status = stream.getInt(); if (status != 0) { string message = stream.getString(); string sqlState = ""; if (protocolVersion >= Protocol.PROTOCOL_VERSION2) { sqlState = stream.getString(); } // If empty string, use the state from NuoDbSqlCode if (StringUtils.size(sqlState) == 0) { sqlState = NuoDbSqlCode.FindSQLState(status); } throw new NuoDbSqlException(message, sqlState, status); } } } catch (IOException exception) { throw new NuoDbSqlException(exception); } }
private void doOpen(string hostName) { networkErrorOccurred = false; string databaseName = parsedConnectionString.Database; int index = hostName.IndexOf(':'); int port = PORT; if (index != -1) { try { port = Int32.Parse(hostName.Substring(index + 1)); } catch (FormatException e) { throw new ArgumentException("Invalid port number in connection string", "ConnectionString", e); } hostName = hostName.Substring(0, index); } dataStream = new EncodedDataStream(); authenticating = false; try { StringDictionary properties = new StringDictionary(); Tag tag = new Tag("Connection"); tag.addAttribute("Service", "SQL2"); tag.addAttribute("Database", databaseName); if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.ServerKey)) { tag.addAttribute("Server", parsedConnectionString.Server); properties["Server"] = parsedConnectionString.Server; } string userName = null; if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.UserKey)) { properties["User"] = userName = parsedConnectionString.User; tag.addAttribute("User", userName); } else { throw new ArgumentException("Username is missing in connection string", "ConnectionString"); } string password = ""; if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.PasswordKey)) { password = parsedConnectionString.Password; } string cipher = DEFAULT_CIPHER; if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.CipherKey)) { properties["Cipher"] = cipher = parsedConnectionString.Cipher; } if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.SchemaKey)) { tag.addAttribute("Schema", parsedConnectionString.Schema); properties["Schema"] = parsedConnectionString.Schema; } if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.LBTagKey)) { properties["LBTag"] = parsedConnectionString.LBTag; } if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.ClientInfoKey)) { properties["clientInfo"] = parsedConnectionString.ClientInfo; } properties["clientProcessID"] = Process.GetCurrentProcess().Id.ToString(); // see comment below ... for now these are the only two types that // we can support in the client code if ((!cipher.Equals("RC4")) && (!cipher.Equals("None"))) throw new NuoDbSqlException("Unknown cipher: " + cipher); tag.addAttribute("Cipher", cipher); string xml = tag.ToString(); CryptoSocket brokerSocket = new CryptoSocket(hostName, port); inputStream = brokerSocket.InputStream; outputStream = brokerSocket.OutputStream; dataStream.write(xml); dataStream.send(outputStream); dataStream.getMessage(inputStream); string response = dataStream.readString(); brokerSocket.Close(); Tag responseTag = new Tag(); responseTag.parse(response); if (responseTag.Name.Equals("Error")) { throw new NuoDbSqlException(responseTag.getAttribute("text", "error text not found")); } serverAddress = responseTag.getAttribute("Address", null); serverPort = responseTag.getIntAttribute("Port", 0); if (serverAddress == null || serverPort == 0) { throw new NuoDbSqlException("no NuoDB nodes are available for database \"" + databaseName + "\""); } socket = new CryptoSocket(serverAddress, serverPort); //socket.TcpNoDelay = true; inputStream = socket.InputStream; outputStream = socket.OutputStream; dataStream.reset(); dataStream.write(xml); dataStream.send(outputStream); RemotePassword remotePassword = new RemotePassword(); string userKey = remotePassword.genClientKey(); dataStream.startMessage(Protocol.OpenDatabase); dataStream.encodeInt(Protocol.PROTOCOL_VERSION); dataStream.encodeString(databaseName); getProcessConnection(databaseName); string dbUUId = processConnection.DatabaseUUId.ToString(); #if __MonoCS__ // On Mono, timezone support is too much platform dependent sqlContext.TimeZone = TimeZoneInfo.Local; #else // see if the app set the TimeZone. If so, it will be sent to the server // so set the local TZ to be the same. If not, send the current default // TZ to the server. (Of course, this affects this connection only) if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.TimeZoneKey)) { string tzone = parsedConnectionString.TimeZone; properties["TimeZone"] = tzone; sqlContext.TimeZone = OlsonDatabase.FindWindowsTimeZone(tzone); } else { // Save the default at the time the connection was opened string tzone = TimeZoneInfo.Local.Id; properties["TimeZone"] = OlsonDatabase.FindOlsonTimeZone(tzone); // As described in http://msdn.microsoft.com/en-us/library/system.timezoneinfo.local.aspx TimeZoneInfo.Local // always applies the DST setting of the current time, even if the DST settings of the tested date used different // rules; so we fetch the complete definition from the database sqlContext.TimeZone = TimeZoneInfo.FindSystemTimeZoneById(tzone); } #endif int count = properties.Count + 1 + ((dbUUId == null) ? 0 : 1); // Add LastCommitInfo and DatabaseUUId dataStream.encodeInt(count); foreach (DictionaryEntry property in properties) { string name = (string)property.Key; string value = (string)property.Value; dataStream.encodeString(name); dataStream.encodeString(value); } // LastCommitInfo and DatabaseUUId are sent as properties. This avoids sending another // message and keeps them from being protocol version sensitive string lastCommitParam = getProcessConnection(databaseName).getLastCommitInfo(); dataStream.encodeString("LastCommitInfo"); dataStream.encodeString(lastCommitParam); if (dbUUId != null) { dataStream.encodeString("DatabaseUUId"); dataStream.encodeString(dbUUId); } // This would have been the last commit txn id if that scheme was ever fully // implemented but it wasn't and this is now obsolete. keep it for compatibility with older servers dataStream.encodeLong(0); dataStream.encodeString(userKey); sendAndReceive(dataStream); protocolVersion = dataStream.getInt(); string serverKey = dataStream.getString(); string salt = dataStream.getString(); dataStream.ProtocolVersion = protocolVersion; if (protocolVersion >= Protocol.PROTOCOL_VERSION5) { processConnection.DatabaseUUId = dataStream.getUUId(); } string upperUserName = userName.ToUpper(); byte[] key = remotePassword.computeSessionKey(upperUserName, password, salt, serverKey); // NOTE: unlike the C++ implementation we only support RC4 in .NET // and it's a hard-coded class (instead of the factory interface // on the C++ CryptoSocket) so there's no checking to see which // cipher was requested here inputStream.encrypt(new CipherRC4(key)); outputStream.encrypt(new CipherRC4(key)); dataStream.startMessage(Protocol.Authentication); dataStream.encodeString("Success!"); authenticating = true; sendAndReceive(dataStream); // if the caller requested a cipher of None and we got here then the // server accepted it and expects us to disable crypto now if (cipher.Equals("None")) { inputStream.encrypt(null); outputStream.encrypt(null); } } catch (NuoDbSqlException e) { #if DEBUG System.Diagnostics.Trace.WriteLine("NuoDBConnection::doOpen(): exception " + e.ToString()); #endif if (authenticating) { throw new NuoDbSqlException("Authentication failed for database \"" + databaseName + "\""); } throw e; } catch (IOException exception) { #if DEBUG System.Diagnostics.Trace.WriteLine("NuoDBConnection::doOpen(): exception " + exception.ToString()); #endif networkErrorOccurred = true; if (socket != null && socket.Connected) { try { socket.Close(); socket = null; } catch (IOException) { // just ignore } } throw new NuoDbSqlException(exception.ToString()); } catch (XmlException exception) { #if DEBUG System.Diagnostics.Trace.WriteLine("NuoDBConnection::doOpen(): exception " + exception.ToString()); #endif if (socket != null && socket.Connected) { try { socket.Close(); socket = null; } catch (IOException) { // just ignore } } throw new NuoDbSqlException(exception.ToString()); } if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.ApplicationIntentKey)) { string applicationIntent = parsedConnectionString.ApplicationIntent; if (applicationIntent.Equals("ReadOnly", StringComparison.InvariantCultureIgnoreCase)) { dataStream.startMessage(Protocol.SetReadOnly); dataStream.encodeBoolean(true); sendAsync(dataStream); } } if (parsedConnectionString.ContainsKey(NuoDbConnectionStringBuilder.IsolationLevelKey)) { string isolationLevel = parsedConnectionString.IsolationLevel; int level = 0; if (isolationLevel.Equals("ReadCommitted", StringComparison.InvariantCultureIgnoreCase)) { // static const int TRANSACTION_READ_COMMITTED = 2; level = 2; } else if (isolationLevel.Equals("Serializable", StringComparison.InvariantCultureIgnoreCase)) { // static const int TRANSACTION_SERIALIZABLE = 8; level = 8; } else if (isolationLevel.Equals("WriteCommitted", StringComparison.InvariantCultureIgnoreCase)) { // static const int TRANSACTION_WRITE_COMMITTED = 5; level = 5; } else if (isolationLevel.Equals("ConsistentRead", StringComparison.InvariantCultureIgnoreCase)) { // static const int TRANSACTION_CONSISTENT_READ = 7; level = 7; } else { throw new NuoDbSqlException("\"" + isolationLevel + "\" is not a valid isolation level"); } dataStream.startMessage(Protocol.SetTransactionIsolation); dataStream.encodeInt(level); sendAndReceive(dataStream); } }