forked from cyrilgdn/terraform-provider-postgresql
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request cyrilgdn#2 from SpencerBinXia/table-sequence-data-…
…sources Postgresql_tables and postgresql_sequences data sources
- Loading branch information
Showing
11 changed files
with
775 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package postgresql | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
) | ||
|
||
const ( | ||
queryConcatKeywordWhere = "WHERE" | ||
queryConcatKeywordAnd = "AND" | ||
queryArrayKeywordAny = "ANY" | ||
queryArrayKeywordAll = "ALL" | ||
likePatternQuery = "LIKE" | ||
notLikePatternQuery = "NOT LIKE" | ||
regexPatternQuery = "~" | ||
) | ||
|
||
func applyOptionalPatternMatchingToQuery(query string, patternMatchingTarget string, queryConcatKeyword *string, d *schema.ResourceData) string { | ||
likeAnyPatterns := d.Get("like_any_patterns").([]interface{}) | ||
likeAllPatterns := d.Get("like_all_patterns").([]interface{}) | ||
notLikeAllPatterns := d.Get("not_like_all_patterns").([]interface{}) | ||
regexPattern := d.Get("regex_pattern").(string) | ||
|
||
if len(likeAnyPatterns) > 0 { | ||
query = finalizeQueryWithPatternMatching(query, patternMatchingTarget, likePatternQuery, generatePatternArrayString(likeAnyPatterns, queryArrayKeywordAny), queryConcatKeyword) | ||
} | ||
if len(likeAllPatterns) > 0 { | ||
query = finalizeQueryWithPatternMatching(query, patternMatchingTarget, likePatternQuery, generatePatternArrayString(likeAllPatterns, queryArrayKeywordAll), queryConcatKeyword) | ||
} | ||
if len(notLikeAllPatterns) > 0 { | ||
query = finalizeQueryWithPatternMatching(query, patternMatchingTarget, notLikePatternQuery, generatePatternArrayString(notLikeAllPatterns, queryArrayKeywordAll), queryConcatKeyword) | ||
} | ||
if regexPattern != "" { | ||
query = finalizeQueryWithPatternMatching(query, patternMatchingTarget, regexPatternQuery, fmt.Sprintf("'%s'", regexPattern), queryConcatKeyword) | ||
} | ||
|
||
return query | ||
} | ||
|
||
func generatePatternArrayString(patterns []interface{}, queryArrayKeyword string) string { | ||
formattedPatterns := []string{} | ||
|
||
for _, pattern := range patterns { | ||
formattedPatterns = append(formattedPatterns, fmt.Sprintf("'%s'", pattern.(string))) | ||
} | ||
return fmt.Sprintf("%s (array[%s])", queryArrayKeyword, strings.Join(formattedPatterns, ",")) | ||
} | ||
|
||
func applyEqualsAnyFilteringToQuery(query string, queryConcatKeyword *string, objectKeyword string, objects []interface{}) string { | ||
if len(objects) > 0 { | ||
query = fmt.Sprintf("%s %s %s = %s", query, *queryConcatKeyword, objectKeyword, generatePatternArrayString(objects, queryArrayKeywordAny)) | ||
*queryConcatKeyword = queryConcatKeywordAnd | ||
} | ||
|
||
return query | ||
} | ||
|
||
func finalizeQueryWithPatternMatching(query string, patternMatchingTarget string, additionalQuery string, pattern string, queryConcatKeyword *string) string { | ||
finalizedQuery := fmt.Sprintf("%s %s %s %s %s", query, *queryConcatKeyword, patternMatchingTarget, additionalQuery, pattern) | ||
|
||
//Set the query concatenation keyword from WHERE to AND if it has already been used. | ||
*queryConcatKeyword = queryConcatKeywordAnd | ||
|
||
return finalizedQuery | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package postgresql | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
) | ||
|
||
const ( | ||
sequenceQuery = ` | ||
SELECT sequence_name, sequence_schema, data_type | ||
FROM information_schema.sequences | ||
` | ||
sequencePatternMatchingTarget = "sequence_name" | ||
sequenceSchemaKeyword = "sequence_schema" | ||
) | ||
|
||
func dataSourcePostgreSQLDatabaseSequences() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: PGResourceFunc(dataSourcePostgreSQLSequencesRead), | ||
Schema: map[string]*schema.Schema{ | ||
"database": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
Description: "The PostgreSQL database which will be queried for sequence names", | ||
}, | ||
"schemas": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
MinItems: 0, | ||
Description: "The PostgreSQL schema(s) which will be queried for sequence names. Queries all schemas in the database by default", | ||
}, | ||
"like_any_patterns": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
MinItems: 0, | ||
Description: "Expression(s) which will be pattern matched against sequence names in the query using the PostgreSQL LIKE ANY operator", | ||
}, | ||
"like_all_patterns": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
MinItems: 0, | ||
Description: "Expression(s) which will be pattern matched against sequence names in the query using the PostgreSQL LIKE ALL operator", | ||
}, | ||
"not_like_all_patterns": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
MinItems: 0, | ||
Description: "Expression(s) which will be pattern matched against sequence names in the query using the PostgreSQL NOT LIKE ALL operator", | ||
}, | ||
"regex_pattern": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Description: "Expression which will be pattern matched against sequence names in the query using the PostgreSQL ~ (regular expression match) operator", | ||
}, | ||
"sequences": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"object_name": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"schema_name": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"data_type": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
}, | ||
Description: "The list of PostgreSQL sequence names retrieved by this data source. Note that this returns a set, so duplicate table names across different schemas will be consolidated.", | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func dataSourcePostgreSQLSequencesRead(db *DBConnection, d *schema.ResourceData) error { | ||
database := d.Get("database").(string) | ||
|
||
txn, err := startTransaction(db.client, database) | ||
if err != nil { | ||
return err | ||
} | ||
defer deferredRollback(txn) | ||
|
||
query := sequenceQuery | ||
queryConcatKeyword := queryConcatKeywordWhere | ||
|
||
query = applyEqualsAnyFilteringToQuery(query, &queryConcatKeyword, sequenceSchemaKeyword, d.Get("schemas").([]interface{})) | ||
query = applyOptionalPatternMatchingToQuery(query, sequencePatternMatchingTarget, &queryConcatKeyword, d) | ||
|
||
rows, err := txn.Query(query) | ||
if err != nil { | ||
return err | ||
} | ||
defer rows.Close() | ||
|
||
sequences := make([]interface{}, 0) | ||
for rows.Next() { | ||
var object_name string | ||
var schema_name string | ||
var data_type string | ||
|
||
if err = rows.Scan(&object_name, &schema_name, &data_type); err != nil { | ||
return fmt.Errorf("could not scan sequence output for database: %w", err) | ||
} | ||
|
||
result := make(map[string]interface{}) | ||
result["object_name"] = object_name | ||
result["schema_name"] = schema_name | ||
result["data_type"] = data_type | ||
sequences = append(sequences, result) | ||
} | ||
|
||
d.Set("sequences", sequences) | ||
d.SetId(generateDataSourceSequencesID(d, database)) | ||
|
||
return nil | ||
} | ||
|
||
func generateDataSourceSequencesID(d *schema.ResourceData, databaseName string) string { | ||
return strings.Join([]string{ | ||
databaseName, | ||
generatePatternArrayString(d.Get("schemas").([]interface{}), queryArrayKeywordAny), | ||
generatePatternArrayString(d.Get("like_any_patterns").([]interface{}), queryArrayKeywordAny), | ||
generatePatternArrayString(d.Get("like_all_patterns").([]interface{}), queryArrayKeywordAll), | ||
generatePatternArrayString(d.Get("not_like_all_patterns").([]interface{}), queryArrayKeywordAll), | ||
d.Get("regex_pattern").(string), | ||
}, "_") | ||
} |
Oops, something went wrong.