-- Since Comp.ai.philosophy is still dead
-- I thought I would introduce a more random
-- version. Unfortunately, while I thought I
-- owned a developers edition of sql server
-- my home version does not work so this
-- code is untested.
declare @x varchar(max);
declare @x2 varchar(max); declare @i int; declare @q varchar(1); declare @l int;
declare @r int;
-- I use @x to store the program
set @x = '''-- Since Comp.ai.philosophy is still dead
-- I thought I would introduce a more random
-- version. Unfortunately, while I thought I
-- owned a developers edition of sql server
-- my home version does not work so this
-- code is untested.
declare @x varchar(max);
declare @x2 varchar(max); declare @i int; declare @q varchar(1); declare @l int;
declare @r int;
-- I use @x to store the program
set @x = ;
-- @q is the quote character
set @q = LEFT(@x,1);
-- the second caracter is the pipe character
-- @i is set to the second instance of the pipe caracter
set @i = CHARINDEX(substring(@x,2,1),@x,3);
-- slice and dice
set @l = round(rand()*(len(@x)-2),0); set @r = round(rand()*(len(@x)-2),0);
set @x2 = substring(@x,3,@l) + @q + @q + @x + @q + right(@x,@r);
-- does the new string execute
begin try
exec(left(@x2,len(@x)-10) end try
begin catch
set @x2 = substring(@x,3,@i-3) + @q + @q + @x + @q + right(@x,len(@x)-@i); end catch;
-- now print the random string if it executes
-- otherwise print the known string;
print @x2;';
-- @q is the quote character
set @q = LEFT(@x,1);
-- the second caracter is the pipe character
-- @i is set to the second instance of the pipe caracter
set @i = CHARINDEX(substring(@x,2,1),@x,3);
-- slice and dice
set @l = round(rand()*(len(@x)-2),0); set @r = round(rand()*(len(@x)-2),0);
set @x2 = substring(@x,3,@l) + @q + @q + @x + @q + right(@x,@r);
-- does the new string execute
begin try
exec(left(@x2,len(@x)-10) end try
begin catch
set @x2 = substring(@x,3,@i-3) + @q + @q + @x + @q + right(@x,len(@x)-@i); end catch;
-- now print the random string if it executes
-- otherwise print the known string;
print @x2;
My random version didn't work.
I gave up and tried it on a machine where I had sqlserver installed.
While playing around with it I came up with this more direct version
of the earlier program:
declare @q varchar(1);
declare @p varchar(1);
declare @x varchar(max);
set @q='''';
set @p='|';
set @x='declare @q varchar(1);
declare @p varchar(1);
declare @x varchar(max);
set @q='''''''';
set @p=''|'';
set @x=''||'';
print REPLACE(@x,@p+@p,REPLACE(@x,@q,@q+@q));';
print REPLACE(@x,@p+@p,REPLACE(@x,@q,@q+@q));
I got a somewhat random version to work but it broke
on the fourth recursion. I needed to make sure @q
was set or the routine failed. This routine would
be quite brittle. It turns out exec() doesn't allow
a function, at least on the version I'm running.
The easiest way to handle the try/catch was like
this except first setting @x2 to the randomized
version rather than the non-random version.
set @pr = '
print @x2+@pr;';
set @x2=REPLACE(@x,@p+@p,REPLACE(@x,@q,@q+@q));
begin try
exec(@x2);
print '--new routine';
end try
begin catch
print '--old routine';
set @x2=REPLACE(@x,@p+@p,REPLACE(@x,@q,@q+@q));
end catch
print @x2+@pr;
a less brittle routine would need to do some basic
checking for health such as replacing duplicate declares
with new names and making sure quotes were paired.
I guess I'll have to get a developers edition of sqlserver 2012.
I realized I can't manually handle the generations. While the
4th generation broke I didn't allow the routines that didn't
break to reproduce. It seems to me that I need to encapsulate
the routine and save off the generations. The simplest approach
would be to run the whole thing from within an exec. I don't
know if exec can be nested. I'll need to find out. If so
then I know temp tables survive a dynamic sql call.
would be shorter, it would make hopeful monsters less likely
to be able to produce multiple children. Letting the routine
create the temp table would also allow for the possibility
of creating two unique tables. It seems unlikely the routine
would ever write to multiple unique tables who knows.
I think the simplest selection algorithm would be number
of unique children within a certain number of offspring
with population control starting at some point.
In my first random reproducer the fourth generation produced
an empty string. During development I found several cases
where it duplicated some of the set commands. Most of the
cases just appended to comment lines. I specifically included
lots of comment lines so this would be more probable. I
think I need to have the routine inject new characters so
the pool isn't limited to the one's in the original routine.
It may take awhile for me to get my hands on a developer's
edition of sqlserver. You won't hear again until I get some results, positive or negative.
Some milestones would be: surviving generations 10, 100, 1000, etc.
producing multiple offspring in a single run.
creating multiple tables.
creating a permanent table.
While I could make the production of multiple offsring
more likely by adding lots of comments just before and
after the insert statement I don't think my originator
will be that generous, at least to start.