@@ -391,36 +391,60 @@ package struct ProtocolPrepared
391391 }
392392 }
393393
394- static void sendCommand (Connection conn, uint hStmt, PreparedStmtHeaders psh,
394+ static ubyte [] sendCommand (Connection conn, uint hStmt, PreparedStmtHeaders psh,
395395 MySQLVal[] inParams, ParameterSpecialization[] psa)
396396 {
397- conn.autoPurge();
397+ ubyte [] impl ()
398+ {
399+ conn.autoPurge();
398400
399- ubyte [] packet;
400- conn.resetPacket();
401+ ubyte [] packet;
402+ conn.resetPacket();
403+
404+ ubyte [] prefix = makePSPrefix(hStmt, 0 );
405+ size_t len = prefix.length;
406+ bool longData;
407+
408+ if (psh.paramCount)
409+ {
410+ ubyte [] one = [ 1 ];
411+ ubyte [] vals;
412+ ubyte [] types = analyseParams(inParams, psa, vals, longData);
413+ ubyte [] nbm = makeBitmap(inParams);
414+ packet = prefix ~ nbm ~ one ~ types ~ vals;
415+ }
416+ else
417+ packet = prefix;
401418
402- ubyte [] prefix = makePSPrefix(hStmt, 0 );
403- size_t len = prefix.length;
404- bool longData;
419+ if (longData)
420+ sendLongData(conn._socket, hStmt, psa);
405421
406- if (psh.paramCount)
422+ assert (packet.length <= uint .max);
423+ packet.setPacketHeader(conn.pktNumber);
424+ conn.bumpPacket();
425+ conn._socket.send(packet);
426+
427+ return conn.getPacket();
428+ }
429+
430+ if (conn._socket.connected)
407431 {
408- ubyte [] one = [ 1 ];
409- ubyte [] vals;
410- ubyte [] types = analyseParams(inParams, psa, vals, longData);
411- ubyte [] nbm = makeBitmap(inParams);
412- packet = prefix ~ nbm ~ one ~ types ~ vals;
432+ try
433+ {
434+ return impl ();
435+ }
436+ catch (Exception )
437+ {
438+ // convert all exceptions here as stale connections. This might be the
439+ // first try to send a request to the server on an
440+ // already-existing connection.
441+ throw new MYXStaleConnection(" Possible stale connection" );
442+ }
413443 }
414444 else
415- packet = prefix;
416-
417- if (longData)
418- sendLongData(conn._socket, hStmt, psa);
419-
420- assert (packet.length <= uint .max);
421- packet.setPacketHeader(conn.pktNumber);
422- conn.bumpPacket();
423- conn._socket.send(packet);
445+ {
446+ return impl ();
447+ }
424448 }
425449}
426450
@@ -454,22 +478,21 @@ package(mysql) bool execQueryImpl(Connection conn, ExecQueryImplInfo info, out u
454478 scope (failure) conn.kill();
455479
456480 // Send data
481+ ubyte [] packet;
457482 if (info.isPrepared)
458483 {
459484 logTrace(" prepared SQL: %s" , info.hStmt);
460485
461- ProtocolPrepared.sendCommand(conn, info.hStmt, info.psh, info.inParams, info.psa);
486+ packet = ProtocolPrepared.sendCommand(conn, info.hStmt, info.psh, info.inParams, info.psa);
462487 }
463488 else
464489 {
465490 logTrace(" exec query: %s" , info.sql);
466491
467- conn.sendCmd(CommandType.QUERY , info.sql);
492+ packet = conn.sendCmd(CommandType.QUERY , info.sql);
468493 conn._fieldCount = 0 ;
469494 }
470495
471- // Handle response
472- ubyte [] packet = conn.getPacket();
473496 bool rv;
474497 if (packet.front == ResultPacketMarker.ok || packet.front == ResultPacketMarker.error)
475498 {
688711 _socket.write(data);
689712}
690713
691- package (mysql) void sendCmd(T)(Connection conn, CommandType cmd, const (T)[] data)
714+ // returns the first packet received
715+ package (mysql) ubyte [] sendCmd(T)(Connection conn, CommandType cmd, const (T)[] data)
692716in
693717{
694718 // Internal thread states. Clients shouldn't use this
709733out
710734{
711735 // at this point we should have sent a command
712- assert (conn.pktNumber == 1 );
736+ // assert(conn.pktNumber == 1);
713737}
714738do
715739{
716- scope (failure) conn.kill();
717-
718740 conn._lastCommandID++ ;
719741
720- if ( ! conn._socket.connected )
742+ ubyte [] impl ( )
721743 {
722- if (cmd == CommandType.QUIT )
723- return ; // Don't bother reopening connection just to quit
744+ scope (failure) conn.kill();
724745
725- conn._open = Connection.OpenState.notConnected;
726- conn.connect(conn._clientCapabilities);
727- }
746+ conn.autoPurge();
728747
729- conn.autoPurge ();
748+ conn.resetPacket ();
730749
731- conn.resetPacket();
750+ ubyte [] header;
751+ header.length = 4 /* header*/ + 1 /* cmd*/ ;
752+ header.setPacketHeader(conn.pktNumber, cast (uint )data.length + 1 /* cmd byte*/ );
753+ header[4 ] = cmd;
754+ conn.bumpPacket();
732755
733- ubyte [] header;
734- header.length = 4 /* header*/ + 1 /* cmd*/ ;
735- header.setPacketHeader(conn.pktNumber, cast (uint )data.length + 1 /* cmd byte*/ );
736- header[4 ] = cmd;
737- conn.bumpPacket();
756+ conn._socket.send(header, cast (const (ubyte )[])data);
757+
758+ // now, get the first packet, but only if the command is not QUIT
759+ if (cmd == CommandType.QUIT )
760+ return null ;
761+
762+ return conn.getPacket();
763+ }
764+
765+ if (conn._socket.connected)
766+ {
767+ try
768+ {
769+ return impl ();
770+ }
771+ catch (Exception )
772+ {
773+ // convert all exceptions here as stale connections. This is the
774+ // first try to send a request to the server on an already-existing connection.
775+ throw new MYXStaleConnection(" Possible stale connection" );
776+ }
777+ }
778+ else
779+ {
780+ if (cmd == CommandType.QUIT )
781+ return null ; // Don't bother reopening connection just to quit
738782
739- conn._socket.send(header, cast (const (ubyte )[])data);
783+ conn._open = Connection.OpenState.notConnected;
784+ conn.connect(conn._clientCapabilities);
785+ return impl ();
786+ }
740787}
741788
742- package (mysql) OKErrorPacket getCmdResponse(Connection conn, bool asString = false )
789+ package (mysql) OKErrorPacket getCmdResponse(Connection conn, ubyte [] packet )
743790{
744- auto okp = OKErrorPacket(conn.getPacket() );
791+ auto okp = OKErrorPacket(packet );
745792 enforcePacketOK(okp);
746793 conn._serverStatus = okp.serverStatus;
747794 return okp;
@@ -960,10 +1007,9 @@ package(mysql) PreparedServerInfo performRegister(Connection conn, const(char[])
9601007
9611008 PreparedServerInfo info;
9621009
963- conn.sendCmd(CommandType.STMT_PREPARE , sql);
1010+ ubyte [] packet = conn.sendCmd(CommandType.STMT_PREPARE , sql);
9641011 conn._fieldCount = 0 ;
9651012
966- ubyte [] packet = conn.getPacket();
9671013 if (packet.front == ResultPacketMarker.ok)
9681014 {
9691015 packet.popFront();
@@ -1046,8 +1092,7 @@ Get a textual report on the server status.
10461092+/
10471093package (mysql) string serverStats(Connection conn)
10481094{
1049- conn.sendCmd(CommandType.STATISTICS , []);
1050- auto result = conn.getPacket();
1095+ auto result = conn.sendCmd(CommandType.STATISTICS , []);
10511096 return (() @trusted => cast (string )result)();
10521097}
10531098
@@ -1071,10 +1116,8 @@ package(mysql) void enableMultiStatements(Connection conn, bool on)
10711116 t.length = 2 ;
10721117 t[0 ] = on ? 0 : 1 ;
10731118 t[1 ] = 0 ;
1074- conn.sendCmd(CommandType.STMT_OPTION , t);
1075-
10761119 // For some reason this command gets an EOF packet as response
1077- auto packet = conn.getPacket( );
1120+ auto packet = conn.sendCmd(CommandType. STMT_OPTION , t );
10781121 enforce! MYXProtocol(packet[0 ] == 254 && packet.length == 5 , " Unexpected response to SET_OPTION command" );
10791122}
10801123
0 commit comments