11using FreeSql . Internal ;
2+ using System ;
23using System . Collections . Generic ;
34using System . Data . Common ;
45using System . Linq ;
@@ -17,6 +18,7 @@ public PostgreSQLInsertOrUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExp
1718
1819 public override string ToSql ( )
1920 {
21+ if ( ( _orm as IPostgreSQLProviderOptions ) ? . UseMergeInto == true ) return ToSqlMergeInto ( ) ;
2022 var dbParams = new List < DbParameter > ( ) ;
2123 if ( _sourceSql != null )
2224 {
@@ -87,5 +89,76 @@ string getInsertSql(List<T1> data, bool flagInsert, bool noneParameter)
8789 return sql ;
8890 }
8991 }
92+
93+ public string ToSqlMergeInto ( )
94+ {
95+ var dbParams = new List < DbParameter > ( ) ;
96+ if ( _sourceSql != null ) return getMergeSql ( null ) ;
97+ if ( _source ? . Any ( ) != true ) return null ;
98+
99+ var sqls = new string [ 2 ] ;
100+ var ds = SplitSourceByIdentityValueIsNull ( _source ) ;
101+ if ( ds . Item1 . Any ( ) ) sqls [ 0 ] = string . Join ( "\r \n \r \n ;\r \n \r \n " , ds . Item1 . Select ( a => getMergeSql ( a ) ) ) ;
102+ if ( ds . Item2 . Any ( ) ) sqls [ 1 ] = string . Join ( "\r \n \r \n ;\r \n \r \n " , ds . Item2 . Select ( a => getInsertSql ( a ) ) ) ;
103+ _params = dbParams . ToArray ( ) ;
104+ if ( ds . Item2 . Any ( ) == false ) return sqls [ 0 ] ;
105+ if ( ds . Item1 . Any ( ) == false ) return sqls [ 1 ] ;
106+ return string . Join ( "\r \n \r \n ;\r \n \r \n " , sqls ) ;
107+
108+ string getMergeSql ( List < T1 > data )
109+ {
110+ if ( _tempPrimarys . Any ( ) == false ) throw new Exception ( CoreErrorStrings . InsertOrUpdate_Must_Primary_Key ( _table . CsName ) ) ;
111+
112+ var tempPrimaryIsIdentity = _tempPrimarys . Any ( b => b . Attribute . IsIdentity ) ;
113+ var sb = new StringBuilder ( ) ;
114+ if ( IdentityColumn != null && tempPrimaryIsIdentity ) sb . Append ( "SET IDENTITY_INSERT " ) . Append ( _commonUtils . QuoteSqlName ( TableRuleInvoke ( ) ) ) . Append ( " ON;\r \n " ) ;
115+ sb . Append ( "MERGE INTO " ) . Append ( _commonUtils . QuoteSqlName ( TableRuleInvoke ( ) ) ) . Append ( " t1 \r \n USING (" ) ;
116+ WriteSourceSelectUnionAll ( data , sb , dbParams ) ;
117+ sb . Append ( " ) t2 ON (" ) . Append ( string . Join ( " AND " , _tempPrimarys . Select ( a => $ "t1.{ _commonUtils . QuoteSqlName ( a . Attribute . Name ) } = t2.{ _commonUtils . QuoteSqlName ( a . Attribute . Name ) } ") ) ) . Append ( ") \r \n " ) ;
118+
119+ var cols = _table . Columns . Values . Where ( a => _updateSetDict . ContainsKey ( a . Attribute . Name ) ||
120+ _tempPrimarys . Contains ( a ) == false && a . Attribute . CanUpdate == true && a . Attribute . IsIdentity == false && _updateIgnore . ContainsKey ( a . Attribute . Name ) == false ) ;
121+ if ( _doNothing == false && cols . Any ( ) )
122+ sb . Append ( "WHEN MATCHED THEN \r \n " )
123+ . Append ( " update set " ) . Append ( string . Join ( ", " , cols . Select ( a =>
124+ {
125+ if ( _updateSetDict . TryGetValue ( a . Attribute . Name , out var valsql ) )
126+ return $ "{ _commonUtils . QuoteSqlName ( a . Attribute . Name ) } = { valsql } ";
127+ return a . Attribute . IsVersion && a . Attribute . MapType != typeof ( byte [ ] ) ?
128+ $ "{ _commonUtils . QuoteSqlName ( a . Attribute . Name ) } = t1.{ _commonUtils . QuoteSqlName ( a . Attribute . Name ) } + 1" :
129+ $ "{ _commonUtils . QuoteSqlName ( a . Attribute . Name ) } = t2.{ _commonUtils . QuoteSqlName ( a . Attribute . Name ) } ";
130+ } ) ) ) . Append ( " \r \n " ) ;
131+
132+ cols = _table . Columns . Values . Where ( a => a . Attribute . CanInsert == true ) ;
133+ if ( tempPrimaryIsIdentity == false ) cols = cols . Where ( a => a . Attribute . IsIdentity == false || string . IsNullOrEmpty ( a . DbInsertValue ) == false ) ;
134+ if ( cols . Any ( ) )
135+ sb . Append ( "WHEN NOT MATCHED THEN \r \n " )
136+ . Append ( " insert (" ) . Append ( string . Join ( ", " , cols . Select ( a => _commonUtils . QuoteSqlName ( a . Attribute . Name ) ) ) ) . Append ( ") \r \n " )
137+ . Append ( " values (" ) . Append ( string . Join ( ", " , cols . Select ( a =>
138+ {
139+ //InsertValueSql = "seq.nextval"
140+ if ( tempPrimaryIsIdentity == false && a . Attribute . IsIdentity && string . IsNullOrEmpty ( a . DbInsertValue ) == false ) return a . DbInsertValue ;
141+ return $ "t2.{ _commonUtils . QuoteSqlName ( a . Attribute . Name ) } ";
142+ } ) ) ) . Append ( ");" ) ;
143+
144+ if ( IdentityColumn != null && tempPrimaryIsIdentity ) sb . Append ( ";\r \n SET IDENTITY_INSERT " ) . Append ( _commonUtils . QuoteSqlName ( TableRuleInvoke ( ) ) ) . Append ( " OFF;" ) ;
145+
146+ return sb . ToString ( ) ;
147+ }
148+ string getInsertSql ( List < T1 > data )
149+ {
150+ var insert = _orm . Insert < T1 > ( )
151+ . AsTable ( _tableRule ) . AsType ( _table . Type )
152+ . WithConnection ( _connection )
153+ . WithTransaction ( _transaction )
154+ . NoneParameter ( true ) as Internal . CommonProvider . InsertProvider < T1 > ;
155+ insert . _source = data ;
156+ insert . _table = _table ;
157+ var sql = insert . ToSql ( ) ;
158+ if ( string . IsNullOrEmpty ( sql ) ) return null ;
159+ if ( insert . _params ? . Any ( ) == true ) dbParams . AddRange ( insert . _params ) ;
160+ return sql ;
161+ }
162+ }
90163 }
91164}
0 commit comments