mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 17:20:49 +08:00 
			
		
		
		
	- 调整 pgsql10 自增映射使用 GENERATED BY DEFAULT AS IDENTITY,低版本仍然使用 serial;
This commit is contained in:
		@@ -85,10 +85,11 @@ namespace FreeSql.Odbc.PostgreSQL
 | 
			
		||||
            var sb = new StringBuilder();
 | 
			
		||||
            var seqcols = new List<NativeTuple<ColumnInfo, string[], bool>>(); //序列
 | 
			
		||||
 | 
			
		||||
            var is96 = true;
 | 
			
		||||
            var isPg96 = true;
 | 
			
		||||
            var isPg10 = (_orm.DbFirst as OdbcPostgreSQLDbFirst).IsPg10;
 | 
			
		||||
            using (var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)))
 | 
			
		||||
            {
 | 
			
		||||
                is96 = OdbcPostgreSQLDbFirst.PgVersionIs96(conn.Value.ServerVersion);
 | 
			
		||||
                isPg96 = OdbcPostgreSQLDbFirst.PgVersionIs96(conn.Value.ServerVersion);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var obj in objects)
 | 
			
		||||
@@ -134,8 +135,13 @@ namespace FreeSql.Odbc.PostgreSQL
 | 
			
		||||
                        sb.Append("CREATE TABLE IF NOT EXISTS ").Append(createTableName).Append(" ( ");
 | 
			
		||||
                        foreach (var tbcol in tb.ColumnsByPosition)
 | 
			
		||||
                        {
 | 
			
		||||
                            sb.Append(" \r\n  ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(",");
 | 
			
		||||
                            if (tbcol.Attribute.IsIdentity == true) seqcols.Add(NativeTuple.Create(tbcol, tbname, true));
 | 
			
		||||
                            sb.Append(" \r\n  ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
 | 
			
		||||
                            if (tbcol.Attribute.IsIdentity == true)
 | 
			
		||||
                            {
 | 
			
		||||
                                if (isPg10) sb.Append(" GENERATED BY DEFAULT AS IDENTITY");
 | 
			
		||||
                                else seqcols.Add(NativeTuple.Create(tbcol, tbname, true));
 | 
			
		||||
                            }
 | 
			
		||||
                            sb.Append(",");
 | 
			
		||||
                        }
 | 
			
		||||
                        if (tb.Primarys.Any())
 | 
			
		||||
                        {
 | 
			
		||||
@@ -183,7 +189,7 @@ namespace FreeSql.Odbc.PostgreSQL
 | 
			
		||||
                    tboldname = null; //如果新表已经存在,不走改表名逻辑
 | 
			
		||||
 | 
			
		||||
                //对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
 | 
			
		||||
                var sql = _commonUtils.FormatSql(@"
 | 
			
		||||
                var sql = _commonUtils.FormatSql($@"
 | 
			
		||||
select
 | 
			
		||||
a.attname,
 | 
			
		||||
t.typname,
 | 
			
		||||
@@ -193,7 +199,7 @@ case when a.attnotnull then '0' else '1' end as is_nullable,
 | 
			
		||||
--e.adsrc,
 | 
			
		||||
(select pg_get_expr(adbin, adrelid) from pg_attrdef where adrelid = e.adrelid limit 1) is_identity,
 | 
			
		||||
a.attndims,
 | 
			
		||||
d.description as comment
 | 
			
		||||
d.description as comment{(isPg10 ? ", a.attidentity" : "")}
 | 
			
		||||
from pg_class c
 | 
			
		||||
inner join pg_attribute a on a.attnum > 0 and a.attrelid = c.oid
 | 
			
		||||
inner join pg_type t on t.oid = a.atttypid
 | 
			
		||||
@@ -202,7 +208,7 @@ left join pg_description d on d.objoid = a.attrelid and d.objsubid = a.attnum
 | 
			
		||||
left join pg_attrdef e on e.adrelid = a.attrelid and e.adnum = a.attnum
 | 
			
		||||
inner join pg_namespace ns on ns.oid = c.relnamespace
 | 
			
		||||
inner join pg_namespace ns2 on ns2.oid = t.typnamespace
 | 
			
		||||
where ns.nspname = {0} and c.relname = {1}", tboldname ?? tbname);
 | 
			
		||||
where ns.nspname = {{0}} and c.relname = {{1}}", tboldname ?? tbname);
 | 
			
		||||
                var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
 | 
			
		||||
                var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a =>
 | 
			
		||||
                {
 | 
			
		||||
@@ -221,13 +227,16 @@ where ns.nspname = {0} and c.relname = {1}", tboldname ?? tbname);
 | 
			
		||||
                        if (attndims == 0) attndims++;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (sqlType.StartsWith("_")) sqlType = sqlType.Substring(1);
 | 
			
		||||
                    var is_identity_pg9 = string.Concat(a[5]).StartsWith(@"nextval('") && (string.Concat(a[5]).EndsWith(@"'::regclass)") || string.Concat(a[5]).EndsWith(@"')"));
 | 
			
		||||
                    return new
 | 
			
		||||
                    {
 | 
			
		||||
                        column = string.Concat(a[0]),
 | 
			
		||||
                        sqlType = string.Concat(sqlType),
 | 
			
		||||
                        max_length = long.Parse(string.Concat(a[2])),
 | 
			
		||||
                        is_nullable = string.Concat(a[4]) == "1",
 | 
			
		||||
                        is_identity = string.Concat(a[5]).StartsWith(@"nextval('") && (string.Concat(a[5]).EndsWith(@"'::regclass)") || string.Concat(a[5]).EndsWith(@"')")),
 | 
			
		||||
                        is_identity_pg9 = is_identity_pg9,
 | 
			
		||||
                        is_identity = is_identity_pg9
 | 
			
		||||
                            || isPg10 && new[] { "a", "d" }.Contains(string.Concat(a[8])), //pg10 GENERATED { BY DEFAULT | AWAYS } AS IDENTITY
 | 
			
		||||
                        attndims,
 | 
			
		||||
                        comment = string.Concat(a[7])
 | 
			
		||||
                    };
 | 
			
		||||
@@ -266,7 +275,27 @@ where ns.nspname = {0} and c.relname = {1}", tboldname ?? tbname);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity)
 | 
			
		||||
                                seqcols.Add(NativeTuple.Create(tbcol, tbname, tbcol.Attribute.IsIdentity == true));
 | 
			
		||||
                            {
 | 
			
		||||
                                if (isPg10)
 | 
			
		||||
                                {
 | 
			
		||||
                                    if (tbstructcol.is_identity)
 | 
			
		||||
                                    {
 | 
			
		||||
                                        if (tbstructcol.is_identity_pg9)
 | 
			
		||||
                                            seqcols.Add(NativeTuple.Create(tbcol, tbname, false));
 | 
			
		||||
                                        sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" DROP IDENTITY IF EXISTS;\r\n");
 | 
			
		||||
                                    }
 | 
			
		||||
                                    else
 | 
			
		||||
                                    {
 | 
			
		||||
                                        sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ADD GENERATED BY DEFAULT AS IDENTITY");
 | 
			
		||||
                                        var maxval = _orm.Ado.QuerySingle<int>($"select max({_commonUtils.QuoteSqlName(tbcol.Attribute.Name)}) from {_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")}");
 | 
			
		||||
                                        if (maxval > 0)
 | 
			
		||||
                                            sbalter.Append(" (START ").Append(maxval + 1).Append(")");
 | 
			
		||||
                                        sbalter.Append(";\r\n");
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                                else
 | 
			
		||||
                                    seqcols.Add(NativeTuple.Create(tbcol, tbname, tbcol.Attribute.IsIdentity == true));
 | 
			
		||||
                            }
 | 
			
		||||
                            if (string.Compare(tbstructcol.column, tbcol.Attribute.OldName, true) == 0)
 | 
			
		||||
                                //修改列名
 | 
			
		||||
                                sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(";\r\n");
 | 
			
		||||
@@ -278,14 +307,20 @@ where ns.nspname = {0} and c.relname = {1}", tboldname ?? tbname);
 | 
			
		||||
                        sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType.Split(' ').First()).Append(";\r\n");
 | 
			
		||||
                        sbalter.Append("UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" = ").Append(tbcol.DbDefaultValue).Append(";\r\n");
 | 
			
		||||
                        if (tbcol.Attribute.IsNullable == false) sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" SET NOT NULL;\r\n");
 | 
			
		||||
                        if (tbcol.Attribute.IsIdentity == true) seqcols.Add(NativeTuple.Create(tbcol, tbname, tbcol.Attribute.IsIdentity == true));
 | 
			
		||||
                        if (tbcol.Attribute.IsIdentity == true)
 | 
			
		||||
                        {
 | 
			
		||||
                            if (isPg10)
 | 
			
		||||
                                sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ADD GENERATED BY DEFAULT AS IDENTITY;\r\n");
 | 
			
		||||
                            else
 | 
			
		||||
                                seqcols.Add(NativeTuple.Create(tbcol, tbname, tbcol.Attribute.IsIdentity == true));
 | 
			
		||||
                        }
 | 
			
		||||
                        if (string.IsNullOrEmpty(tbcol.Comment) == false) sbalter.Append("COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment)).Append(";\r\n");
 | 
			
		||||
                    }
 | 
			
		||||
                    var dsuksql = _commonUtils.FormatSql($@"
 | 
			
		||||
select
 | 
			
		||||
c.attname,
 | 
			
		||||
b.relname,
 | 
			
		||||
{(is96 ? "case when pg_index_column_has_property(b.oid, c.attnum, 'desc') = 't' then 1 else 0 end" : "0")} IsDesc,
 | 
			
		||||
{(isPg96 ? "case when pg_index_column_has_property(b.oid, c.attnum, 'desc') = 't' then 1 else 0 end" : "0")} IsDesc,
 | 
			
		||||
case when indisunique = 't' then 1 else 0 end IsUnique
 | 
			
		||||
from pg_index a
 | 
			
		||||
inner join pg_class b on b.oid = a.indexrelid
 | 
			
		||||
@@ -299,7 +334,7 @@ where ns.nspname in ({{0}}) and d.relname in ({{1}}) and a.indisprimary = 'f'",
 | 
			
		||||
                        if (string.IsNullOrEmpty(uk.Name) || uk.Columns.Any() == false) continue;
 | 
			
		||||
                        var ukname = ReplaceIndexName(uk.Name, tbname[1]);
 | 
			
		||||
                        var dsukfind1 = dsuk.Where(a => string.Compare(a[1], ukname, true) == 0).ToArray();
 | 
			
		||||
                        if (dsukfind1.Any() == false || dsukfind1.Length != uk.Columns.Length || dsukfind1.Where(a => uk.Columns.Where(b => (a[3] == "1") == uk.IsUnique && string.Compare(b.Column.Attribute.Name, a[0], true) == 0 && ((a[2] == "1") == b.IsDesc || is96 == false)).Any()).Count() != uk.Columns.Length)
 | 
			
		||||
                        if (dsukfind1.Any() == false || dsukfind1.Length != uk.Columns.Length || dsukfind1.Where(a => uk.Columns.Where(b => (a[3] == "1") == uk.IsUnique && string.Compare(b.Column.Attribute.Name, a[0], true) == 0 && ((a[2] == "1") == b.IsDesc || isPg96 == false)).Any()).Count() != uk.Columns.Length)
 | 
			
		||||
                        {
 | 
			
		||||
                            if (dsukfind1.Any()) sbalter.Append("DROP INDEX ").Append(_commonUtils.QuoteSqlName(ukname)).Append(";\r\n");
 | 
			
		||||
                            sbalter.Append("CREATE ");
 | 
			
		||||
@@ -345,8 +380,13 @@ where pg_namespace.nspname={0} and pg_class.relname={1} and pg_constraint.contyp
 | 
			
		||||
                sb.Append("CREATE TABLE IF NOT EXISTS ").Append(tmptablename).Append(" ( ");
 | 
			
		||||
                foreach (var tbcol in tb.ColumnsByPosition)
 | 
			
		||||
                {
 | 
			
		||||
                    sb.Append(" \r\n  ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(",");
 | 
			
		||||
                    if (tbcol.Attribute.IsIdentity == true) seqcols.Add(NativeTuple.Create(tbcol, tbname, true));
 | 
			
		||||
                    sb.Append(" \r\n  ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
 | 
			
		||||
                    if (tbcol.Attribute.IsIdentity == true)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (isPg10) sb.Append(" GENERATED BY DEFAULT AS IDENTITY");
 | 
			
		||||
                        else seqcols.Add(NativeTuple.Create(tbcol, tbname, true));
 | 
			
		||||
                    }
 | 
			
		||||
                    sb.Append(",");
 | 
			
		||||
                }
 | 
			
		||||
                if (tb.Primarys.Any())
 | 
			
		||||
                {
 | 
			
		||||
@@ -403,11 +443,27 @@ where pg_namespace.nspname={0} and pg_class.relname={1} and pg_constraint.contyp
 | 
			
		||||
                    }
 | 
			
		||||
                    sb.Remove(sb.Length - 2, 2).Append(");\r\n");
 | 
			
		||||
                }
 | 
			
		||||
                if (isPg10)
 | 
			
		||||
                {
 | 
			
		||||
                    foreach (var tbcol in tb.ColumnsByPosition)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (tbcol.Attribute.IsIdentity)
 | 
			
		||||
                        {
 | 
			
		||||
                            var maxval = _orm.Ado.QuerySingle<int>($"select max({_commonUtils.QuoteSqlName(tbcol.Attribute.Name)}) from {tablename}");
 | 
			
		||||
                            if (maxval > 0)
 | 
			
		||||
                            {
 | 
			
		||||
                                sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" SET GENERATED BY DEFAULT");
 | 
			
		||||
                                sb.Append(" RESTART ").Append(maxval + 1).Append("");
 | 
			
		||||
                                sb.Append(";\r\n");
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            foreach (var seqcol in seqcols)
 | 
			
		||||
            {
 | 
			
		||||
                var tbname = seqcol.Item2;
 | 
			
		||||
                var seqname = Utils.GetCsName($"{tbname[0]}.{tbname[1]}_{seqcol.Item1.Attribute.Name}_sequence_name").ToLower(); ;
 | 
			
		||||
                var seqname = Utils.GetCsName($"{tbname[0]}.{tbname[1]}_{seqcol.Item1.Attribute.Name}_sequence_name").ToLower();
 | 
			
		||||
                var tbname2 = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}");
 | 
			
		||||
                var colname2 = _commonUtils.QuoteSqlName(seqcol.Item1.Attribute.Name);
 | 
			
		||||
                sb.Append("ALTER TABLE ").Append(tbname2).Append(" ALTER COLUMN ").Append(colname2).Append(" SET DEFAULT null;\r\n");
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user