@@ -682,6 +682,8 @@ func (b *Builder) buildResolvedTable(inScope *scope, db, schema, name string, as
682682 asOfLit = asof
683683 }
684684
685+
686+ // TODO: even if it's a view here; it might not have been before?
685687 if view := b .resolveView (name , database , asOfLit ); view != nil {
686688 // TODO: Schema name
687689 return resolvedViewScope (outScope , view , db , name )
@@ -812,56 +814,74 @@ func resolvedViewScope(outScope *scope, view sql.Node, db string, name string) (
812814 return outScope , true
813815}
814816
817+ func (b * Builder ) resolveViewDef (name string , database sql.Database , viewDef sql.ViewDefinition , asOf interface {}) * sql.View {
818+ oldOpts := b .parserOpts
819+ defer func () {
820+ b .parserOpts = oldOpts
821+ }()
822+ outerAsOf := b .ViewCtx ().AsOf
823+ outerDb := b .ViewCtx ().DbName
824+ b .ViewCtx ().AsOf = asOf
825+ b .ViewCtx ().DbName = database .Name ()
826+ defer func () {
827+ b .ViewCtx ().AsOf = outerAsOf
828+ b .ViewCtx ().DbName = outerDb
829+ }()
830+ b .parserOpts = sql .NewSqlModeFromString (viewDef .SqlMode ).ParserOptions ()
831+ stmt , _ , _ , err := b .parser .ParseWithOptions (b .ctx , viewDef .CreateViewStatement , ';' , false , b .parserOpts )
832+ if err != nil {
833+ b .handleErr (err )
834+ }
835+ node , _ , err := b .bindOnlyWithDatabase (database , stmt , viewDef .CreateViewStatement )
836+ if err != nil {
837+ // TODO: Need to account for non-existing functions or
838+ // users without appropriate privilege to the referenced table/column/function.
839+ if sql .ErrTableNotFound .Is (err ) || sql .ErrColumnNotFound .Is (err ) {
840+ // TODO: ALTER VIEW should not return this error
841+ err = sql .ErrInvalidRefInView .New (database .Name (), name )
842+ }
843+ b .handleErr (err )
844+ }
845+ create , ok := node .(* plan.CreateView )
846+ if ! ok {
847+ err = fmt .Errorf ("expected create view statement, found: %T" , node )
848+ b .handleErr (err )
849+ }
850+ switch n := create .Child .(type ) {
851+ case * plan.SubqueryAlias :
852+ return n .AsView (viewDef .CreateViewStatement )
853+ default :
854+ view := plan .NewSubqueryAlias (name , create .Definition .TextDefinition , n ).AsView (viewDef .CreateViewStatement )
855+ b .qFlags .Set (sql .QFlagRelSubquery )
856+ return view
857+ }
858+ }
859+
815860func (b * Builder ) resolveView (name string , database sql.Database , asOf interface {}) sql.Node {
816861 var view * sql.View
817862
818- if vdb , vok := database .(sql.ViewDatabase ); vok {
863+ if asOf != nil {
864+ vdb , vok := database .(sql.VersionedViewDatabase )
865+ if ! vok {
866+ b .handleErr (sql .ErrAsOfNotSupported .New (database .Name ()))
867+ }
868+ viewDef , vdok , err := vdb .GetViewDefinitionAsOf (b .ctx , name , asOf )
869+ if err != nil {
870+ b .handleErr (err )
871+ }
872+ if vdok {
873+ view = b .resolveViewDef (name , database , viewDef , asOf )
874+ }
875+ } else if vdb , vok := database .(sql.ViewDatabase ); vok {
819876 viewDef , vdok , err := vdb .GetViewDefinition (b .ctx , name )
820877 if err != nil {
821878 b .handleErr (err )
822879 }
823- oldOpts := b .parserOpts
824- defer func () {
825- b .parserOpts = oldOpts
826- }()
827880 if vdok {
828- outerAsOf := b .ViewCtx ().AsOf
829- outerDb := b .ViewCtx ().DbName
830- b .ViewCtx ().AsOf = asOf
831- b .ViewCtx ().DbName = database .Name ()
832- defer func () {
833- b .ViewCtx ().AsOf = outerAsOf
834- b .ViewCtx ().DbName = outerDb
835- }()
836- b .parserOpts = sql .NewSqlModeFromString (viewDef .SqlMode ).ParserOptions ()
837- stmt , _ , _ , err := b .parser .ParseWithOptions (b .ctx , viewDef .CreateViewStatement , ';' , false , b .parserOpts )
838- if err != nil {
839- b .handleErr (err )
840- }
841- node , _ , err := b .bindOnlyWithDatabase (database , stmt , viewDef .CreateViewStatement )
842- if err != nil {
843- // TODO: Need to account for non-existing functions or
844- // users without appropriate privilege to the referenced table/column/function.
845- if sql .ErrTableNotFound .Is (err ) || sql .ErrColumnNotFound .Is (err ) {
846- // TODO: ALTER VIEW should not return this error
847- err = sql .ErrInvalidRefInView .New (database .Name (), name )
848- }
849- b .handleErr (err )
850- }
851- create , ok := node .(* plan.CreateView )
852- if ! ok {
853- err = fmt .Errorf ("expected create view statement, found: %T" , node )
854- b .handleErr (err )
855- }
856- switch n := create .Child .(type ) {
857- case * plan.SubqueryAlias :
858- view = n .AsView (viewDef .CreateViewStatement )
859- default :
860- view = plan .NewSubqueryAlias (name , create .Definition .TextDefinition , n ).AsView (viewDef .CreateViewStatement )
861- b .qFlags .Set (sql .QFlagRelSubquery )
862- }
881+ view = b .resolveViewDef (name , database , viewDef , asOf )
863882 }
864883 }
884+
865885 // If we didn't find the view from the database directly, use the in-session registry
866886 if view == nil {
867887 view , _ = b .ctx .GetViewRegistry ().View (database .Name (), name )
0 commit comments