/// <summary> /// SQL文を生成する /// </summary> /// <param name="context">生成先のコンテキスト</param> public void ToElementCode(ElementCode context) { var delayedCode = new DelayedCodeGenerator((wb) => { var ec = new ElementCode(); ec.BeginParenthesize(); ec.Add(SqlKeyword.Values); var list = this.List; for (int i = 0, n = list.Count; i < n; i++) { if (i != 0) { ec.AddComma(); } ec.BeginParenthesize(); ec.AddValues <TColumns>(list[i]); ec.EndParenthesize(); } ec.EndParenthesize(); ec.Add(this); ec.BeginParenthesize(); ec.AddColumns(this.ColumnMap, column => ec.Concat(column.Name)); ec.EndParenthesize(); ec.Build(wb); }); context.Add(delayedCode); context.RegisterBuildHandler(this, (item, wb) => { // delayedCode 内でエイリアス名付与するので、既存の処理をオーバーライドし何もしないようにする }); }
/// <summary> /// SQL文を生成する /// </summary> /// <param name="context">生成先のコンテキスト</param> public void ToElementCode(ElementCode context) { int i = 0; context.Add(SqlKeyword.Select); context.AddColumns(this.ColumnMap, column => { context.Add(column.Source); context.Add(SqlKeyword.As); context.Concat("c" + (i++)); }); }
static void Drop(ElementCode context, string tableName, IUniqueDef unique) { if (unique == null) { return; } context.Add(SqlKeyword.AlterTable, SqlKeyword.IfExists); context.Concat(tableName); context.Add(SqlKeyword.DropConstraint, SqlKeyword.IfExists); context.Concat(unique.Name); context.Go(); }
public override void CreateDatabase(ICodeDbConnection connection, string databaseName, string owner) { using (var cmd = connection.CreateCommand()) { var context = new ElementCode(); context.Add(SqlKeyword.CreateDatabase); context.Concat(Quote(databaseName)); context.Add(SqlKeyword.Owner); context.Concat(Quote(owner)); context.Go(); context.Build().Execute(cmd); } }
static void Drop(ElementCode context, string tableName, IPrimaryKeyDef primaryKey) { if (primaryKey == null) { return; } context.Add(SqlKeyword.AlterTable, SqlKeyword.IfExists); context.Concat(tableName); context.Add(SqlKeyword.DropConstraint, SqlKeyword.IfExists); context.Concat(primaryKey.Name); context.Go(); }
static void Drop(ElementCode context, string tableName, IColumnDef column) { if (column == null) { return; } context.Add(SqlKeyword.AlterTable, SqlKeyword.IfExists); context.Concat(tableName); context.Add(SqlKeyword.DropColumn, SqlKeyword.IfExists); context.Concat(column.Name); context.Go(); }
public override void CreateRole(ICodeDbConnection connection, string roleName, string password) { using (var cmd = connection.CreateCommand()) { var context = new ElementCode(); context.Add(SqlKeyword.CreateRole); context.Concat(Quote(roleName)); context.Add(SqlKeyword.Password); context.Concat(string.Concat("'", password, "'")); context.Concat("LOGIN"); context.Go(); context.Build().Execute(cmd); } }
static void Add(ElementCode context, string tableName, IColumnDef column, Action <IColumnDef> columnOption) { if (column == null) { return; } context.Add(SqlKeyword.AlterTable, SqlKeyword.IfExists); context.Concat(tableName); context.Add(SqlKeyword.AddColumn); context.Concat(column.Name); if (columnOption != null) { columnOption(column); } context.Go(); }
/// <summary> /// 同一値が存在しない場合のみ挿入するように判定を追加する /// </summary> /// <param name="columnCountToWhere">NOT EXISTS (SELECT * FROM t WHERE t.Name = "test") の部分で判定に使用する列数、0が指定されたら全て使用する</param> public void IfNotExists(int columnCountToWhere = 0) { var valueSetter = this.ValueNode as ValueSetter; if (valueSetter != null) { if (columnCountToWhere <= 0 || this.ColumnMap.Count < columnCountToWhere) { columnCountToWhere = this.ColumnMap.Count; } // WHERE NOT EXISTS部作成 var notExistsSelectFrom = new ElementCode(); var columnMap = this.ColumnMap; notExistsSelectFrom.Add(SqlKeyword.NotExists); notExistsSelectFrom.BeginParenthesize(); notExistsSelectFrom.Add(SqlKeyword.Select, SqlKeyword.Asterisk, SqlKeyword.From); notExistsSelectFrom.Add(this.Table); notExistsSelectFrom.Add(SqlKeyword.Where); for (int i = 0; i < columnCountToWhere; i++) { if (i != 0) { notExistsSelectFrom.Add(SqlKeyword.And); } notExistsSelectFrom.Add(columnMap[i]); notExistsSelectFrom.Concat("="); notExistsSelectFrom.Add(valueSetter.ColumnMap[i].Source); } notExistsSelectFrom.EndParenthesize(); valueSetter.Where(notExistsSelectFrom); } }
static void Add(ElementCode context, string tableName, IIndexDef index) { if (index == null) { return; } context.Add(SqlKeyword.CreateIndex, SqlKeyword.IfNotExists); context.Concat(index.Name); context.Add(SqlKeyword.On); context.Concat(tableName); if ((index.Flags & IndexFlags.Gin) != 0) { context.Add(SqlKeyword.Using); context.Concat("gin"); } context.AddColumnDefs(index.Columns); context.Go(); }
public void ToElementCode(ElementCode context) { // SELECT 部分作成 int i = 0; context.Add(SqlKeyword.Select); context.AddColumns(this.ColumnMap, column => { context.Add(column.Source); context.Add(SqlKeyword.As); context.Concat("c" + (i++)); }); // WHERE 部分作成 if (this.WhereNode != null) { this.WhereNode.ToElementCode(context); } }
static void Drop(ElementCode context, string tableName, IIndexDef index) { if (index == null) { return; } context.Add(SqlKeyword.DropIndex, SqlKeyword.IfExists); context.Concat(index.Name); context.Go(); }
/// <summary> /// SQL文を生成する /// </summary> /// <param name="context">生成先のコンテキスト</param> public void ToElementCode(ElementCode context) { if (this.FromNode == null) { throw new ApplicationException(); } // SELECT 部作成 int i = 0; context.Add(SqlKeyword.Select); context.AddColumns(this.ColumnMap, column => { context.Add(column.Source); context.Add(SqlKeyword.As); context.Concat("c" + (i++)); }); // FROM 部作成 this.FromNode.ToElementCode(context); }
/// <summary> /// SQL文を生成する /// </summary> /// <param name="context">生成先のコンテキスト</param> public void ToElementCode(ElementCode context) { if (this.SelectNode != null) { this.SelectNode.ToElementCode(context); } if (this.Table != null) { context.Add(SqlKeyword.From); context.Add(this.Table); } if (this.JoinNodes != null) { foreach (var join in this.JoinNodes) { join.ToElementCode(context); } } if (this.WhereNode != null) { this.WhereNode.ToElementCode(context); } if (this.GroupByNode != null) { this.GroupByNode.ToElementCode(context); } if (this.OrderByNode != null) { this.OrderByNode.ToElementCode(context); } if (this.LimitNode != null) { this.LimitNode.ToElementCode(context); } }
public void NotExistsSelect <TColumns>(TColumns columns, Expression <Func <TColumns, bool> > selectWhereExpression) { var expression = new ElementCode(selectWhereExpression, this.Owner.AllColumns, columns); var table = expression.FindTables().FirstOrDefault(); if (table == null) { throw new ApplicationException(); } var whereExpression = new ElementCode(); whereExpression.Add(SqlKeyword.NotExists); whereExpression.BeginParenthesize(); whereExpression.Add(SqlKeyword.Select, SqlKeyword.Asterisk, SqlKeyword.From); whereExpression.Add(table); whereExpression.Add(SqlKeyword.Where); whereExpression.Add(expression); whereExpression.EndParenthesize(); this.Expression = whereExpression; }
protected override Expression VisitUnary(UnaryExpression node) { _Code.Add(node.NodeType); _Code.Push(); this.Visit(node.Operand); _Code.Pop(); return(node); }
/// <summary> /// SQL文を生成する /// </summary> /// <param name="context">生成先のコンテキスト</param> public void ToElementCode(ElementCode context) { var environment = this.Table.Environment; context.Add(SqlKeyword.InsertInto); context.Concat(this.Table.Name); context.AddColumnDefs(this.ColumnMap); var valueNode = this.ValueNode; if (valueNode != null) { valueNode.ToElementCode(context); return; } throw new ApplicationException(); }
/// <summary> /// SQL文を生成する /// </summary> /// <param name="context">生成先のコンテキスト</param> public void ToElementCode(ElementCode context) { switch (this.JoinType) { case JoinType.Inner: context.Add(SqlKeyword.InnerJoin); break; case JoinType.Left: context.Add(SqlKeyword.LeftJoin); break; case JoinType.Right: context.Add(SqlKeyword.RightJoin); break; } context.Add(this.Table); context.Add(SqlKeyword.On); context.Add(this.On); }
/// <summary> /// SQL文を生成する /// </summary> /// <param name="context">生成先のコンテキスト</param> public void ToElementCode(ElementCode context) { context.Add(SqlKeyword.GroupBy); context.AddColumns(this.Columns); }
static void Main(string[] args) { var E = TestDb.E; using (var con = E.CreateConnection("User ID=postgres;Password=wertyu89?;Host=localhost;Port=5432;Database=postgres;")) { con.Open(); try { E.CreateRole(con, RoleName, "Passw0rd!"); } catch (CodeDbEnvironmentException ex) { if (ex.ErrorType != DbEnvironmentErrorType.DuplicateObject) { throw; } } try { E.CreateDatabase(con, DbName, RoleName); } catch (CodeDbEnvironmentException ex) { if (ex.ErrorType != DbEnvironmentErrorType.DuplicateDatabase) { throw; } } } using (var con = E.CreateConnection($"User ID={RoleName};Password='******';Host=localhost;Port=5432;Database={DbName};")) { con.Open(); var cmd = con.CreateCommand(); cmd.CommandTimeout = 0; { var s = TestDb.E.NewSql(); s.DropTable(TestDb.User); s.Build().Execute(cmd); } // データベースの状態を取得 var current = E.ReadDatabaseDef(con); // クラスからデータベース定義を生成する var target = E.GenerateDatabaseDef(typeof(TestDb), "test_db"); // 差分を生成 var delta = E.GetDatabaseDelta(current, target); // 差分を適用する var context = new ElementCode(); E.ApplyDatabaseDelta(context, delta); context.Build().Execute(cmd); { var sql = TestDb.E.NewSql(); sql.InsertIntoWithValue(TestDb.User, t => new[] { t.UserName == "a" }); sql.InsertIntoWithValue(TestDb.User, t => new[] { t.UserName == "b" }); sql.InsertIntoWithValue(TestDb.User, t => new[] { t.UserName == "c" }); sql.BuildAction().Execute(cmd); } { var sql = TestDb.E.NewSql(); var select = sql.From(TestDb.User).Where(t => t.UserName == "a").Select(t => new { t.UserName, t.UserID, t.CreateDateTime }); var f = sql.BuildSelectFunc(select); using (var reader = f.Execute(cmd)) { foreach (var record in reader.Records) { Console.WriteLine($"{record.UserID} {record.UserName} {record.CreateDateTime}"); } } } { var code = new ElementCode(); var arg1 = new Argument(0); var arg2 = new Argument(0); code.Concat("SELECT ARRAY[1, 2, 3], '{8EA22A18-EB0A-49E5-B61D-F026CA7773FF}'::uuid, now(),"); code.Add(arg1); code.Go(); code.Concat("SELECT ARRAY[1, 2, 3], '{8EA22A18-EB0A-49E5-B61D-F026CA7773FF}'::uuid, now(),"); code.Add(arg2); code.Go(); var s = TestDb.E.NewSql(); s.Code(code); var commandable = s.BuildFunc <int, int, Tuple <int[], Guid, DateTime, int> >(arg1, arg2); using (var reader = commandable.Execute(cmd, 16, 32)) { do { foreach (var record in reader.Records) { Console.WriteLine(record); } } while (reader.DataReader.NextResult()); } } } }
/// <summary> /// SQL文を生成する /// </summary> /// <param name="context">生成先のコンテキスト</param> public void ToElementCode(ElementCode context) { context.Add(this.Code); }
/// <summary> /// SQL文を生成する /// </summary> /// <param name="context">生成先のコンテキスト</param> public void ToElementCode(ElementCode context) { context.Add(SqlKeyword.Limit); context.Add(this.Value); }
/// <summary> /// SQL文を生成する /// </summary> /// <param name="context">生成先のコンテキスト</param> public void ToElementCode(ElementCode context) { context.Add(SqlKeyword.Where); context.Add(this.Expression); }
public override void ApplyDatabaseDelta(ElementCode context, IDatabaseDelta databaseDelta) { // 列の型など付与するデリゲート Action <IColumnDef> columnOption = (column) => { context.Concat(column.DbType.ToDbTypeString((column.Flags & ColumnFlags.Serial) != 0 ? DbTypeStringFlags.Serial : 0)); if ((column.Flags & ColumnFlags.Nullable) != 0) { context.Add(SqlKeyword.Null); } else { context.Add(SqlKeyword.NotNull); } if ((column.Flags & ColumnFlags.DefaultCurrentTimestamp) != 0) { context.Add(SqlKeyword.Default, SqlKeyword.CurrentTimestamp); } }; // 捨てるべきテーブルを捨てる foreach (var table in databaseDelta.TablesToDrop) { context.Add(SqlKeyword.DropTable, SqlKeyword.IfExists); context.Concat(table.Name); context.Go(); } // 新たに増えるテーブルを作成する foreach (var table in databaseDelta.TablesToAdd) { var tableName = table.Name; // テーブル本体 context.Add(SqlKeyword.CreateTable, SqlKeyword.IfNotExists); context.Concat(tableName); context.AddColumnDefs(table.ColumnDefs, null, columnOption); context.Go(); // プライマリキー Add(context, tableName, table.GetPrimaryKey()); // インデックス foreach (var index in table.GetIndices()) { Add(context, tableName, index); } // ユニークキー foreach (var unique in table.GetUniques()) { Add(context, tableName, unique); } } // 変化するテーブルに対応する foreach (var table in databaseDelta.TablesToModify) { var tableName = table.Name; // 先にプライマリキー等の制約を捨てる Drop(context, tableName, table.PrimaryKeyToDrop); foreach (var index in table.IndicesToDrop) { Drop(context, tableName, index); } foreach (var unique in table.UniquesToDrop) { Drop(context, tableName, unique); } // 列を捨てる foreach (var column in table.ColumnsToDrop) { Drop(context, tableName, column); } // 列を追加する foreach (var column in table.ColumnsToAdd) { Add(context, tableName, column, columnOption); } // プライマリキー追加 Add(context, tableName, table.PrimaryKeyToAdd); // インデックス追加 foreach (var index in table.IndicesToAdd) { Add(context, tableName, index); } // ユニークキー追加 foreach (var unique in table.UniquesToAdd) { Add(context, tableName, unique); } } }
public SelectFrom(IFrom from, Expression body) { this.Parent = from.Parent; this.From(from); this.Parent.AddChild(this); this.ColumnMap = new ColumnMap(); this.Columns = TypewiseCache <TSelectedColumns> .Creator(); if (body == null) { // 全列選択に対応 var sourceColumns = from.Table.ColumnMap; var environment = this.Owner.Environment; for (int i = 0; i < sourceColumns.Count; i++) { var column = sourceColumns[i]; var pi = column.Property; var ec = new ElementCode(); ec.Add(column); BindColumn(pi.Name, "c" + i, environment.CreateDbTypeFromType(pi.PropertyType), 0, ec); } } else if (body.NodeType == ExpressionType.New) { // new 演算子でのクラス生成式に対応 // クラスのプロパティ数とコンストラクタ引数の数が異なるならエラーとする var newexpr = body as NewExpression; var args = newexpr.Arguments; var properties = typeof(TSelectedColumns).GetProperties(); if (args.Count != properties.Length) { throw new ApplicationException(); } // プロパティと列定義を結びつけその生成元としてコンストラクタ引数を指定する var owner = this.Owner; var environment = owner.Environment; var allColumns = owner.AllColumns; for (int i = 0; i < properties.Length; i++) { var pi = properties[i]; if (pi.PropertyType != args[i].Type) { throw new ApplicationException(); } BindColumn(pi.Name, "c" + i, environment.CreateDbTypeFromType(pi.PropertyType), 0, new ElementCode(args[i], allColumns)); } } else if (body.NodeType == ExpressionType.MemberInit) { // メンバ初期化式に対応 // クラスのプロパティ数とコンストラクタ引数の数が異なるならエラーとする var initexpr = body as MemberInitExpression; var bindings = initexpr.Bindings; // プロパティと列定義を結びつけその生成元としてコンストラクタ引数を指定する var owner = this.Owner; var environment = owner.Environment; var allColumns = owner.AllColumns; for (int i = 0; i < bindings.Count; i++) { var binding = bindings[i]; if (binding.BindingType != MemberBindingType.Assignment) { throw new ApplicationException(); } var assign = binding as MemberAssignment; var member = binding.Member; if (member.MemberType != System.Reflection.MemberTypes.Property) { throw new ApplicationException(); } var property = (PropertyInfo)member; BindColumn(property.Name, "c" + i, environment.CreateDbTypeFromType(property.PropertyType), 0, new ElementCode(assign.Expression, allColumns)); } } else { throw new ApplicationException(); } }
/// <summary> /// SQL文を生成する /// </summary> /// <param name="context">生成先のコンテキスト</param> public void ToElementCode(ElementCode context) { context.Add(SqlKeyword.DropTable, SqlKeyword.IfExists); context.Concat(this.Table.Name); }