@@ -17,6 +17,11 @@ public partial class Compiler
1717        protected  virtual  string  LastId  {  get ;  set ;  }  =  "" ; 
1818        protected  virtual  string  EscapeCharacter  {  get ;  set ;  }  =  "\\ " ; 
1919
20+ 
21+         protected  virtual  string  SingleInsertStartClause  {  get ;  set ;  }  =  "INSERT INTO" ; 
22+         protected  virtual  string  MultiInsertStartClause  {  get ;  set ;  }  =  "INSERT INTO" ; 
23+ 
24+ 
2025        protected  Compiler ( ) 
2126        { 
2227            _compileConditionMethodsProvider  =  new  ConditionsCompilerProvider ( this ) ; 
@@ -391,81 +396,84 @@ protected virtual SqlResult CompileInsertQuery(Query query)
391396            } ; 
392397
393398            if  ( ! ctx . Query . HasComponent ( "from" ,  EngineCode ) ) 
394-             { 
395399                throw  new  InvalidOperationException ( "No table set to insert" ) ; 
396-             } 
397400
398401            var  fromClause  =  ctx . Query . GetOneComponent < AbstractFrom > ( "from" ,  EngineCode ) ; 
399- 
400402            if  ( fromClause  is  null ) 
401-             { 
402403                throw  new  InvalidOperationException ( "Invalid table expression" ) ; 
403-             } 
404404
405405            string  table  =  null ; 
406- 
407406            if  ( fromClause  is  FromClause  fromClauseCast ) 
408-             { 
409407                table  =  Wrap ( fromClauseCast . Table ) ; 
410-             } 
411- 
412408            if  ( fromClause  is  RawFromClause  rawFromClause ) 
413409            { 
414410                table  =  WrapIdentifiers ( rawFromClause . Expression ) ; 
415411                ctx . Bindings . AddRange ( rawFromClause . Bindings ) ; 
416412            } 
417413
418414            if  ( table  is  null ) 
419-             { 
420415                throw  new  InvalidOperationException ( "Invalid table expression" ) ; 
421-             } 
422416
423417            var  inserts  =  ctx . Query . GetComponents < AbstractInsertClause > ( "insert" ,  EngineCode ) ; 
418+             if  ( inserts [ 0 ]  is  InsertQueryClause  insertQueryClause ) 
419+                 return  CompileInsertQueryClause ( ctx ,  table ,  insertQueryClause ) ; 
420+             else 
421+                 return  CompileValueInsertClauses ( ctx ,  table ,  inserts . Cast < InsertClause > ( ) ) ; 
422+         } 
424423
425-              if   ( inserts [ 0 ]   is   InsertClause   insertClause ) 
426-             { 
427-                  var   columns   =   string . Join ( ", " ,   WrapArray ( insertClause . Columns ) ) ; 
428-                  var   values   =   string . Join ( ", " ,   Parameterize ( ctx ,   insertClause . Values ) ) ; 
424+         protected   virtual   SqlResult   CompileInsertQueryClause ( 
425+             SqlResult   ctx ,   string   table ,   InsertQueryClause   clause ) 
426+         { 
427+             string   columns   =   GetInsertColumnsList ( clause . Columns ) ; 
429428
430-                 ctx . RawSql  =  $ "INSERT INTO { table }  ({ columns } ) VALUES ({ values } )"; 
429+             var  subCtx  =  CompileSelectQuery ( clause . Query ) ; 
430+             ctx . Bindings . AddRange ( subCtx . Bindings ) ; 
431431
432-                 if  ( insertClause . ReturnId  &&  ! string . IsNullOrEmpty ( LastId ) ) 
433-                 { 
434-                     ctx . RawSql  +=  ";"  +  LastId ; 
435-                 } 
436-             } 
437-             else 
438-             { 
439-                 var  clause  =  inserts [ 0 ]  as  InsertQueryClause ; 
432+             ctx . RawSql  =  $ "{ SingleInsertStartClause }  { table } { columns }  { subCtx . RawSql } "; 
440433
441-                 var  columns  =  "" ; 
434+             return  ctx ; 
435+         } 
442436
443-                  if   ( clause . Columns . Any ( ) ) 
444-                  { 
445-                      columns   =   $ " ( { string . Join ( ", " ,   WrapArray ( clause . Columns ) ) } ) " ; 
446-                  } 
437+         protected   virtual   SqlResult   CompileValueInsertClauses ( 
438+             SqlResult   ctx ,   string   table ,   IEnumerable < InsertClause >   insertClauses ) 
439+         { 
440+             bool   isMultiValueInsert   =   insertClauses . Skip ( 1 ) . Any ( ) ; 
447441
448-                 var  subCtx  =  CompileSelectQuery ( clause . Query ) ; 
449-                 ctx . Bindings . AddRange ( subCtx . Bindings ) ; 
442+             var  insertInto  =  ( isMultiValueInsert )  ?  MultiInsertStartClause  :  SingleInsertStartClause ; 
450443
451-                 ctx . RawSql  =  $ "INSERT INTO { table } { columns } { subCtx . RawSql } "; 
452-             } 
444+             var  firstInsert  =  insertClauses . First ( ) ; 
445+             string  columns  =  GetInsertColumnsList ( firstInsert . Columns ) ; 
446+             var  values  =  string . Join ( ", " ,  Parameterize ( ctx ,  firstInsert . Values ) ) ; 
453447
454-             if  ( inserts . Count  >  1 ) 
455-             { 
456-                 foreach  ( var  insert  in  inserts . GetRange ( 1 ,  inserts . Count  -  1 ) ) 
457-                 { 
458-                     var  clause  =  insert  as  InsertClause ; 
448+             ctx . RawSql  =  $ "{ insertInto }  { table } { columns }  VALUES ({ values } )"; 
459449
460-                     ctx . RawSql  +=  ", ("  +  string . Join ( ", " ,  Parameterize ( ctx ,  clause . Values ) )  +  ")" ; 
450+             if  ( isMultiValueInsert ) 
451+                 return  CompileRemainingInsertClauses ( ctx ,  table ,  insertClauses ) ; 
461452
462-                  } 
463-             } 
453+             if   ( firstInsert . ReturnId   &&   ! string . IsNullOrEmpty ( LastId ) ) 
454+                  ctx . RawSql   +=   ";"   +   LastId ; 
464455
456+             return  ctx ; 
457+         } 
465458
459+         protected  virtual  SqlResult  CompileRemainingInsertClauses ( SqlResult  ctx ,  string  table ,  IEnumerable < InsertClause >  inserts ) 
460+         { 
461+             foreach  ( var  insert  in  inserts . Skip ( 1 ) ) 
462+             { 
463+                 string  values  =  string . Join ( ", " ,  Parameterize ( ctx ,  insert . Values ) ) ; 
464+                 ctx . RawSql  +=  $ ", ({ values } )"; 
465+             } 
466466            return  ctx ; 
467467        } 
468468
469+         protected  string  GetInsertColumnsList ( List < string >  columnList ) 
470+         { 
471+             var  columns  =  "" ; 
472+             if  ( columnList . Any ( ) ) 
473+                 columns  =  $ " ({ string . Join ( ", " ,  WrapArray ( columnList ) ) } )"; 
474+ 
475+             return  columns ; 
476+         } 
469477
470478        protected  virtual  SqlResult  CompileCteQuery ( SqlResult  ctx ,  Query  query ) 
471479        { 
0 commit comments