public void CheckTable(VxSchema schema, string tabname, string schemastr) { string key = "Table/" + tabname; WVPASSEQ(schema[key].type, "Table"); WVPASSEQ(schema[key].name, tabname); WVPASSEQ(schema[key].text, schemastr); WVPASSEQ(schema[key].encrypted, false); }
// // The ISchema interface // public VxSchemaErrors Put(VxSchema schema, VxSchemaChecksums sums, VxPutOpts opts) { log.print("Put\n"); bool no_retry = (opts & VxPutOpts.NoRetry) != 0; int old_err_count = -1; IEnumerable<string> keys = schema.Keys; VxSchemaErrors errs = new VxSchemaErrors(); // Sometimes we'll get schema elements in the wrong order, so retry // until the number of errors stops decreasing. while (errs.Count != old_err_count) { log.print("Calling Put on {0} entries\n", old_err_count == -1 ? schema.Count : errs.Count); old_err_count = errs.Count; errs.Clear(); List<string> tables = new List<string>(); List<string> nontables = new List<string>(); foreach (string key in keys) { if (schema[key].type == "Table") tables.Add(key); else nontables.Add(key); } errs.Add(PutSchemaTables(tables, schema, sums, opts)); foreach (string key in nontables) { log.print("Calling PutSchema on {0}\n", key); VxSchemaError e = PutSchemaElement(schema[key], opts); if (e != null) errs.Add(key, e); } // If we only had one schema element, retrying it isn't going to // fix anything. We retry to fix ordering problems. if (no_retry || errs.Count == 0 || schema.Count == 1) break; log.print("Got {0} errors, old_errs={1}, retrying\n", errs.Count, old_err_count); keys = errs.Keys.ToList(); } return errs; }
VxSchemaError VxPutSchema(string type, string name, string text, VxPutOpts opts) { VxSchemaElement elem = VxSchemaElement.create(type, name, text, false); VxSchema schema = new VxSchema(elem); VxSchemaErrors errs = VxPutSchema(schema, opts); if (errs == null || errs.Count == 0) return null; WVPASSEQ(errs.Count, 1); // Just return the first error foreach (var p in errs) return p.Value[0]; WVFAIL("Shouldn't happen: couldn't find error to return"); return null; }
// // The ISchema interface // // Note: this implementation ignores the sums. public VxSchemaErrors Put(VxSchema schema, VxSchemaChecksums sums, VxPutOpts opts) { WvDbusMsg call = methodcall("PutSchema", String.Format("{0}i", VxSchema.GetDbusSignature())); WvDbusWriter writer = new WvDbusWriter(); schema.WriteSchema(writer); writer.Write((int)opts); call.Body = writer.ToArray(); WvDbusMsg reply = bus.send_and_wait(call); if (reply.signature == VxSchemaErrors.GetDbusSignature()) return new VxSchemaErrors(reply.iter().pop()); else reply.check(VxSchemaErrors.GetDbusSignature()); return null; }
public VxSchema Get(IEnumerable<string> keys) { VxSchema fullschema = new VxSchema(); VxSchema schema = new VxSchema(); ReadExportedDir(fullschema, null); if (keys == null) return fullschema; // This is a bit slow and stupid - we could just read only the // required keys from disk. But the key-limiting is mainly for the // much slower dbus and database backends, so it's probably not worth // fixing. foreach (string key in keys) schema.Add(key, fullschema[key]); if (schema.Count == 0) schema = fullschema; return schema; }
public void TestTableUpdate(string tabname, string tabschema, VxPutOpts opts, string expected_warning) { VxSchema schema = new VxSchema(); schema.Add("Table", tabname, tabschema, false); VxSchemaErrors errs = dbus.Put(schema, null, opts); log.print("Received errors: {0}\n", errs.ToString()); int errcount = 0; int warncount = 0; foreach (var errlist in errs) foreach (var err in errlist.Value) { log.print("Got error, err.level={0}\n", err.level); if (err.level == WvLog.L.Error) errcount++; else if (err.level == WvLog.L.Warning) warncount++; } WVPASSEQ(errcount, 0); WVPASSEQ(warncount, expected_warning.ne() ? 1 : 0); WVPASSEQ(errs.Count, errcount + warncount); if (expected_warning.ne()) { string key = "Table/" + tabname; WVPASSEQ(errs[key][0].key, key); WVPASSEQ(errs[key][0].msg, expected_warning); WVPASSEQ(errs[key][0].errnum, -1); WVPASSEQ((int)errs[key][0].level, (int)WvLog.L.Warning); WVPASSEQ(errs[key].Count, 1); } schema = dbus.Get("Table/" + tabname); WVPASSEQ(schema.Count, 1); CheckTable(schema, tabname, tabschema); }
// // The ISchemaBackend interface // // Export the current schema to the backing directory, in a format that can // be read back later. public VxSchemaErrors Put(VxSchema schema, VxSchemaChecksums sums, VxPutOpts opts) { bool isbackup = (opts & VxPutOpts.IsBackup) != 0; DirectoryInfo dir = new DirectoryInfo(exportdir); dir.Create(); foreach (var p in schema) { if (!sums.ContainsKey(p.Key)) throw new ArgumentException("Missing checksum for " + p.Key); VxSchemaElement elem = p.Value; if (elem.text == null || elem.text == "") DropSchema(new string[] {elem.key}); else ExportToDisk(p.Value, sums[p.Key], isbackup); } // Writing schemas to disk doesn't give us any per-element errors. return new VxSchemaErrors(); }
public string Csv2Inserts(string tablename, string csvtext) { StringBuilder result = new StringBuilder(); WvCsv csvhandler = new WvCsv(csvtext); ArrayList asarray, columns; string sql; string prefix = ""; bool has_ident = false; var tab_names = new List<string>(); var coltypes = new Dictionary<string,string>(); VxSchema schema = new VxSchema(); string ident_seed, ident_incr, coltype; tab_names.Add(tablename); RetrieveTableSchema(schema, tab_names); columns = csvhandler.GetLine(); //columns' names string[] columns_array = (string[])columns.ToArray( Type.GetType("System.String")); foreach (KeyValuePair<string,VxSchemaElement> p in schema) { if (p.Value is VxSchemaTable) { foreach (VxSchemaTableElement te in ((VxSchemaTable)p.Value)) { if (te.elemtype == "column") { if (columns_array.Contains(te.GetParam("name"))) { coltypes.Add(te.GetParam("name"),te.GetParam("type")); ident_seed = te.GetParam("identity_seed"); ident_incr = te.GetParam("identity_incr"); if (ident_seed.ne() && ident_incr.ne()) has_ident = true; } } } } } if (has_ident) result.Append("SET IDENTITY_INSERT [" + tablename + "] ON;\n"); prefix = "INSERT INTO " + tablename + " ([" + String.Join("],[",columns_array)+"]) VALUES ("; if (!csvhandler.hasMore()) return ""; while (csvhandler.hasMore()) { sql = ""; asarray = csvhandler.GetLine(); if (asarray.Count < columns_array.Length) return ""; for (int i=0;i<asarray.Count;i++) { sql += (i==0 ? prefix : ","); coltype = ""; if (coltypes[columns_array[i]] != null) coltype = coltypes[columns_array[i]]; if (asarray[i]!=null) if ((coltype == "varchar") || (coltype == "datetime") || (coltype == "char") || (coltype == "image") ) if (coltype == "image") sql += "0x"+bin2hex(System.Convert.FromBase64String( asarray[i].ToString() .Replace("\n",""))); else sql += "'" + asarray[i].ToString().Replace("'", "''") + "'"; else sql += asarray[i].ToString(); else sql += "NULL"; } result.Append(sql + ");\n"); } if (has_ident) result.Append("SET IDENTITY_INSERT [" + tablename + "] OFF;\n"); return result.ToString(); }
public VxSchema Get(IEnumerable<string> keys) { log.print("Get\n"); List<string> all_names = new List<string>(); List<string> proc_names = new List<string>(); List<string> xml_names = new List<string>(); List<string> tab_names = new List<string>(); // FIXME: This variable is unused. Get rid of it, and perhaps throw // an error if we see an index show up. List<string> idx_names = new List<string>(); foreach (string key in keys) { string fullname = EscapeSchemaElementName(key); log.print("CallGetSchema: Read name " + fullname); all_names.Add(fullname); string[] parts = fullname.Split(new char[] {'/'}, 2); if (parts.Length == 2) { string type = parts[0]; string name = parts[1]; if (type == "Table") tab_names.Add(name); else if (type == "Index") idx_names.Add(name); else if (type == "XMLSchema") xml_names.Add(name); else proc_names.Add(name); } else { // No type given, just try them all proc_names.Add(fullname); xml_names.Add(fullname); tab_names.Add(fullname); idx_names.Add(fullname); } } VxSchema schema = new VxSchema(); if (proc_names.Count > 0 || all_names.Count == 0) { foreach (string type in ProcedureTypes) { RetrieveProcSchemas(schema, proc_names, type, 0); RetrieveProcSchemas(schema, proc_names, type, 1); } } if (xml_names.Count > 0 || all_names.Count == 0) RetrieveXmlSchemas(schema, xml_names); if (tab_names.Count > 0 || all_names.Count == 0) RetrieveTableSchema(schema, tab_names); return schema; }
void RetrieveTableSchema(VxSchema schema, List<string> names) { string tablenames = (names.Count > 0 ? "and t.name in ('" + names.join("','") + "')" : ""); string query = @"select t.name tabname, c.name colname, typ.name typename, c.length len, c.xprec xprec, c.xscale xscale, def.text defval, c.isnullable nullable, columnproperty(t.id, c.name, 'IsIdentity') isident, ident_seed(t.name) ident_seed, ident_incr(t.name) ident_incr from sysobjects t join syscolumns c on t.id = c.id join systypes typ on c.xtype = typ.xtype and c.xusertype = typ.xusertype left join syscomments def on def.id = c.cdefault where t.xtype = 'U' and typ.name <> 'sysname' " + tablenames + @" order by tabname, c.colorder, typ.status"; VxSchemaTable table = null; foreach (WvSqlRow row in DbiSelect(query)) { string tabname = row[0]; string colname = row[1]; string typename = row[2]; short len = row[3]; byte xprec = row[4]; byte xscale = row[5]; string defval = row[6].IsNull ? (string)null : row[6]; int isnullable = row[7]; int isident = row[8]; string ident_seed = row[9]; string ident_incr = row[10]; if (table != null && tabname != table.name) { schema.Add(table.key, table); table = null; } if (isident == 0) ident_seed = ident_incr = null; string lenstr = ""; string precstr = null; string scalestr = null; if (typename.EndsWith("nvarchar") || typename.EndsWith("nchar")) { if (len == -1) lenstr = "max"; else { len /= 2; lenstr = len.ToString(); } } else if (typename.EndsWith("char") || typename.EndsWith("binary")) { lenstr = (len == -1 ? "max" : len.ToString()); } else if (typename.EndsWith("decimal") || typename.EndsWith("numeric") || typename.EndsWith("real")) { precstr = xprec.ToString(); scalestr = xscale.ToString(); } if (defval.ne()) { // MSSQL returns default values wrapped in an irritatingly // variable number of ()s defval = StripMatchingParens(defval); } if (table == null) table = new VxSchemaTable(tabname); table.AddColumn(colname, typename, isnullable, lenstr, defval, precstr, scalestr, isident, ident_seed, ident_incr); } if (table != null) { log.print("Adding table {0}\n", table.key); schema.Add(table.key, table); } AddIndexesToTables(schema, names); }
void RetrieveXmlSchemas(VxSchema schema, List<string> names) { bool do_again = true; for (int count = 0; do_again; count++) { do_again = false; string query = XmlSchemasQuery(count, names); foreach (WvSqlRow row in DbiSelect(query)) { string owner = row[0]; string name = row[1]; string contents = row[2]; if (contents.e()) continue; do_again = true; if (count == 0) schema.Add("XMLSchema", name, String.Format( "\nCREATE XML SCHEMA COLLECTION [{0}].[{1}] AS '", owner, name), false); schema.Add("XMLSchema", name, contents, false); } } // Close the quotes on all the XMLSchemas foreach (KeyValuePair<string, VxSchemaElement> p in schema) { if (p.Value.type == "XMLSchema") p.Value.text += "'\n"; } }
// Adds the indexes for each table in "names" to the table elements. void AddIndexesToTables(VxSchema schema, List<string> names) { string tabnames = (names.Count > 0) ? "and (object_name(i.object_id) in ('" + names.join("','") + "'))" : ""; string query = @" select convert(varchar(128), object_name(i.object_id)) tabname, convert(varchar(128), i.name) idxname, convert(int, i.type) idxtype, convert(int, i.is_unique) idxunique, convert(int, i.is_primary_key) idxprimary, convert(varchar(128), c.name) colname, convert(int, ic.index_column_id) colid, convert(int, ic.is_descending_key) coldesc from sys.indexes i join sys.index_columns ic on ic.object_id = i.object_id and ic.index_id = i.index_id join sys.columns c on c.object_id = i.object_id and c.column_id = ic.column_id where object_name(i.object_id) not like 'sys%' and object_name(i.object_id) not like 'queue_%' " + tabnames + @" order by i.name, i.object_id, ic.index_column_id"; log.print("Adding index information for {0}\n", names.Count > 0 ? names.join(",") : "all tables"); WvSqlRow[] data = DbiSelect(query).ToArray(); int old_colid = 0; List<string> cols = new List<string>(); // FIXME: use foreach for (int ii = 0; ii < data.Length; ii++) { WvSqlRow row = data[ii]; string tabname = row[0]; string idxname = row[1]; int idxtype = row[2]; int idxunique = row[3]; int idxprimary = row[4]; string colname = row[5]; int colid = row[6]; int coldesc = row[7]; // Check that we're getting the rows in order. wv.assert(colid == old_colid + 1 || colid == 1); old_colid = colid; cols.Add(coldesc == 0 ? colname : colname + " DESC"); WvSqlRow nextrow = ((ii+1) < data.Length) ? data[ii+1] : null; string next_tabname = (nextrow != null) ? (string)nextrow[0] : null; string next_idxname = (nextrow != null) ? (string)nextrow[1] : null; // If we've finished reading the columns for this index, add the // index to the schema. Note: depends on the statement's ORDER BY. if (tabname != next_tabname || idxname != next_idxname) { VxSchemaTable table; string tabkey = "Table/" + tabname; if (schema.ContainsKey(tabkey)) { table = (VxSchemaTable)schema[tabkey]; log.print("Found table, idxtype={0}, cols={1}\n", idxtype, cols.join(",")); if (idxprimary != 0) table.AddPrimaryKey(idxname, idxtype, cols.ToArray()); else table.AddIndex(idxname, idxunique, idxtype, cols.ToArray()); } else throw new ArgumentException( "Schema is missing table '" + tabkey + "'!"); cols.Clear(); } } return; }
public void TestApplySchemaDiff(ISchemaBackend backend) { log.print("In TestApplySchemaDiff({0})\n", backend.GetType().ToString()); SchemaCreator sc = new SchemaCreator(this); sc.Create(); string msg2 = "Hello, world, this used to be Func1!"; string func1q2 = "create procedure Func1 as select '" + msg2 + "'\n"; VxSchema origschema = dbus.Get(); VxSchemaChecksums origsums = dbus.GetChecksums(); VxSchema newschema = new VxSchema(origschema); VxSchemaChecksums newsums = new VxSchemaChecksums(origsums); // Don't bother putting the data again if we're talking to dbus: // we already snuck it in the back door. if (backend != dbus) backend.Put(origschema, origsums, VxPutOpts.None); VxSchemaChecksums diffsums = new VxSchemaChecksums(newsums); // Make some changes to create an interesting diff. // Change the text and sums of Func1, schedule TestSchema for // deletion, and act like Tab2 is new. newschema["Procedure/Func1"].text = func1q2; newsums.AddSum("Procedure/Func1", 123); newsums.Remove("XMLSchema/TestSchema"); origsums.Remove("Table/Tab2"); WVASSERT(VxExec("drop table Tab2")); VxSchemaDiff diff = new VxSchemaDiff(origsums, newsums); using (IEnumerator<KeyValuePair<string,VxDiffType>> iter = diff.GetEnumerator()) { WVPASS(iter.MoveNext()); WVPASSEQ(iter.Current.Key, "XMLSchema/TestSchema"); WVPASSEQ((char)iter.Current.Value, (char)VxDiffType.Remove); WVPASS(iter.MoveNext()); WVPASSEQ(iter.Current.Key, "Table/Tab2"); WVPASSEQ((char)iter.Current.Value, (char)VxDiffType.Add); WVPASS(iter.MoveNext()); WVPASSEQ(iter.Current.Key, "Procedure/Func1"); WVPASSEQ((char)iter.Current.Value, (char)VxDiffType.Change); WVFAIL(iter.MoveNext()); } VxSchema diffschema = newschema.GetDiffElements(diff); WVPASSEQ(diffschema["XMLSchema/TestSchema"].type, "XMLSchema"); WVPASSEQ(diffschema["XMLSchema/TestSchema"].name, "TestSchema"); WVPASSEQ(diffschema["XMLSchema/TestSchema"].text, ""); WVPASSEQ(diffschema["Table/Tab2"].type, "Table"); WVPASSEQ(diffschema["Table/Tab2"].name, "Tab2"); WVPASSEQ(diffschema["Table/Tab2"].text, sc.tab2sch); WVPASSEQ(diffschema["Procedure/Func1"].type, "Procedure"); WVPASSEQ(diffschema["Procedure/Func1"].name, "Func1"); WVPASSEQ(diffschema["Procedure/Func1"].text, func1q2); VxSchemaErrors errs = backend.Put(diffschema, diffsums, VxPutOpts.None); WVPASSEQ(errs.Count, 0); VxSchema updated = backend.Get(null); WVASSERT(!updated.ContainsKey("XMLSchema/TestSchema")); WVPASSEQ(updated["Table/Tab1"].text, newschema["Table/Tab1"].text); WVPASSEQ(updated["Table/Tab2"].text, newschema["Table/Tab2"].text); WVPASSEQ(updated["Procedure/Func1"].text, newschema["Procedure/Func1"].text); sc.Cleanup(); }
public void TestPutSchemaRetry() { try { VxExec("drop view View1"); } catch { } try { VxExec("drop view View2"); } catch { } try { VxExec("drop view View3"); } catch { } try { VxExec("drop view View4"); } catch { } // Create the views in the wrong order, so it'll take a few tries // to get them all working. The server seems to sort them // alphabetically when it runs them, though this isn't a guarantee. string view1q = "create view View1 as select * from View2"; string view2q = "create view View2 as select * from View3"; string view3q = "create view View3 as select * from View4"; string view4q = "create view View4(viewcol1) as select 42"; VxSchema schema = new VxSchema(); schema.Add("View", "View1", view1q, false); schema.Add("View", "View2", view2q, false); schema.Add("View", "View3", view3q, false); schema.Add("View", "View4", view4q, false); VxSchemaErrors errs = VxPutSchema(schema, VxPutOpts.NoRetry); WVPASSEQ(errs.Count, 3); WVPASSEQ(errs["View/View1"][0].key, "View/View1"); WVPASSEQ(errs["View/View2"][0].key, "View/View2"); WVPASSEQ(errs["View/View3"][0].key, "View/View3"); WVPASSEQ(errs["View/View1"][0].msg, "Invalid object name 'View2'."); WVPASSEQ(errs["View/View2"][0].msg, "Invalid object name 'View3'."); WVPASSEQ(errs["View/View3"][0].msg, "Invalid object name 'View4'."); WVPASSEQ(errs["View/View1"][0].errnum, 208); WVPASSEQ(errs["View/View2"][0].errnum, 208); WVPASSEQ(errs["View/View3"][0].errnum, 208); WVPASSEQ(errs["View/View1"].Count, 1); WVPASSEQ(errs["View/View2"].Count, 1); WVPASSEQ(errs["View/View3"].Count, 1); try { VxExec("drop view View4"); } catch { } errs = VxPutSchema(schema, VxPutOpts.None); WVPASSEQ(errs.Count, 0); object result; WVASSERT(VxScalar("select viewcol1 from View1;", out result)); WVPASSEQ((int)result, 42); try { VxExec("drop view View1"); } catch { } try { VxExec("drop view View2"); } catch { } try { VxExec("drop view View3"); } catch { } try { VxExec("drop view View4"); } catch { } }
public void TestSubmoduleExceptions() { VxSchema schema1 = new VxSchema(); VxSchemaChecksums sums1 = new VxSchemaChecksums(); VxSchema schema2 = new VxSchema(); VxSchemaChecksums sums2 = new VxSchemaChecksums(); schema1.Add("Procedure", "Func1", "Random contents", false); sums1.AddSum("Procedure/Func1", 1); schema2.Add("Procedure", "Func1", "Random contents 2", false); sums2.AddSum("Procedure/Func1", 2); string tmpdir = GetTempDir(); try { Directory.CreateDirectory(tmpdir); VxDiskSchema disk = new VxDiskSchema(tmpdir); disk.Put(schema2, sums2, VxPutOpts.None); try { WVEXCEPT(VxDiskSchema.AddFromDir(tmpdir, schema1, sums1)) } catch (System.ArgumentException e) { WVPASSEQ(e.Message, "Conflicting schema key: Procedure/Func1"); } } finally { Directory.Delete(tmpdir, true); } WVPASS(!Directory.Exists(tmpdir)); }
public void TestDropSchemaFromDisk() { string tmpdir = GetTempDir(); try { Directory.CreateDirectory(tmpdir); VxDiskSchema backend = new VxDiskSchema(tmpdir); VxSchema schema = new VxSchema(); schema.Add("Table", "Foo", "column: name=foo,type=int\n", false); schema.Add("Table", "Bar", "column: name=bar,type=int\n", false); schema.Add("Procedure", "Func1", "Func1 contents", false); schema.Add("ScalarFunction", "Func2", "Func2 contents", false); VxSchemaChecksums sums = new VxSchemaChecksums(); sums.AddSum("Table/Foo", 1); sums.AddSum("Table/Bar", 2); sums.AddSum("Procedure/Func1", 3); sums.AddSum("ScalarFunction/Func2", 5); backend.Put(schema, sums, VxPutOpts.None); WVPASS(File.Exists(Path.Combine(tmpdir, "Table/Foo"))); WVPASS(File.Exists(Path.Combine(tmpdir, "Table/Bar"))); WVPASS(File.Exists(Path.Combine(tmpdir, "Procedure/Func1"))); WVPASS(File.Exists(Path.Combine(tmpdir, "ScalarFunction/Func2"))); VxSchema newschema = backend.Get(null); VxSchemaChecksums newsums = backend.GetChecksums(); WVPASSEQ(newschema.Count, schema.Count); WVPASSEQ(newsums.Count, sums.Count); WVPASS(newschema.ContainsKey("Table/Foo")); WVPASS(newschema.ContainsKey("Table/Bar")); WVPASS(newschema.ContainsKey("Procedure/Func1")); WVPASS(newschema.ContainsKey("ScalarFunction/Func2")); string[] todrop = { "Table/Foo" }; backend.DropSchema(todrop); WVPASS(!File.Exists(Path.Combine(tmpdir, "Table/Foo"))) WVPASS(File.Exists(Path.Combine(tmpdir, "Table/Bar"))) WVPASS(File.Exists(Path.Combine(tmpdir, "Procedure/Func1"))) WVPASS(File.Exists(Path.Combine(tmpdir, "ScalarFunction/Func2"))) newschema = backend.Get(null); newsums = backend.GetChecksums(); WVPASSEQ(newschema.Count, 3); WVPASSEQ(newsums.Count, 3); WVPASS(!newschema.ContainsKey("Table/Foo")); WVPASS(newschema.ContainsKey("Table/Bar")); WVPASS(newschema.ContainsKey("Procedure/Func1")); WVPASS(newschema.ContainsKey("ScalarFunction/Func2")); todrop = new string[] { "Procedure/Func1", "ScalarFunction/Func2" }; backend.DropSchema(todrop); WVPASS(!File.Exists(Path.Combine(tmpdir, "Table/Foo"))) WVPASS(File.Exists(Path.Combine(tmpdir, "Table/Bar"))) WVPASS(!File.Exists(Path.Combine(tmpdir, "Procedure/Func1"))) WVPASS(!File.Exists(Path.Combine(tmpdir, "ScalarFunction/Func2"))) newschema = backend.Get(null); newsums = backend.GetChecksums(); WVPASSEQ(newschema.Count, 1); WVPASSEQ(newsums.Count, 1); WVPASS(!newschema.ContainsKey("Table/Foo")); WVPASS(newschema.ContainsKey("Table/Bar")); WVPASS(!newschema.ContainsKey("Procedure/Func1")); WVPASS(!newschema.ContainsKey("ScalarFunction/Func2")); } finally { Directory.Delete(tmpdir, true); } WVPASS(!Directory.Exists(tmpdir)); }
public void TestSubmoduleSupport() { VxSchema schema1 = new VxSchema(); VxSchemaChecksums sums1 = new VxSchemaChecksums(); VxSchema schema2 = new VxSchema(); VxSchemaChecksums sums2 = new VxSchemaChecksums(); schema1.Add("Table", "Tab1", "column: name=random\n", false); sums1.AddSum("Table/Tab1", 1); schema2.Add("Table", "Tab2", "column: name=ignored\n", false); sums2.AddSum("Table/Tab2", 2); string tmpdir = GetTempDir(); try { Directory.CreateDirectory(tmpdir); VxDiskSchema disk = new VxDiskSchema(tmpdir); disk.Put(schema2, sums2, VxPutOpts.None); VxDiskSchema.AddFromDir(tmpdir, schema1, sums1); WVPASSEQ(sums1["Table/Tab1"].GetSumString(), "0x00000001"); WVPASSEQ(schema1["Table/Tab1"].name, "Tab1"); WVPASSEQ(schema1["Table/Tab1"].type, "Table"); WVPASSEQ(schema1["Table/Tab1"].text, "column: name=random\n"); WVPASSEQ(schema1["Table/Tab1"].encrypted, false); WVPASSEQ(sums1["Table/Tab2"].GetSumString(), "0x00000002"); WVPASSEQ(schema1["Table/Tab2"].name, "Tab2"); WVPASSEQ(schema1["Table/Tab2"].type, "Table"); WVPASSEQ(schema1["Table/Tab2"].text, "column: name=ignored\n"); WVPASSEQ(schema1["Table/Tab2"].encrypted, false); } finally { Directory.Delete(tmpdir, true); } WVPASS(!Directory.Exists(tmpdir)); }
private void VerifyExportedSchema(string exportdir, VxSchema schema, VxSchemaChecksums sums, SchemaCreator sc, int backupnum, Dictionary<string, int> base_filecounts) { int filemultiplier = backupnum + 1; string suffix = backupnum == 0 ? "" : "-" + backupnum; string procdir = Path.Combine(exportdir, "Procedure"); string scalardir = Path.Combine(exportdir, "ScalarFunction"); string idxdir = Path.Combine(exportdir, "Index"); string tabdir = Path.Combine(exportdir, "Table"); string tabfuncdir = Path.Combine(exportdir, "TableFunction"); string triggerdir = Path.Combine(exportdir, "Trigger"); string viewdir = Path.Combine(exportdir, "View"); string xmldir = Path.Combine(exportdir, "XMLSchema"); WVPASSEQ(Directory.GetFiles(exportdir).Length, 0); WVPASS(Directory.Exists(procdir)); WVPASS(Directory.Exists(scalardir)); // We no longer store indexes in a separate directory; make sure // that directory doesn't get created. WVPASS(!Directory.Exists(idxdir)); WVPASS(Directory.Exists(tabdir)); WVPASS(Directory.Exists(tabfuncdir)); WVPASS(Directory.Exists(triggerdir)); WVPASS(Directory.Exists(viewdir)); WVPASS(Directory.Exists(xmldir)); WVPASSEQ(Directory.GetDirectories(exportdir).Length, 7); Dictionary<string, int> filecounts = GetFileCounts(exportdir); // Procedures WVPASSEQ(Directory.GetDirectories(procdir).Length, 0); WVPASSEQ(filecounts["Procedure"], (1 + base_filecounts["Procedure"]) * filemultiplier); string func1file = Path.Combine(procdir, "Func1" + suffix); CheckExportedFileContents(func1file, "!!SCHEMAMATIC 2ae46ac0748aede839fb9cd167ea1180 0xd983a305 ", sc.func1q); // Scalar functions WVPASSEQ(Directory.GetDirectories(scalardir).Length, 0); WVPASSEQ(filecounts["ScalarFunction"], (1 + base_filecounts["ScalarFunction"]) * filemultiplier); string func2file = Path.Combine(scalardir, "Func2" + suffix); CheckExportedFileContents(func2file, "!!SCHEMAMATIC c7c257ba4f7817e4e460a3cef0c78985 0xd6fe554f ", sc.func2q); // Table-valued functions WVPASSEQ(Directory.GetDirectories(tabfuncdir).Length, 0); WVPASSEQ(filecounts["TableFunction"], (1 + base_filecounts["TableFunction"]) * filemultiplier); string tabfunc1file = Path.Combine(tabfuncdir, "TabFunc1" + suffix); CheckExportedFileContents(tabfunc1file, "!!SCHEMAMATIC 1d3f1392a80e44876254209feebe7860 0x4b96fbe4 ", sc.tabfuncq); // Tables WVPASSEQ(Directory.GetDirectories(tabdir).Length, 0); WVPASSEQ(filecounts["Table"], (2 + base_filecounts["Table"]) * filemultiplier); string tab1file = Path.Combine(tabdir, "Tab1" + suffix); string tab2file = Path.Combine(tabdir, "Tab2" + suffix); WVPASS(File.Exists(tab1file)); CheckExportedFileContents(tab1file, "!!SCHEMAMATIC 72c64bda7c48a954e63f359ff1fa4e79 " + sums["Table/Tab1"].GetSumString() + " ", sc.tab1sch); WVPASS(File.Exists(tab2file)); CheckExportedFileContents(tab2file, "!!SCHEMAMATIC 69b15b6da6961a0f006fa55106cb243b " + sums["Table/Tab2"].GetSumString() + " ", sc.tab2sch); // Triggers WVPASSEQ(Directory.GetDirectories(triggerdir).Length, 0); WVPASSEQ(filecounts["Trigger"], (1 + base_filecounts["Trigger"]) * filemultiplier); string triggerfile = Path.Combine(triggerdir, "Trigger1" + suffix); CheckExportedFileContents(triggerfile, "!!SCHEMAMATIC eb7556c49140340ff74f06660a55457b 0x5a93c375 ", sc.triggerq); // Views WVPASSEQ(Directory.GetDirectories(viewdir).Length, 0); WVPASSEQ(filecounts["View"], (1 + base_filecounts["View"]) * filemultiplier); string viewfile = Path.Combine(viewdir, "View1" + suffix); CheckExportedFileContents(viewfile, "!!SCHEMAMATIC b43a8c712d3a274a6842fc2413516665 0xe0af9ccd ", sc.viewq); // XML Schemas WVPASSEQ(Directory.GetDirectories(xmldir).Length, 0); WVPASSEQ(filecounts["XMLSchema"], (1 + base_filecounts["XMLSchema"]) * filemultiplier); string testschemafile = Path.Combine(xmldir, "TestSchema" + suffix); WVPASS(File.Exists(testschemafile)); CheckExportedFileContents(testschemafile, "!!SCHEMAMATIC f45c4ea54c268c91f41c7054c8f20bc9 0xf4b2c764 ", sc.xmlq); }
public void TestExportEmptySchema() { string tmpdir = GetTempDir(); try { Directory.CreateDirectory(tmpdir); VxSchema schema = new VxSchema(); VxSchemaChecksums sums = new VxSchemaChecksums(); // Check that exporting an empty schema doesn't touch anything. VxDiskSchema backend = new VxDiskSchema(tmpdir); backend.Put(schema, sums, VxPutOpts.None); WVPASSEQ(Directory.GetDirectories(tmpdir).Length, 0); WVPASSEQ(Directory.GetFiles(tmpdir).Length, 0); } finally { Directory.Delete(tmpdir); } WVASSERT(!Directory.Exists(tmpdir)); }
public void TestQuotedIdentifiers() { try { VxExec("drop procedure Proc1"); } catch { } string quote_proc = "create procedure Proc1 as " + "select \"I'm a double-quoted string!\"\n"; VxSchema schema = new VxSchema(); schema.Add("Procedure", "Proc1", quote_proc, false); VxSchemaErrors errs = VxPutSchema(schema, VxPutOpts.None); WVPASSEQ(errs.Count, 0); try { VxExec("drop procedure Proc1"); } catch { } }
private VxSchemaErrors PutSchemaTables(List<string> tables, VxSchema newschema, VxSchemaChecksums newsums, VxPutOpts opts) { VxSchema curschema = Get(tables); VxSchemaErrors errs = new VxSchemaErrors(); foreach (string key in tables) { log.print("Putting table {0}\n", key); string curtype = curschema.ContainsKey(key) ? curschema[key].type : "Table"; string newtype = newschema.ContainsKey(key) ? newschema[key].type : "Table"; if (newtype != "Table" || curtype != "Table") throw new ArgumentException("PutSchemaTables called on " + "non-table element '" + key + "'."); // Check for the easy cases, an all-new table or table deletion if (!curschema.ContainsKey(key)) { // New table, let PutSchemaElement handle it like before. VxSchemaError e = PutSchemaElement(newschema[key], opts); if (e != null) errs.Add(key, e); continue; } if (!newschema.ContainsKey(key)) { // Deleted table, let DropSchemaElement deal with it. VxSchemaError e = DropSchemaElement(key); if (e != null) errs.Add(key, e); continue; } // An existing table has been modified. VxSchemaTable newtable; VxSchemaTable curtable; if (newschema[key] is VxSchemaTable) newtable = (VxSchemaTable)newschema[key]; else newtable = new VxSchemaTable(newschema[key]); if (curschema[key] is VxSchemaTable) curtable = (VxSchemaTable)curschema[key]; else curtable = new VxSchemaTable(curschema[key]); VxSchemaErrors put_table_errs = null; put_table_errs = PutSchemaTable(curtable, newtable, opts); // If anything goes wrong updating a table in destructive mode, // drop and re-add it. We want to be sure the schema is updated // exactly. bool destructive = (opts & VxPutOpts.Destructive) != 0; if (destructive && put_table_errs.Count > 0) { put_table_errs = null; log.print("Couldn't cleanly modify table '{0}'. Dropping " + "and re-adding it.\n", newtable.name); VxSchemaError e = PutSchemaElement(newschema[key], opts); if (e != null) errs.Add(key, e); } if (put_table_errs != null && put_table_errs.Count > 0) errs.Add(put_table_errs); } return errs; }
// Adds the contents of extradir to the provided schema and sums. // Throws an ArgumentException if the directory contains an entry that // already exists in schema or sums. public static void AddFromDir(string extradir, VxSchema schema, VxSchemaChecksums sums) { VxDiskSchema disk = new VxDiskSchema(extradir); disk.ReadExportedDir(schema, sums); }
static void CallPutSchema(WvDbus conn, WvDbusMsg call, out WvDbusMsg reply) { if (call.signature != String.Format("{0}i", VxSchema.GetDbusSignature())) { reply = CreateUnknownMethodReply(call, "PutSchema"); return; } string clientid = GetClientId(call); if (clientid == null) { reply = call.err_reply("org.freedesktop.DBus.Error.Failed", "Could not identify the client"); return; } var it = call.iter(); VxSchema schema = new VxSchema(it.pop()); int opts = it.pop(); VxSchemaErrors errs; using (var dbi = VxSqlPool.create(clientid)) { VxDbSchema backend = new VxDbSchema(dbi); errs = backend.Put(schema, null, (VxPutOpts)opts); } WvDbusWriter writer = new WvDbusWriter(); VxSchemaErrors.WriteErrors(writer, errs); reply = call.reply(VxSchemaErrors.GetDbusSignature()).write(writer); if (errs != null && errs.Count > 0) { reply.type = Wv.Dbus.MType.Error; reply.err = "org.freedesktop.DBus.Error.Failed"; } }
public void TestPutSchemaErrors() { //WvLog.maxlevel = WvLog.L.Debug4; WVPASS("hello"); SchemaCreator sc = new SchemaCreator(this); sc.Create(); // Check that putting the same elements doesn't cause errors VxPutOpts no_opts = VxPutOpts.None; WVPASS("getting"); VxSchema schema = dbus.Get(); WVPASS("putting"); VxSchemaErrors errs = VxPutSchema(schema, no_opts); WVPASSEQ(errs.Count, 0); // Check that invalid SQL causes errors. schema = new VxSchema(); schema.Add("ScalarFunction", "ErrSF", "I am not valid SQL", false); schema.Add("TableFunction", "ErrTF", "I'm not valid SQL either", false); errs = VxPutSchema(schema, no_opts); log.print("Results: \n{0}", errs.ToString()); log.print("Done results.\n"); WVPASSEQ(errs.Count, 2); WVPASSEQ(errs["ScalarFunction/ErrSF"][0].key, "ScalarFunction/ErrSF"); WVPASSEQ(errs["ScalarFunction/ErrSF"][0].msg, "Incorrect syntax near the keyword 'not'."); WVPASSEQ(errs["ScalarFunction/ErrSF"][0].errnum, 156); WVPASSEQ(errs["ScalarFunction/ErrSF"].Count, 1); WVPASSEQ(errs["TableFunction/ErrTF"][0].key, "TableFunction/ErrTF"); WVPASSEQ(errs["TableFunction/ErrTF"][0].msg, "Unclosed quotation mark after the character string 'm not valid SQL either'."); WVPASSEQ(errs["TableFunction/ErrTF"][0].errnum, 105); WVPASSEQ(errs["TableFunction/ErrTF"].Count, 1); sc.Cleanup(); }
// Retrieves both the schema and its checksums from exportdir, and puts // them into the parameters. void ReadExportedDir(VxSchema schema, VxSchemaChecksums sums) { DirectoryInfo exportdirinfo = new DirectoryInfo(exportdir); if (exportdirinfo.Exists) { // Read all files that match */* and Index/*/*. foreach (DirectoryInfo dir1 in exportdirinfo.GetDirectories()) { if (dir1.Name == "DATA") continue; string type = dir1.Name; foreach (DirectoryInfo dir2 in dir1.GetDirectories()) { if (dir2.Name == "DATA" || dir1.Name != "Index") continue; // This is the Index/*/* part foreach (FileInfo file in dir2.GetFiles()) { if (!IsFileNameUseful(file.Name)) continue; string name = wv.PathCombine(dir2.Name, file.Name); AddFromFile(file.FullName, type, name, schema, sums); } } // This is the */* part foreach (FileInfo file in dir1.GetFiles()) { if (!IsFileNameUseful(file.Name)) continue; AddFromFile(file.FullName, type, file.Name, schema, sums); } } } }
void RetrieveProcSchemas(VxSchema schema, List<string> names, string type, int encrypted) { string query = RetrieveProcSchemasQuery(type, encrypted, false, names); log.print(WvLog.L.Debug3, "Query={0}\n", query); foreach (WvSqlRow row in DbiSelect(query)) { string name = row[0]; //short colid = row[1]; string text; // FIXME: Retrieving encrypted data is kind of broken anyway. if (encrypted > 0) text = row[2];//.ToHex(); else text = row[2]; // Skip dt_* functions and sys_* views if (name.StartsWith("dt_") || name.StartsWith("sys_")) continue; // Fix characters not allowed in filenames name.Replace('/', '!'); name.Replace('\n', '!'); schema.Add(type, name, text, encrypted > 0); } }
// Helper method to load a given on-disk element's schema and checksums // into the container objects. // Throws an ArgumentException if the schema or sums already contains the // given key. static void AddFromFile(string path, string type, string name, VxSchema schema, VxSchemaChecksums sums) { string key = wv.fmt("{0}/{1}", type, name); // schema/sums.Add would throw an exception in this situation anyway, // but it's nice to provide a more helpful error message. if (schema != null && schema.ContainsKey(key)) throw new ArgumentException("Conflicting schema key: " + key); if (sums != null && sums.ContainsKey(key)) throw new ArgumentException("Conflicting sums key: " + key); VxSchemaChecksum sum; VxSchemaElement elem; ReadSchemaFile(path, type, name, out elem, out sum); if (schema != null && elem != null) schema.Add(key, elem); if (sums != null && sum != null) sums.Add(key, sum); }
VxSchemaErrors VxPutSchema(VxSchema schema, VxPutOpts opts) { log.print(" + VxPutSchema\n"); return dbus.Put(schema, null, opts); }
public void TestSchemaEquality(VxSchema left, VxSchema right) { foreach (KeyValuePair<string,VxSchemaElement> p in right) { WVPASSEQ(left[p.Key].type, p.Value.type); WVPASSEQ(left[p.Key].name, p.Value.name); WVPASSEQ(left[p.Key].text, p.Value.text); WVPASSEQ(left[p.Key].encrypted, p.Value.encrypted); } WVPASSEQ(left.Count, right.Count); }
// Utility API so you can say Get("foo"). public VxSchema Get(params string[] keys) { WvDbusMsg call = methodcall("GetSchema", "as"); WvDbusWriter writer = new WvDbusWriter(); if (keys == null) keys = new string[0]; writer.WriteArray(4, keys, (w2, k) => { w2.Write(k); }); call.Body = writer.ToArray(); WvDbusMsg reply = bus.send_and_wait(call); reply.check("a(sssy)"); VxSchema schema = new VxSchema(reply.iter().pop()); return schema; }