static void do_pascalgen(string classname, string dir, Dictionary<string,string> global_syms, string outfile) { if (!classname.StartsWith("T")) { Console.Error.Write("Classname must start with T.\n"); return; } Console.Error.Write("Generating Pascal file...\n"); // Replace leading 'T' with a 'u' string unitname = "u" + classname.Remove(0, 1); VxDiskSchema disk = new VxDiskSchema(dir); VxSchema schema = disk.Get(null); var types = new List<string>(); var iface = new List<string>(); var impl = new List<string>(); var setters = new List<string>(); var keys = schema.Keys.ToList(); keys.Sort(StringComparer.Ordinal); foreach (var key in keys) { var elem = schema[key]; if (elem.type != "Procedure") continue; var sp = new StoredProcedure(elem.text); var pargs = new List<PascalArg>(); foreach (SPArg arg in sp.args) pargs.Add(new PascalArg(elem.name, arg)); var decls = new List<string>(); var impls = new List<string>(); var ctors = new List<string>(); foreach (PascalArg parg in pargs) { if (!global_syms.ContainsKey(parg.varname.ToLower())) { decls.Add(parg.GetDecl()); impls.Add(parg.GetDefine()); ctors.Add(parg.GetCtor()); } else { string old = global_syms[parg.varname.ToLower()]; if (old.ne() && old.ToLower() != parg.pascaltype.ToLower()) { log.print("Definition for global '{0}' differs! " + "old '{1}', new '{2}'\n", parg.varname, old, parg.pascaltype); } else { // The global declaration supplants the local // declaration and implementation, but not the ctor. global_syms[parg.varname.ToLower()] = parg.pascaltype; ctors.Add(parg.GetCtor()); } } } // Factory function that produces builder objects iface.Add(wv.fmt("function {0}\n" + " ({1}): _T{0};\n", elem.name, decls.join(";\n "))); // Actual implementation of the factory function impl.Add(wv.fmt( "function {0}.{1}\n" + " ({2}): _T{1};\n" + "begin\n" + " result := _T{1}.Create(db)\n" + " {3};\n" + "end;\n\n", classname, elem.name, impls.join(";\n "), ctors.join("\n ") )); var memberdecls = new List<string>(); var methoddecls = new List<string>(); foreach (PascalArg parg in pargs) { memberdecls.Add(parg.GetMemberDecl()); methoddecls.Add(parg.GetMethodDecl()); } // Declaration for per-procedure builder class types.Add("_T" + elem.name + " = class(TPwDataCmd)\n" + " private\n" + " " + memberdecls.join("\n ") + "\n" + " public\n" + " function MakeRawSql: string; override;\n" + " " + methoddecls.join("\n ") + "\n" + " end;\n" ); // Member functions of the builder classes var argstrs = new List<string>(); var argcalls = new List<string>(); foreach (PascalArg parg in pargs) { argstrs.Add(wv.fmt("'{0}'", parg.varname)); argcalls.Add(parg.call); } setters.Add(wv.fmt( "function _T{0}.MakeRawSql: string;\n" + "begin\n" + " result := TPwDatabase.ExecStr('{0}',\n" + " [{1}],\n" + " [{2}]);\n" + "end;\n\n", elem.name, argstrs.join( ",\n "), argcalls.join(",\n "))); foreach (PascalArg parg in pargs) setters.Add(parg.GetSetters()); } var sb = new StringBuilder(); sb.Append("(*\n" + " * THIS FILE IS AUTOMATICALLY GENERATED BY sm.exe\n" + " * DO NOT EDIT!\n" + " *)\n" + "unit " + unitname + ";\n\n"); var global_syms_keys = global_syms.Keys.ToList(); global_syms_keys.Sort(); var globalfields = new List<string>(); var globalprops = new List<string>(); foreach (var sym in global_syms_keys) { string type = global_syms[sym]; if (type.e()) { log.print(WvLog.L.Error, "Global symbol '{0}' is never used in any procedure!\n", sym); return; } globalfields.Add(wv.fmt("p_{0}: {1};", sym, type)); globalprops.Add(wv.fmt("property {0}: {1} read p_{0} write p_{0};", sym, type)); } sb.Append("interface\n\n" + "uses Classes, uPwData;\n" + "\n" + "{$M+}\n" + "type\n" + " " + types.join("\n ") + " \n" + " " + classname + " = class(TComponent)\n" + " private\n" + " fDb: TPwDatabase;\n" + " " + globalfields.join("\n ") + "\n" + " published\n" + " property db: TPwDatabase read fDb write fDb;\n" + " " + globalprops.join("\n ") + "\n" + " public\n" + " constructor Create(db: TPwDatabase); reintroduce;\n" + " " + iface.join(" ") + " end;\n\n"); sb.Append("implementation\n" + "\n" + "constructor " + classname + ".Create(db: TPwDatabase);\n" + "begin\n" + " inherited Create(db);\n" + " self.db := db;\n" + "end;\n" + "\n" + impl.join("") ); sb.Append(setters.join("")); sb.Append("\n\nend.\n"); if (outfile.e()) Console.Write(sb.ToString()); else { Console.Error.Write("Writing file: {0}\n", outfile); using (var f = new FileStream(outfile, FileMode.Create, FileAccess.Write)) { f.write(sb.ToUTF8()); } } Console.Error.Write("Done.\n"); }
public string CsvFix(string tablename, string csvtext) { List<string> result = new List<string>(); WvCsv csvhandler = new WvCsv(csvtext); string coltype, colsstr; List<string> values = new List<string>(); List<string> cols = new List<string>(); List<string> allcols = new List<string>(); int[] fieldstoskip = new int[skipfields.Count]; for (int i=0; i < skipfields.Count; i++) fieldstoskip[i] = -1; Dictionary<string,string> coltypes = new Dictionary<string,string>(); VxDiskSchema disk = new VxDiskSchema(exportdir); VxSchema schema = disk.Get(null); Console.WriteLine("Fixing data of table ["+tablename+"]"); string[] csvcolumns = (string[])csvhandler.GetLine() .ToArray(Type.GetType("System.String")); for (int i=0; i<csvcolumns.Length; i++) csvcolumns[i] = csvcolumns[i].ToLower(); int ii = 0; foreach (KeyValuePair<string,VxSchemaElement> p in schema) { if (!(p.Value is VxSchemaTable)) continue; if (((VxSchemaTable)p.Value).name.ToLower() != tablename.ToLower()) continue; foreach (VxSchemaTableElement te in ((VxSchemaTable)p.Value)) { if (te.GetElemType() != "column") continue; if (csvcolumns.Contains(te.GetParam("name").ToLower())) coltypes.Add(te.GetParam("name").ToLower(), te.GetParam("type")); allcols.Add(te.GetParam("name").ToLower()); if (csvcolumns.Contains(te.GetParam("name").ToLower())) { if (skipfields.Contains(te.GetParam("name").ToLower())) fieldstoskip[skipfields.IndexOf( te.GetParam("name").ToLower())] = ii; else if (skipfields.Contains( tablename.ToLower()+"."+ te.GetParam("name").ToLower())) fieldstoskip[skipfields.IndexOf( tablename.ToLower()+"."+ te.GetParam("name").ToLower())] = ii; else cols.Add(te.GetParam("name")); } ii++; } } colsstr = "\"" + cols.join("\",\"") + "\"\n"; if (!csvhandler.hasMore()) return colsstr; while (csvhandler.hasMore()) { string[] asarray = (string[])csvhandler.GetLine() .ToArray(Type.GetType("System.String")); if (asarray.Length != csvcolumns.Length) return ""; values.Clear(); for (int i=0;i<asarray.Length;i++) { if (Array.IndexOf(fieldstoskip,i)>=0) continue; if (replaces.ContainsKey(csvcolumns[i])) asarray[i] = replaces[csvcolumns[i]]; if (replaces.ContainsKey(tablename.ToLower() + "." + csvcolumns[i])) asarray[i] = replaces[tablename.ToLower() + "." + csvcolumns[i]].ToLower(); if (coltypes.ContainsKey(csvcolumns[i]) && (coltypes[csvcolumns[i]] != null)) coltype = coltypes[csvcolumns[i]]; else coltype = ""; if (asarray[i] == null) values.Add(""); else if ((coltype == "varchar") || (coltype == "datetime") || (coltype == "char") || (coltype == "nchar") || (coltype == "text")) { // Double-quote chars for SQL safety string esc = asarray[i].Replace("\"", "\"\""); //indication that single quotes are already doubled if (esc.IndexOf("''") < 0) esc = esc.Replace("'", "''"); if (WvCsv.RequiresQuotes(esc)) values.Add('"' + esc + '"'); else values.Add(esc); } else if (coltype == "image") { string temp = asarray[i].Replace("\n",""); string tmp = ""; while (temp.Length > 0) { if (temp.Length > 75) { tmp += temp.Substring(0,76) + "\n"; temp = temp.Substring(76); } else { tmp += temp + "\n"; break; } } values.Add("\""+tmp+"\""); } else values.Add(asarray[i]); } result.Add(values.join(",") + "\n"); } result.Sort(StringComparer.Ordinal); return colsstr+result.join(""); }
public void TestExportSchema() { SchemaCreator sc = new SchemaCreator(this); string tmpdir = GetTempDir(); DirectoryInfo tmpdirinfo = new DirectoryInfo(tmpdir); try { tmpdirinfo.Create(); // Establish a baseline for the number of existing elements. VxSchema schema = dbus.Get(); VxSchemaChecksums sums = dbus.GetChecksums(); VxDiskSchema disk = new VxDiskSchema(tmpdir); disk.Put(schema, sums, VxPutOpts.None); var base_filecounts = GetFileCounts(tmpdir); // Clobber the directory and start fresh. tmpdirinfo.Delete(true); tmpdirinfo.Create(); // Now create our test schema and do the real tests. sc.Create(); // Check that having mangled checksums fails schema = dbus.Get(); sums = new VxSchemaChecksums(); disk = new VxDiskSchema(tmpdir); try { WVEXCEPT(disk.Put(schema, sums, VxPutOpts.None)); } catch (Wv.Test.WvAssertionFailure e) { throw e; } catch (System.Exception e) { WVPASS(e is ArgumentException); WVPASS(e.Message.StartsWith("Missing checksum for ")); log.print(e.ToString() + "\n"); } // Check that the normal exporting works. schema = dbus.Get(); sums = dbus.GetChecksums(); WVPASSEQ(schema.Count, sums.Count); disk.Put(schema, sums, VxPutOpts.None); int backup_generation = 0; VerifyExportedSchema(tmpdir, schema, sums, sc, backup_generation, base_filecounts); // Check that we read back the same stuff VxSchema schemafromdisk = disk.Get(null); VxSchemaChecksums sumsfromdisk = disk.GetChecksums(); WVPASS(1); TestSchemaEquality(schema, schemafromdisk); TestChecksumEquality(sums, sumsfromdisk); WVPASS(2); // Doing it twice doesn't change anything. disk.Put(schema, sums, VxPutOpts.None); VerifyExportedSchema(tmpdir, schema, sums, sc, backup_generation, base_filecounts); WVPASS(3); // Check backup mode disk.Put(schema, sums, VxPutOpts.IsBackup); backup_generation++; VerifyExportedSchema(tmpdir, schema, sums, sc, backup_generation, base_filecounts); WVPASS(4); // Check backup mode again disk.Put(schema, sums, VxPutOpts.IsBackup); backup_generation++; VerifyExportedSchema(tmpdir, schema, sums, sc, backup_generation, base_filecounts); WVPASS(5); } finally { tmpdirinfo.Delete(true); sc.Cleanup(); } WVASSERT(!tmpdirinfo.Exists); }
public void TestCopySchema() { 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(); string tmpdir = GetTempDir(); try { Directory.CreateDirectory(tmpdir); VxDiskSchema disk = new VxDiskSchema(tmpdir); // Test that the copy function will create new elements VxSchema.CopySchema(dbus, disk); VxSchema newschema = disk.Get(null); VxSchemaChecksums newsums = disk.GetChecksums(); WVPASS(1); TestSchemaEquality(origschema, newschema); WVPASS(2); TestChecksumEquality(origsums, newsums); WVPASS(3); // Test that the copy function updates changed elements, and // deletes old ones. origschema["Procedure/Func1"].text = func1q2; dbus.Put(origschema, null, VxPutOpts.None); dbus.DropSchema("Table/Tab2"); origschema.Remove("Table/Tab2"); origsums = dbus.GetChecksums(); VxSchema.CopySchema(dbus, disk); newschema = disk.Get(null); newsums = disk.GetChecksums(); WVPASS(4); TestSchemaEquality(origschema, newschema); WVPASS(5); TestChecksumEquality(origsums, newsums); WVPASS(6); } finally { Directory.Delete(tmpdir, true); } WVPASS(!Directory.Exists(tmpdir)); sc.Cleanup(); }
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)); }