@@ -60,22 +60,25 @@ public string Build(SqlQueryStructure structure)
6060 /// <inheritdoc />
6161 public string Build ( SqlInsertStructure structure )
6262 {
63- // TODO: these should be put in a transcation
63+ // No need to put into transaction as LAST_INSERT_ID is session level variable
6464 return $ "INSERT INTO { QuoteIdentifier ( structure . TableName ) } ({ Build ( structure . InsertColumns ) } ) " +
6565 $ "VALUES ({ string . Join ( ", " , ( structure . Values ) ) } ); " +
66- $ "SELECT { MakeInsertSelections ( structure ) } ";
66+ $ " SET @ROWCOUNT=ROW_COUNT(); " +
67+ $ "SELECT { MakeInsertSelections ( structure ) } WHERE @ROWCOUNT > 0;";
6768 }
6869
6970 /// <inheritdoc />
7071 public string Build ( SqlUpdateStructure structure )
7172 {
72- // TODO: these should be put in a transaction
73- return $ "UPDATE { QuoteIdentifier ( structure . TableName ) } " +
73+ ( string sets , string updates , string select ) = MakeStoreUpdatePK ( structure . PrimaryKey ( ) ) ;
74+
75+ return sets + ";\n " +
76+ $ "UPDATE { QuoteIdentifier ( structure . TableName ) } " +
7477 $ "SET { Build ( structure . UpdateOperations , ", " ) } " +
75- $ "WHERE { Build ( structure . Predicates ) } ; " +
76- $ "SELECT { Build ( structure . PrimaryKey ( ) ) } " +
77- $ "FROM { QuoteIdentifier ( structure . TableName ) } " +
78- $ "WHERE { Build ( structure . Predicates ) } ; ";
78+ ", " + updates +
79+ $ " WHERE { Build ( structure . Predicates ) } ; " +
80+ $ " SET @ROWCOUNT=ROW_COUNT(); " +
81+ $ "SELECT " + select + $ " WHERE @ROWCOUNT > 0; ";
7982 }
8083
8184 /// <inheritdoc />
@@ -88,8 +91,36 @@ public string Build(SqlDeleteStructure structure)
8891 /// <inheritdoc />
8992 public string Build ( SqlUpsertQueryStructure structure )
9093 {
91- // TODO: these should be put in a transcation
92- throw new NotImplementedException ( ) ;
94+ ( string sets , string updates , string select ) = MakeStoreUpdatePK ( structure . PrimaryKey ( ) ) ;
95+
96+ string insert = $ "INSERT INTO { QuoteIdentifier ( structure . TableName ) } ({ Build ( structure . InsertColumns ) } ) " +
97+ $ "VALUES ({ string . Join ( ", " , ( structure . Values ) ) } ) ";
98+
99+ return sets + ";\n " +
100+ insert + " ON DUPLICATE KEY " +
101+ $ "UPDATE { Build ( structure . UpdateOperations , ", " ) } " +
102+ $ ", " + updates + ";" +
103+ $ " SET @ROWCOUNT=ROW_COUNT(); " +
104+ $ "SELECT " + select + $ " WHERE @ROWCOUNT != 1;" +
105+ $ "SELECT { MakeUpsertSelections ( structure ) } WHERE @ROWCOUNT = 1;";
106+ }
107+
108+ /// <summary>
109+ /// Makes the query segments to store PK during an update
110+ /// </summary>
111+ private ( string , string , string ) MakeStoreUpdatePK ( List < string > primaryKey )
112+ {
113+ // Create local variables to store the pk columns
114+ string sets = String . Join ( ";\n " , primaryKey . Select ( ( x , index ) => $ "SET { "@LU_" + index . ToString ( ) } := 0") ) ;
115+
116+ // Fetch the value to local variables
117+ string updates = String . Join ( ", " , primaryKey . Select ( ( x , index ) =>
118+ $ "{ QuoteIdentifier ( x ) } = (SELECT { "@LU_" + index . ToString ( ) } := { QuoteIdentifier ( x ) } )") ) ;
119+
120+ // Select local variables and mapping to original column name
121+ string select = String . Join ( ", " , primaryKey . Select ( ( x , index ) => $ "{ "@LU_" + index . ToString ( ) } AS { QuoteIdentifier ( x ) } ") ) ;
122+
123+ return ( sets , updates , select ) ;
93124 }
94125
95126 /// <summary>
@@ -126,8 +157,11 @@ private string MakeInsertSelections(SqlInsertStructure structure)
126157 {
127158 List < string > selections = new ( ) ;
128159
160+ List < string > fields = structure . PrimaryKey ( )
161+ . Union ( structure . InsertColumns ) . ToList ( ) ;
162+
129163 int index = 0 ;
130- foreach ( string colName in structure . PrimaryKey ( ) )
164+ foreach ( string colName in fields )
131165 {
132166 string quotedColName = QuoteIdentifier ( colName ) ;
133167 if ( structure . InsertColumns . Contains ( colName ) )
@@ -137,11 +171,41 @@ private string MakeInsertSelections(SqlInsertStructure structure)
137171 }
138172 else if ( structure . GetColumnDefinition ( colName ) . IsAutoGenerated )
139173 {
174+ //TODO: This assumes one column PK
140175 selections . Add ( $ "LAST_INSERT_ID() AS { quotedColName } ") ;
141176 }
142177 }
143178
144179 return string . Join ( ", " , selections ) ;
145180 }
181+
182+ private string MakeUpsertSelections ( SqlUpsertQueryStructure structure )
183+ {
184+ List < string > selections = new ( ) ;
185+
186+ List < string > fields = structure . AllColumns ( ) ;
187+
188+ int index = 0 ;
189+ foreach ( string colName in fields )
190+ {
191+ string quotedColName = QuoteIdentifier ( colName ) ;
192+
193+ if ( structure . InsertColumns . Contains ( colName ) )
194+ {
195+ selections . Add ( $ "{ structure . Values [ index ] } AS { quotedColName } ") ;
196+ index ++ ;
197+ }
198+ else if ( structure . GetColumnDefinition ( colName ) . IsAutoGenerated )
199+ {
200+ selections . Add ( $ "LAST_INSERT_ID() AS { quotedColName } ") ;
201+ }
202+ else
203+ {
204+ selections . Add ( $ "NULL AS { quotedColName } ") ;
205+ }
206+ }
207+
208+ return string . Join ( ", " , selections ) ;
209+ }
146210 }
147211}
0 commit comments