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()