internal void ReadOk(bool read) { try { if (read) { packet = stream.ReadPacket(); } byte marker = (byte)packet.ReadByte(); if (marker != 0) { throw new MyCatException("Out of sync with server", true, null); } packet.ReadFieldLength(); /* affected rows */ packet.ReadFieldLength(); /* last insert id */ if (packet.HasMoreData) { serverStatus = (ServerStatusFlags)packet.ReadInteger(2); packet.ReadInteger(2); /* warning count */ if (packet.HasMoreData) { packet.ReadLenString(); /* message */ } } } catch (MyCatException ex) { HandleException(ex); throw; } }
internal void Serialize(MyCatPacket packet, bool binary, MyCatConnectionStringBuilder settings) { if (!binary && (paramValue == null || paramValue == DBNull.Value)) { packet.WriteStringNoNull("NULL"); } else { if (ValueObject.MyCatDbType == MyCatDbType.Guid) { MyCatGuid g = (MyCatGuid)ValueObject; g.OldGuids = settings.OldGuids; ValueObject = g; } if (ValueObject.MyCatDbType == MyCatDbType.Geometry) { MyCatGeometry v = (MyCatGeometry)ValueObject; if (v.IsNull && Value != null) { MyCatGeometry.TryParse(Value.ToString(), out v); } ValueObject = v; } ValueObject.WriteValue(packet, binary, paramValue, Size); } }
// private void ClearFetchedRow() // { // if (lastCommandResult == 0) return; //TODO /* CommandResult result = (CommandResult)commandResults[lastCommandResult]; * result.ReadRemainingColumns(); * * stream.OpenPacket(); * if (! stream.IsLastPacket) * throw new MyCatException("Cursor reading out of sync"); * * ReadEOF(false); * lastCommandResult = 0;*/ // } /// <summary> /// FetchDataRow is the method that the data reader calls to see if there is another /// row to fetch. In the non-prepared mode, it will simply read the next data packet. /// In the prepared mode (statementId > 0), it will /// </summary> public bool FetchDataRow(int statementId, int columns) { /* ClearFetchedRow(); * * if (!commandResults.ContainsKey(statementId)) return false; * * if ( (serverStatus & ServerStatusFlags.LastRowSent) != 0) * return false; * * stream.StartPacket(9, true); * stream.WriteByte((byte)DBCmd.FETCH); * stream.WriteInteger(statementId, 4); * stream.WriteInteger(1, 4); * stream.Flush(); * * lastCommandResult = statementId; */ packet = stream.ReadPacket(); if (packet.IsLastPacket) { CheckEOF(); return(false); } nullMap = null; if (statementId > 0) { ReadNullMap(columns); } return(true); }
public void SendPacket(MyCatPacket packet) { byte[] buffer = packet.Buffer; int length = packet.Position - 4; if ((ulong)length > maxPacketSize) { throw new MyCatException(Resources.QueryTooLarge, (int)MyCatErrorCode.PacketTooLarge); } int offset = 0; while (length > 0) { int lenToSend = length > maxBlockSize ? maxBlockSize : length; buffer[offset] = (byte)(lenToSend & 0xff); buffer[offset + 1] = (byte)((lenToSend >> 8) & 0xff); buffer[offset + 2] = (byte)((lenToSend >> 16) & 0xff); buffer[offset + 3] = sequenceByte++; outStream.Write(buffer, offset, lenToSend + 4); outStream.Flush(); length -= lenToSend; offset += lenToSend; } }
/// <summary> /// Serializes the given parameter to the given memory stream /// </summary> /// <remarks> /// <para>This method is called by PrepareSqlBuffers to convert the given /// parameter to bytes and write those bytes to the given memory stream. /// </para> /// </remarks> /// <returns>True if the parameter was successfully serialized, false otherwise.</returns> private bool SerializeParameter(MyCatParameterCollection parameters, MyCatPacket packet, string parmName, int parameterIndex) { MyCatParameter parameter = null; if (!parameters.containsUnnamedParameters) { parameter = parameters.GetParameterFlexible(parmName, false); } else { if (parameterIndex <= parameters.Count) { parameter = parameters[parameterIndex]; } else { throw new MyCatException(Resources.ParameterIndexNotFound); } } if (parameter == null) { // if we are allowing user variables and the parameter name starts with @ // then we can't throw an exception if (parmName.StartsWith("@", StringComparison.Ordinal) && ShouldIgnoreMissingParameter(parmName)) { return(false); } throw new MyCatException( String.Format(Resources.ParameterMustBeDefined, parmName)); } parameter.Serialize(packet, false, Connection.Settings); return(true); }
public void ExecuteStatement(MyCatPacket packetToExecute) { warnings = 0; packetToExecute.SetByte(4, (byte)DBCmd.EXECUTE); ExecutePacket(packetToExecute); serverStatus |= ServerStatusFlags.AnotherQuery; }
public virtual void ExecuteDirect(string sql) { MyCatPacket p = new MyCatPacket(Encoding); p.WriteString(sql); SendQuery(p); NextResult(0, false); }
protected virtual void BindParameters() { MyCatParameterCollection parameters = command.Parameters; int index = 0; while (true) { InternalBindParameters(ResolvedCommandText, parameters, null); // if we are not batching, then we are done. This is only really relevant the // first time through if (command.Batch == null) { return; } while (index < command.Batch.Count) { MyCatCommand batchedCmd = command.Batch[index++]; MyCatPacket packet = (MyCatPacket)buffers[buffers.Count - 1]; // now we make a guess if this statement will fit in our current stream long estimatedCmdSize = batchedCmd.EstimatedSize(); if (((packet.Length - 4) + estimatedCmdSize) > Connection.driver.MaxPacketSize) { // it won't, so we setup to start a new run from here parameters = batchedCmd.Parameters; break; } // looks like we might have room for it so we remember the current end of the stream buffers.RemoveAt(buffers.Count - 1); //long originalLength = packet.Length - 4; // and attempt to stream the next command string text = ResolvedCommandText; if (text.StartsWith("(", StringComparison.Ordinal)) { packet.WriteStringNoNull(", "); } else { packet.WriteStringNoNull("; "); } InternalBindParameters(text, batchedCmd.Parameters, packet); if ((packet.Length - 4) > Connection.driver.MaxPacketSize) { //TODO //stream.InternalBuffer.SetLength(originalLength); parameters = batchedCmd.Parameters; break; } } if (index == command.Batch.Count) { return; } } }
public virtual void Prepare() { // strip out names from parameter markers string text; List <string> parameter_names = PrepareCommandText(out text); // ask our connection to send the prepare command MyCatField[] paramList = null; statementId = Driver.PrepareStatement(text, ref paramList); // now we need to assign our field names since we stripped them out // for the prepare for (int i = 0; i < parameter_names.Count; i++) { //paramList[i].ColumnName = (string) parameter_names[i]; string parameterName = (string)parameter_names[i]; MyCatParameter p = Parameters.GetParameterFlexible(parameterName, false); if (p == null) { throw new InvalidOperationException( String.Format(Resources.ParameterNotFoundDuringPrepare, parameterName)); } p.Encoding = paramList[i].Encoding; parametersToSend.Add(p); } // now prepare our null map int numNullBytes = 0; if (paramList != null && paramList.Length > 0) { #if NET451 nullMap = new BitArray(paramList.Length); #else nullMap = new RtBitArray(paramList.Length); #endif numNullBytes = (nullMap.Count + 7) / 8; } packet = new MyCatPacket(Driver.Encoding); // write out some values that do not change run to run packet.WriteByte(0); packet.WriteInteger(statementId, 4); packet.WriteByte((byte)0); // flags; always 0 for 4.1 packet.WriteInteger(1, 4); // interation count; 1 for 4.1 nullMapPosition = packet.Position; packet.Position += numNullBytes; // leave room for our null map packet.WriteByte(1); // rebound flag // write out the parameter types foreach (MyCatParameter p in parametersToSend) { packet.WriteInteger(p.GetPSType(), 2); } dataPosition = packet.Position; }
public int PrepareStatement(string sql, ref MyCatField[] parameters) { //TODO: check this //ClearFetchedRow(); packet.Length = sql.Length * 4 + 5; byte[] buffer = packet.Buffer; int len = Encoding.GetBytes(sql, 0, sql.Length, packet.Buffer, 5); packet.Position = len + 5; buffer[4] = (byte)DBCmd.PREPARE; ExecutePacket(packet); packet = stream.ReadPacket(); int marker = packet.ReadByte(); if (marker != 0) { throw new MyCatException("Expected prepared statement marker"); } int statementId = packet.ReadInteger(4); int numCols = packet.ReadInteger(2); int numParams = packet.ReadInteger(2); //TODO: find out what this is needed for packet.ReadInteger(3); if (numParams > 0) { parameters = owner.GetColumns(numParams); // we set the encoding for each parameter back to our connection encoding // since we can't trust what is coming back from the server for (int i = 0; i < parameters.Length; i++) { parameters[i].Encoding = Encoding; } } if (numCols > 0) { while (numCols-- > 0) { packet = stream.ReadPacket(); //TODO: handle streaming packets } ReadEOF(); } return(statementId); }
private void InternalBindParameters(string sql, MyCatParameterCollection parameters, MyCatPacket packet) { bool sqlServerMode = command.Connection.Settings.SqlServerMode; if (packet == null) { packet = new MyCatPacket(Driver.Encoding); packet.Version = Driver.Version; packet.WriteByte(0); } MyCatTokenizer tokenizer = new MyCatTokenizer(sql); tokenizer.ReturnComments = true; tokenizer.SqlServerMode = sqlServerMode; int pos = 0; string token = tokenizer.NextToken(); int parameterCount = 0; while (token != null) { // serialize everything that came before the token (i.e. whitespace) packet.WriteStringNoNull(sql.Substring(pos, tokenizer.StartIndex - pos)); pos = tokenizer.StopIndex; if (MyCatTokenizer.IsParameter(token)) { if ((!parameters.containsUnnamedParameters && token.Length == 1 && parameterCount > 0) || parameters.containsUnnamedParameters && token.Length > 1) { throw new MyCatException(Resources.MixedParameterNamingNotAllowed); } parameters.containsUnnamedParameters = token.Length == 1; if (SerializeParameter(parameters, packet, token, parameterCount)) { token = null; } parameterCount++; } if (token != null) { if (sqlServerMode && tokenizer.Quoted && token.StartsWith("[", StringComparison.Ordinal)) { token = String.Format("`{0}`", token.Substring(1, token.Length - 2)); } packet.WriteStringNoNull(token); } token = tokenizer.NextToken(); } buffers.Add(packet); }
public MyCatStream(Encoding encoding) { // we have no idea what the real value is so we start off with the max value // The real value will be set in NativeDriver.Configure() maxPacketSize = ulong.MaxValue; // we default maxBlockSize to MaxValue since we will get the 'real' value in // the authentication handshake and we know that value will not exceed // true maxBlockSize prior to that. maxBlockSize = Int32.MaxValue; packet = new MyCatPacket(encoding); }
public override void ExecuteStatement(MyCatPacket packetToExecute) { base.ExecuteStatement(packetToExecute); int pos = packetToExecute.Position; packetToExecute.Position = 1; int statementId = packetToExecute.ReadInteger(4); packetToExecute.Position = pos; MyCatTrace.TraceEvent(TraceEventType.Information, MyCatTraceEventType.StatementExecuted, Resources.TraceStatementExecuted, driverId, statementId, ThreadID); }
private void ExecutePacket(MyCatPacket packetToExecute) { try { warnings = 0; stream.SequenceByte = 0; stream.SendPacket(packetToExecute); } catch (MyCatException ex) { HandleException(ex); throw; } }
public virtual bool ExecuteNext() { if (buffers.Count == 0) { return(false); } MyCatPacket packet = (MyCatPacket)buffers[0]; //MemoryStream ms = stream.InternalBuffer; Driver.SendQuery(packet); buffers.RemoveAt(0); return(true); }
/// <summary> /// Query is the method that is called to send all queries to the server /// </summary> public void SendQuery(MyCatPacket queryPacket) { warnings = 0; queryPacket.SetByte(4, (byte)DBCmd.QUERY); ExecutePacket(queryPacket); // the server will respond in one of several ways with the first byte indicating // the type of response. // 0 == ok packet. This indicates non-select queries // 0xff == error packet. This is handled in stream.OpenPacket // > 0 = number of columns in select query // We don't actually read the result here since a single query can generate // multiple resultsets and we don't want to duplicate code. See ReadResult // Instead we set our internal server status flag to indicate that we have a query waiting. // This flag will be maintained by ReadResult serverStatus |= ServerStatusFlags.AnotherQuery; }
public long GetResult(ref long affectedRow, ref long insertedId) { try { packet = stream.ReadPacket(); } catch (TimeoutException) { // Do not reset serverStatus, allow to reenter, e.g when // ResultSet is closed. throw; } catch (Exception) { serverStatus = 0; throw; } var fieldCount = (long)packet.ReadFieldLength(); if (-1 == fieldCount) { string filename = packet.ReadString(); SendFileToServer(filename); return(GetResult(ref affectedRow, ref insertedId)); } else if (fieldCount == 0) { // the code to read last packet will set these server status vars // again if necessary. serverStatus &= ~(ServerStatusFlags.AnotherQuery | ServerStatusFlags.MoreResults); affectedRow = (int)packet.ReadFieldLength(); insertedId = (long)packet.ReadFieldLength(); serverStatus = (ServerStatusFlags)packet.ReadInteger(2); warnings += packet.ReadInteger(2); if (packet.HasMoreData) { packet.ReadLenString(); //TODO: server message } } return(fieldCount); }
private void GetColumnData(MyCatField field) { stream.Encoding = Encoding; packet = stream.ReadPacket(); field.Encoding = Encoding; field.CatalogName = packet.ReadLenString(); field.DatabaseName = packet.ReadLenString(); field.TableName = packet.ReadLenString(); field.RealTableName = packet.ReadLenString(); field.ColumnName = packet.ReadLenString(); field.OriginalColumnName = packet.ReadLenString(); packet.ReadByte(); field.CharacterSetIndex = packet.ReadInteger(2); field.ColumnLength = packet.ReadInteger(4); MyCatDbType type = (MyCatDbType)packet.ReadByte(); ColumnFlags colFlags; if ((connectionFlags & ClientFlags.LONG_FLAG) != 0) { colFlags = (ColumnFlags)packet.ReadInteger(2); } else { colFlags = (ColumnFlags)packet.ReadByte(); } field.Scale = (byte)packet.ReadByte(); if (packet.HasMoreData) { packet.ReadInteger(2); // reserved } if (type == MyCatDbType.Decimal || type == MyCatDbType.NewDecimal) { field.Precision = (byte)(field.ColumnLength - 2); if ((colFlags & ColumnFlags.UNSIGNED) != 0) { field.Precision++; } } field.SetTypeAndFlags(type, colFlags); }
public override void SendQuery(MyCatPacket p) { rowSizeInBytes = 0; string cmdText = Encoding.GetString(p.Buffer, 5, p.Length - 5); string normalized_query = null; if (cmdText.Length > 300) { QueryNormalizer normalizer = new QueryNormalizer(); normalized_query = normalizer.Normalize(cmdText); cmdText = cmdText.Substring(0, 300); } base.SendQuery(p); MyCatTrace.TraceEvent(TraceEventType.Information, MyCatTraceEventType.QueryOpened, Resources.TraceQueryOpened, driverId, ThreadID, cmdText); if (normalized_query != null) { MyCatTrace.TraceEvent(TraceEventType.Information, MyCatTraceEventType.QueryNormalized, Resources.TraceQueryNormalized, driverId, ThreadID, normalized_query); } }
public virtual void ExecuteStatement(MyCatPacket packetToExecute) { handler.ExecuteStatement(packetToExecute); }
public virtual void SendQuery(MyCatPacket p) { handler.SendQuery(p); firstResult = true; }
internal void SendPacket(MyCatPacket p) { stream.SendPacket(p); }
internal MyCatPacket ReadPacket() { return(packet = stream.ReadPacket()); }
private void ReadEOF() { packet = stream.ReadPacket(); CheckEOF(); }
public void Open() { // connect to one of our specified hosts try { baseStream = StreamCreator.GetStream(Settings); #if NET451 if (Settings.IncludeSecurityAsserts) { MyCatSecurityPermission.CreatePermissionSet(false).Assert(); } #endif } catch (System.Security.SecurityException) { throw; } catch (Exception ex) { throw new MyCatException(Resources.UnableToConnectToHost, (int)MyCatErrorCode.UnableToConnectToHost, ex); } if (baseStream == null) { throw new MyCatException(Resources.UnableToConnectToHost, (int)MyCatErrorCode.UnableToConnectToHost); } int maxSinglePacket = 255 * 255 * 255; stream = new MyCatStream(baseStream, Encoding, false); stream.ResetTimeout((int)Settings.ConnectionTimeout * 1000); // read off the welcome packet and parse out it's values packet = stream.ReadPacket(); int protocol = packet.ReadByte(); string versionString = packet.ReadString(); owner.isFabric = versionString.EndsWith("fabric", StringComparison.OrdinalIgnoreCase); version = DBVersion.Parse(versionString); if (!owner.isFabric && !version.isAtLeast(5, 0, 0)) { throw new NotSupportedException(Resources.ServerTooOld); } threadId = packet.ReadInteger(4); encryptionSeed = packet.ReadString(); maxSinglePacket = (256 * 256 * 256) - 1; // read in Server capabilities if they are provided ClientFlags serverCaps = 0; if (packet.HasMoreData) { serverCaps = (ClientFlags)packet.ReadInteger(2); } /* New protocol with 16 bytes to describe server characteristics */ owner.ConnectionCharSetIndex = (int)packet.ReadByte(); serverStatus = (ServerStatusFlags)packet.ReadInteger(2); // Since 5.5, high bits of server caps are stored after status. // Previously, it was part of reserved always 0x00 13-byte filler. uint serverCapsHigh = (uint)packet.ReadInteger(2); serverCaps |= (ClientFlags)(serverCapsHigh << 16); packet.Position += 11; string seedPart2 = packet.ReadString(); encryptionSeed += seedPart2; string authenticationMethod = ""; if ((serverCaps & ClientFlags.PLUGIN_AUTH) != 0) { authenticationMethod = packet.ReadString(); } else { // Some MyCat versions like 5.1, don't give name of plugin, default to native password. authenticationMethod = "mysql_native_password"; } // based on our settings, set our connection flags SetConnectionFlags(serverCaps); packet.Clear(); packet.WriteInteger((int)connectionFlags, 4); if ((serverCaps & ClientFlags.SSL) == 0) { if ((Settings.SslMode != MyCatSslMode.None) && (Settings.SslMode != MyCatSslMode.Preferred)) { // Client requires SSL connections. string message = String.Format(Resources.NoServerSSLSupport, Settings.Server); throw new MyCatException(message); } } else if (Settings.SslMode != MyCatSslMode.None) { stream.SendPacket(packet); StartSSL(); packet.Clear(); packet.WriteInteger((int)connectionFlags, 4); } packet.WriteInteger(maxSinglePacket, 4); packet.WriteByte(8); packet.Write(new byte[23]); Authenticate(authenticationMethod, false); // if we are using compression, then we use our CompressedStream class // to hide the ugliness of managing the compression if ((connectionFlags & ClientFlags.COMPRESS) != 0) { stream = new MyCatStream(baseStream, Encoding, true); } // give our stream the server version we are connected to. // We may have some fields that are read differently based // on the version of the server we are connected to. packet.Version = version; stream.MaxBlockSize = maxSinglePacket; }