Exemple #1
0
 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);
 }
Exemple #2
0
    //
    // 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;
    }
Exemple #3
0
    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;
    }
Exemple #5
0
    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;
    }
Exemple #6
0
    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);
    }
Exemple #7
0
    //
    // 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();
    }
Exemple #8
0
    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();
    }
Exemple #9
0
    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;
    }
Exemple #10
0
    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);
    }
Exemple #11
0
    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";
        }
    }
Exemple #12
0
    // 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;
    }
Exemple #13
0
    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();
    }
Exemple #14
0
    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 { }
    }
Exemple #15
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));
    }
Exemple #16
0
    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));
    }
Exemple #17
0
    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));
    }
Exemple #18
0
    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);

    }
Exemple #19
0
    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));
    }
Exemple #20
0
    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 { }
    }
Exemple #21
0
    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;
    }
Exemple #22
0
    // 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);
    }
Exemple #23
0
    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";
        }
    }
Exemple #24
0
    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();
    }
Exemple #25
0
    // 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);
                }
            }
        }
    }
Exemple #26
0
    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);
        }
    }
Exemple #27
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);
    }
Exemple #28
0
    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;
    }