COOPY » Guide
version 0.6.5
|
00001 #include <coopy/SqlCompare.h> 00002 00003 using namespace std; 00004 using namespace coopy::store; 00005 using namespace coopy::cmp; 00006 00007 bool SqlCompare::validateSchema() { 00008 vector<string> all_cols1 = local.getColumnNames(); 00009 vector<string> all_cols2 = remote.getColumnNames(); 00010 00011 if (all_cols1!=all_cols2) { 00012 dbg_printf("Columns do not match, cannot make quick comparison\n"); 00013 return false; 00014 } 00015 00016 vector<string> key_cols1 = local.getPrimaryKey(); 00017 vector<string> key_cols2 = remote.getPrimaryKey(); 00018 00019 if (key_cols1!=key_cols2) { 00020 dbg_printf("Keys do not match, cannot make quick comparison\n"); 00021 return false; 00022 } 00023 00024 if (key_cols1.size()==0) { 00025 dbg_printf("No key, cannot make quick comparison\n"); 00026 return false; 00027 } 00028 00029 return true; 00030 } 00031 00032 00033 bool SqlCompare::apply() { 00034 00035 if (!db) return false; 00036 if (!validateSchema()) return false; 00037 00038 dbg_printf("Making quick comparison\n"); 00039 00040 vector<string> key_cols = local.getPrimaryKey(); 00041 vector<string> data_cols = local.getAllButPrimaryKey(); 00042 vector<string> all_cols = local.getColumnNames(); 00043 00044 string sql_table1 = local.getQuotedTableName(); 00045 string sql_table2 = remote.getQuotedTableName(); 00046 string sql_key_cols; 00047 for (int i=0; i<(int)key_cols.size(); i++) { 00048 if (i>0) sql_key_cols += ","; 00049 sql_key_cols += local.getQuotedColumnName(key_cols[i]); 00050 } 00051 string sql_all_cols; 00052 for (int i=0; i<(int)all_cols.size(); i++) { 00053 if (i>0) sql_all_cols += ","; 00054 sql_all_cols += local.getQuotedColumnName(all_cols[i]); 00055 } 00056 string sql_key_match; 00057 for (int i=0; i<(int)key_cols.size(); i++) { 00058 if (i>0) sql_key_match += " AND "; 00059 string n = local.getQuotedColumnName(key_cols[i]); 00060 sql_key_match += sql_table1 + "." + n + " IS " + sql_table2 + "." + n; 00061 } 00062 string sql_data_mismatch; 00063 for (int i=0; i<(int)data_cols.size(); i++) { 00064 if (i>0) sql_data_mismatch += " OR "; 00065 string n = local.getQuotedColumnName(data_cols[i]); 00066 sql_data_mismatch += sql_table1 + "." + n + " IS NOT " + sql_table2 + "." + n; 00067 } 00068 string sql_dbl_cols; 00069 for (int i=0; i<(int)all_cols.size(); i++) { 00070 if (i>0) sql_dbl_cols += ","; 00071 string n = local.getQuotedColumnName(all_cols[i]); 00072 char buf[256]; 00073 sprintf(buf,"__coopy_%d", i); 00074 sql_dbl_cols += sql_table1 + "." + n + " AS " + buf; 00075 sql_dbl_cols += ","; 00076 sql_dbl_cols += sql_table2 + "." + n + " AS " + buf + "b"; 00077 } 00078 00079 string sql_inserts = string("SELECT ") + sql_all_cols + " FROM " + sql_table2 + " WHERE NOT EXISTS (SELECT 1 FROM " + sql_table1 + " WHERE " + sql_key_match + ")"; 00080 00081 00082 string sql_updates = string("SELECT ") + sql_dbl_cols + " FROM " + sql_table1 + " INNER JOIN " + sql_table2 + " ON " + sql_key_match + " WHERE " + sql_data_mismatch; 00083 00084 /* 00085 string sql_concat1 = ""; 00086 string sql_concat2 = ""; 00087 for (int i=0; i<(int)all_cols.size(); i++) { 00088 if (i>0) sql_concat1 += " || "; 00089 if (i>0) sql_concat2 += " || "; 00090 char buf[256]; 00091 sprintf(buf,"__coopy_%d", i); 00092 sql_concat1 += string("quote(") + buf + ")"; 00093 sql_concat2 += string("quote(") + buf + "b)"; 00094 } 00095 string sql_updates2 = string("SELECT ") + sql_dbl_cols + " FROM " + sql_table1 + " INNER JOIN " + sql_table2 + " ON " + sql_key_match + " AND (" + sql_concat1 + ") IS NOT (" + sql_concat2 + ")"; 00096 */ 00097 00098 string sql_deletes = string("SELECT ") + sql_all_cols + " FROM " + sql_table1 + " WHERE NOT EXISTS (SELECT 1 FROM " + sql_table2 + " WHERE " + sql_key_match + ")"; 00099 00100 RowChange::txt2bool indexes; 00101 for (int i=0; i<(int)data_cols.size(); i++) { 00102 indexes[data_cols[i]] = false; 00103 } 00104 for (int i=0; i<(int)key_cols.size(); i++) { 00105 indexes[key_cols[i]] = true; 00106 } 00107 00108 dbg_printf(" SQL to find inserts: %s\n", sql_inserts.c_str()); 00109 00110 if (db->begin(sql_inserts)) { 00111 while (db->read()) { 00112 RowChange rc; 00113 rc.mode = ROW_CHANGE_INSERT; 00114 for (int i=0; i<(int)all_cols.size(); i++) { 00115 SheetCell c = db->get(i); 00116 string key = all_cols[i]; 00117 dbg_printf("[%s] +%s\n", 00118 key.c_str(), 00119 c.toString().c_str()); 00120 rc.val[key] = c; 00121 rc.names.push_back(key); 00122 } 00123 rc.allNames = all_cols; 00124 rc.indexes = indexes; 00125 output.changeRow(rc); 00126 } 00127 db->end(); 00128 } 00129 00130 dbg_printf(" SQL to find updates: %s\n", sql_updates.c_str()); 00131 00132 if (db->begin(sql_updates)) { 00133 // double all_cols 00134 while (db->read()) { 00135 RowChange rc; 00136 rc.mode = ROW_CHANGE_UPDATE; 00137 for (int i=0; i<(int)all_cols.size(); i++) { 00138 SheetCell c1 = db->get(2*i); 00139 SheetCell c2 = db->get(2*i+1); 00140 string key = all_cols[i]; 00141 dbg_printf("[%s] %s => %s\n", 00142 key.c_str(), 00143 c1.toString().c_str(), c2.toString().c_str()); 00144 rc.cond[key] = c1; 00145 if (c1!=c2) { 00146 rc.val[key] = c2; 00147 } 00148 rc.names.push_back(key); 00149 } 00150 rc.allNames = all_cols; 00151 rc.indexes = indexes; 00152 output.changeRow(rc); 00153 } 00154 db->end(); 00155 } 00156 00157 dbg_printf(" SQL to find deletes: %s\n", sql_deletes.c_str()); 00158 00159 if (db->begin(sql_deletes)) { 00160 while (db->read()) { 00161 RowChange rc; 00162 rc.mode = ROW_CHANGE_DELETE; 00163 for (int i=0; i<(int)all_cols.size(); i++) { 00164 SheetCell c = db->get(i); 00165 string key = all_cols[i]; 00166 dbg_printf("[%s] -%s\n", 00167 key.c_str(), 00168 c.toString().c_str()); 00169 rc.cond[key] = c; 00170 rc.names.push_back(key); 00171 } 00172 rc.allNames = all_cols; 00173 rc.indexes = indexes; 00174 output.changeRow(rc); 00175 } 00176 db->end(); 00177 } 00178 00179 return true; 00180 } 00181