@@ -18,6 +18,7 @@ const (
1818 dataShareProducerNamespaceAttr = "producer_namespace"
1919 dataShareCreatedAttr = "created"
2020 dataShareSchemasAttr = "schemas"
21+ dataShareSchemaTablesAttr = "schema_tables"
2122)
2223
2324func redshiftDatashare () * schema.Resource {
@@ -92,6 +93,18 @@ such as RA3.
9293 },
9394 },
9495 },
96+ dataShareSchemaTablesAttr : {
97+ Type : schema .TypeSet ,
98+ Optional : true ,
99+ Description : "Defines which schema tables are exposed to the data share." ,
100+ Set : schema .HashString ,
101+ Elem : & schema.Schema {
102+ Type : schema .TypeString ,
103+ StateFunc : func (val interface {}) string {
104+ return strings .ToLower (val .(string ))
105+ },
106+ },
107+ },
95108 },
96109 }
97110}
@@ -152,6 +165,20 @@ func resourceRedshiftDatashareCreate(db *DBConnection, d *schema.ResourceData) e
152165 }
153166 }
154167
168+ var schemas []string
169+ var tables []string
170+ for _ , schemaTable := range d .Get (dataShareSchemaTablesAttr ).(* schema.Set ).List () {
171+ schemaName := strings .Split (schemaTable .(string ), "." )[0 ]
172+ appendIfTrue (contains (schemas , schemaName ), schemaName , & schemas )
173+ tableName := schemaTable .(string )
174+ appendIfTrue (contains (tables , tableName ), tableName , & tables )
175+ }
176+
177+ err = addSchemaTablesToDatashare (tx , shareName , schemas , tables )
178+ if err != nil {
179+ return err
180+ }
181+
155182 if err = tx .Commit (); err != nil {
156183 return fmt .Errorf ("could not commit transaction: %w" , err )
157184 }
@@ -172,6 +199,19 @@ func addSchemaToDatashare(tx *sql.Tx, shareName string, schemaName string) error
172199 return err
173200}
174201
202+ func addSchemaTablesToDatashare (tx * sql.Tx , shareName string , schemas []string , tables []string ) error {
203+ schemasString := strings .Join (schemas , "," )
204+ tablesString := strings .Join (tables , "," )
205+ err := resourceRedshiftDatashareAddTablesInSchema (tx , shareName , schemasString , tablesString )
206+ return err
207+ }
208+
209+ func removeSchemaTablesFromDatashare (tx * sql.Tx , shareName string , tables []string ) error {
210+ tablesString := strings .Join (tables , "," )
211+ err := resourceRedshiftDatashareRemoveTablesInSchema (tx , shareName , tablesString )
212+ return err
213+ }
214+
175215func resourceRedshiftDatashareAddSchema (tx * sql.Tx , shareName string , schemaName string ) error {
176216 query := fmt .Sprintf ("ALTER DATASHARE %s ADD SCHEMA %s" , pq .QuoteIdentifier (shareName ), pq .QuoteIdentifier (schemaName ))
177217 log .Printf ("[DEBUG] %s\n " , query )
@@ -208,6 +248,35 @@ func resourceRedshiftDatashareAddAllTables(tx *sql.Tx, shareName string, schemaN
208248 return err
209249}
210250
251+ func resourceRedshiftDatashareAddTablesInSchema (tx * sql.Tx , shareName string , schemas string , tables string ) error {
252+ query := fmt .Sprintf ("ALTER DATASHARE %s ADD SCHEMA %s" , pq .QuoteIdentifier (shareName ), pq .QuoteIdentifier (schemas ))
253+ log .Printf ("[DEBUG] %s\n " , query )
254+ _ , err := tx .Exec (query )
255+ if err != nil {
256+ // if the schema is already in the datashare we get a "duplicate schema" error code. This is fine.
257+ if pqErr , ok := err .(* pq.Error ); ok {
258+ if string (pqErr .Code ) == pqErrorCodeDuplicateSchema {
259+ log .Printf ("[WARN] Schema %s already exists in datashare %s\n " , schemas , shareName )
260+ } else {
261+ return err
262+ }
263+ } else {
264+ return err
265+ }
266+ }
267+ query = fmt .Sprintf ("ALTER DATASHARE %s ADD TABLE %s" , pq .QuoteIdentifier (shareName ), pq .QuoteIdentifier (tables ))
268+ log .Printf ("[DEBUG] %s\n " , query )
269+ _ , err = tx .Exec (query )
270+ return err
271+ }
272+
273+ func resourceRedshiftDatashareRemoveTablesInSchema (tx * sql.Tx , shareName string , tables string ) error {
274+ query := fmt .Sprintf ("ALTER DATASHARE %s REMOVE TABLE %s" , pq .QuoteIdentifier (shareName ), pq .QuoteIdentifier (tables ))
275+ log .Printf ("[DEBUG] %s\n " , query )
276+ _ , err := tx .Exec (query )
277+ return err
278+ }
279+
211280func removeSchemaFromDatashare (tx * sql.Tx , shareName string , schemaName string ) error {
212281 err := resourceRedshiftDatashareRemoveAllFunctions (tx , shareName , schemaName )
213282 if err != nil {
@@ -293,6 +362,10 @@ func resourceRedshiftDatashareRead(db *DBConnection, d *schema.ResourceData) err
293362 return err
294363 }
295364
365+ if err = readDatashareSchemaTables (tx , shareName , d ); err != nil {
366+ return err
367+ }
368+
296369 if err = tx .Commit (); err != nil {
297370 return err
298371 }
@@ -328,6 +401,34 @@ func readDatashareSchemas(tx *sql.Tx, shareName string, d *schema.ResourceData)
328401 return nil
329402}
330403
404+ func readDatashareSchemaTables (tx * sql.Tx , shareName string , d * schema.ResourceData ) error {
405+ query := `
406+ SELECT
407+ object_name
408+ FROM svv_datashare_objects
409+ WHERE share_type = 'OUTBOUND'
410+ AND object_type = 'table'
411+ AND share_name = $1
412+ `
413+ log .Printf ("[DEBUG] %s, $1=%s\n " , query , shareName )
414+ rows , err := tx .Query (query , shareName )
415+ if err != nil {
416+ return err
417+ }
418+ defer rows .Close ()
419+
420+ schemaTables := schema .NewSet (schema .HashString , nil )
421+ for rows .Next () {
422+ var schemaTableName string
423+ if err = rows .Scan (& schemaTableName ); err != nil {
424+ return err
425+ }
426+ schemaTables .Add (schemaTableName )
427+ }
428+ d .Set (dataShareSchemaTablesAttr , schemaTables )
429+ return nil
430+ }
431+
331432func resourceRedshiftDatashareUpdate (db * DBConnection , d * schema.ResourceData ) error {
332433 tx , err := startTransaction (db .client , "" )
333434 if err != nil {
@@ -347,6 +448,10 @@ func resourceRedshiftDatashareUpdate(db *DBConnection, d *schema.ResourceData) e
347448 return err
348449 }
349450
451+ if err := setDatashareTableSchemas (tx , d ); err != nil {
452+ return err
453+ }
454+
350455 if err = tx .Commit (); err != nil {
351456 return fmt .Errorf ("could not commit transaction: %w" , err )
352457 }
@@ -420,6 +525,48 @@ func setDatashareSchemas(tx *sql.Tx, d *schema.ResourceData) error {
420525 return nil
421526}
422527
528+ func setDatashareTableSchemas (tx * sql.Tx , d * schema.ResourceData ) error {
529+ if ! d .HasChange (dataShareSchemaTablesAttr ) {
530+ return nil
531+ }
532+ before , after := d .GetChange (dataShareSchemaTablesAttr )
533+ if before == nil {
534+ before = schema .NewSet (schema .HashString , nil )
535+ }
536+ if after == nil {
537+ after = schema .NewSet (schema .HashString , nil )
538+ }
539+
540+ add := after .(* schema.Set ).Difference (before .(* schema.Set ))
541+ remove := before .(* schema.Set ).Difference (after .(* schema.Set ))
542+
543+ shareName := d .Get (dataShareSchemaTablesAttr ).(string )
544+
545+ var schemas []string
546+ var tables []string
547+ for _ , schemaTable := range add .List () {
548+ schemaName := strings .Split (schemaTable .(string ), "." )[0 ]
549+ appendIfTrue (contains (schemas , schemaName ), schemaName , & schemas )
550+ tableName := schemaTable .(string )
551+ appendIfTrue (contains (tables , tableName ), tableName , & tables )
552+ }
553+ err := addSchemaTablesToDatashare (tx , shareName , schemas , tables )
554+ if err != nil {
555+ return err
556+ }
557+
558+ var tablesToBeRemoved []string
559+ for _ , schemaTable := range remove .List () {
560+ tableName := schemaTable .(string )
561+ appendIfTrue (contains (tablesToBeRemoved , tableName ), tableName , & tablesToBeRemoved )
562+ }
563+ if err := removeSchemaTablesFromDatashare (tx , shareName , tablesToBeRemoved ); err != nil {
564+ return err
565+ }
566+
567+ return nil
568+ }
569+
423570func resourceRedshiftDatashareDelete (db * DBConnection , d * schema.ResourceData ) error {
424571 tx , err := startTransaction (db .client , "" )
425572 if err != nil {
0 commit comments