1
1
using System ;
2
+ using System . Collections . Generic ;
2
3
using System . Data ;
3
4
using MySql . Data . MySqlClient ;
4
5
using MySqlConnector . Protocol ;
@@ -16,6 +17,18 @@ public StatementPreparer(string commandText, MySqlParameterCollection parameters
16
17
m_options = options ;
17
18
}
18
19
20
+ public ParsedStatements SplitStatements ( )
21
+ {
22
+ var statements = new List < ParsedStatement > ( ) ;
23
+ var statementStartEndIndexes = new List < int > ( ) ;
24
+ var writer = new ByteBufferWriter ( m_commandText . Length + 1 ) ;
25
+ var parser = new PreparedCommandSqlParser ( this , statements , statementStartEndIndexes , writer ) ;
26
+ parser . Parse ( m_commandText ) ;
27
+ for ( var i = 0 ; i < statements . Count ; i ++ )
28
+ statements [ i ] . StatementBytes = writer . ArraySegment . Slice ( statementStartEndIndexes [ i * 2 ] , statementStartEndIndexes [ i * 2 + 1 ] - statementStartEndIndexes [ i * 2 ] ) ;
29
+ return new ParsedStatements ( statements , writer . ToPayloadData ( ) ) ;
30
+ }
31
+
19
32
public ArraySegment < byte > ParseAndBindParameters ( )
20
33
{
21
34
var writer = new ByteBufferWriter ( m_commandText . Length + 1 ) ;
@@ -30,6 +43,22 @@ public ArraySegment<byte> ParseAndBindParameters()
30
43
return writer . ArraySegment ;
31
44
}
32
45
46
+ private int GetParameterIndex ( string name )
47
+ {
48
+ var index = m_parameters . NormalizedIndexOf ( name ) ;
49
+ if ( index == - 1 && ( m_options & StatementPreparerOptions . AllowUserVariables ) == 0 )
50
+ throw new MySqlException ( "Parameter '{0}' must be defined. To use this as a variable, set 'Allow User Variables=true' in the connection string." . FormatInvariant ( name ) ) ;
51
+ return index ;
52
+ }
53
+
54
+ private MySqlParameter GetInputParameter ( int index )
55
+ {
56
+ var parameter = m_parameters [ index ] ;
57
+ if ( parameter . Direction != ParameterDirection . Input && ( m_options & StatementPreparerOptions . AllowOutputParameters ) == 0 )
58
+ throw new MySqlException ( "Only ParameterDirection.Input is supported when CommandType is Text (parameter name: {0})" . FormatInvariant ( parameter . ParameterName ) ) ;
59
+ return parameter ;
60
+ }
61
+
33
62
private sealed class ParameterSqlParser : SqlParser
34
63
{
35
64
public ParameterSqlParser ( StatementPreparer preparer , ByteBufferWriter writer )
@@ -38,18 +67,11 @@ public ParameterSqlParser(StatementPreparer preparer, ByteBufferWriter writer)
38
67
m_writer = writer ;
39
68
}
40
69
41
- protected override void OnBeforeParse ( string sql )
42
- {
43
- }
44
-
45
70
protected override void OnNamedParameter ( int index , int length )
46
71
{
47
- var parameterName = m_preparer . m_commandText . Substring ( index , length ) ;
48
- var parameterIndex = m_preparer . m_parameters . NormalizedIndexOf ( parameterName ) ;
72
+ var parameterIndex = m_preparer . GetParameterIndex ( m_preparer . m_commandText . Substring ( index , length ) ) ;
49
73
if ( parameterIndex != - 1 )
50
74
DoAppendParameter ( parameterIndex , index , length ) ;
51
- else if ( ( m_preparer . m_options & StatementPreparerOptions . AllowUserVariables ) == 0 )
52
- throw new MySqlException ( "Parameter '{0}' must be defined. To use this as a variable, set 'Allow User Variables=true' in the connection string." . FormatInvariant ( parameterName ) ) ;
53
75
}
54
76
55
77
protected override void OnPositionalParameter ( int index )
@@ -60,30 +82,83 @@ protected override void OnPositionalParameter(int index)
60
82
61
83
private void DoAppendParameter ( int parameterIndex , int textIndex , int textLength )
62
84
{
63
- AppendString ( m_preparer . m_commandText , m_lastIndex , textIndex - m_lastIndex ) ;
64
- var parameter = m_preparer . m_parameters [ parameterIndex ] ;
65
- if ( parameter . Direction != ParameterDirection . Input && ( m_preparer . m_options & StatementPreparerOptions . AllowOutputParameters ) == 0 )
66
- throw new MySqlException ( "Only ParameterDirection.Input is supported when CommandType is Text (parameter name: {0})" . FormatInvariant ( parameter . ParameterName ) ) ;
67
- m_preparer . m_parameters [ parameterIndex ] . AppendSqlString ( m_writer , m_preparer . m_options , parameter . ParameterName ) ;
85
+ m_writer . Write ( m_preparer . m_commandText , m_lastIndex , textIndex - m_lastIndex ) ;
86
+ var parameter = m_preparer . GetInputParameter ( parameterIndex ) ;
87
+ parameter . AppendSqlString ( m_writer , m_preparer . m_options ) ;
68
88
m_lastIndex = textIndex + textLength ;
69
89
}
70
90
71
91
protected override void OnParsed ( )
72
92
{
73
- AppendString ( m_preparer . m_commandText , m_lastIndex , m_preparer . m_commandText . Length - m_lastIndex ) ;
93
+ m_writer . Write ( m_preparer . m_commandText , m_lastIndex , m_preparer . m_commandText . Length - m_lastIndex ) ;
94
+ }
95
+
96
+ readonly StatementPreparer m_preparer ;
97
+ readonly ByteBufferWriter m_writer ;
98
+ int m_currentParameterIndex ;
99
+ int m_lastIndex ;
100
+ }
101
+
102
+ private sealed class PreparedCommandSqlParser : SqlParser
103
+ {
104
+ public PreparedCommandSqlParser ( StatementPreparer preparer , List < ParsedStatement > statements , List < int > statementStartEndIndexes , ByteBufferWriter writer )
105
+ {
106
+ m_preparer = preparer ;
107
+ m_statements = statements ;
108
+ m_statementStartEndIndexes = statementStartEndIndexes ;
109
+ m_writer = writer ;
110
+ }
111
+
112
+ protected override void OnStatementBegin ( int index )
113
+ {
114
+ m_statements . Add ( new ParsedStatement ( ) ) ;
115
+ m_statementStartEndIndexes . Add ( m_writer . Position ) ;
116
+ m_writer . Write ( ( byte ) CommandKind . StatementPrepare ) ;
117
+ m_lastIndex = index ;
74
118
}
75
119
76
- private void AppendString ( string value , int offset , int length )
120
+ protected override void OnNamedParameter ( int index , int length )
77
121
{
78
- m_writer . Write ( value , offset , length ) ;
122
+ var parameterName = m_preparer . m_commandText . Substring ( index , length ) ;
123
+ DoAppendParameter ( parameterName , - 1 , index , length ) ;
124
+ }
125
+
126
+ protected override void OnPositionalParameter ( int index )
127
+ {
128
+ DoAppendParameter ( null , m_currentParameterIndex , index , 1 ) ;
129
+ m_currentParameterIndex ++ ;
130
+ }
131
+
132
+ private void DoAppendParameter ( string parameterName , int parameterIndex , int textIndex , int textLength )
133
+ {
134
+ // write all SQL up to the parameter
135
+ m_writer . Write ( m_preparer . m_commandText , m_lastIndex , textIndex - m_lastIndex ) ;
136
+ m_lastIndex = textIndex + textLength ;
137
+
138
+ // replace the parameter with a ? placeholder
139
+ m_writer . Write ( ( byte ) '?' ) ;
140
+
141
+ // store the parameter index
142
+ m_statements [ m_statements . Count - 1 ] . ParameterNames . Add ( parameterName ) ;
143
+ m_statements [ m_statements . Count - 1 ] . ParameterIndexes . Add ( parameterIndex ) ;
144
+ }
145
+
146
+ protected override void OnStatementEnd ( int index )
147
+ {
148
+ m_writer . Write ( m_preparer . m_commandText , m_lastIndex , index - m_lastIndex ) ;
149
+ m_lastIndex = index ;
150
+ m_statementStartEndIndexes . Add ( m_writer . Position ) ;
79
151
}
80
152
81
153
readonly StatementPreparer m_preparer ;
154
+ readonly List < ParsedStatement > m_statements ;
155
+ readonly List < int > m_statementStartEndIndexes ;
82
156
readonly ByteBufferWriter m_writer ;
83
157
int m_currentParameterIndex ;
84
158
int m_lastIndex ;
85
159
}
86
160
161
+
87
162
readonly string m_commandText ;
88
163
readonly MySqlParameterCollection m_parameters ;
89
164
readonly StatementPreparerOptions m_options ;
0 commit comments