On Mon, Jun 30, 2014 at 9:15 PM, Tom Lane <tgl@xxxxxxxxxxxxx> wrote: > Craig Ringer <craig@xxxxxxxxxxxxxxx> writes: >> I was unaware that the planner made any attempt to catch users' errors >> in marking the strictness of functions. I thought it pretty much trusted >> the user not to lie about the mutability of functions invoked >> indirectly. I'm not really sure where in the inlining code to look to >> figure that out. > > It's in optimizer/util/clauses.c: > > /* > * Additional validity checks on the expression. It mustn't return a set, > * and it mustn't be more volatile than the surrounding function (this is > * to avoid breaking hacks that involve pretending a function is immutable > * when it really ain't). If the surrounding function is declared strict, > * then the expression must contain only strict constructs and must use > * all of the function parameters (this is overkill, but an exact analysis > * is hard). > */ > if (expression_returns_set(newexpr)) > goto fail; > > if (funcform->provolatile == PROVOLATILE_IMMUTABLE && > contain_mutable_functions(newexpr)) > goto fail; > else if (funcform->provolatile == PROVOLATILE_STABLE && > contain_volatile_functions(newexpr)) > goto fail; > > As the comment says, this wasn't really coded with an eye towards > "catching user error". Rather, there are known use-cases where people > intentionally use SQL wrapper functions to lie about the mutability > of some underlying function; inlining would expose the truth of the > matter and thus defeat such hacks. Now I'd be the first to agree > that this isn't a terribly high-performance way of doing that, but > the point here was to not change the behavior that existed before > SQL inlining did. some points: *) there are several cases that look superficially immutable to the user but are really stable. Mostly this comes up with date time functions because of the database dependency. The issue I have with the status quo is that the server punishes you by mis-decorating the function (it gets treaded as volatile). *) some formulations of functions like to_char() are immutable depending on arguments (julian day for example). so if the user wraps this for purposes of indexing and then uses that same function for querying, the operation is non inlineable. *) unless you really know your stuff server inlining is completely abstracted from you, except in terms of performance Adding up the above, the way things work today is kind of a pain -- in may ways I feel that if I mark a function IMMUTABLE, the server should not overrule me. If that argument doesn't hold water, then server should at least tell you when a function is inlineable -- perhaps via \df+. merlin