3535 */
3636public class OracleDialect implements JDBCDialect {
3737
38+ private final String SQL_DEFAULT_PLACEHOLDER = " ? " ;
39+ private final String DEAL_CHAR_KEY = "char" ;
40+ private String RPAD_FORMAT = " rpad(?, %d, ' ') " ;
41+
42+ private List <String > fieldList ;
43+ private List <String > fieldTypeList ;
44+ private List <TableInfo .FieldExtraInfo > fieldExtraInfoList ;
45+
3846 @ Override
3947 public boolean canHandle (String url ) {
4048 return url .startsWith ("jdbc:oracle:" );
@@ -48,39 +56,50 @@ public Optional<String> defaultDriverName() {
4856 @ Override
4957 public Optional <String > getUpsertStatement (String schema , String tableName , String [] fieldNames , String [] uniqueKeyFields , boolean allReplace ) {
5058 tableName = DtStringUtil .getTableFullPath (schema , tableName );
51- StringBuilder sb = new StringBuilder ();
52- sb .append ("MERGE INTO " + tableName + " T1 USING "
53- + "(" + buildDualQueryStatement (fieldNames ) + ") T2 ON ("
54- + buildConnectionConditions (uniqueKeyFields ) + ") " );
59+ StringBuilder mergeIntoSql = new StringBuilder ();
60+ mergeIntoSql .append ("MERGE INTO " + tableName + " T1 USING (" )
61+ .append (buildDualQueryStatement (fieldNames ))
62+ .append (") T2 ON (" )
63+ .append (buildConnectionConditions (uniqueKeyFields ) + ") " );
5564
5665 String updateSql = buildUpdateConnection (fieldNames , uniqueKeyFields , allReplace );
5766
5867 if (StringUtils .isNotEmpty (updateSql )) {
59- sb .append (" WHEN MATCHED THEN UPDATE SET " );
60- sb .append (updateSql );
68+ mergeIntoSql .append (" WHEN MATCHED THEN UPDATE SET " );
69+ mergeIntoSql .append (updateSql );
6170 }
6271
63- sb .append (" WHEN NOT MATCHED THEN "
64- + "INSERT (" + Arrays .stream (fieldNames ).map (this ::quoteIdentifier ).collect (Collectors .joining ("," )) + ") VALUES ("
65- + Arrays .stream (fieldNames ).map (col -> "T2." + quoteIdentifier (col )).collect (Collectors .joining ("," )) + ")" );
72+ mergeIntoSql .append (" WHEN NOT MATCHED THEN " )
73+ .append ("INSERT (" )
74+ .append (Arrays .stream (fieldNames ).map (this ::quoteIdentifier ).collect (Collectors .joining ("," )))
75+ .append (") VALUES (" )
76+ .append (Arrays .stream (fieldNames ).map (col -> "T2." + quoteIdentifier (col )).collect (Collectors .joining ("," )))
77+ .append (")" );
6678
67- return Optional .of (sb .toString ());
79+ return Optional .of (mergeIntoSql .toString ());
6880 }
6981
7082 /**
71- * build T1."A"=T2."A" or T1."A"=nvl(T2."A",T1."A")
83+ * build T1."A"=T2."A" or T1."A"=nvl(T2."A",T1."A")
7284 * @param fieldNames
7385 * @param uniqueKeyFields
7486 * @param allReplace
7587 * @return
7688 */
7789 private String buildUpdateConnection (String [] fieldNames , String [] uniqueKeyFields , boolean allReplace ) {
7890 List <String > uniqueKeyList = Arrays .asList (uniqueKeyFields );
79- return Arrays .stream (fieldNames ).filter (col -> !uniqueKeyList .contains (col )).map (col -> {
80- return allReplace ? quoteIdentifier ("T1" ) + "." + quoteIdentifier (col ) + " = " + quoteIdentifier ("T2" ) + "." + quoteIdentifier (col ) :
81- quoteIdentifier ("T1" ) + "." + quoteIdentifier (col ) + " =nvl(" + quoteIdentifier ("T2" ) + "." + quoteIdentifier (col ) + ","
82- + quoteIdentifier ("T1" ) + "." + quoteIdentifier (col ) + ")" ;
83- }).collect (Collectors .joining ("," ));
91+ String updateConnectionSql = Arrays .stream (fieldNames ).
92+ filter (col -> !uniqueKeyList .contains (col ))
93+ .map (col -> buildConnectionByAllReplace (allReplace , col ))
94+ .collect (Collectors .joining ("," ));
95+ return updateConnectionSql ;
96+ }
97+
98+ private String buildConnectionByAllReplace (boolean allReplace , String col ) {
99+ String conncetionSql = allReplace ? quoteIdentifier ("T1" ) + "." + quoteIdentifier (col ) + " = " + quoteIdentifier ("T2" ) + "." + quoteIdentifier (col ) :
100+ quoteIdentifier ("T1" ) + "." + quoteIdentifier (col ) + " =nvl(" + quoteIdentifier ("T2" ) + "." + quoteIdentifier (col ) + ","
101+ + quoteIdentifier ("T1" ) + "." + quoteIdentifier (col ) + ")" ;
102+ return conncetionSql ;
84103 }
85104
86105
@@ -96,8 +115,43 @@ private String buildConnectionConditions(String[] uniqueKeyFields) {
96115 */
97116 public String buildDualQueryStatement (String [] column ) {
98117 StringBuilder sb = new StringBuilder ("SELECT " );
99- String collect = Arrays .stream (column ).map (col -> " ? " + quoteIdentifier (col )).collect (Collectors .joining (", " ));
118+ String collect = Arrays .stream (column )
119+ .map (col -> wrapperPlaceholder (col ) + quoteIdentifier (col ))
120+ .collect (Collectors .joining (", " ));
100121 sb .append (collect ).append (" FROM DUAL" );
101122 return sb .toString ();
102123 }
124+
125+
126+ /**
127+ * char type is wrapped with rpad
128+ * @param fieldName
129+ * @return
130+ */
131+ public String wrapperPlaceholder (String fieldName ) {
132+ int pos = fieldList .indexOf (fieldName );
133+ String type = fieldTypeList .get (pos );
134+
135+ if (StringUtils .contains (type .toLowerCase (), DEAL_CHAR_KEY )) {
136+ TableInfo .FieldExtraInfo fieldExtraInfo = fieldExtraInfoList .get (pos );
137+ int charLength = fieldExtraInfo == null ? 0 : fieldExtraInfo .getLength ();
138+ if (charLength > 0 ) {
139+ return String .format (RPAD_FORMAT , charLength );
140+ }
141+ }
142+ return SQL_DEFAULT_PLACEHOLDER ;
143+ }
144+
145+
146+ public void setFieldList (List <String > fieldList ) {
147+ this .fieldList = fieldList ;
148+ }
149+
150+ public void setFieldTypeList (List <String > fieldTypeList ) {
151+ this .fieldTypeList = fieldTypeList ;
152+ }
153+
154+ public void setFieldExtraInfoList (List <TableInfo .FieldExtraInfo > fieldExtraInfoList ) {
155+ this .fieldExtraInfoList = fieldExtraInfoList ;
156+ }
103157}
0 commit comments