Fast Create Table for MySQL

Neden bilmiyorum, ne zaman bir projeye başlasam veritabanını tasarlarken kağıt kalem varsa önümde karalarım, yoksa kalkıp almaya üşeniyorum açıyorum bir notepad yazıyorum veritabanını kendi okuyacağım şekilde.

Kullanacağınızı sanmıyorum ama kod örneği olması açısından paylaşıyorum. Şuan sadece değişken ve tür kontrolleri var, bazı yerlere not düştüm 2.version da yapacağıma dair. Onlardan da emin değilim SQL bilmeyen kullanmasın diyip sıyrılmak istiyorum =)

Kullandığım yapı şu şekilde (örnek veriyorum);

vars
	id int pk ai
	_key vc 100
	_val txt

usr_group
	id int pk ai
	name vc 50

usrs
	id int pk ai
	grp_id int fk > usr_group(id)
	nick vc 25
	psw vc 32
	email vc 50

Program otomatikman SQL koduna çeviriyor;

    CREATE TABLE vars(
    	id INT PRIMARY KEY AUTO_INCREMENT ,
    	_key VARCHAR (100) ,
    	_val TEXT ,
    )

    CREATE TABLE usr_group(
    	id INT PRIMARY KEY AUTO_INCREMENT ,
    	name VARCHAR (50) ,

    )

    CREATE TABLE usrs(
    	id INT PRIMARY KEY AUTO_INCREMENT ,
    	grp_id INT FOREIGN KEY REFERENCES usr_group(id),
    	nick VARCHAR (25) ,
    	psw VARCHAR (32) ,
    	email VARCHAR (50) ,

    )

Kaynak kodu da hemen altta. Çok eksik var yazdığım bir kaç fonksiyonu kullanamadım bile şimdilik kalsın onlar da ilerleyen zamanlar da bakarım artık.

   #-*- coding: utf-8 -*-

__author__ = u"Fatih Mert Doğancan"
# Web: 				http://fatihmertdogancan.com
# Release v0.1:		16.01.2018
# Github:			@fatihmert

import re,sys

# TOKENS
tCOMMENT = "--" #todo version2
tNULL = "null" #todo version2
tNOT_NULL = "!null" #todo version2
tREFERENCES = ">"
tFOREIGN_KEY = "fk"
tPRIMARY_KEY = "pk"
tUNIQUE = "u" #todo version2
tAUTO_INCREMENT = "ai"

class Token:
	def __init__(self,line):
		self.line = str(line)

	def do(self):
		return self.line.split(' ')

# NOT HAVING PARAMs TYPE (todo v2)
_NOT_P_TYPES = ["TEXT","BLOB","TINYBLOB","MEDIUMBLOB","LONGBLOB","BOOLEAN","BOOL",]

# DATA TYPES
_TYPES = {
	"INT" : "int",
	"TINYINT" : "tint|tinyint",
	"SMALLINT" : "sint|smallint",
	"MEDIUMINT" : "mint|mediumint",
	"BIGINT" : "bint|bigint",
	"FLOAT" : "float",
	"DOUBLE" : "double",
	"DECIMAL" : "decimal",
	"DATE" : "date",
	"DATETIME" : "dtime|datatime",
	"TIMESTAMP" : "ts|stamp|timestamp|tstamp",
	"TIME" : "time",
	"YEAR" : "year",
	"CHAR" : "c|chr",
	"VARCHAR" : "vc|vchar",
	"BLOB" : "bb|blob",
	"TINYBLOB" : "tbb|tblob",
	"MEDIUMBLOB" : "mbb|mblob",
	"LONGBLOB" : "lbb|lblob",
	"TEXT" : "txt|text",
	"TINYTEXT" : "ttxt|ttext",
	"MEDIUMTEXT" : "mtxt|mtext",
	"LONGTEXT" : "ltxt|ltext",
	"ENUM" : "enum",
}

_CONVERT_TYPES = {}
res = dict((v,k) for k,v in _TYPES.iteritems())
for k,v in res.iteritems():
	for key_ in k.split('|'):
		_CONVERT_TYPES[key_] = v

del res


class Utils:
	def __init__(self):
		self.var_regex = r"^[a-z_A-Z][0-9_a-zA-Z]*"
		self.escape_dict={'\a':r'\a','\b':r'\b','\c':r'\c','\f':r'\f','\n':r'\n','\r':r'\r','\t':r'\t','\v':r'\v','\'':r'\'','\"':r'\"'}

		self.last_detect_type = ""

	def syntaxVariable(self,s):	#reserveler eklenecek
		return True if len(re.compile(self.var_regex).findall(s)) > 0 else False

	def checkVariableType(self,s):
		global _TYPES
		values = _TYPES.values()

		detect = 0
		for val in values.split('|'):
			detect += 1 if s == val else detect
			self.last_detect_type = s

		return True if detect > 0 else False

	def indentControl(self,token):
		return True if token[0][0] == "\t" else False

	def isTable(self,token):
		return True if len(token) == 1 and self.syntaxVariable(token[0]) else False

	def isColumn(self,token):
		return True if len(token) >= 2 and self.indentControl(token) and self.syntaxVariable(token[0][2:]) else False

	def convertRaw(self,s):
		nw_str = ""
		for c in s:
			try:
				nw_str += self.escape_dict[c]
			except KeyError:
				nw_str += c
		return nw_str

	def haveNewLine(self,s):
		return list(s)[slice(-1,None)] == ["\n"]


SQL = ""

CUR_LINE = 1
TOTAL_TABLES = 0
INDENT = 0

util = Utils()

if len(sys.argv) == 2:
	fname = sys.argv[1]
	test = open(fname,"r")
	for line in test.read().split("\n"):
		current = Token(line).do()
		if util.isTable(current):
			#print "Tablo: ",current[0]
			SQL += "CREATE TABLE %s(\n"%current[0]
			
			INDENT = 1
			TOTAL_TABLES += 1

		elif util.isColumn(current):
			# Get column name
			column_name = current[0][1:]

			SQL += "\t%s "%column_name

			column_type = None


			# Get column type
			try:
				column_type = _CONVERT_TYPES[current[1]]
			except KeyError:
				assert("Unknown MySQL Type !")

			SQL += "%s "%column_type

			# This section I'll do version 2
			# If type's have param(s)
			#more_params = False
			#try:
			#	if len(current[2].split(',')) > 1:
			#		more_params = True
			#		print current[2].split(',')
			#	else:
			#		# Try to integer for type length
			#		try:
			#			column_params = int(current[2])
			#			more_params = False
			#		except:
			#			pass
			#except:
			#	pass

			column_params = False
			save_index = 2
			try:
				column_params = int(current[2])
				SQL += "(%s) "%column_params
				save_index = 3
			except:
				column_params = False
				assert("MySQL Type Length Must Be Integer !")

			if save_index == 3 and len(current) == 3:
				SQL += ",\n"
				#continue





			primary_key = False
			try:
				if current[save_index] == tPRIMARY_KEY:
					primary_key = True
					SQL += "PRIMARY KEY "
			except:
				pass

			auto_increment = False
			try:
				if current[save_index+1] == tAUTO_INCREMENT:
					auto_increment = True
					SQL += "AUTO_INCREMENT "
			except:
				pass

			# type and pk via ai ctrl - todo version 2

			if primary_key == False:
				foreign_key = False
				try:
					if current[save_index] == tFOREIGN_KEY:
						foreign_key = True
						SQL += "FOREIGN KEY "
				except:
					pass

				if foreign_key:
					if current[save_index+1] == tREFERENCES:
						SQL += "REFERENCES %s\n"%current[save_index+2]
			else:
				SQL += ",\n"


			#print "Column: ",column_name,column_type


		if len(current) == 1 and len(current[0]) == 0:
			INDENT = 0

		if INDENT == 0:
			SQL += "\n)\n\n"

		#print current


		# LINE ++ (for detect line's error detecting)
		CUR_LINE += 1


	#print u"Tablo sayısı: ",TOTAL_TABLES
	with open("%s.sql"%fname.split('.')[0],"a") as w:
		w.write(SQL)
	#print "-"*50
	#print SQL
	#curr = test.readlines()
	#print type(curr)
	#print util.convertRaw(curr)
	#print util.isTable(util.convertRaw(curr))
	print "Completed"
	test.close()
2 Beğeni

Merhaba.

Programla ilgili bir yorum değil de bir bilgi paylaşmak istiyorum. Kodları şurada bahsedildiği gibi üç çentik(```) arasına alırsanız, kodlar sözdizimi renklendirmesi ile çok daha okunabilir olur. Küçük programlarda sorun olmuyor da bunun gibi nispeten uzun programlarda okumak biraz zor oluyor renklendirme olmadan bana göre.

İyi çalışmalar.

Bir de programlarınızı bir GitHub veri havuzunda ya da Gist’te paylaşmayı düşünmez miydiniz? Bizler için hem elde etmesi hem de katkı sağlaması çok daha kolay olurdu böylece.

Atacağım zaten de dün gece üşendim biraz. Bu akşam üstü muhtemelen.

Güzel bir proje olmuş. Python’u bir şeyleri kısaltmak için kullanmayı çok seviyorum. Ellerinize sağlık :slight_smile: