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); }
// 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); }
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"; } }
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); } }
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 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)); }
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 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 { } }
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 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(); }
public void TestColumnInsertOrder() { string tabname = "TestTable"; try { VxExec("drop table " + tabname); } catch { } // Make sure that table columns get added in the order we give them, // not alphabetical or something. WVPASS(1); string schema1 = "column: name=c,type=int,null=0\n" + "column: name=d,type=int,null=0\n" + "column: name=b,type=int,null=0\n"; TestTableUpdate(tabname, schema1); // Modified columns go to the end if we had to drop and add them. WVPASS(2); string schema2_sent = "column: name=c,type=tinyint,null=0,identity_seed=1,identity_incr=1\n" + "column: name=d,type=int,null=0\n" + "column: name=b,type=int,null=0\n"; string schema2_returned = "column: name=d,type=int,null=0\n" + "column: name=b,type=int,null=0\n" + "column: name=c,type=tinyint,null=0,identity_seed=1,identity_incr=1\n"; VxSchema schema = new VxSchema(); schema.Add("Table", tabname, schema2_sent, false); VxSchemaErrors errs = dbus.Put(schema, null, VxPutOpts.Destructive); log.print("Received errors: {0}\n", errs.ToString()); WVPASSEQ(errs.Count, 0); schema = dbus.Get("Table/" + tabname); WVPASSEQ(schema.Count, 1); CheckTable(schema, tabname, schema2_returned); // New columns go to the end too, but stay in order. WVPASS(3); string schema3_sent = "column: name=e,type=int,null=0\n" + "column: name=a,type=int,null=0\n" + "column: name=c,type=tinyint,null=0,identity_seed=1,identity_incr=1\n" + "column: name=d,type=int,null=0\n" + "column: name=b,type=int,null=0\n"; string schema3_returned = "column: name=d,type=int,null=0\n" + "column: name=b,type=int,null=0\n" + "column: name=c,type=tinyint,null=0,identity_seed=1,identity_incr=1\n" + "column: name=e,type=int,null=0\n" + "column: name=a,type=int,null=0\n"; schema = new VxSchema(); schema.Add("Table", tabname, schema3_sent, false); errs = dbus.Put(schema, null, VxPutOpts.Destructive); log.print("Received errors: {0}\n", errs.ToString()); WVPASSEQ(errs.Count, 0); schema = dbus.Get("Table/" + tabname); WVPASSEQ(schema.Count, 1); CheckTable(schema, tabname, schema3_returned); // Changing the columns completely inserts the new ones in order WVPASS(4); string schema4 = "column: name=cc,type=int,null=0\n" + "column: name=bb,type=int,null=0\n" + "column: name=dd,type=int,null=0\n"; TestTableUpdate(tabname, schema4, VxPutOpts.Destructive); try { VxExec("drop table " + tabname); } catch { } }
public void TestChangingPrimaryKeys() { try { VxExec("drop table TestTable"); } catch { } WVPASS(1); string testschema = "column: name=f1,type=int,null=0\n" + "column: name=f2,type=money,null=0\n" + "column: name=f3,type=varchar,null=1,length=80\n" + "index: column=f2,column=f3 DESC,name=Idx1,unique=1,clustered=2\n" + "primary-key: column=f1,column=f2,clustered=1\n"; TestTableUpdate("TestTable", testschema); // Change the primary-key: line: try specifying a name, changing the // columns, and omitting the optional "clustered" parameter. WVPASS(2); string testschema2 = "column: name=f1,type=int,null=0\n" + "column: name=f2,type=money,null=0\n" + "column: name=f3,type=varchar,null=1,length=80\n" + "index: column=f1,column=f3 DESC,name=Idx1,unique=1,clustered=2\n" + "primary-key: name=TestPK,column=f1\n"; VxSchema schema = new VxSchema(); schema.Add("Table", "TestTable", testschema2, false); VxSchemaErrors errs = dbus.Put(schema, null, VxPutOpts.None); // We'll get the default clustered value added back testschema2 = testschema2.Replace("primary-key: name=TestPK,column=f1", "primary-key: name=TestPK,column=f1,clustered=2"); log.print("Received errors: {0}\n", errs.ToString()); WVPASSEQ(errs.Count, 0); schema = dbus.Get("Table/TestTable"); WVPASSEQ(schema.Count, 1); CheckTable(schema, "TestTable", testschema2); // Remove the primary-key: line. WVPASS(3); string testschema3 = "column: name=f1,type=int,null=0\n" + "column: name=f2,type=money,null=0\n" + "column: name=f3,type=varchar,null=1,length=80\n" + "index: column=f1,column=f3 DESC,name=Idx1,unique=1,clustered=2\n"; TestTableUpdate("TestTable", testschema3); // Try to add two primary keys // Note: VxSchemaTable now checks for this, which makes it hard to // actually test that the server rejects these. It's pretty safe to // assume that the server would have just as much trouble creating one // as we would though, and that the exception would make its way back. WVPASS(4); string testschema4 = "column: name=f1,type=int,null=0\n" + "column: name=f2,type=money,null=0\n" + "column: name=f3,type=varchar,null=1,length=80\n" + "index: column=f1,column=f3 DESC,name=Idx1,unique=1,clustered=2\n" + "primary-key: column=f1,clustered=1\n" + "primary-key: column=f2,clustered=1\n"; string errmsg = "Duplicate table entry 'primary-key' found."; schema = new VxSchema(); try { WVEXCEPT(schema.Add("Table", "TestTable", testschema4, false)); } catch (VxBadSchemaException e) { WVPASSEQ(e.Message, errmsg); log.print(e.ToString() + "\n"); } try { VxExec("drop table TestTable"); } catch { } }
public void TestChangingIndexes() { try { VxExec("drop table TestTable"); } catch { } WVPASS(1); string testschema = "column: name=f1,type=int,null=0\n" + "column: name=f2,type=money,null=0\n" + "column: name=f3,type=varchar,null=1,length=80\n" + "index: column=f2,column=f3 DESC,name=Idx1,unique=1,clustered=2\n" + "primary-key: column=f1,column=f2,clustered=1\n"; TestTableUpdate("TestTable", testschema); // Change the index: line slightly. WVPASS(2); string testschema2 = "column: name=f1,type=int,null=0\n" + "column: name=f2,type=money,null=0\n" + "column: name=f3,type=varchar,null=1,length=80\n" + "index: column=f1,column=f3 DESC,name=Idx1,unique=1,clustered=2\n" + "primary-key: column=f1,column=f2,clustered=1\n"; TestTableUpdate("TestTable", testschema2); // No index at all WVPASS(3); string testschema3 = "column: name=f1,type=int,null=0\n" + "column: name=f2,type=money,null=0\n" + "column: name=f3,type=varchar,null=1,length=80\n" + "primary-key: column=f1,column=f2,clustered=1\n"; TestTableUpdate("TestTable", testschema3); // Add the index back, and another for good measure WVPASS(4); string testschema4 = "column: name=f1,type=int,null=0\n" + "column: name=f2,type=money,null=0\n" + "column: name=f3,type=varchar,null=1,length=80\n" + "index: column=f1,column=f3 DESC,name=Idx1,unique=1,clustered=2\n" + "index: column=f2,column=f3,name=Idx2\n" + "primary-key: column=f1,column=f2,clustered=1\n"; VxSchema schema = new VxSchema(); schema.Add("Table", "TestTable", testschema4, false); VxSchemaErrors errs = dbus.Put(schema, null, VxPutOpts.None); log.print("Received errors: {0}\n", errs.ToString()); WVPASSEQ(errs.Count, 0); // Check that we get the default unique=0 and clustered=2 parameters. testschema4 = testschema4.Replace("Idx2", "Idx2,unique=0,clustered=2"); schema = dbus.Get("Table/TestTable"); WVPASSEQ(schema.Count, 1); CheckTable(schema, "TestTable", testschema4); // Check that duplicate index names give errors. // Note: VxSchemaTable now checks for this, which makes it hard to // actually test that the server rejects these. It's pretty safe to // assume that the server would have just as much trouble creating one // as we would though, and that the exception would make its way back. WVPASS(5); string testschema5 = "column: name=f1,type=int,null=0\n" + "column: name=f2,type=money,null=0\n" + "column: name=f3,type=varchar,null=1,length=80\n" + "index: column=f1,column=f3 DESC,name=Idx1,unique=1,clustered=2\n" + "index: column=f2,column=f3,name=Idx1,unique=1,clustered=2\n" + "primary-key: column=f1,column=f2,clustered=1\n"; string errmsg = "Duplicate table entry 'index: Idx1' found."; schema = new VxSchema(); try { WVEXCEPT(schema.Add("Table", "TestTable", testschema5, false)); } catch (VxBadSchemaException e) { WVPASSEQ(e.Message, errmsg); log.print(e.ToString() + "\n"); } // Try renaming an index. // Note that indexes are returned alphabetically, and the default name // for a primary key is PK_TableName, so the renamed index will show // up after the primary key. WVPASS(6); string testschema6 = "column: name=f1,type=int,null=0\n" + "column: name=f2,type=money,null=0\n" + "column: name=f3,type=varchar,null=1,length=80\n" + "primary-key: column=f1,column=f2,clustered=1\n" + "index: column=f1,column=f3 DESC,name=RenamedIndex," + "unique=1,clustered=2\n"; TestTableUpdate("TestTable", testschema6); try { VxExec("drop table TestTable"); } catch { } }
public void TestTableUpdateError(string tabname, string tabschema, string errmsg, string oldval, VxPutOpts opts, int errno, WvLog.L level) { string key = "Table/" + tabname; 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()); WVPASSEQ(errs.Count, 1); WVPASSEQ(errs[key][0].key, key); log.print("Expected error prefix: [{0}]\n", errmsg); WVPASS(errs[key][0].msg.StartsWith(errmsg)); WVPASSEQ(errs[key][0].errnum, errno); WVPASSEQ((int)errs[key][0].level, (int)level); WVPASSEQ(errs[key].Count, 1); // Ensure that we didn't break what was already there. schema = dbus.Get(key); if (oldval.ne()) { WVPASSEQ(schema.Count, 1); CheckTable(schema, tabname, oldval); } else WVPASSEQ(schema.Count, 0); }