Skip to content

Commit 6e2a83d

Browse files
authored
Merge pull request #32 from Recidiviz/dan/view-schema-perf
Detect view schema from changed catalog
2 parents 1c53f99 + d3f3cba commit 6e2a83d

File tree

3 files changed

+47
-29
lines changed

3 files changed

+47
-29
lines changed

internal/contentdata/repository.go

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,27 +104,50 @@ func (r *Repository) CreateTable(ctx context.Context, tx *connection.Tx, table *
104104
return nil
105105
}
106106

107-
func (r *Repository) CreateView(ctx context.Context, tx *connection.Tx, table *bigqueryv2.Table) error {
107+
func getSchemaFromResult(result sql.Result) (*bigqueryv2.TableSchema, error) {
108+
changedCatalog, err := zetasqlite.ChangedCatalogFromResult(result)
109+
if err != nil {
110+
return nil, fmt.Errorf("failed to get changed catalog: %w", err)
111+
}
112+
if len(changedCatalog.Table.Added) != 1 {
113+
return nil, fmt.Errorf("catalog detected %d tables added; but expected one", len(changedCatalog.Table.Added))
114+
}
115+
createdTable := changedCatalog.Table.Added[0]
116+
fields := make([]*bigqueryv2.TableFieldSchema, 0, len(createdTable.Columns))
117+
for _, col := range createdTable.Columns {
118+
zetasqlType, err := col.Type.ToZetaSQLType()
119+
if err != nil {
120+
return nil, fmt.Errorf("failed to get zetasql type: %w", err)
121+
}
122+
fields = append(fields, types.TableFieldSchemaFromZetaSQLType(col.Name, zetasqlType))
123+
}
124+
125+
return &bigqueryv2.TableSchema{Fields: fields}, nil
126+
}
127+
128+
func (r *Repository) CreateView(ctx context.Context, tx *connection.Tx, table *bigqueryv2.Table) (*bigqueryv2.TableSchema, error) {
108129
if err := tx.ContentRepoMode(); err != nil {
109-
return err
130+
return nil, err
110131
}
111132
defer func() {
112133
_ = tx.MetadataRepoMode()
113134
}()
114135
ref := table.TableReference
115136
if ref == nil {
116-
return fmt.Errorf("TableReference is nil")
137+
return nil, fmt.Errorf("TableReference is nil")
117138
}
118139
viewDefinition := table.View
119140
if viewDefinition == nil {
120-
return fmt.Errorf("ViewDefinition is nil")
141+
return nil, fmt.Errorf("ViewDefinition is nil")
121142
}
122143
tablePath := r.tablePath(ref.ProjectId, ref.DatasetId, ref.TableId)
123144
query := fmt.Sprintf("CREATE VIEW `%s` AS (%s)", tablePath, strings.TrimRight(viewDefinition.Query, ViewQueryEndCutset))
124-
if _, err := tx.Tx().ExecContext(ctx, query); err != nil {
125-
return fmt.Errorf("failed to create view %s: %w", query, err)
145+
result, err := tx.Tx().ExecContext(ctx, query)
146+
if err != nil {
147+
return nil, fmt.Errorf("failed to create view %s: %w", query, err)
126148
}
127-
return nil
149+
schema, err := getSchemaFromResult(result)
150+
return schema, err
128151
}
129152

130153
func (r *Repository) encodeSchemaField(field *bigqueryv2.TableFieldSchema) string {

server/handler.go

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2644,18 +2644,6 @@ func createTableMetadata(ctx context.Context, tx *connection.Tx, server *Server,
26442644
if table.View != nil {
26452645
table.Type = string(internaltypes.ViewTableType)
26462646
table.View.Query = strings.TrimRight(table.View.Query, contentdata.ViewQueryEndCutset)
2647-
response, err := server.contentRepo.Query(
2648-
ctx,
2649-
tx,
2650-
table.TableReference.ProjectId,
2651-
table.TableReference.DatasetId,
2652-
fmt.Sprintf("SELECT * FROM (%s) LIMIT 0", table.View.Query),
2653-
nil,
2654-
)
2655-
if err != nil {
2656-
return nil, errInvalidQuery(fmt.Sprintf("could not determine schema from query: %s", err.Error()))
2657-
}
2658-
table.Schema = response.Schema
26592647
}
26602648
table.Kind = "bigquery#table"
26612649
table.SelfLink = fmt.Sprintf(
@@ -2703,20 +2691,27 @@ func (h *tablesInsertHandler) Handle(ctx context.Context, r *tablesInsertRequest
27032691
}
27042692
defer tx.RollbackIfNotCommitted()
27052693

2706-
table, serverErr := createTableMetadata(ctx, tx, r.server, r.project, r.dataset, r.table)
2707-
if serverErr != nil {
2708-
return nil, serverErr
2709-
}
2710-
if table.Type == string(internaltypes.DefaultTableType) && table.Schema != nil {
2711-
if err := r.server.contentRepo.CreateTable(ctx, tx, r.table); err != nil {
2694+
if r.table.View != nil {
2695+
schema, err := r.server.contentRepo.CreateView(ctx, tx, r.table)
2696+
if err != nil {
2697+
if strings.HasSuffix(err.Error(), "already exists (1)") {
2698+
return nil, errDuplicate(err.Error())
2699+
}
27122700
return nil, errInvalidQuery(err.Error())
27132701
}
2714-
}
2715-
if table.Type == string(internaltypes.ViewTableType) {
2716-
if err := r.server.contentRepo.CreateView(ctx, tx, r.table); err != nil {
2702+
r.table.Schema = schema
2703+
} else if r.table.Schema != nil {
2704+
if err := r.server.contentRepo.CreateTable(ctx, tx, r.table); err != nil {
2705+
if strings.HasSuffix(err.Error(), "already exists (1)") {
2706+
return nil, errDuplicate(err.Error())
2707+
}
27172708
return nil, errInvalidQuery(err.Error())
27182709
}
27192710
}
2711+
table, serverErr := createTableMetadata(ctx, tx, r.server, r.project, r.dataset, r.table)
2712+
if serverErr != nil {
2713+
return nil, serverErr
2714+
}
27202715
if err := tx.Commit(); err != nil {
27212716
return nil, errInternalError(fmt.Errorf("failed to commit table: %w", err).Error())
27222717
}

server/server_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1223,7 +1223,7 @@ func TestDuplicateTableWithSchema(t *testing.T) {
12231223
t.Fatalf("%+v", ge)
12241224
}
12251225
} else {
1226-
t.Fatalf(("Threre should be error, when table name duplicates."))
1226+
t.Fatalf(("There should be error, when table name duplicates."))
12271227
}
12281228
}
12291229

0 commit comments

Comments
 (0)