internal Query(Connection conn, SqlStringTemplate sql, CommandParams cmdParams) { //***a query uses conn resource such as parser,writer //so 1 query=> 1 connection if (sql == null) { throw new Exception("Sql command can not null."); } Query bindingQuery = conn.BindingQuery; if (bindingQuery != null) { //check if binding query can be close if (!bindingQuery.LateClose()) { //can't use this conn throw new Exception("connection is in used"); } } //-------------------------------------------------------------- conn.BindingQuery = this; //-------------------------------------------------------------- _conn = conn; _cmdParams = cmdParams; //-------------------------------------------------------------- _nestTables = false; _sqlParserMx = conn.MySqlParserMx; _writer = conn.PacketWriter; //_receiveBuffer = null; _sqlStrTemplate = sql; }
public Connection(ConnectionConfig userConfig) { config = userConfig; recvBufferSize = userConfig.recvBufferSize; sendBufferSize = userConfig.sendBufferSize; socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // switch ((CharSets)config.charsetNumber) { case CharSets.UTF8_GENERAL_CI: //_parser = new PacketParser(Encoding.UTF8); _writer = new MySqlStreamWriter(Encoding.UTF8); break; case CharSets.ASCII: //_parser = new PacketParser(Encoding.ASCII); _writer = new MySqlStreamWriter(Encoding.ASCII); break; default: throw new NotImplementedException(); } //------------------ //we share recvSendArgs between recvIO and sendIO //similar to simple http //it is simple, (NOT duplex like web socket) //------------------ recvSendArgs = new SocketAsyncEventArgs(); recvSendArgs.SetBuffer(new byte[recvBufferSize + sendBufferSize], 0, recvBufferSize + sendBufferSize); recvIO = new RecvIO(recvSendArgs, recvSendArgs.Offset, recvBufferSize, HandleReceive); sendIO = new SendIO(recvSendArgs, recvSendArgs.Offset + recvBufferSize, sendBufferSize, HandleSend); //------------------ //common(shared) event listener*** recvSendArgs.Completed += (object sender, SocketAsyncEventArgs e) => { switch (e.LastOperation) { case SocketAsyncOperation.Receive: recvIO.ProcessReceivedData(); break; case SocketAsyncOperation.Send: sendIO.ProcessWaitingData(); break; default: throw new ArgumentException("The last operation completed on the socket was not a receive or send"); } }; //------------------ recvSendArgs.AcceptSocket = socket; _mysqlParserMx = new MySqlParserMx(config); }
public Connection(ConnectionConfig userConfig) { _config = userConfig; _recvBufferSize = userConfig.recvBufferSize; _sendBufferSize = userConfig.sendBufferSize; _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _writer = new MySqlStreamWriter(_config.GetEncoding()); //------------------ //we share recvSendArgs between recvIO and sendIO //similar to simple http //it is simple, (NOT duplex like web socket) //------------------ _recvSendArgs = new SocketAsyncEventArgs(); _recvSendArgs.SetBuffer(new byte[_recvBufferSize + _sendBufferSize], 0, _recvBufferSize + _sendBufferSize); _recvIO = new RecvIO(_recvSendArgs, _recvSendArgs.Offset, _recvBufferSize, HandleReceive); _sendIO = new SendIO(_recvSendArgs, _recvSendArgs.Offset + _recvBufferSize, _sendBufferSize, HandleSend); //------------------ //common(shared) event listener*** _recvSendArgsCompleted = (object sender, SocketAsyncEventArgs e) => { if (_isDisposed) { //it should not occur return; } switch (e.LastOperation) { case SocketAsyncOperation.Receive: _recvIO.ProcessReceivedData(); break; case SocketAsyncOperation.Send: _sendIO.ProcessWaitingData(); break; default: throw new ArgumentException("The last operation completed on the socket was not a receive or send"); } }; _recvSendArgs.Completed += _recvSendArgsCompleted; //------------------ _recvSendArgs.AcceptSocket = _socket; _mysqlParserMx = new MySqlParserMx(_config); }
public static PacketHeader Write(MySqlStreamWriter writer, uint stmtId) { //for those who don't want to alloc an new packet //just write it into a stream writer.ReserveHeader(); writer.WriteByte((byte)Command.STMT_CLOSE); writer.WriteUnsigned4(stmtId); var h = new PacketHeader(writer.OnlyPacketContentLength, writer.IncrementPacketNumber()); writer.WriteHeader(h); return h; }
public static void Write(MySqlStreamWriter writer, uint stmtId, MyStructData[] _prepareValues) { //for those who don't want to alloc an new packet //just write it into a stream writer.ReserveHeader(); writer.WriteByte((byte)Command.STMT_EXECUTE); writer.WriteUnsignedNumber(4, stmtId); writer.WriteByte((byte)CursorFlags.CURSOR_TYPE_NO_CURSOR); writer.WriteUnsignedNumber(4, 1);//iteration-count, always 1 //write NULL-bitmap, length: (num-params+7)/8 MyStructData[] fillValues = _prepareValues; int paramNum = _prepareValues.Length; if (paramNum > 0) { uint bitmap = 0; uint bitValue = 1; for (int i = 0; i < paramNum; i++) { MySqlDataType dataType = _prepareValues[i].type; if (dataType == MySqlDataType.NULL) { bitmap += bitValue; } bitValue <<= 1; //shift to left 1 bit if (bitValue == 256) { //end of 8 bits //just store data writer.WriteUnsigned1(bitmap); bitmap = 0; bitValue = 1; } } if (bitValue != 1) { writer.WriteUnsigned1(bitmap); } } //new-params-bound - flag writer.WriteByte(1); //------------------------------------------------------- //data types for (int i = 0; i < paramNum; i++) { writer.WriteUnsignedNumber(2, (byte)_prepareValues[i].type); } //-------------------------------------- //actual data //-------------------------------------- //stream of data may large than 1 packet var tempSingleValueHolder = new TempSingleValueHolder(); tempSingleValueHolder.headerLenBuffer = new byte[9]; tempSingleValueHolder.generalContent = new byte[16]; for (int i = 0; i < paramNum; i++) { bool isComplete = WriteValueByType(writer, ref _prepareValues[i], ref tempSingleValueHolder); var header = new PacketHeader(writer.OnlyPacketContentLength, writer.IncrementPacketNumber()); writer.WriteHeader(header); //-------------------------------------------------------------------------------------------------- while (!isComplete) { //write until complete tempSingleValueHolder.round++; writer.ReserveHeader(); isComplete = WriteValueByType(writer, ref _prepareValues[i], ref tempSingleValueHolder); header = new PacketHeader(writer.OnlyPacketContentLength, writer.IncrementPacketNumber()); writer.WriteHeader(header); } //reset tempSingleValueHolder.Reset(); } //-------------------------------------- }
public abstract void WritePacket(MySqlStreamWriter writer);
//---------------------------- static bool WriteValueByType(MySqlStreamWriter writer, ref MyStructData dataTemp, ref TempSingleValueHolder singleValueHolder) { int availableContentSpace = Packet.MAX_PACKET_LENGTH - (int)writer.OnlyPacketContentLength; if (singleValueHolder.round == 0) { //--------------------------- //this is first round *** //--------------------------- switch (dataTemp.type) { case MySqlDataType.NULL: //we not write null data return true; case MySqlDataType.BIT: case MySqlDataType.BLOB: case MySqlDataType.MEDIUM_BLOB: case MySqlDataType.LONG_BLOB: //writer.WriteLengthCodedBuffer(dataTemp.myBuffer); //this is first round singleValueHolder.isBufferOrString = true; singleValueHolder.bufferContent = dataTemp.myBuffer; singleValueHolder.contentLen = singleValueHolder.bufferContent.Length; //generate output singleValueHolder.encodedLengthLen = writer.GenerateEncodeLengthNumber(singleValueHolder.contentLen, singleValueHolder.headerLenBuffer); if (availableContentSpace > singleValueHolder.TotalLength) { //write in first round writer.WriteLengthCodedBuffer(singleValueHolder.bufferContent); return true; } //go below break; case MySqlDataType.VARCHAR: case MySqlDataType.VAR_STRING: case MySqlDataType.STRING: { //this is first round singleValueHolder.isBufferOrString = true; singleValueHolder.bufferContent = Encoding.UTF8.GetBytes(dataTemp.myString); singleValueHolder.contentLen = singleValueHolder.bufferContent.Length; //generate output singleValueHolder.encodedLengthLen = writer.GenerateEncodeLengthNumber(singleValueHolder.contentLen, singleValueHolder.headerLenBuffer); if (availableContentSpace > singleValueHolder.TotalLength) { //write in first round writer.WriteLengthCodedBuffer(singleValueHolder.bufferContent); return true; } //go below } break; case MySqlDataType.TINY: //if we can write in 1st round if (availableContentSpace > 1) { writer.WriteUnsignedNumber(1, dataTemp.myUInt32); return true; } else { //go below MySqlStreamWriter.WriteUnsignedNumber(1, dataTemp.myUInt32, singleValueHolder.generalContent); } break; case MySqlDataType.SHORT: if (availableContentSpace > 2) { writer.WriteUnsignedNumber(2, dataTemp.myUInt32); return true; } else { MySqlStreamWriter.WriteUnsignedNumber(2, dataTemp.myUInt32, singleValueHolder.generalContent); } break; case MySqlDataType.LONG: if (availableContentSpace > 4) { writer.WriteUnsignedNumber(4, dataTemp.myUInt32); return true; } else { MySqlStreamWriter.WriteUnsignedNumber(4, dataTemp.myUInt32, singleValueHolder.generalContent); //go below } break; case MySqlDataType.LONGLONG: if (availableContentSpace > 8) { writer.WriteInt64(dataTemp.myInt64); return true; } else { //go below MySqlStreamWriter.Write(dataTemp.myInt64, singleValueHolder.generalContent); } break; case MySqlDataType.FLOAT: if (availableContentSpace > 4) { writer.WriteFloat((float)dataTemp.myDouble); return true; } else { //go below MySqlStreamWriter.Write((float)dataTemp.myDouble, singleValueHolder.generalContent); } break; case MySqlDataType.DOUBLE: if (availableContentSpace > 8) { writer.WriteDouble(dataTemp.myDouble); return true; } else { //go below MySqlStreamWriter.Write(dataTemp.myDouble, singleValueHolder.generalContent); } break; default: //TODO: review here throw new NotSupportedException(); //writer.WriteLengthCodedNull(); } } //---------------------------------------------------------------------------------------------------------- if (singleValueHolder.isBufferOrString) { //write encoded len & data //check if we write complete header or not if (singleValueHolder.encodedLengthBufferWriteIndex < singleValueHolder.encodedLengthLen) { //can we write complete encoded length header here? int remaining = singleValueHolder.encodedLengthLen - singleValueHolder.encodedLengthBufferWriteIndex; if (availableContentSpace > remaining) { for (int i = 0; i < remaining; ++i) { writer.WriteByte(singleValueHolder.headerLenBuffer[singleValueHolder.encodedLengthBufferWriteIndex]); singleValueHolder.encodedLengthBufferWriteIndex++; } availableContentSpace -= remaining; } else if (availableContentSpace == remaining) { //TODO: review here throw new NotSupportedException(); //we can write only header *** for (int i = 0; i < remaining; ++i) { writer.WriteByte(singleValueHolder.headerLenBuffer[singleValueHolder.encodedLengthBufferWriteIndex]); singleValueHolder.encodedLengthBufferWriteIndex++; } availableContentSpace -= remaining; } else { //can't complete encoded length here in this step for (int i = 0; i < availableContentSpace; ++i) { writer.WriteByte(singleValueHolder.headerLenBuffer[singleValueHolder.encodedLengthBufferWriteIndex]); singleValueHolder.encodedLengthBufferWriteIndex++; } return false; } } //--------------- //write the body int remainBodyLen = singleValueHolder.contentLen - singleValueHolder.contentStart; if (availableContentSpace > remainBodyLen) { //write buffer //we use bufferContent **** writer.WriteBuffer(singleValueHolder.bufferContent, singleValueHolder.contentStart, remainBodyLen); singleValueHolder.contentStart += remainBodyLen; return true; } else if (availableContentSpace == remainBodyLen) { //TODO: review here throw new NotSupportedException(); //this needs last packet with 0 byte content size *** writer.WriteBuffer(singleValueHolder.generalContent, singleValueHolder.contentStart, remainBodyLen); singleValueHolder.contentStart += remainBodyLen; return false; } else { //write buffer //we use bufferContent **** writer.WriteBuffer(singleValueHolder.bufferContent, singleValueHolder.contentStart, availableContentSpace); singleValueHolder.contentStart += availableContentSpace; return false; } } else { //--------------- //write the body int remainBodyLen = singleValueHolder.contentLen - singleValueHolder.contentStart; if (availableContentSpace > remainBodyLen) { //write buffer //we use generalContent **** writer.WriteBuffer(singleValueHolder.generalContent, singleValueHolder.contentStart, remainBodyLen); singleValueHolder.contentStart += remainBodyLen; return true; } else if (availableContentSpace == remainBodyLen) { //TODO: review here throw new NotSupportedException(); //this needs last packet with 0 byte content size *** writer.WriteBuffer(singleValueHolder.generalContent, singleValueHolder.contentStart, remainBodyLen); singleValueHolder.contentStart += remainBodyLen; return false; } else { //write buffer //we use generalContent **** writer.WriteBuffer(singleValueHolder.generalContent, singleValueHolder.contentStart, availableContentSpace); singleValueHolder.contentStart += availableContentSpace; return false; } } }
public override void WritePacket(MySqlStreamWriter writer) { throw new NotImplementedException(); //writer.ReserveHeader();//allocate packet header //writer.WriteUnsigned1(0xfe); //if (protocol41) //{ // writer.WriteUnsigned2(warningCount); // writer.WriteUnsigned2(serverStatus); //} //_header = new PacketHeader((uint)writer.Length - 4, writer.IncrementPacketNumber()); //writer.WriteHeader(_header);//write packet header }
public override void WritePacket(MySqlStreamWriter writer) { writer.ReserveHeader(); writer.WriteUnsigned4(_statement_id); writer.WriteUnsigned2((uint)_param_id); WriteValueByType(writer, _data); }
/// <summary> /// /// </summary> /// <param name="writer"></param> /// <param name="sql"></param> /// <returns></returns> public static void Write(MySqlStreamWriter writer, string sql) { //for those who don't want to alloc an new packet //just write it into a stream byte[] buffer = writer.GetEncodeBytes(sql.ToCharArray()); int totalLen = buffer.Length; int packetCount = (totalLen / Packet.MAX_PACKET_LENGTH) + 1; if (packetCount <= 1) { writer.ReserveHeader(); writer.WriteByte((byte)Command.QUERY); //check if we can write data in 1 packet or not writer.WriteBinaryString(buffer); var header = new PacketHeader(writer.OnlyPacketContentLength, writer.IncrementPacketNumber()); writer.WriteHeader(header); } else { //we need to split to multiple packet int currentPacketContentSize = Packet.MAX_PACKET_LENGTH; int pos = 0; for (int i = 0; i < packetCount; ++i) { //write each packet to stream writer.ReserveHeader(); if (i == 0) { //first packet writer.WriteByte((byte)Command.QUERY); writer.WriteBinaryString(buffer, pos, currentPacketContentSize - 1);//remove 1 query cmd pos += (currentPacketContentSize - 1); } else if (i == packetCount - 1) { //last packet currentPacketContentSize = totalLen - pos; writer.WriteBinaryString(buffer, pos, currentPacketContentSize); } else { writer.WriteBinaryString(buffer, pos, currentPacketContentSize); pos += (currentPacketContentSize); } //check if we can write data in 1 packet or not var header = new PacketHeader((uint)currentPacketContentSize, writer.IncrementPacketNumber()); writer.WriteHeader(header); } } }
public override void WritePacket(MySqlStreamWriter writer) { writer.ReserveHeader();//allocate header if (protocol41) { writer.WriteUnsigned4(clientFlags); writer.WriteUnsigned4(maxPacketSize); writer.WriteUnsigned1(charsetNumber); writer.WriteFiller(23); writer.WriteNullTerminatedString(user); writer.WriteLengthCodedBuffer(scrambleBuff); writer.WriteNullTerminatedString(database); } else { writer.WriteUnsigned2(clientFlags); writer.WriteUnsigned3(maxPacketSize); writer.WriteNullTerminatedString(user); writer.WriteBuffer(scrambleBuff); if (database != null && database.Length > 0) { writer.WriteFiller(1); writer.WriteBuffer(Encoding.ASCII.GetBytes(database)); } } _header = new PacketHeader(writer.OnlyPacketContentLength, writer.IncrementPacketNumber()); writer.WriteHeader(_header); }
public override void WritePacket(MySqlStreamWriter writer) { throw new NotImplementedException(); //writer.writeUnsignedNumber(1, this.protocolVersion); //writer.writeNullTerminatedString(this.serverVersion); //writer.writeUnsignedNumber(4, this.threadId); //writer.writeBuffer(this.scrambleBuff1); //writer.writeFiller(1); //writer.writeUnsignedNumber(2, this.serverCapabilities1); //writer.writeUnsignedNumber(1, this.serverLanguage); //writer.writeUnsignedNumber(2, this.serverStatus); //if (this.protocol41) { // writer.writeUnsignedNumber(2, this.serverCapabilities2); // writer.writeUnsignedNumber(1, this.scrambleLength); // writer.writeFiller(10); //} //writer.writeNullTerminatedBuffer(this.scrambleBuff2); //if (this.pluginData !== undefined) { // writer.writeNullTerminatedString(this.pluginData); //} }
public Query(Connection conn, SqlStringTemplate sql, CommandParams cmdParams) { //*** query use conn resource such as parser,writer //so 1 query 1 connection Query bindingQuery = conn.BindingQuery; if (bindingQuery != null) { //check if binding query can be close if (!bindingQuery.LateClose()) { //can't use this conn throw new Exception("connection is in used"); } } //-------------------------------------------------------------- conn.BindingQuery = this; //-------------------------------------------------------------- if (sql == null) { throw new Exception("Sql command can not null."); } //-------------------------------------------------------------- this._conn = conn; this._cmdParams = cmdParams; //-------------------------------------------------------------- nestTables = false; _sqlParserMx = conn.MySqlParserMx; _writer = conn.PacketWriter; //_receiveBuffer = null; _sqlStrTemplate = sql; }
public override void WritePacket(MySqlStreamWriter writer) { _header = Write(writer, this._statementId); }
public static PacketHeader Write(MySqlStreamWriter writer, uint stmtId) { writer.ReserveHeader(); writer.WriteByte((byte)Command.STMT_RESET); writer.WriteUnsigned4(stmtId); var _header = new PacketHeader(writer.OnlyPacketContentLength, writer.IncrementPacketNumber()); writer.WriteHeader(_header); return _header; }
public override void WritePacket(MySqlStreamWriter writer) { this._header = Write(writer, this._sql); }
void WriteValueByType(MySqlStreamWriter writer, MyStructData dataTemp) { switch (dataTemp.type) { case MySqlDataType.VARCHAR: case MySqlDataType.VAR_STRING: case MySqlDataType.STRING: writer.WriteLengthCodedString(dataTemp.myString); break; case MySqlDataType.LONG: writer.WriteUnsignedNumber(4, (uint)dataTemp.myInt32); break; case MySqlDataType.LONGLONG: writer.WriteInt64(dataTemp.myInt64); break; case MySqlDataType.FLOAT: writer.WriteFloat((float)dataTemp.myDouble); break; case MySqlDataType.DOUBLE: writer.WriteDouble(dataTemp.myDouble); break; case MySqlDataType.BIT: case MySqlDataType.BLOB: case MySqlDataType.MEDIUM_BLOB: case MySqlDataType.LONG_BLOB: writer.WriteLengthCodedBuffer(dataTemp.myBuffer); break; default: writer.WriteLengthCodedNull(); break; } }
public static PacketHeader Write(MySqlStreamWriter writer, string sql) { //for those who don't want to alloc an new packet //just write it into a stream writer.ReserveHeader(); writer.WriteByte((byte)Command.STMT_PREPARE); writer.WriteString(sql); var h = new PacketHeader(writer.OnlyPacketContentLength, writer.IncrementPacketNumber()); writer.WriteHeader(h); return h; }
public override void WritePacket(MySqlStreamWriter writer) { throw new NotImplementedException(); }
public override void WritePacket(MySqlStreamWriter writer) { Write(writer, this._statementId, _prepareValues); }