Hi,

First of all, sorry about breaking the thread; I don't subscribe to -general so I can't copy the original email. This is in response to the problem here: http://www.postgresql.org/message-id/CACfv+p+8dToaR7h06_M_YMjpV5Na-CQq7kN=kgjq_k84h7u...@mail.gmail.com

Attached is a very ugly proof-of-concept patch of how this could work. With this applied, the ALTER TABLE becomes fast:

=# create domain test_domain numeric check (value > 0);
CREATE DOMAIN
Time: 2,443 ms
=# create table test_domain_table as select generate_series(1, 2000000);
SELECT 2000000
Time: 1802,681 ms
=# alter table test_domain_table add column t test_domain;
ALTER TABLE
Time: 4,991 ms

The patch is obviously a load of horse crap, but does anyone have any objections to the general approach of making this pattern faster? To do this optimization we do have to assume that CHECKs in DOMAINs are at least STABLE, but I don't see that as a problem; those should be IMMUTABLE anyway, I think.


.marko
*** a/src/backend/commands/tablecmds.c
--- b/src/backend/commands/tablecmds.c
***************
*** 4795,4815 **** ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
  			Oid			baseTypeId;
  			int32		baseTypeMod;
  			Oid			baseTypeColl;
  
  			baseTypeMod = typmod;
  			baseTypeId = getBaseTypeAndTypmod(typeOid, &baseTypeMod);
  			baseTypeColl = get_typcollation(baseTypeId);
! 			defval = (Expr *) makeNullConst(baseTypeId, baseTypeMod, baseTypeColl);
! 			defval = (Expr *) coerce_to_target_type(NULL,
! 													(Node *) defval,
! 													baseTypeId,
! 													typeOid,
! 													typmod,
! 													COERCION_ASSIGNMENT,
! 													COERCE_IMPLICIT_CAST,
! 													-1);
! 			if (defval == NULL) /* should not happen */
  				elog(ERROR, "failed to coerce base type to domain");
  		}
  
  		if (defval)
--- 4795,4833 ----
  			Oid			baseTypeId;
  			int32		baseTypeMod;
  			Oid			baseTypeColl;
+ 			Expr	   *nullval;
+ 			ExprState  *nullvalState;
+ 			ExprContext *econtext;
+ 			bool		isnull;
+ 			Snapshot	snapshot;
+ 			EState	   *estate;
  
  			baseTypeMod = typmod;
  			baseTypeId = getBaseTypeAndTypmod(typeOid, &baseTypeMod);
  			baseTypeColl = get_typcollation(baseTypeId);
! 			nullval = (Expr *) makeNullConst(baseTypeId, baseTypeMod, baseTypeColl);
! 			nullval = (Expr *) coerce_to_target_type(NULL,
! 													 (Node *) nullval,
! 													 baseTypeId,
! 													 typeOid,
! 													 typmod,
! 													 COERCION_ASSIGNMENT,
! 													 COERCE_IMPLICIT_CAST,
! 													 -1);
! 			if (nullval == NULL) /* should not happen */
  				elog(ERROR, "failed to coerce base type to domain");
+ 			nullval = expression_planner(nullval);
+ 			nullvalState = ExecInitExpr(nullval, NULL);
+ 			estate = CreateExecutorState();
+ 			econtext = GetPerTupleExprContext(estate);
+ 			snapshot = RegisterSnapshot(GetLatestSnapshot());
+ 			(void) ExecEvalExpr(nullvalState,
+ 								econtext,
+ 								&isnull,
+ 								NULL);
+ 			(void) isnull;
+ 			UnregisterSnapshot(snapshot);
+ 			FreeExecutorState(estate);
  		}
  
  		if (defval)
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to