COOPY » Guide  version 0.6.5
/home/paulfitz/cvs/coopy_scm/coopy/src/libcoopy_sqldiff/SqlCompare.cpp
Go to the documentation of this file.
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 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines