github.com/eden-framework/sqlx@v0.0.2/postgresqlconnector/schemas.go (about)

     1  package postgresqlconnector
     2  
     3  import (
     4  	"regexp"
     5  	"strings"
     6  
     7  	"github.com/eden-framework/sqlx"
     8  	"github.com/eden-framework/sqlx/builder"
     9  )
    10  
    11  func toInterfaces(list ...string) []interface{} {
    12  	s := make([]interface{}, len(list))
    13  	for i, v := range list {
    14  		s[i] = v
    15  	}
    16  	return s
    17  }
    18  
    19  func dbFromInformationSchema(db sqlx.DBExecutor) *sqlx.Database {
    20  	d := db.D()
    21  
    22  	dbName := d.Name
    23  	dbSchema := d.Schema
    24  	tableNames := d.Tables.TableNames()
    25  
    26  	d = sqlx.NewDatabase(dbName).WithSchema(dbSchema)
    27  
    28  	tableColumnSchema := SchemaDatabase.T(&ColumnSchema{}).WithSchema("information_schema")
    29  	columnSchemaList := make([]ColumnSchema, 0)
    30  
    31  	tableSchema := "public"
    32  	if d.Schema != "" {
    33  		tableSchema = d.Schema
    34  	}
    35  
    36  	stmt := builder.Select(tableColumnSchema.Columns.Clone()).From(tableColumnSchema,
    37  		builder.Where(
    38  			builder.And(
    39  				tableColumnSchema.F("TABLE_SCHEMA").Eq(tableSchema),
    40  				tableColumnSchema.F("TABLE_NAME").In(toInterfaces(tableNames...)...),
    41  			),
    42  		),
    43  	)
    44  
    45  	err := db.QueryExprAndScan(stmt, &columnSchemaList)
    46  	if err != nil {
    47  		panic(err)
    48  	}
    49  
    50  	for _, columnSchema := range columnSchemaList {
    51  		table := d.Table(columnSchema.TABLE_NAME)
    52  		if table == nil {
    53  			table = builder.T(columnSchema.TABLE_NAME)
    54  			d.AddTable(table)
    55  		}
    56  		col := builder.Col(columnSchema.COLUMN_NAME)
    57  		table.AddCol(col)
    58  	}
    59  
    60  	if tableColumnSchema.Columns.Len() != 0 {
    61  		tableIndexSchema := SchemaDatabase.T(&IndexSchema{})
    62  
    63  		indexList := make([]IndexSchema, 0)
    64  
    65  		err = db.QueryExprAndScan(
    66  			builder.Select(tableIndexSchema.Columns.Clone()).
    67  				From(
    68  					tableIndexSchema,
    69  					builder.Where(
    70  						builder.And(
    71  							tableIndexSchema.F("TABLE_SCHEMA").Eq(tableSchema),
    72  							tableIndexSchema.F("TABLE_NAME").In(toInterfaces(tableNames...)...),
    73  						),
    74  					),
    75  				),
    76  			&indexList,
    77  		)
    78  
    79  		if err != nil {
    80  			panic(err)
    81  		}
    82  
    83  		for _, indexSchema := range indexList {
    84  			table := d.Table(indexSchema.TABLE_NAME)
    85  
    86  			key := &builder.Key{}
    87  			key.Name = indexSchema.INDEX_NAME[len(table.Name)+1:]
    88  			key.Method = strings.ToUpper(regexp.MustCompile(`USING ([^ ]+)`).FindString(indexSchema.INDEX_DEF)[6:])
    89  			key.IsUnique = strings.Index(indexSchema.INDEX_DEF, "UNIQUE") > -1
    90  
    91  			fields := regexp.MustCompile(`\([^\)]+\)`).FindString(indexSchema.INDEX_DEF)
    92  			if len(fields) > 0 {
    93  				fields = fields[1 : len(fields)-1]
    94  			}
    95  			key.Columns, _ = table.Cols(strings.Split(fields, ", ")...)
    96  			table.AddKey(key)
    97  		}
    98  	}
    99  
   100  	return d
   101  }
   102  
   103  var SchemaDatabase = sqlx.NewDatabase("INFORMATION_SCHEMA")
   104  
   105  func init() {
   106  	SchemaDatabase.Register(&ColumnSchema{})
   107  	SchemaDatabase.Register(&IndexSchema{})
   108  }
   109  
   110  type ColumnSchema struct {
   111  	TABLE_SCHEMA string `db:"table_schema"`
   112  	TABLE_NAME   string `db:"table_name"`
   113  	COLUMN_NAME  string `db:"column_name"`
   114  }
   115  
   116  func (ColumnSchema) TableName() string {
   117  	return "columns"
   118  }
   119  
   120  type IndexSchema struct {
   121  	TABLE_SCHEMA string `db:"schemaname"`
   122  	TABLE_NAME   string `db:"tablename"`
   123  	INDEX_NAME   string `db:"indexname"`
   124  	INDEX_DEF    string `db:"indexdef"`
   125  }
   126  
   127  func (IndexSchema) TableName() string {
   128  	return "pg_indexes"
   129  }