It is called from a procedure that also sets the value of ct_global.cts$protocol to the appropriate schema name, thus the need for dynamic sql in the package.
The package executes dynamic sql query once (at initialization) and then returnes results cached in an array. The idea is that when the function is called for the first time for this session, the array will be populated. The first call will take a little time. Subsequent calls to get_optpages should result in a very fast responce.
Like I said, both the package and the calling procedure compile without errors. Dbms_sql is used because my db version is 8.1.7.0.0 and the NDS is not available.