From daf364d5627c7d472262c4c06da8d04bdcb91366 Mon Sep 17 00:00:00 2001 From: Alex Jeannopoulos Date: Mon, 13 Jul 2020 08:58:21 -0400 Subject: [PATCH] Fixed array bounds issue parsing mysql db meta --- README.md | 12 ++++++++---- _test/dbmeta/main.go | 2 +- code_http.md | 4 ++-- dbmeta/codegen.go | 2 +- dbmeta/meta_mysql.go | 4 +++- go.mod | 4 ++-- main.go | 6 +----- packrd/packed-packr.go | 2 +- readme/main.go | 2 +- template/GEN_README.md.tmpl | 2 ++ 10 files changed, 22 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index c19dd2c..de605ce 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,8 @@ Options: --module=example.com/example module path --overwrite Overwrite existing files (default) --no-overwrite disable overwriting files + --windows use windows line endings in generated files + --no-color disable color output --context= context file (json) to populate context with --mapping= mapping file (json) to map sql types to golang/protobuf etc --exec= execute script for custom code generation @@ -273,9 +275,9 @@ The following info is available within use of the exec template. "AdvancesSample" string "\n{{ range $i, $table := .tables }}\n {{$singular := singular $table -}}\n {{$plural := pluralize $table -}}\n {{$title := title $table -}}\n {{$lower := toLower $table -}}\n {{$lowerCamel := toLowerCamelCase $table -}}\n {{$snakeCase := toSnakeCase $table -}}\n {{ printf \"[%-2d] %-20s %-20s %-20s %-20s %-20s %-20s %-20s\" $i $table $singular $plural $title $lower $lowerCamel $snakeCase}}{{- end }}\n\n\n{{ range $i, $table := .tables }}\n {{$name := toUpper $table -}}\n {{$filename := printf \"My%s\" $name -}}\n {{ printf \"[%-2d] %-20s %-20s\" $i $table $filename}}\n {{ GenerateTableFile $table \"custom.go.tmpl\" \"test\" $filename true}}\n{{- end }}\n" - "Config" *dbmeta.Config &dbmeta.Config{SQLType:"sqlite3", SQLConnStr:"./example/sample.db", SQLDatabase:"main", Module:"github.com/alexj212/test", ModelPackageName:"model", ModelFQPN:"github.com/alexj212/test/model", AddJSONAnnotation:true, AddGormAnnotation:true, AddProtobufAnnotation:true, AddXMLAnnotation:true, AddDBAnnotation:true, UseGureguTypes:false, JSONNameFormat:"snake", XMLNameFormat:"snake", ProtobufNameFormat:"", DaoPackageName:"dao", DaoFQPN:"github.com/alexj212/test/dao", APIPackageName:"api", APIFQPN:"github.com/alexj212/test/api", GrpcPackageName:"", GrpcFQPN:"", Swagger:(*dbmeta.SwaggerInfoDetails)(0xc000aac480), ServerPort:8080, ServerHost:"127.0.0.1", Verbose:false, OutDir:".", Overwrite:true, LineEndingCRLF:false, CmdLine:"/tmp/go-build602781270/b001/exe/readme --sqltype=sqlite3 --connstr ./example/sample.db --database main --table invoices", CmdLineWrapped:"/tmp/go-build602781270/b001/exe/readme \\\n --sqltype=sqlite3 \\\n --connstr \\\n ./example/sample.db \\\n --database \\\n main \\\n --table \\\n invoices", CmdLineArgs:[]string{"/tmp/go-build602781270/b001/exe/readme", "--sqltype=sqlite3", "--connstr", "./example/sample.db", "--database", "main", "--table", "invoices"}, FileNamingTemplate:"{{.}}", ModelNamingTemplate:"{{FmtFieldName .}}", FieldNamingTemplate:"{{FmtFieldName (stringifyFirstChar .) }}", string:"", ContextMap:map[string]interface {}{"GenHelp":"Usage of gen:\n\tgen [-v] --sqltype=mysql --connstr \"user:password@/dbname\" --database --module=example.com/example [--json] [--gorm] [--guregu] [--generate-dao] [--generate-proj]\ngit fetch up\n sqltype - sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n\n\nOptions:\n --sqltype=mysql sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n -c, --connstr=nil database connection string\n -d, --database=nil Database to for connection\n -t, --table= Table to build struct from\n -x, --exclude= Table(s) to exclude\n --templateDir= Template Dir\n --save= Save templates to dir\n --model=model name to set for model package\n --model_naming={{FmtFieldName .}} model naming template to name structs\n --field_naming={{FmtFieldName (stringifyFirstChar .) }} field naming template to name structs\n --file_naming={{.}} file_naming template to name files\n --dao=dao name to set for dao package\n --api=api name to set for api package\n --grpc=grpc name to set for grpc package\n --out=. output dir\n --module=example.com/example module path\n --overwrite Overwrite existing files (default)\n --no-overwrite disable overwriting files\n --context= context file (json) to populate context with\n --mapping= mapping file (json) to map sql types to golang/protobuf etc\n --exec= execute script for custom code generation\n --json Add json annotations (default)\n --no-json Disable json annotations\n --json-fmt=snake json name format [snake | camel | lower_camel | none]\n --xml Add xml annotations (default)\n --no-xml Disable xml annotations\n --xml-fmt=snake xml name format [snake | camel | lower_camel | none]\n --gorm Add gorm annotations (tags)\n --protobuf Add protobuf annotations (tags)\n --proto-fmt=snake proto name format [snake | camel | lower_camel | none]\n --gogo-proto= location of gogo import \n --db Add db annotations (tags)\n --guregu Add guregu null types\n --copy-templates Copy regeneration templates to project directory\n --mod Generate go.mod in output dir\n --makefile Generate Makefile in output dir\n --server Generate server app output dir\n --generate-dao Generate dao functions\n --generate-proj Generate project readme and gitignore\n --rest Enable generating RESTful api\n --run-gofmt run gofmt on output dir\n --host=localhost host for server\n --port=8080 port for server\n --swagger_version=1.0 swagger version\n --swagger_path=/ swagger base path\n --swagger_tos= swagger tos url\n --swagger_contact_name=Me swagger contact name\n --swagger_contact_url=http://me.com/terms.html swagger contact url\n --swagger_contact_email=me@me.com swagger contact email\n -v, --verbose Enable verbose output\n --name_test= perform name test using the --model_naming or --file_naming options\n -h, --help Show usage message\n --version Show version\n\n", "tableInfos":map[string]*dbmeta.ModelInfo{"invoices":(*dbmeta.ModelInfo)(0xc000b91540)}}, TemplateLoader:(dbmeta.TemplateLoader)(0x8a2140)} + "Config" *dbmeta.Config &dbmeta.Config{SQLType:"sqlite3", SQLConnStr:"./example/sample.db", SQLDatabase:"main", Module:"github.com/alexj212/test", ModelPackageName:"model", ModelFQPN:"github.com/alexj212/test/model", AddJSONAnnotation:true, AddGormAnnotation:true, AddProtobufAnnotation:true, AddXMLAnnotation:true, AddDBAnnotation:true, UseGureguTypes:false, JSONNameFormat:"snake", XMLNameFormat:"snake", ProtobufNameFormat:"", DaoPackageName:"dao", DaoFQPN:"github.com/alexj212/test/dao", APIPackageName:"api", APIFQPN:"github.com/alexj212/test/api", GrpcPackageName:"", GrpcFQPN:"", Swagger:(*dbmeta.SwaggerInfoDetails)(0xc000990480), ServerPort:8080, ServerHost:"127.0.0.1", Verbose:false, OutDir:".", Overwrite:true, LineEndingCRLF:false, CmdLine:"/tmp/go-build435445761/b001/exe/readme --sqltype=sqlite3 --connstr ./example/sample.db --database main --table invoices", CmdLineWrapped:"/tmp/go-build435445761/b001/exe/readme \\\n --sqltype=sqlite3 \\\n --connstr \\\n ./example/sample.db \\\n --database \\\n main \\\n --table \\\n invoices", CmdLineArgs:[]string{"/tmp/go-build435445761/b001/exe/readme", "--sqltype=sqlite3", "--connstr", "./example/sample.db", "--database", "main", "--table", "invoices"}, FileNamingTemplate:"{{.}}", ModelNamingTemplate:"{{FmtFieldName .}}", FieldNamingTemplate:"{{FmtFieldName (stringifyFirstChar .) }}", string:"", ContextMap:map[string]interface {}{"GenHelp":"Usage of gen:\n\tgen [-v] --sqltype=mysql --connstr \"user:password@/dbname\" --database --module=example.com/example [--json] [--gorm] [--guregu] [--generate-dao] [--generate-proj]\ngit fetch up\n sqltype - sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n\n\nOptions:\n --sqltype=mysql sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n -c, --connstr=nil database connection string\n -d, --database=nil Database to for connection\n -t, --table= Table to build struct from\n -x, --exclude= Table(s) to exclude\n --templateDir= Template Dir\n --save= Save templates to dir\n --model=model name to set for model package\n --model_naming={{FmtFieldName .}} model naming template to name structs\n --field_naming={{FmtFieldName (stringifyFirstChar .) }} field naming template to name structs\n --file_naming={{.}} file_naming template to name files\n --dao=dao name to set for dao package\n --api=api name to set for api package\n --grpc=grpc name to set for grpc package\n --out=. output dir\n --module=example.com/example module path\n --overwrite Overwrite existing files (default)\n --no-overwrite disable overwriting files\n --windows use windows line endings in generated files\n --no-color disable color output\n --context= context file (json) to populate context with\n --mapping= mapping file (json) to map sql types to golang/protobuf etc\n --exec= execute script for custom code generation\n --json Add json annotations (default)\n --no-json Disable json annotations\n --json-fmt=snake json name format [snake | camel | lower_camel | none]\n --xml Add xml annotations (default)\n --no-xml Disable xml annotations\n --xml-fmt=snake xml name format [snake | camel | lower_camel | none]\n --gorm Add gorm annotations (tags)\n --protobuf Add protobuf annotations (tags)\n --proto-fmt=snake proto name format [snake | camel | lower_camel | none]\n --gogo-proto= location of gogo import \n --db Add db annotations (tags)\n --guregu Add guregu null types\n --copy-templates Copy regeneration templates to project directory\n --mod Generate go.mod in output dir\n --makefile Generate Makefile in output dir\n --server Generate server app output dir\n --generate-dao Generate dao functions\n --generate-proj Generate project readme and gitignore\n --rest Enable generating RESTful api\n --run-gofmt run gofmt on output dir\n --host=localhost host for server\n --port=8080 port for server\n --swagger_version=1.0 swagger version\n --swagger_path=/ swagger base path\n --swagger_tos= swagger tos url\n --swagger_contact_name=Me swagger contact name\n --swagger_contact_url=http://me.com/terms.html swagger contact url\n --swagger_contact_email=me@me.com swagger contact email\n -v, --verbose Enable verbose output\n --name_test= perform name test using the --model_naming or --file_naming options\n -h, --help Show usage message\n --version Show version\n\n", "tableInfos":map[string]*dbmeta.ModelInfo{"invoices":(*dbmeta.ModelInfo)(0xc00117d540)}}, TemplateLoader:(dbmeta.TemplateLoader)(0x89c9d0)} "DatabaseName" string "main" - "GenHelp" string "Usage of gen:\n\tgen [-v] --sqltype=mysql --connstr \"user:password@/dbname\" --database --module=example.com/example [--json] [--gorm] [--guregu] [--generate-dao] [--generate-proj]\ngit fetch up\n sqltype - sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n\n\nOptions:\n --sqltype=mysql sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n -c, --connstr=nil database connection string\n -d, --database=nil Database to for connection\n -t, --table= Table to build struct from\n -x, --exclude= Table(s) to exclude\n --templateDir= Template Dir\n --save= Save templates to dir\n --model=model name to set for model package\n --model_naming={{FmtFieldName .}} model naming template to name structs\n --field_naming={{FmtFieldName (stringifyFirstChar .) }} field naming template to name structs\n --file_naming={{.}} file_naming template to name files\n --dao=dao name to set for dao package\n --api=api name to set for api package\n --grpc=grpc name to set for grpc package\n --out=. output dir\n --module=example.com/example module path\n --overwrite Overwrite existing files (default)\n --no-overwrite disable overwriting files\n --context= context file (json) to populate context with\n --mapping= mapping file (json) to map sql types to golang/protobuf etc\n --exec= execute script for custom code generation\n --json Add json annotations (default)\n --no-json Disable json annotations\n --json-fmt=snake json name format [snake | camel | lower_camel | none]\n --xml Add xml annotations (default)\n --no-xml Disable xml annotations\n --xml-fmt=snake xml name format [snake | camel | lower_camel | none]\n --gorm Add gorm annotations (tags)\n --protobuf Add protobuf annotations (tags)\n --proto-fmt=snake proto name format [snake | camel | lower_camel | none]\n --gogo-proto= location of gogo import \n --db Add db annotations (tags)\n --guregu Add guregu null types\n --copy-templates Copy regeneration templates to project directory\n --mod Generate go.mod in output dir\n --makefile Generate Makefile in output dir\n --server Generate server app output dir\n --generate-dao Generate dao functions\n --generate-proj Generate project readme and gitignore\n --rest Enable generating RESTful api\n --run-gofmt run gofmt on output dir\n --host=localhost host for server\n --port=8080 port for server\n --swagger_version=1.0 swagger version\n --swagger_path=/ swagger base path\n --swagger_tos= swagger tos url\n --swagger_contact_name=Me swagger contact name\n --swagger_contact_url=http://me.com/terms.html swagger contact url\n --swagger_contact_email=me@me.com swagger contact email\n -v, --verbose Enable verbose output\n --name_test= perform name test using the --model_naming or --file_naming options\n -h, --help Show usage message\n --version Show version\n\n" + "GenHelp" string "Usage of gen:\n\tgen [-v] --sqltype=mysql --connstr \"user:password@/dbname\" --database --module=example.com/example [--json] [--gorm] [--guregu] [--generate-dao] [--generate-proj]\ngit fetch up\n sqltype - sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n\n\nOptions:\n --sqltype=mysql sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n -c, --connstr=nil database connection string\n -d, --database=nil Database to for connection\n -t, --table= Table to build struct from\n -x, --exclude= Table(s) to exclude\n --templateDir= Template Dir\n --save= Save templates to dir\n --model=model name to set for model package\n --model_naming={{FmtFieldName .}} model naming template to name structs\n --field_naming={{FmtFieldName (stringifyFirstChar .) }} field naming template to name structs\n --file_naming={{.}} file_naming template to name files\n --dao=dao name to set for dao package\n --api=api name to set for api package\n --grpc=grpc name to set for grpc package\n --out=. output dir\n --module=example.com/example module path\n --overwrite Overwrite existing files (default)\n --no-overwrite disable overwriting files\n --windows use windows line endings in generated files\n --no-color disable color output\n --context= context file (json) to populate context with\n --mapping= mapping file (json) to map sql types to golang/protobuf etc\n --exec= execute script for custom code generation\n --json Add json annotations (default)\n --no-json Disable json annotations\n --json-fmt=snake json name format [snake | camel | lower_camel | none]\n --xml Add xml annotations (default)\n --no-xml Disable xml annotations\n --xml-fmt=snake xml name format [snake | camel | lower_camel | none]\n --gorm Add gorm annotations (tags)\n --protobuf Add protobuf annotations (tags)\n --proto-fmt=snake proto name format [snake | camel | lower_camel | none]\n --gogo-proto= location of gogo import \n --db Add db annotations (tags)\n --guregu Add guregu null types\n --copy-templates Copy regeneration templates to project directory\n --mod Generate go.mod in output dir\n --makefile Generate Makefile in output dir\n --server Generate server app output dir\n --generate-dao Generate dao functions\n --generate-proj Generate project readme and gitignore\n --rest Enable generating RESTful api\n --run-gofmt run gofmt on output dir\n --host=localhost host for server\n --port=8080 port for server\n --swagger_version=1.0 swagger version\n --swagger_path=/ swagger base path\n --swagger_tos= swagger tos url\n --swagger_contact_name=Me swagger contact name\n --swagger_contact_url=http://me.com/terms.html swagger contact url\n --swagger_contact_email=me@me.com swagger contact email\n -v, --verbose Enable verbose output\n --name_test= perform name test using the --model_naming or --file_naming options\n -h, --help Show usage message\n --version Show version\n\n" "NonPrimaryKeyNamesList" []string []string{"CustomerId", "InvoiceDate", "BillingAddress", "BillingCity", "BillingState", "BillingCountry", "BillingPostalCode", "Total"} "NonPrimaryKeysJoined" string "CustomerId,InvoiceDate,BillingAddress,BillingCity,BillingState,BillingCountry,BillingPostalCode,Total" "PrimaryKeyNamesList" []string []string{"InvoiceId"} @@ -283,7 +285,7 @@ The following info is available within use of the exec template. "ShortStructName" string "i" "StructName" string "Invoices" "SwaggerInfo" *dbmeta.SwaggerInfoDetails &dbmeta.SwaggerInfoDetails{Version:"1.0.0", Host:"127.0.0.1:8080", BasePath:"/", Title:"Sample CRUD api for main db", Description:"Sample CRUD api for main db", TOS:"My Custom TOS", ContactName:"", ContactURL:"", ContactEmail:""} - "TableInfo" *dbmeta.ModelInfo &dbmeta.ModelInfo{Index:0, IndexPlus1:1, PackageName:"model", StructName:"Invoices", ShortStructName:"i", TableName:"invoices", Fields:[]string{"//[ 0] InvoiceId integer null: false primary: true isArray: false auto: true col: integer len: -1 default: []\n InvoiceID int32 `gorm:\"primary_key;AUTO_INCREMENT;column:InvoiceId;type:integer;\" json:\"invoice_id\" xml:\"invoice_id\" db:\"InvoiceId\" protobuf:\"int32,0,opt,name=InvoiceId\"`", "//[ 1] CustomerId integer null: false primary: false isArray: false auto: false col: integer len: -1 default: []\n CustomerID int32 `gorm:\"column:CustomerId;type:integer;\" json:\"customer_id\" xml:\"customer_id\" db:\"CustomerId\" protobuf:\"int32,1,opt,name=CustomerId\"`", "//[ 2] InvoiceDate datetime null: false primary: false isArray: false auto: false col: datetime len: -1 default: []\n InvoiceDate time.Time `gorm:\"column:InvoiceDate;type:datetime;\" json:\"invoice_date\" xml:\"invoice_date\" db:\"InvoiceDate\" protobuf:\"google.protobuf.Timestamp,2,opt,name=InvoiceDate\"`", "//[ 3] BillingAddress nvarchar(70) null: true primary: false isArray: false auto: false col: nvarchar len: 70 default: []\n BillingAddress sql.NullString `gorm:\"column:BillingAddress;type:nvarchar;size:70;\" json:\"billing_address\" xml:\"billing_address\" db:\"BillingAddress\" protobuf:\"string,3,opt,name=BillingAddress\"`", "//[ 4] BillingCity nvarchar(40) null: true primary: false isArray: false auto: false col: nvarchar len: 40 default: []\n BillingCity sql.NullString `gorm:\"column:BillingCity;type:nvarchar;size:40;\" json:\"billing_city\" xml:\"billing_city\" db:\"BillingCity\" protobuf:\"string,4,opt,name=BillingCity\"`", "//[ 5] BillingState nvarchar(40) null: true primary: false isArray: false auto: false col: nvarchar len: 40 default: []\n BillingState sql.NullString `gorm:\"column:BillingState;type:nvarchar;size:40;\" json:\"billing_state\" xml:\"billing_state\" db:\"BillingState\" protobuf:\"string,5,opt,name=BillingState\"`", "//[ 6] BillingCountry nvarchar(40) null: true primary: false isArray: false auto: false col: nvarchar len: 40 default: []\n BillingCountry sql.NullString `gorm:\"column:BillingCountry;type:nvarchar;size:40;\" json:\"billing_country\" xml:\"billing_country\" db:\"BillingCountry\" protobuf:\"string,6,opt,name=BillingCountry\"`", "//[ 7] BillingPostalCode nvarchar(10) null: true primary: false isArray: false auto: false col: nvarchar len: 10 default: []\n BillingPostalCode sql.NullString `gorm:\"column:BillingPostalCode;type:nvarchar;size:10;\" json:\"billing_postal_code\" xml:\"billing_postal_code\" db:\"BillingPostalCode\" protobuf:\"string,7,opt,name=BillingPostalCode\"`", "//[ 8] Total numeric null: false primary: false isArray: false auto: false col: numeric len: -1 default: []\n Total float64 `gorm:\"column:Total;type:numeric;\" json:\"total\" xml:\"total\" db:\"Total\" protobuf:\"float,8,opt,name=Total\"`"}, DBMeta:(*dbmeta.dbTableMeta)(0xc0005d0600), Instance:(*struct { BillingCity string "json:\"billing_city\""; BillingState string "json:\"billing_state\""; BillingPostalCode string "json:\"billing_postal_code\""; BillingAddress string "json:\"billing_address\""; BillingCountry string "json:\"billing_country\""; Total float64 "json:\"total\""; InvoiceID int "json:\"invoice_id\""; CustomerID int "json:\"customer_id\""; InvoiceDate time.Time "json:\"invoice_date\"" })(0xc000c1e200), CodeFields:[]*dbmeta.FieldInfo{(*dbmeta.FieldInfo)(0xc000c10640), (*dbmeta.FieldInfo)(0xc000c10780), (*dbmeta.FieldInfo)(0xc000c108c0), (*dbmeta.FieldInfo)(0xc000c10a00), (*dbmeta.FieldInfo)(0xc000c10b40), (*dbmeta.FieldInfo)(0xc000c10c80), (*dbmeta.FieldInfo)(0xc000c10dc0), (*dbmeta.FieldInfo)(0xc000c10f00), (*dbmeta.FieldInfo)(0xc000c11040)}} + "TableInfo" *dbmeta.ModelInfo &dbmeta.ModelInfo{Index:0, IndexPlus1:1, PackageName:"model", StructName:"Invoices", ShortStructName:"i", TableName:"invoices", Fields:[]string{"//[ 0] InvoiceId integer null: false primary: true isArray: false auto: true col: integer len: -1 default: []\n InvoiceID int32 `gorm:\"primary_key;AUTO_INCREMENT;column:InvoiceId;type:integer;\" json:\"invoice_id\" xml:\"invoice_id\" db:\"InvoiceId\" protobuf:\"int32,0,opt,name=InvoiceId\"`", "//[ 1] CustomerId integer null: false primary: false isArray: false auto: false col: integer len: -1 default: []\n CustomerID int32 `gorm:\"column:CustomerId;type:integer;\" json:\"customer_id\" xml:\"customer_id\" db:\"CustomerId\" protobuf:\"int32,1,opt,name=CustomerId\"`", "//[ 2] InvoiceDate datetime null: false primary: false isArray: false auto: false col: datetime len: -1 default: []\n InvoiceDate time.Time `gorm:\"column:InvoiceDate;type:datetime;\" json:\"invoice_date\" xml:\"invoice_date\" db:\"InvoiceDate\" protobuf:\"google.protobuf.Timestamp,2,opt,name=InvoiceDate\"`", "//[ 3] BillingAddress nvarchar(70) null: true primary: false isArray: false auto: false col: nvarchar len: 70 default: []\n BillingAddress sql.NullString `gorm:\"column:BillingAddress;type:nvarchar;size:70;\" json:\"billing_address\" xml:\"billing_address\" db:\"BillingAddress\" protobuf:\"string,3,opt,name=BillingAddress\"`", "//[ 4] BillingCity nvarchar(40) null: true primary: false isArray: false auto: false col: nvarchar len: 40 default: []\n BillingCity sql.NullString `gorm:\"column:BillingCity;type:nvarchar;size:40;\" json:\"billing_city\" xml:\"billing_city\" db:\"BillingCity\" protobuf:\"string,4,opt,name=BillingCity\"`", "//[ 5] BillingState nvarchar(40) null: true primary: false isArray: false auto: false col: nvarchar len: 40 default: []\n BillingState sql.NullString `gorm:\"column:BillingState;type:nvarchar;size:40;\" json:\"billing_state\" xml:\"billing_state\" db:\"BillingState\" protobuf:\"string,5,opt,name=BillingState\"`", "//[ 6] BillingCountry nvarchar(40) null: true primary: false isArray: false auto: false col: nvarchar len: 40 default: []\n BillingCountry sql.NullString `gorm:\"column:BillingCountry;type:nvarchar;size:40;\" json:\"billing_country\" xml:\"billing_country\" db:\"BillingCountry\" protobuf:\"string,6,opt,name=BillingCountry\"`", "//[ 7] BillingPostalCode nvarchar(10) null: true primary: false isArray: false auto: false col: nvarchar len: 10 default: []\n BillingPostalCode sql.NullString `gorm:\"column:BillingPostalCode;type:nvarchar;size:10;\" json:\"billing_postal_code\" xml:\"billing_postal_code\" db:\"BillingPostalCode\" protobuf:\"string,7,opt,name=BillingPostalCode\"`", "//[ 8] Total numeric null: false primary: false isArray: false auto: false col: numeric len: -1 default: []\n Total float64 `gorm:\"column:Total;type:numeric;\" json:\"total\" xml:\"total\" db:\"Total\" protobuf:\"float,8,opt,name=Total\"`"}, DBMeta:(*dbmeta.dbTableMeta)(0xc00040d4a0), Instance:(*struct { BillingCity string "json:\"billing_city\""; BillingState string "json:\"billing_state\""; BillingPostalCode string "json:\"billing_postal_code\""; Total float64 "json:\"total\""; InvoiceID int "json:\"invoice_id\""; CustomerID int "json:\"customer_id\""; InvoiceDate time.Time "json:\"invoice_date\""; BillingAddress string "json:\"billing_address\""; BillingCountry string "json:\"billing_country\"" })(0xc0007abe00), CodeFields:[]*dbmeta.FieldInfo{(*dbmeta.FieldInfo)(0xc0011be640), (*dbmeta.FieldInfo)(0xc0011be780), (*dbmeta.FieldInfo)(0xc0011be8c0), (*dbmeta.FieldInfo)(0xc0011bea00), (*dbmeta.FieldInfo)(0xc0011beb40), (*dbmeta.FieldInfo)(0xc0011bec80), (*dbmeta.FieldInfo)(0xc0011bedc0), (*dbmeta.FieldInfo)(0xc0011bef00), (*dbmeta.FieldInfo)(0xc0011bf040)}} "TableName" string "invoices" "apiFQPN" string "github.com/alexj212/test/api" "apiPackageName" string "api" @@ -301,7 +303,7 @@ The following info is available within use of the exec template. "serverPort" int 8080 "sqlConnStr" string "./example/sample.db" "sqlType" string "sqlite3" - "tableInfos" map[string]*dbmeta.ModelInfo map[string]*dbmeta.ModelInfo{"invoices":(*dbmeta.ModelInfo)(0xc000b91540)} + "tableInfos" map[string]*dbmeta.ModelInfo map[string]*dbmeta.ModelInfo{"invoices":(*dbmeta.ModelInfo)(0xc00117d540)} "updateSql" string "UPDATE `invoices` set CustomerId = ?, InvoiceDate = ?, BillingAddress = ?, BillingCity = ?, BillingState = ?, BillingCountry = ?, BillingPostalCode = ?, Total = ? WHERE InvoiceId = ?" @@ -357,6 +359,8 @@ Table Name: registration_source |ms sql |y | y | y | y | y | y| n ## Version History +- v0.9.24 (07/13/2020) + - Fixed array bounds issue parsing mysql db meta - v0.9.23 (07/10/2020) - Added postgres types: bigserial, serial, smallserial, bigserial, float4 to mapping.json - v0.9.22 (07/08/2020) diff --git a/_test/dbmeta/main.go b/_test/dbmeta/main.go index 48dccd4..bf7940b 100644 --- a/_test/dbmeta/main.go +++ b/_test/dbmeta/main.go @@ -30,7 +30,7 @@ func init() { goopt.Description = func() string { return "ORM and RESTful meta data viewer for SQl databases" } - goopt.Version = "v0.9.23 (07/10/2020)" + goopt.Version = "v0.9.24 (07/13/2020)" goopt.Summary = `dbmeta [-v] --sqltype=mysql --connstr "user:password@/dbname" --database sqltype - sql database type such as [ mysql, mssql, postgres, sqlite, etc. ] diff --git a/code_http.md b/code_http.md index 0f51b5c..85d7636 100644 --- a/code_http.md +++ b/code_http.md @@ -138,7 +138,7 @@ func GetInvoices(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { // @Failure 400 {object} api.HTTPError // @Failure 404 {object} api.HTTPError // @Router /invoices [post] -// echo '{"billing_city": "OZXsAdCPKOjTctytoYEwgOtYE","billing_state": "UOfAdBkzjGadsbbjkkhozikYw","billing_postal_code": "GXmsXWLgcCWXRUcuGACWkBVTP","billing_address": "HeOCpxWwhFWfMdiJUZDwKymnA","billing_country": "XiLGkZMtOvVGXsoPVWIIzVCQI","total": 0.10089232722813705,"invoice_id": 97,"customer_id": 7,"invoice_date": "2044-08-15T16:02:07.572705306-05:00"}' | http POST "http://127.0.0.1:8080/invoices" X-Api-User:user123 +// echo '{"billing_city": "cjuHwSGtQsvxoudomCbYKIpzZ","billing_state": "ZYmdoDEweNWlqtWNoZnIoLHSU","billing_postal_code": "EXQosbeNyzdoEZxEsunUdwKab","total": 0.4938656834813154,"invoice_id": 72,"customer_id": 86,"invoice_date": "2092-01-02T22:21:00.61433147-05:00","billing_address": "dfaDgvowdMJWOQrTfwwNUVAcN","billing_country": "igXpMTfRsqHWhALluklMJLYZK"}' | http POST "http://127.0.0.1:8080/invoices" X-Api-User:user123 func AddInvoices(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { ctx := initializeContext(r) invoices := &model.Invoices{} @@ -192,7 +192,7 @@ func AddInvoices(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { // @Failure 400 {object} api.HTTPError // @Failure 404 {object} api.HTTPError // @Router /invoices/{argInvoiceID} [patch] -// echo '{"billing_city": "OZXsAdCPKOjTctytoYEwgOtYE","billing_state": "UOfAdBkzjGadsbbjkkhozikYw","billing_postal_code": "GXmsXWLgcCWXRUcuGACWkBVTP","billing_address": "HeOCpxWwhFWfMdiJUZDwKymnA","billing_country": "XiLGkZMtOvVGXsoPVWIIzVCQI","total": 0.10089232722813705,"invoice_id": 97,"customer_id": 7,"invoice_date": "2044-08-15T16:02:07.572705306-05:00"}' | http PUT "http://127.0.0.1:8080/invoices/1" X-Api-User:user123 +// echo '{"billing_city": "cjuHwSGtQsvxoudomCbYKIpzZ","billing_state": "ZYmdoDEweNWlqtWNoZnIoLHSU","billing_postal_code": "EXQosbeNyzdoEZxEsunUdwKab","total": 0.4938656834813154,"invoice_id": 72,"customer_id": 86,"invoice_date": "2092-01-02T22:21:00.61433147-05:00","billing_address": "dfaDgvowdMJWOQrTfwwNUVAcN","billing_country": "igXpMTfRsqHWhALluklMJLYZK"}' | http PUT "http://127.0.0.1:8080/invoices/1" X-Api-User:user123 func UpdateInvoices(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { ctx := initializeContext(r) diff --git a/dbmeta/codegen.go b/dbmeta/codegen.go index 6aaf62b..fbc5cd0 100644 --- a/dbmeta/codegen.go +++ b/dbmeta/codegen.go @@ -439,7 +439,7 @@ func (c *Config) CreateContextForTableFile(tableInfo *ModelInfo) map[string]inte } // WriteTemplate write a template out -func (c *Config) WriteTemplate(genTemplate *GenTemplate, data map[string]interface{}, outputFile string, formatOutput bool) error{ +func (c *Config) WriteTemplate(genTemplate *GenTemplate, data map[string]interface{}, outputFile string, formatOutput bool) error { if !c.Overwrite && Exists(outputFile) { fmt.Printf("not overwriting %s\n", outputFile) return nil diff --git a/dbmeta/meta_mysql.go b/dbmeta/meta_mysql.go index 679baa4..9741cf1 100644 --- a/dbmeta/meta_mysql.go +++ b/dbmeta/meta_mysql.go @@ -62,7 +62,9 @@ func LoadMysqlMeta(db *sql.DB, sqlType, sqlDatabase, tableName string) (DbTableM if commentIdx > -1 { re := regexp.MustCompile("COMMENT '(.*?)'") match := re.FindStringSubmatch(colDDL) - comment = match[1] + if len(match) > 0 { + comment = match[1] + } } if infoSchema != nil { diff --git a/go.mod b/go.mod index 63f4ed7..8f7fe1e 100644 --- a/go.mod +++ b/go.mod @@ -33,12 +33,12 @@ require ( github.com/sirupsen/logrus v1.6.0 // indirect github.com/spf13/cobra v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect + golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 // indirect golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect golang.org/x/mod v0.3.0 // indirect golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 // indirect golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect - golang.org/x/tools v0.0.0-20200630154851-b2d8b0336632 // indirect + golang.org/x/tools v0.0.0-20200711155855-7342f9734a7d // indirect google.golang.org/appengine v1.6.5 // indirect google.golang.org/genproto v0.0.0-20200608115520-7c474a2e3482 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect diff --git a/main.go b/main.go index df9d725..b1e5ac9 100644 --- a/main.go +++ b/main.go @@ -99,7 +99,7 @@ func init() { goopt.Description = func() string { return "ORM and RESTful API generator for SQl databases" } - goopt.Version = "v0.9.23 (07/10/2020)" + goopt.Version = "v0.9.24 (07/13/2020)" goopt.Summary = `gen [-v] --sqltype=mysql --connstr "user:password@/dbname" --database --module=example.com/example [--json] [--gorm] [--guregu] [--generate-dao] [--generate-proj] git fetch up sqltype - sql database type such as [ mysql, mssql, postgres, sqlite, etc. ] @@ -602,7 +602,6 @@ func generate(conf *dbmeta.Config) error { os.Exit(1) } - if *modGenerate { err = conf.WriteTemplate(GoModuleTmpl, data, filepath.Join(*outDir, "go.mod"), false) if err != nil { @@ -735,7 +734,6 @@ func generateProtobufDefinitionFile(conf *dbmeta.Config, data map[string]interfa os.Exit(1) } - compileOutput, err := CompileProtoC(*outDir, moduleDir, filepath.Join(*outDir, protofile)) if err != nil { fmt.Print(au.Red(fmt.Sprintf("Error compiling proto file %v\n", err))) @@ -757,7 +755,6 @@ func generateProtobufDefinitionFile(conf *dbmeta.Config, data map[string]interfa os.Exit(1) } - if ProtobufTmpl, err = LoadTemplate("protoserver.go.tmpl"); err != nil { fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return err @@ -769,7 +766,6 @@ func generateProtobufDefinitionFile(conf *dbmeta.Config, data map[string]interfa os.Exit(1) } - return nil } diff --git a/packrd/packed-packr.go b/packrd/packed-packr.go index 57dfe13..dffc446 100644 --- a/packrd/packed-packr.go +++ b/packrd/packed-packr.go @@ -33,7 +33,7 @@ var _ = func() error { "93bd183343e73a133e7c243e834a15f8": "1f8b08000000000000ffac554d73db36103d13bf62c31399b854cf4d7d882d67c69d54f2d4b1a7d31b082c243820402f405baaa3ffde014849946ccff4201f2c72f1f6bdfd20765b2e7ef005c2cb4b25b9bbe9df66bcc1cd8631ddb48e02142ccb85b301572167598e448e7c7c524d32102a8322e48c65f94287655757c23593076dff5d769385a32667256393095c74dac86bab1c680f9d4709c18144a52d425822f0b6355af0a09d853a62415be5ce80dbf8f48022c013371d7ad0363878d23cb9f5d0969c40ef2b16d62d8ea47ca04e0478610c00601bc594070419fff940da2ec029785ee256f7997b689194a30625286d0cc610a05ec32f7f83704dab0d82327cc1b23d1fc0c0c6583699c0371ed0874bd7343a9c48eb8072ac958298754d8d74cab406c65752616eaf6f4e28d4f3c19b42737f5aa1b93f16faabb34137787fb2da8d08774a1bd67f99dfdce2f6d180eaac284458c170b5aacbfef70cfca3197c4ac69e3841b1fd72af88662e7c759d9590ae611f1fa17024c1ba002a9eb16c0c8473504da8ae225e15f9009eb900e93c2ffb1a5c11dd595e1bfceefee4e497dcfc713b9f8d651ebcb3d0f2b5715c8270445d1b5264efb81e09bfe51ec5f7b9ddb5b1fa5fb98e951d0977c90e8a6be3536e07c02319596ff1896194deb5f548e135bd4ef611fd01f035fd803fa69fa2c1b7a297c93ea23f00bea61ff0c7f4175cde70e28d1f73d75c42db5b5bee7dfa2093c61e7d2430f2d8290c1d985e00a142422b300d661e78cd3db26c7a01fbbf8f71a257d38b3eb22f6dbb1fb507eefb01ceb203d4c7dde33026dd6281942e449afc61c9033c6b63a046d0f6c9fd4009352a4708b842d1857839fda361d9e0da5fa9b864d29ab974ed1a387812dbe19fd60507893e68dbef97fe8445d5e450489f70488a0b7cd99c25ff91a11c0affc232e9c33dfc760ec3e6abaeadd48422145bc37ddc52731539cb92659ec4ffc37b12656cb956f0218a5497dc7e91928a32ca6684a123dbc7e1ab193e17b988b9c65d1819d25ab55c4a42efe385cc4b966d7abe1843f57ddd6251c2877348ecc3eb3bd452abd4ce00716e7910dcc68e08d76a945b66e50874ccedd7cfa0e1f79e77d6355f351a59949f417ffa94045404a520fa235db22ce5a9fd3f486eaeeeac44326b6d17292c555d6f6b5f947d8ca9ee3bf7ea1643a122cba60f6548c16a13676ddfd977c857878dad9d3351616058c1f979a4819f3f772d9b22b6578f1d37c5ea6c678cdcbb1e46e2b92a5665791039dbb0ff020000ffff099f892465090000", "9ec72c1db17b72aeed9a9dfae4794622": "1f8b08000000000000ff84924d6bdb401086effb2b5e924b0c967a2f6d21d8b49796b46e028510a2b176b45ebada51b52bbb69c87f2f2bc91f710cbe8e9e79e69dd1de9752d7ece3c37b7cf884abdb950db00104c39e5b8aac5159c7681c5360b0b61141bab664588ffc5de4ba7114394cd491eada39d4a26d654b8a563c36d6392c194e429ce2493aac68cd58327b6ca8f5acdf38264a5d5e62b6b89b637e7d83cf9d2f932aa8c2b02f06e336283409aa2d015b21ae1845966d814c931469b98642608d28e835396e578c5234a3249f12965d8852db7facb1b171b51569928fbda37264527be0d87ff35433641898523454fe26c3b952b303ebfea2d6236e2469d6d2b5618a9f3fbefec2f2099a2bea5c04798d2f378b6ffbf1fdc8b48cb475a194da451ead56fcf4e81efb5b54d2aa0cf70b8eade5b5f5062d97d2ea30f81b32d69b87abcb11e0ec3b19d6d962802607bd0c4268b84c7f75941cf60d95be61d6720a417b6aa81c32778d3e6286ca213367c7af99a1b263d20bd9a5eb83630cae8aa230a29e9fb78f14179ae431fc717f1f0d47722e3792c7ba7117c85f5e12feda368c38a339ed18d73f6f20ad4f1bc6e39c37743d785a325eefbc44f7e05bc9ff000000ffff6236e43020040000", "9ecd3f03cbe3e3ef5337a260a193f876": "1f8b08000000000000ff8c945f6fd33014c59f934f71895448509ac1847898d4876d5d61b07f6a2721046873939b60e1d8ad7dc356ac7c77e4c4ddbaf247ed4b1dfbdedf39b64f626d8125970851c1d48d598afb9b0a890991552aa37a21a2b60df7f6e01dd2a110d66633d24d4e17acc6b6056e8041d9c89cb892400a2a24606004cf1154091a73a58bd824506a5583b5d9359b0bf4dde4c6c025d077746b63466ccecc7ab9f08f4e7ec134ab0d0c61c12a04f7f3438dcb060d61017181256b0419e7e355f24797e1bf1086209b7a8efad19c710698e73e61ec6f41942e50f7d2c51c8cd2e4a772259a5aba5ad45a6918c289d6178a26aa9145ea8a275c16fd62e84eebefa719e7740fb99284f7941df7ff69672c7ddc0097f4f64dea850d692eab04628da673fde5db4b6bb35a1528ae58fe8355fe2cb32da9144811135375e7b64fa9f3d6fb4bc08681590a381841646d6650604ee78d203e5b8ab68dc230e0a5d77f368228720d6eaa37633ae78c4b73285771579642f4e26b1475e420e83b5d6318046d18b49bc0d103f0a1ccdaec4af39ae9d5475c990f8a4b2c9c8d75e3f8281b6bfe13b5db599c7488da98a5e8396e2b23286bca660bcd25957134305e6dbe828181cbc96476720d8302a6979f663039b93e7e0f93d3e9ec71eef2e2ec739482590a7ff2dbd79284410b280cc23f1c2d94a14aa3d9c9d4edc0dc6ed83a3b3d3f75831d1dec2ab0c6a6bba0438f1c1f65539c7359c4662992fe06ce5455f561905c74f2fd8ccb73c74dfacb7219eb08b32e533ee17dd5739fe0753d2fbb486e303552a3a57b4c61f8ba4b6c8fcd25411fe083917bb1a6eaee5835d283a3a7df9ce87fec070fc3fd0dfef662eedf97b00d436b51166d1bfe0e0000ffff9fb98df146050000", - "a2d5586edb9ff79f53fe610c4e91de3d": "1f8b08000000000000ffbc3bfd5324b7b13f7bfe8acee254e06a771638dbb1712e290eb8f355f8b800e79714bebad5ce68676566a541d2006be0fdedafba5b9a0f582ee77aa9a42a3e466a75b7ba5bfd25ed4566160ba9fdc71df8cb5f61fd7cae1c2807020aa9a5155ee63053a584aa94c24990b9f2e04c6d33094a433af6725195c24bb7913c42b55b96b030b99aa94c786534dca8b284a984d2383f84a5a9612eae254ca5d47023ac96f9131c1bc9da1a729224177fb8385499d44e7e5c9f7b5fb99df1582d8ad4cd952c73972a339e8abc90e30035daad4436977fdcde7c996e8ea6652d53775d6cb48b4d25356f2435b61897bccc8d79dde865bab901177fb8786bf64dd6ae2a4c6e325a50283fafa769661663b71065a9a5f3e342eabf392f7cedd24a476a5fb46c03909ab7e25ab9961c7f8f32456b7b0b703b7f9b5aa1b3f9ab85705eda8d2f5a177605a7b232d6c39eb079777b9686336173e29165fa2cd39f59c99fcf2f4d92f3b944dd8237a684ca9abcce245adedee9877d58dfb3527839042b453e84baca859720740eb92ca5971b707a70760ea252b8f457997988a608336b1668c1ea5a6ac8851753e1640a3d7a688c4966b4a69506fc5c423e853082e6eabc55ba00a145b9fc4d3240c0457cc403423399c925e0540e46d3c8ac148543deae552ef334495e2f692f8833975ea8d231a37dc45353fb80b1ac17c4459df9daca21f11e89d2093590994525bc9a963200825f5632b9517e4e48acbcaa959579c4a6c542ba2191234837a4ad08ad8da743ead22479e7c1d5156acfc14561eca2a3e5569bbf2afddbbc46bd2f36c0e35e11935a54a5c403ecc0998584da09646e21fddce42e85b78d57697900a5b3b2ce65a40a336341d765494b99730717eeaa4c8febb2fc27afea9a5e297441965e5d16e328cbb1bb2ac76bb8e2b531e506180b17456d655113f2f4299e76730c3746b88d04f785c294b795cc90f5a9702a8369ad4a8f4eb0308c294d924921f504fd279bc2189476152960ba241c37c65e8299c199f473389bcb52d7deffc9c1453edd660daee427426e8f1bb80d56ddfe74fb8c351fa98e9fa3b937570b69c59ec9a5fd9383c2fcea8c864a6497a290a869fc5e49bebb72cc701b699224e89de9b406b52aa39336823881c6003ea8517ba1b4cc018d53f11949c7f29680c60c9be65338bb2a95972f3be7f683c333c3a2a518d23b79335396e60621582e6932994cdc5599ec9d1eec9e1fc0f9eeebc3031888725a2fdc20594f00002e76f1f35dfe11e0ddf1f9c1db8353787ffaee68f7f45ff0f7837fc1ee87f39377c77ba7074707c7e7707c720ec71f0e0f87bcf45cf9527ec43f8f7fde3dddfb69f7747debbbcd8dc760bbd62be79144a4d0077873727af0eeed31d15b6fa1d1afbd39383d38de3b388381a06137e841245f7d75720cfb078707e707707c02bb7be7ef4e8ee1e4183ebcdfdfed8e251b288c646d6d6d0dceadd06e66ec02cf9b37385198040d174818d181dc255f8dc717b0f911828ce00bffa7b49785b4fd413c413b3013a5930095550b61973be06d2d0140d4de341f9929779ee028a5de81d1167fe47226ead2efc0c5c7e42b666e1f57c0049dd0ce20a0ff7429973fa2063f352afc919dc84ed8d18fb8eb9da0961f0780f6bcc316f249e503c8a73b83003a400feecdb49eed0c94f62fb7879b4353f9213ad257cd8a09cb6ceb2390717ca9c400f4b5b0d95c58b6a0cfca2c7cb3ccc207c92ce2e8c96cebbbcda73263e6425c0b420b92a129964bcfaa7f74ea37b9b3f5dd6623268f902ca373feb39510a31e6eb52262e8209fed8f10adf83f6f53cfcae777d81433d733aa683981ef674c87665bdb09c04f8d67bb633ccd9a49f240c714dd6bf46d988060181414e231e161476ba5f34dc2a31c54c6390aff14f2f7774f20b3750eb35a5312e38680ee1ce642e7a5b46e080b712931a11f46f7eca4bd9616849520ae85a2a09bc2de5c669780b908857133235f7b917558947940e13eaeaf35717d74c6634d7c78adb4b04b78a79d1765c931623299bcde3dfb09a7158fb789d9ba9b9bbaccb150087332c704ed7fc785194f95e62d80abad6cc650124a634961a1127e9e265f63542ea487510dcfa5a0c45e6e6e746944de8883c24f137d92afe106d1ac088a3d5c632b6ec69c863f8d6949a86238683d4d151fd184f5a8e058317d3e7842aeec06ee586a188ddc558936faca8538fa0b469baf4623cc6c9db730485bc606cd6c437b21948666983284f88107a2fde04c2a7e925dc60f349b96bb38ba30795d6216c5d4b946707e155cf37730ce662a186f8fbfd16ce15f398d46d13017643dca85793a88d26d79bd96f6c62a2f494998d3e59145d6d43a8f55d664d2395649345acc9dec36a81968e35b73456564792b82e46bb6d9f84994f858b4357146274aa0e4a64a374bd7d6e0662e3594a2d6d91c1d776bfe7e2eb85638fbc7211a1089a6cda4946bd00693716241d602c2d1373381dc5690a6e3b4631a007888da2d10d32795d420606acd8d93164f65a86f914e3937ceef7cbff9fde6d8dd88a29076ac742e6fd3b95f94b4fc8393749ac6596dcb312e551291cca4cfe670adc8d92d30ab2d9596097bae9504389b4b10cf73109c3925e45903755148fccc8c76a694c9dd5dfa56ea9f64593db003267785da56baa0ea349ec370fe30a96d4c10bdb3146ec936c395624e1bc0532ddca54b931730216dcd65594d6004a572bef5b2e0852da4770d186142b85e821b2c6592a29f9934c04131086e6b562f3a8068a7c1b544533ebb2ac944f269d7261af53aa84a91313d6e8ab8de7c72e2e7a8706618e42d6e042590cbebb85994de4100ef0a2f94c09d8a20986be37382754e1a721334529979639729bc8945724438390a3a984026349e9eda718ce8c9ad7b8aa92848a7c2cd93de4924ad87be4088693ddf1b14ffa8d020bf50eb1c25f22cdfc90b887c26002f90c7595d366324bde0311027c63ed7da52e442fa2c8577ced592d53ec16de6ca55a5589259618cae6a8fe4d242795568639960a13cf027d12a4c449abc80c2a40b93339881e0999df47535844a380793e8af27d4c8200c4e7a4fac7674119686340a265def1e8592bc80d383ddfda38374c124df87c5568a7c21931720aa6accae7e8cf1272d0cc1712a016f9586339a1d729a13dc0b28ad7c73eaa4a693242a35fe0b979c9866fd35e2a26e11e546a8536b4a4c879217900bb3121e53a9268b0a368c9ba72c4c6474c65015314f7881a290e54a5c5ca03bb0b2b2d2494d521460cd4df022d9bc3d0cb49e3cd6da5aa75d12d2aae4055cbc3d393d22fe88973791c98febe9182df3532ecc278cd5e922df40f8b37f1cfef3dfc1bbabf236c2ff847e97607f0a6963038abe36821de17e9b19da7d9c7a1fd25ed89733549232ba018c2931c1f2e16b3a7921dcd75e95ea37c9310ab53fb362216f8cbd1c026d3e9f1238aafeec265867aba2681eb9c96a340bce3951706a757ba3507a5418ad32fc8b458628cc4a60c26ee81f027dfb250d3204e46461350328909928cd98803642ea7cc6fd3099c37eb00e97ecd5d64aedcb653b3b4c467024ac12fbaff1afe5d93f0e9311bc37ce1756f2c791caac7166e6d1f786c3948c82234e92f7a5d0985d0694c9084eacc842a6d2e702ce9795744972649ceff6f0b07e700d47a491a3a5bb2a879111378c7e1fd57674865f69e8ead44e726cad2a5420659de42429c379e4e4459e3790dc7783d7cbe88186643358f2592dca068e90513e2472ccb27493d0c93c8577b3482366835e6ac0ea2bcfc97845197799e7dc57ab5df484e82999ca2b79ebad4891fb492f930153219694adbdf195615958d0b2c8e1b997e937b72c1860524aa42621dd17d7f255078002040e8626b2f6d48c0d055c8bc71b8c5bedb234792d4b73c39d3bd42256a06155578a4370738e82bd19636112fa109394922edc1535baee122eb507eeaafc84621cecc020c00e8671b230cd1c7711daa9e8311a80e9d24bd7594aa548334bcdddb347380af32976945b3aa1a11c6009f4a1cd1777f36ba1339993d2d84ee34d05e733313c8852f9250ab4144b2c7da80c3537ba0992336317c293daace34bafed60139424be678ca4fab2a3a3a68d3f198de2e8beb2af2661318cc0cf957bd414e5eca4b1cf474853386ff0a3d14b4599dd94dadb7ccce95682369c604ece76c4d6dc313a48c78b65c77ee0bc61a5313fb9984a3a31ed9ed052982589674b17742f43b53bdc50e1ef2a99a9d9f2b31ba79228b64a28980659a709ca53386e198f46f25666afdaba86b41852e3de0925bea90f4064bbe02eb3aae23c03b1d55e82f27c9b14a6e6c27552023a67940428cd9a478e71b92151e3282559ecce48d0417a02334c8749b52c4d85c6e20d64b5f366a1c21554a73f64669cdbc2bf4c0d19c9ae34a6023fb7a62ed872a8e2c0638c0c852b1a7d6d2e653289b9c5394ebda174da5880669c86d22421ec4283289d81ca5475d95e7a692f6f3d7be6e9f2b1e5923be418315dd28e3b3e93d666fed55f1a67ffd7a85d966d1b04628d1c03c0f33c905954c232a1c6e4319c52bb3b0e25e3311cf644d58aa7b24a7bea7cb5991c4d5c0bab4c4d16bc681d6a0383e56470198e93b5878704093d91f33a2d3a160b396c98c4714d239ccfefc73a220e20002e09eddb61702a2734095363ca8d2e31a6f31f441ea63884b5a51019335a6e53d486b855bba66b88a7a6d9689a24777760852e247c7d299743f8fa5a94b5849d5790c2c3037ae1bb3bd6c20c067f5c1b6d7f7b3d205078787834397ab9790e7f5cc3794612fe7978b8bb03a973c49734a57db827d36211eb7b3155e4bba99ea5c3e6a407d1de2453fed1b33f2aa5ba8ec735582525225d3ba7d2894b29597e62c2afeeee067777e9c3c3e0e161425c040c910c62ca1f19570a3f47eb6b6a926e5a141285966fc34f2fd88b9209bb3a9b8370ed79460de1acb005a5c9c828427ef2d2f957b59376827833a37f0d347b01a9bb27f21c93d1088f2b0ec9c91059b856f2066e62938a4183939fa221dc37c50800dc031d10203b847b60e34bee47a351f3ffe41e455b9774d971cfe11461277777cdc4808607f0f03001b84feeabb2b602cb89274bda99c76b7cb8c5e9c3f3e8135873686ee45386e2f853f80f55b5129ec79fc1bf2716b2dcc302f119422dc033143f87e111c0530c675a5cca6716b7738fd67119f3e8e0c51e914b5a7def809585729e03db27ee40a17d508d8920b8f00d392524db298b193522493a6632a14336787848e9bf036208eee1ee6eb082d2801c0b2e6374cf2c6e26bf1405b446f92cb20ecc17a37daaf1e7d13f85fd1d641e9bc5e7c83c86fd1d643a06f4390a1db0ff92a8c8017ffa2f09ec7713fbfd62fb7f9058072bb9479cc22f01d12f03f865f0cb6003cf7bc0b09a70bbf8332cc4b9010c0825b00b595b8363e3a5e3d6c655398423d7eb2b701b88afd0a8b6126d336d21bda00494ae18a85f1b03fa552ded323cfbe2a734e18d19c5c4da1b503ab3f49669186f9901b310046d5e2751fe833901e5e6c62e3a6fa9d264c431cd31d9c09c367ae4bcd0b9b0790ff1faf1c971735b1d2e082d7075bad1490862a2c0cddd9c3beffbafe1487ac13d9a4343efcc927b1ca6d0baac28a81e47bee11ede07d27f974bfcdcc52dbf8b5bc6913d7e33762835dc375d8b9f31c1ba878c5ee7419e97fd08bdeaffc97db8e004b85f123bcbc7ffb987e53d2c93fb2aeaf4df80eae47eb17457e517a05c38f80240be0cfe595a87d9c84fca617a9c8ce07a33fd21dd7e09eb9b7f1e6f6d8eb737b73737a85130825daa6c1b8ea941b40353553869952887d0fcbb1065193f3af3b3d208ff0de56a9d4e5043749b886e7edf237a440f6a650e85294c4a9d11c8e8aede1bcae8de9ebcdf3dff89ee23e7c2e65820e66958fc810c3c0f77ed20ad3516735f0f546a59e7e398ce4cadbdb432ef6d3633a5b1a166e0d63582f74046236d4601ae6a9e3168a379b1fa0dad9a53bbb8d12ddee89f7b1b3d9595c82e7b755cf30af43aa849d78b2915d4740cd306e1e62a846fd4adccc14abab6e16d2a0dd6d45edab430a95f546500adabc2529fb07959cab2e55b13d84ab7be89b4b67e58452b8ae246e91c0b7aaa03bc01ba68a6a23694c87ba7876f20425123426a3cb96ec8cd821bc549fa92df679425d45add06e770f8a6b7a461e97b58dffc6efc7273c5f6430a86e54253ab8b1bb1e49e0f1a0cb51472becc886f031bc96efd7915ea533913584e76fa3cd44aa14ad21b984aefa5057e10dc8abe29c6bb320b36e30d5d6a1666b620e30c26d7dcae350c7d470c6dfff064af54cdf5b5cb9bcc4479ad743697bab85d7d92f369ef25aad292bb3f5e2da4f36251f9df1afadf32fd973dfaf490272ba5d075153a71bc935088158574a1f9c70b624b2e18b8eb56999255f285f8225fdface28bf7c9aa0d57667cf26519da606ad6a9e4495ccd33cc1e0e795b19e283e2db3b0c82d74ad0a54c26cab2e5e325f3b1dde36346b698958c82da58f1d5b5233cb99cc9e856a675410be842da5d95b78f04d390da26525bdff448d1dd573617ba90391cd5ce1f5033c200fd4b7787e83d952ec656fada6ae4a8ebd5a2cf642159194fd00cf2ba2a15f5ea87a02509d64a90a52c84f62da43365cdd9405f80fce4d91bc0723b75f3661f5bbc8f55aa8bfd0acf0d44666a18348a9ba17e5920cc3d9cc6a5f1369058685bba9e6720c962a0e4bc88b2b5b92973695bc7b2c99c6df5387bcdfa617f66a5b74a5e23f9f82ab194baf07336268ad9bd1d750f1a47f45a3b556899432e33b510258c303cd271a68019b9f9611533bc1745f7e5c410e3a4d3db34537298189b4b3be92f0a774664676fa5df6d7beae891e89d37a5772cabc6c4d9dbaecc0d3aea72d2f79493197d2d75131f4983f430df0cf11471525bd82a836e5fe549fbe833d45cafe8eed0fb6c3faa2b113c7924c4e6cd42471e562e0ce9f9aa367c1475f39309a5c31b152be91621488a83c7e60f2b24453b0db7bf1d2223f89f77ef61bd34e632de32912f548bca9a6bfe9dc1b3226f8e18a5e0cf5a5d636fad85625adbe89723cca3342c7a05762f26c77d3e9aea5db5b9aa541ee2ebc94e134f695257c5573794193ccab83a17fa43e8ddd7736cedfe508b5eca44ba710318a2be1d6f7db742ec5df661dab944657e7361ba5df418ed4383f2319d6f98ceb73d3afbdd3bf818dee2db5347cf5be2fa97bcbeefbf9bc8d884812177f9390cf2dd089e183a3b746a1ea52e210e48dfabb5c2933d3c28e1ca86f35f7eee1b175daaaa559a9af530845fd42817defe792cd642939c975f8b52e54d9c22bd472f37840517b155b7880d4f367b87b0eb3454b8c7c18c2f2490d4ac4d0bc3f1868ded93a7a1160dbfd48ae12a84320657f1174690d7148d62dcead90915e0e1f8f1af711a8fcac34ef99a7f3f84dac154b52f6dc72e49e94c92b87239a3e7ac4a433e5de5bb51c53151896f5f99ef504ae7708374da6639bd6d14dc2077f116825fa5244d65c026b6fd7cb64679d5b067975bfd453cba0a518cb1f994fa0e7cf31512616e40f06fbfb890a69b8a78d8f95d416f0a95418f5dbc28fa3e21de8743a8ff5a87d903a3502faaaafb62ace12bee3d6c7b7ffff039345d5f1962fa36fd824c623ebc1dcad8ef87f0e1ece0f4d3fec19b77c707fb2ca56fc32f848cf6564d6b6f2897b810a5bcfd757b6bf5539838b901230081e5326a5c5f9265c7496266ae1cbfe542d4687a4972262567615987e40e5c743f573feae9bde52eaca8e66edc5db591fc5f000000ffff6215d34b293b0000", + "a2d5586edb9ff79f53fe610c4e91de3d": "1f8b08000000000000ffbc3bfd5324b7b13f7bfe8acee254e06a771638dbb1712e290eb8f355f8b800e79714bebad5ce68676566a541d2006be0fdedafba5b9a0f582ee77aa9a42a3e466a75b7ba5bfd25ed4566160ba9fdc71df8cb5f61fd7cae1c2807020aa9a5155ee63053a584aa94c24990b9f2e04c6d33094a433af6725195c24bb7913c42b55b96b030b99aa94c786534dca8b284a984d2383f84a5a9612eae254ca5d47023ac96f9131c1bc9da1a729224177fb8385499d44e7e5c9f7b5fb99df1582d8ad4cd952c73972a339e8abc90e30035daad4436977fdcde7c996e8ea6652d53775d6cb48b4d25356f2435b61897bccc8d79dde865bab901177fb8786bf64dd6ae2a4c6e325a50283fafa769661663b71065a9a5f3e342eabf392f7cedd24a476a5fb46c03909ab7e25ab9961c7f8f32456b7b0b703b7f9b5aa1b3f9ab85705eda8d2f5a177605a7b232d6c39eb079777b9686336173e29165fa2cd39f59c99fcf2f4d92f3b944dd8237a684ca9abcce245adedee9877d58dfb3527839042b453e84baca859720740eb92ca5971b707a70760ea252b8f457997988a608336b1668c1ea5a6ac8851753e1640a3d7a688c4966b4a69506fc5c423e853082e6eabc55ba00a145b9fc4d3240c0457cc403423399c925e0540e46d3c8ac148543deae552ef334495e2f692f8833975ea8d231a37dc45353fb80b1ac17c4459df9daca21f11e89d2093590994525bc9a963200825f5632b9517e4e48acbcaa959579c4a6c542ba2191234837a4ad08ad8da743ead22479e7c1d5156acfc14561eca2a3e5569bbf2afddbbc46bd2f36c0e35e11935a54a5c403ecc0998584da09646e21fddce42e85b78d57697900a5b3b2ce65a40a336341d765494b99730717eeaa4c8febb2fc27afea9a5e297441965e5d16e328cbb1bb2ac76bb8e2b531e506180b17456d655113f2f4299e76730c3746b88d04f785c294b795cc90f5a9702a8369ad4a8f4eb0308c294d924921f504fd279bc2189476152960ba241c37c65e8299c199f473389bcb52d7deffc9c1453edd660daee427426e8f1bb80d56ddfe74fb8c351fa98e9fa3b937570b69c59ec9a5fd9383c2fcea8c864a6497a290a869fc5e49bebb72cc701b699224e89de9b406b52aa39336823881c6003ea8517ba1b4cc018d53f11949c7f29680c60c9be65338bb2a95972f3be7f683c333c3a2a518d23b79335396e60621582e6932994cdc5599ec9d1eec9e1fc0f9eeebc3031888725a2fdc20594f00002e76f1f35dfe11e0ddf1f9c1db8353787ffaee68f7f45ff0f7837fc1ee87f39377c77ba7074707c7e7707c720ec71f0e0f87bcf45cf9527ec43f8f7fde3dddfb69f7747debbbcd8dc760bbd62be79144a4d0077873727af0eeed31d15b6fa1d1afbd39383d38de3b388381a06137e841245f7d75720cfb078707e707707c02bb7be7ef4e8ee1e4183ebcdfdfed8e251b288c646d6d6d0dceadd06e66ec02cf9b37385198040d174818d181dc255f8dc717b0f911828ce00bffa7b49785b4fd413c413b3013a5930095550b61973be06d2d0140d4de341f9929779ee028a5de81d1167fe47226ead2efc0c5c7e42b666e1f57c0049dd0ce20a0ff7429973fa2063f352afc919dc84ed8d18fb8eb9da0961f0780f6bcc316f249e503c8a73b83003a400feecdb49eed0c94f62fb7879b4353f9213ad257cd8a09cb6ceb2390717ca9c400f4b5b0d95c58b6a0cfca2c7cb3ccc207c92ce2e8c96cebbbcda73263e6425c0b420b92a129964bcfaa7f74ea37b9b3f5dd6623268f902ca373feb39510a31e6eb52262e8209fed8f10adf83f6f53cfcae777d81433d733aa683981ef674c87665bdb09c04f8d67bb633ccd9a49f240c714dd6bf46d988060181414e231e161476ba5f34dc2a31c54c6390aff14f2f7774f20b3750eb35a5312e38680ee1ce642e7a5b46e080b712931a11f46f7eca4bd9616849520ae85a2a09bc2de5c669780b908857133235f7b917558947940e13eaeaf35717d74c6634d7c78adb4b04b78a79d1765c931623299bcde3dfb09a7158fb789d9ba9b9bbaccb150087332c704ed7fc785194f95e62d80abad6cc650124a634961a1127e9e265f63542ea487510dcfa5a0c45e6e6e746944de8883c24f137d92afe106d1ac088a3d5c632b6ec69c863f8d6949a86238683d4d151fd184f5a8e058317d3e7842aeec06ee586a188ddc558936faca8538fa0b469baf4623cc6c9db730485bc606cd6c437b21948666983284f88107a2fde04c2a7e925dc60f349b96bb38ba30795d6216c5d4b946707e155cf37730ce662a186f8fbfd16ce15f398d46d13017643dca85793a88d26d79bd96f6c62a2f494998d3e59145d6d43a8f55d664d2395649345acc9dec36a81968e35b73456564792b82e46bb6d9f84994f858b4357146274aa0e4a64a374bd7d6e0662e3594a2d6d91c1d776bfe7e2eb85638fbc7211a1089a6cda4946bd00693716241d602c2d1373381dc5690a6e3b4631a007888da2d10d32795d420606acd8d93164f65a86f914e3937ceef7cbff9fde6d8dd88a29076ac742e6fd3b95f94b4fc8393749ac6596dcb312e551291cca4cfe670adc8d92d30ab2d9596097bae9504389b4b10cf73109c3925e45903755148fccc8c76a694c9dd5dfa56ea9f64593db003267785da56baa0ea349ec370fe30a96d4c10bdb3146ec936c395624e1bc0532ddca54b931730216dcd65594d6004a572bef5b2e0852da4770d186142b85e821b2c6592a29f9934c04131086e6b562f3a8068a7c1b544533ebb2ac944f269d7261af53aa84a91313d6e8ab8de7c72e2e7a8706618e42d6e042590cbebb85994de4100ef0a2f94c09d8a20986be37382754e1a721334529979639729bc8945724438390a3a984026349e9eda718ce8c9ad7b8aa92848a7c2cd93de4924ad87be4088693ddf1b14ffa8d020bf50eb1c25f22cdfc90b887c26002f90c7595d366324bde0311027c63ed7da52e442fa2c8577ced592d53ec16de6ca55a5589259618cae6a8fe4d242795568639960a13cf027d12a4c449abc80c2a40b93339881e0999df47535844a380793e8af27d4c8200c4e7a4fac7674119686340a265def1e8592bc80d383ddfda38374c124df87c5568a7c21931720aa6accae7e8cf1272d0cc1712a016f9586339a1d729a13dc0b28ad7c73eaa4a693242a35fe0b979c9866fd35e2a26e11e546a8536b4a4c879217900bb3121e53a9268b0a368c9ba72c4c6474c65015314f7881a290e54a5c5ca03bb0b2b2d2494d521460cd4df022d9bc3d0cb49e3cd6da5aa75d12d2aae4055cbc3d393d22fe88973791c98febe9182df3532ecc278cd5e922df40f8b37f1cfef3dfc1bbabf236c2ff847e97607f0a6963038abe36821de17e9b19da7d9c7a1fd25ed89733549232ba018c2931c1f2e16b3a7921dcd75e95ea37c9310ab53fb362216f8cbd1c026d3e9f1238aafeec265867aba2681eb9c96a340bce3951706a757ba3507a5418ad32fc8b458628cc4a60c26ee81f027dfb250d3204e46461350328909928cd98803642ea7cc6fd3099c37eb00e97ecd5d64aedcb653b3b4c467024ac12fbaff1afe5d93f0e9311bc37ce1756f2c791caac7166e6d1f786c3948c82234e92f7a5d0985d0694c9084eacc842a6d2e702ce9795744972649ceff6f0b07e700d47a491a3a5bb2a879111378c7e1fd57674865f69e8ead44e726cad2a5420659de42429c379e4e4459e3790dc7783d7cbe88186643358f2592dca068e90513e2472ccb27493d0c93c8577b3482366835e6ac0ea2bcfc97845197799e7dc57ab5df484e82999ca2b79ebad4891fb492f930153219694adbdf195615958d0b2c8e1b997e937b72c1860524aa42621dd17d7f255078002040e8626b2f6d48c0d055c8bc71b8c5bedb234792d4b73c39d3bd42256a06155578a4370738e82bd19636112fa109394922edc1535baee122eb507eeaafc84621cecc020c00e8671b230cd1c7711daa9e8311a80e9d24bd7594aa548334bcdddb347380af32976945b3aa1a11c6009f4a1cd1777f36ba1339993d2d84ee34d05e733313c8852f9250ab4144b2c7da80c3537ba0992336317c293daace34bafed60139424be678ca4fab2a3a3a68d3f198de2e8beb2af2661318cc0cf957bd414e5eca4b1cf474853386ff0a3d14b4599dd94dadb7ccce95682369c604ece76c4d6dc313a48c78b65c77ee0bc61a5313fb9984a3a31ed9ed052982589674b17742f43b53bdc50e1ef2a99a9d9f2b31ba79228b64a28980659a709ca53386e198f46f25666afdaba86b41852e3de0925bea90f4064bbe02eb3aae23c03b1d55e82f27c9b14a6e6c27552023a67940428cd9a478e71b92151e3282559ecce48d0417a02334c8749b52c4d85c6e20d64b5f366a1c21554a73f64669cdbc2bf4c0d19c9ae34a6023fb7a62ed872a8e2c0638c0c852b1a7d6d2e653289b9c5394ebda174da5880669c86d22421ec4283289d81ca5475d95e7a692f6f3d7be6e9f2b1e5923be418315dd28e3b3e93d666fed55f1a67ffd7a85d966d1b04628d1c03c0f33c905954c232a1c6e4319c52bb3b0e25e3311cf644d58aa7b24a7bea7cb5991c4d5c0bab4c4d16bc681d6a0383e56470198e93b5878704093d91f33a2d3a160b396c98c4714d239ccfefc73a220e20002e09eddb61702a2734095363ca8d2e31a6f31f441ea63884b5a51019335a6e53d486b855bba66b88a7a6d9689a24777760852e247c7d299743f8fa5a94b5849d5790c2c3037ae1bb3bd6c20c067f5c1b6d7f7b3d205078787834397ab9790e7f5cc3794612fe7978b8bb03a973c49734a57db827d36211eb7b3155e4bba99ea5c3e6a407d1de2453fed1b33f2aa5ba8ec735582525225d3ba7d2894b29597e62c2afeeee067777e9c3c3e0e161425c040c910c62ca1f19570a3f47eb6b6a926e5a141285966fc34f2fd88b9209bb3a9b8370ed79460de1acb005a5c9c828427ef2d2f957b59376827833a37f0d347b01a9bb27f21c93d1088f2b0ec9c91059b856f2066e62938a4183939fa221dc37c50800dc031d10203b847b60e34bee47a351f3ffe41e455b9774d971cfe11461277777cdc4808607f0f03001b84feeabb2b602cb89274bda99c76b7cb8c5e9c3f3e8135873686ee45386e2f853f80f55b5129ec79fc1bf2716b2dcc302f119422dc033143f87e111c0530c675a5cca6716b7738fd67119f3e8e0c51e914b5a7def809585729e03db27ee40a17d508d8920b8f00d392524db298b193522493a6632a14336787848e9bf036208eee1ee6eb082d2801c0b2e6374cf2c6e26bf1405b446f92cb20ecc17a37daaf1e7d13f85fd1d641e9bc5e7c83c86fd1d643a06f4390a1db0ff92a8c8017ffa2f09ec7713fbfd62fb7f9058072bb9479cc22f01d12f03f865f0cb6003cf7bc0b09a70bbf8332cc4b9010c0825b00b595b8363e3a5e3d6c655398423d7eb2b701b88afd0a8b6126d336d21bda00494ae18a85f1b03fa552ded323cfbe2a734e18d19c5c4da1b503ab3f49669186f9901b310046d5e2751fe833901e5e6c62e3a6fa9d264c431cd31d9c09c367ae4bcd0b9b0790ff1faf1c971735b1d2e082d7075bad1490862a2c0cddd9c3beffbafe1487ac13d9a4343efcc927b1ca6d0baac28a81e47bee11ede07d27f974bfcdcc52dbf8b5bc6913d7e33762835dc375d8b9f31c1ba878c5ee7419e97fd08bdeaffc97db8e004b85f123bcbc7ffb987e53d2c93fb2aeaf4df80eae47eb17457e517a05c38f80240be0cfe595a87d9c84fca617a9c8ce07a33fd21ddfe06d637ff3cde7a39dededcdedca046c108dea85b9983b0562c616a6a9d3b50d4a88f050873984fc90a1b5c2f19d7660fd72e55c9cdeea9d9b40353553869952887d0fcbb1065193f3af3b3d208ff0de57d9dae5243749b886e7edf237a448f73650e85294c4a5d16c8e8dedf1bca0edf9ebcdf3dff89ee36e7c2e6586ce66958fc810e4b1eeeed415a6b2ce6d11ea86cb3cec7319d995a7b6965dedb6c664a6343fdc16d7004ef818c46da8c025cd53c89d046f362f51b9e104e13e346b778a37fee6df4545622bbecd584cd8bd2eba0725d2fa6549cd3914e1b849bab10b2eaada42b20dea6d2604deda54d0b93fa455506d0ba2a2cf51c9b57aa2c5bbe8181ad74eb9b486beb8755b4a2286e94cecd8de39ac21ba04b6b2a9043b9bd777af80622143535a4462fe086dc78b8519cf02ff9ad475942add56d7034876f7a4b1a96be87f5cdefc62f37576c3fa473587a3475bfb8114bee1fa1c1507b22e78b91f8ceb091ecd69f57a13e953381a569a767446d19aa4abd81a9f45e5ae0c7c5ade89bc2be2bb36033ded0056961660b32ce6072cd4d5dc3d077c4d0f60f4ff64a95615fbbbcc94c94d74a6773a98bdbd527399ff65eb52a2db993e4d5423a2f1695ffada1ff2dd3ef7b197a14949552e8ba0a5d3dde4928ea8a42bad048e405b1bd170cdc752b56c92af9427c91af6f56f1c5fb64d586eb373ef9b20c2d3535eb7405485ccd93ce1e0e795b19e28362e53b0ca8d74ad0054f26cab2e5e325f3b1dde36346b698958c825a62f105b7233cb99cc9e856a675410be872db5d95b78f04d390da26525bdff448d13d5a3617ba90391cd5ce1f5063c300fd4bf790e83d952ec656fada6ae4a8ebd5a2cf642159194fd00cf2ba2a15f5fd87a02509d64a90a52c84f62da43365cd99455f80fc7cda1bc0d23d75f3661f5bbc8f55aa8bbd0fcfcd48666a18348a9ba1de5b20ccfda0c6a5f13690586881ba9e6720c962ece31c8b32bfb92973695bc7b2c99c6df5387bcdfa617f66a5b74a5e23f9f8c2b194baf07336268aaebd1d750f1ac7de5a3b556899432e33b510258c303cd271a68019b9f9611533bc170ee9c410e3a4d3db34667298189b4b3be92f0af74f64676fa5df6dfbf3e891e8cd38a58a2cabc6c4d9dbaecc0d3aea72d2f79493197d2d75131f4983f4c8df0cf11471825cd82a836e8fe6492bea33d45caf80efd0fb6c6fab2b113c7924c4e6fd43471e562e0ce9f9aa367c1475f3f30ba5c37b172be94622488a83c7e60f2b24453b0d37c91d2223f89f77ef61bd34e632de58912f548bca9a6bfecdc2b3226f8e18a5f3cf5a5d636fad85628adce89723cca3342c7a05762f26c77d3e9aea5ddbb9aa541ee24bcc4e4350695257c5d74094193ccab83a8f0386d0bbfbe7d8dafdd117bdba8974e30630447d3bdefa6e85d8bbecc3b47321cbfce6c2743bf231da8766e7633adf309d6f7b74f6bbf7f931bcc577ac8e9ecac4f52f797ddf7f3791b1090343be31e030c8f72c7862e8ecd0a97994ba8438207daf6e0bcffff0a084eb1fce7ff9e9705c74a9aa56696ad6c3107e9da35c7847e8b1f00b0d775e7e2d4a9537718af41ebddc10165c1057dd82383cffec1dc2aed350e14e0833be904052e3372d0cc71b36b64f9e865a34fcea2b86ab10ca185cc55f2b415e53348a71ab672754cc87e3c7bfec693c2a0f3be56bfe2d126a0753d5beb41dbb24a53349e2cae58c9ec62a0df97495ef4615c74425bea365be43599ec30dd2691beff44e5270b3ddc51b0d7ee1923495019bd8f6f3d91ae555c39e5d6ef517f1e82a4431c686ea916fd14222cccd0cfe1d1917e574eb110f3bbf51e84da132e8e18c1745df27c4bb7508f55feb307b6014ea4555755f9f357cc5bd876defef1f3e87a6eb2b434cdfa65fa349cc87b74319fbfd103e9c1d9c7eda3f78f3eef8609fa5f46df8b591d1deaa69ed0de51217a294b7bf6e6fad7e56132737600420b05c468deb4bb2ec3849cccc95e37761881a4d2f49cea4e42c2ceb90dc818beee7ea0742bd77e18515d5dc8dbbab3692ff0b0000ffff4db6351b753b0000", "a42f6cfa87833f9ac66f4293e399925f": "1f8b08000000000000ffbc55df6fdb36107eb6fe8a9b50acf6a0c859d7270f0196a60ddaadedbcdad9060c43c1506799ad4c7247aa4ec6f27f1f48298e65589e3b74cd4b94e3fdf8bebbfb2ece15b8101221655abcad75c12ce6a5caed4a57a9f7c9780c57d1e85c3eb35473fb9aadd0fbd60a0c8c90658540c81515b020b502e7f239bbaeb075b5e11b8404bbc4f0f6945976cdccdd73d1fe196afd30ab572b46b79bf4f22e71088f79bac963d053349c84b642c9ff0bd79c9506767a101fce39476d01de1925a3614aaaa839b616e788c912e1c1426055c0e40c1a082fe442e517aac0cb6037de3b0762d1bae55312a10b3fe1ed39954db1989a115b0138d7eb07de836676b9e533fbe5e52ba6b590653e5bb3b2449adfeae868a94648ef3d2f5455afe42bb42c6f73a5cea12c02b8f82be980e8eec3b52a6e8371a50aaca68cbf6765dbc87cd7b5a9db0e6af7b19957da2e03e7680c3c3a3d05a7aedf21b7feb81a31fc9289aa2684c73be14c8b6ef0f3f97cfa8c48d14ed8e34f097ba36a8b04e30e12f80856bd546ba4d0c4cfb50a0e9c3be9df8113efc17727077f6866f9f2cf8014f952c143e7e6eac7d9cfafb741bc90c632c9114ebd7f081f6169ad86e9d51cd2f035198f9d7b901ba40f48cf95b1de4fee0d53453640fb02ec370b7bc9de63102df81dba29c0ef27e75a9c5c19a4496d90be7df45db2a825df7fcd86ebc8357f83462b69f03712162903826f5afb5f351a9b8136d191e2acf328053302970cb8bd099c841456b04afc8d174a5abcb1431a1d7f0392c3dcc1fb241938d7df9b0c902814d8e3148b4c1999308da13659907e7faa74940cc422e6fbea0ca4a802cb01a1ad49c6a51f727b93c13a038a55479bd764108874ee4640ddb31701edd74769daf90da2c91910b222ecef9032e84d3efafe4802cee50553ddf2cf889eb0a29d71875d0200f7487aabe74f70a10867ec030e779140fcf9cf6800a081d15f7c4aa819e1707434dc5f59258238863d37b691cee767b2096f696d4df90e522bc02635c5d5ddfe579e66c743fe94353eb0b719bc6dd476b697e4fe33136a859c47de03f8d77bb04fe8f7d7604785fd64f669fdc054639f0060cba7e9d63adccda8ca3bef032537572249fe090000ffffb63231ca860a0000", "abfb948144ce2666cf818384c00cc754": "1f8b08000000000000ff84924d6bdb401086effb2b5ee24b0c967a2f6d21d8b49796b46e028510a2b176b45ebada11da954d1af2dfcb4af2471c83afa3679e7967b40fa5d435fbf8f8119fbee0fa6e6d036c00c1b0e796226b54d6311ac71418ac6d4490ae2d19d623ff10b96e1c450e5375a2ba710eb5685bd992a2158fad750e2b8693106778960e6bda3056cc1e5b6a3deb778ea9529309e6cbfb051637b7f8daf932a9822a0cfb6230ee824293a0da11b015e29a5164d90ec8344991966b2804d688825e93e36ecd2845334af22961d98528b5fdc71a5b1bd73b9126f9dc3b2a4726b5078efd374f35438681294543e55f329c2b353fb21e2e6a3de2569266235d1b66f8fdebfb1fac9ea1b9a2ce4590d7f876bbfc7118df8f4ccb485b174aa97de4d16ac5cf4eee71b84525adcaf0b0e4d85ade586fd07229ad0e83bf2163bd79bc9e8c00673fc9b0ce9603343dea651042c365faaba3e4b86fa8f40df39653083a5043e598b96ff40933548e99053b7ecb0c953d935ec83e5d1f1c637055148511f5f2b27ba4b8d2244fe9844f862339971bc963ddb82be4afaf097f6b1b465cd09c778ceb5f3690d6e70de3712e1bba1e3c2f19af7759a27bf0bde47f000000ffffa7724c4920040000", "ac60daf3c3958d476b98234112b3896c": "1f8b08000000000000ffcc5a7b53e33812ffdbfe14bdaebd2d7bca38c070d4547653750c0c4cae76598ec7de555114232c396871249f2cc330b97cf7ab9664c7491cc8bca89d3f8658ea6ef5af5f564b2e487a47460c26938414fcc43e1d93319b4e7d9f8f0ba93484be17a45268f65107be1730914acac5a8f76729050e646333ce658fcb4af31c1f04d3bd5bad0bfc5d6a954a718f3f351f33fc5b899264f8eb1a8211d7b7d54d92ca71af245a2ade1bc9a4aa380d7cdf0b2693841279f8af93e3e934b0cf6349595e8ff85e5bc0888b8d91143cc55fc1fcdc9f55ce9928d3db31a75639252bcd54e047be7f4f14843e00c0350c00d54cce582a05855e0f9c1ddaa3995450893b211f0454255a900b2005f7bd5455f49da085e442973026c565a91517a3ab57fbaaa27b27435caed703f7049495a9e237ac04c5fe5bb1529740ee09cfc94dcecc321a7f95285fdf32a044931b52325f3f16ac11526a55a51a26be87be83d63fbb786be003baad1f083266c107dfdb578c687671faeb33f4a9a1bbae548e5ca74c2bceeed9efc2b2aee2528eee5a8a25dedf887844e66779c7443cd6cc17055d4bddcad0d55c072c67eb70514357731d329dde1e1cfc5af3ade2ca90ee9ad2bc663c478f0d45261dddab3a68e7f22b99913941c6d3d75c6432f8e04f7d13262764c4e8292bab5c6384d8bf18160519b1128e98decbf37a22b15131c7330b0d1c6e74e742efeecce34089a83ed29df14fec29baeb927f32c4074493b650a63292b2c9b43129d124f86032eb5c6a929fb2542a8ae1ac17eda871fe5a59026b815e0fde9f9f9fbc534a2a601fc9b8c85de4cf866700f725654e8d76e44aca829ab91fec6c6ea2debfb1d2a4ad73aaa31ddbd11679a989ae4ab821b4cecf996ff6a5c8f8e8d4541148cd43a518606949de134173a6c0d6183fab443a471f46f37413dfb3a4d01fc0ac3825c7ec218c7c6f3251448c18fc6862040328861f1199899ffe00125d4753399d5a5d26938622393346b281e714b00b44c635930913743aad75488ede9d87418fd2bcd7276a343c08628cb4039a47cb24cd5c53f59088e94a891afd9cbd8eb85832d9888b0e4b35944e57244b8666a88cd0625f6295232ed6348cb78655f6a5b867ea7de3af7379c445e86cd56daca75866266c6cd832de321b3c2852b4c3c5861368696ce582ebb0126963d78eb5b36509d122bf0950eb549414a6f00a29f6edbec078c3c39768411419976d812766c4f7bceb9c09744ace4498bae1c8f73c9e81991a0c60d3c8f19c9001089efb9e370596976c612a0c5f5d6ec12fbfc0d6e6d5e26a51683718c989342529fca95eef72f32a8aa2cb3e2e7885a27ddff3b2304dfeadb8662a863439b5691e3b2891ef4d8d0fac05b9e09a939c7f620e7aa8e095c964c7174198ea8fe0364c7306e219b8c7612345c10f06a641878c830e9a10a3b165054ba76ae1a1d1b1764faa3f1a7d8dba7f909ce39bd029d7a55a0c0b0862bbe570a53106926a2e054c263f76bdc5f6cc6c04cc14638bd209728bcb398c4ecb4512d42c06e5d6ae1735c01a64180d53dfd6ff457e13a33632bf2f44bb575c42d8a58f5375d99f3365d70b1ebb6647ec748bf69b68558cd0a1588a5117db0dfc7bfb9a8f20347f638bd4c46c8119ab9243a9c67f90bc62a1e18c8c9b0b4cd92068bbf53eb639dbf29adbfe6302960c952962d8da8c617727426f1a3d1f30fbfe79f6fb71b7f71ec0695f165294acced5fbf686c3688bbb8d18ae51677ca127bf1155de923cbc8f7cef2179cf08c5376f72c6741818e9426f9c3f162c8821204591f394a0ab4d6bf333a4b7a8b21e543adb7813748920e92ddb40414a62690f84dc4871cc121b3d43d46901e9a97c28f7b28ca59ad1700538d5a2a9ddf304c236f95f062c869ff1ea52fc2db8ae291e375566a20ff1d96e32396584eee579a892b7923edac8438ae59ac2949a8b3c63a00b31762632b2efa35971b4646617f95971b78406d599a58cdb32f6079bbe573e709dde1a8289efa5a434ad362572bec2bc53ea58ea435909daf7bd5a82dd082667e6e92da16ebda7e55c08ac6ce7d205069affab459a66ea90f09c7db57a435132a5bf8d2cdbd67d1b596f09b53b8475045196912ad7eb904e7dcfeee99b860503163b95beed299121f6bdba21e963ac243626a3d886f31913368d1ecc1b92e18b9f32fc11d5bbc363f630df249900af474d74b7f76bb15b18b370317cbf525ddc9c24465b47dca8e9b2aec03a73c1857e13161d1bc518eed8a37b3345105648d87e21717aa68d864599bc7d44078677cc9405da548ea5578e61b2af9d374f5510b35ac86914d7c564c5cc7401cbd6eeba60b676bf259aaddde7e06cedaec4d39e5a04f47a7b5d40afb7bf25a0d7dbcf017abdbd12507b6a11d0eeceba80e637405f0b08b7394f03dadd5909a83dd50664b651cfa3a9b3fb45a06c6c2d41e086bf5bffb5b2ff4593bf1bc08aa41fae9bf32f9cf2dd205665fa70dd447fe13cef46b12abd87eb66f7374feebf7f7646d065f5cf8c7aebe85ff76b6b0068d633badaceb955102f86072fb0a0fdd7ebb90342e02510d3f79a6e5b4b1831ed3a712e3269ceb5493360ee3b2693e4c05d79d8cddaec06a4d7837f9c55e331518fb8c0170b829b4730e77946e2391995d01ccd9ba1e1416bfec0dcd71406c17783b597a6acd0603a183370a224ad52d61e311dbc550c0aa26fcdb1b756158380d3c059274d5959c2f6e6264ce4cd9f2cd5d3aeabbea4be9a4226dc4f578ac1ce734ccd1671816d674d36085a6d4f0cf406ecd9bfb117a720a4860ce760c3b56a25d4e4667f6ad69a519920b5c0dd01b339ab9d18134de172c4f415ce62d04380fff77bbd5ca624bf95a5eebfd97cb369183e3e7e0ae03f1b7b05dfb82899ea5725535bdbaf6dfa5897af6cda97ce593a72cce411eec8b1c75d3e4e8c7cdfb35e9dcbb2c01e39e3ac2b38fd41d7f19e6911027bd4dc7def54df6b453f77d7ada66588a16e3854d4ccd61d367a2a0679876accdd795e1a45af8c9a3fc8bba70467636d7b872c0c2ad3b762f6645c509b2d7df85b19c436c62358d461eed0c88a345ab96ea3293bb3dbd8ce442590f35283cc80d21c5843fcd42decfa55a9fc1ef23b6ad472597a79d86b54ad2faa48ad6c5e3b8b9fcbe0c63adf3b95ff02c9ba9c2873093b3baf4308a1c534f715c300c6e48e851d1f3320c27ba2408f0b683e70b0378ad07137d75cc72d5ccec174ea7b2863003f39290811b9fa104c263321d36910fbdeecb3853e04bd7a7ee1420ffe075afe2a1f98724cf35f2d7c09a7fb66e173589b2f163e87a9f960e173985adf2b209b79f72d590ee3418f8bd9c707b1f9e265c5cdc711d30d61b8e88768214c2e1709ae608081e1cf6e52b130ff3f0000ffffcdc4073773240000", diff --git a/readme/main.go b/readme/main.go index f82f86e..5fc582b 100644 --- a/readme/main.go +++ b/readme/main.go @@ -32,7 +32,7 @@ func init() { goopt.Description = func() string { return "ORM and RESTful meta data viewer for SQl databases" } - goopt.Version = "v0.9.23 (07/10/2020)" + goopt.Version = "v0.9.24 (07/13/2020)" goopt.Summary = `dbmeta [-v] --sqltype=mysql --connstr "user:password@/dbname" --database sqltype - sql database type such as [ mysql, mssql, postgres, sqlite, etc. ] diff --git a/template/GEN_README.md.tmpl b/template/GEN_README.md.tmpl index e470a22..6647c11 100644 --- a/template/GEN_README.md.tmpl +++ b/template/GEN_README.md.tmpl @@ -249,6 +249,8 @@ Table Name: registration_source |ms sql |y | y | y | y | y | y| n ## Version History +- v0.9.24 (07/13/2020) + - Fixed array bounds issue parsing mysql db meta - v0.9.23 (07/10/2020) - Added postgres types: bigserial, serial, smallserial, bigserial, float4 to mapping.json - v0.9.22 (07/08/2020)