(ctx context.Context, session *Session)
| 708 | } |
| 709 | |
| 710 | func (s *ShowColumnsStatement) Execute(ctx context.Context, session *Session) (*Result, error) { |
| 711 | if session.InReadWriteTransaction() { |
| 712 | // INFORMATION_SCHEMA can not be used in read-write transaction. |
| 713 | // https://cloud.google.com/spanner/docs/information-schema |
| 714 | return nil, errors.New(`"SHOW COLUMNS" can not be used in a read-write transaction`) |
| 715 | } |
| 716 | |
| 717 | stmt := spanner.Statement{SQL: `SELECT |
| 718 | C.COLUMN_NAME as Field, |
| 719 | C.SPANNER_TYPE as Type, |
| 720 | C.IS_NULLABLE as ` + "`NULL`" + `, |
| 721 | I.INDEX_TYPE as Key, |
| 722 | IC.COLUMN_ORDERING as Key_Order, |
| 723 | CONCAT(CO.OPTION_NAME, "=", CO.OPTION_VALUE) as Options |
| 724 | FROM |
| 725 | INFORMATION_SCHEMA.COLUMNS C |
| 726 | LEFT JOIN |
| 727 | INFORMATION_SCHEMA.INDEX_COLUMNS IC USING(TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME) |
| 728 | LEFT JOIN |
| 729 | INFORMATION_SCHEMA.INDEXES I USING(TABLE_SCHEMA, TABLE_NAME, INDEX_NAME) |
| 730 | LEFT JOIN |
| 731 | INFORMATION_SCHEMA.COLUMN_OPTIONS CO USING(TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME) |
| 732 | WHERE |
| 733 | LOWER(C.TABLE_SCHEMA) = LOWER(@table_schema) AND LOWER(C.TABLE_NAME) = LOWER(@table_name) |
| 734 | ORDER BY |
| 735 | C.ORDINAL_POSITION ASC`, |
| 736 | Params: map[string]interface{}{"table_name": s.Table, "table_schema": s.Schema}} |
| 737 | |
| 738 | iter, _ := session.RunQuery(ctx, stmt) |
| 739 | defer iter.Stop() |
| 740 | |
| 741 | rows, columnNames, err := parseQueryResult(iter) |
| 742 | if err != nil { |
| 743 | return nil, err |
| 744 | } |
| 745 | if len(rows) == 0 { |
| 746 | return nil, fmt.Errorf("table %q doesn't exist in schema %q", s.Table, s.Schema) |
| 747 | } |
| 748 | |
| 749 | return &Result{ |
| 750 | ColumnNames: columnNames, |
| 751 | Rows: rows, |
| 752 | AffectedRows: len(rows), |
| 753 | }, nil |
| 754 | } |
| 755 | |
| 756 | func extractSchemaAndTable(s string) (string, string) { |
| 757 | schema, table, found := strings.Cut(s, ".") |
nothing calls this directly
no test coverage detected