diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..99ec4282eb91f3df8b32eb3a1bb39ecd6f7bc26f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +.idea diff --git a/Python/README.md b/Python/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5cae7f5dcee1004aa1d531e4602988efdc40033f --- /dev/null +++ b/Python/README.md @@ -0,0 +1,51 @@ +# Python Api + +### 安装依赖 +```commandline +pip install -r requirements.txt +``` + +### 示例 +```python +from drive import driver +db = driver.Driver( + host="127.0.0.1", + username="root", + password="123456", +) + +try: + db.createDatabase("Linwin") + db.createData("Data", "Linwin") +except driver.DatabaseError as e: + ... +``` + +### Shell +示例 +```commandline +python shell.py +Logon Host[default 127.0.0.1]: localhost +Logon Port[default 8888]: +Logon User[default root]: +Logon Password[default 123456]: +======================= Linwin DB Client ======================= +LinwinDB-Mydb Shell $ something-wrong +Error Command and Script + +LinwinDB-Mydb Shell $ create database 'asdf' +Create Successful! + +Query executed completely! (0.292 sec, 3.42 qps) +LinwinDB-Mydb Shell $ create something-wrong +Command syntax error! + +LinwinDB-Mydb Shell $ list database +asdf + +Query executed completely! (0.277 sec, 3.61 qps) +LinwinDB-Mydb Shell $ +LinwinDB-Mydb Shell $ +LinwinDB-Mydb Shell $ quit + +``` diff --git a/Python/SqlDrive/SqlDrive.py b/Python/SqlDrive/SqlDrive.py deleted file mode 100644 index 024523d2549d6691f2e61f686c7bb99491fc3bb0..0000000000000000000000000000000000000000 --- a/Python/SqlDrive/SqlDrive.py +++ /dev/null @@ -1,86 +0,0 @@ -import requests -import time -import hashlib - -class SQL_DO(object): - def __init__(self,remote,user,passwd) -> None: - self.userName = user - self.Passwd = passwd - self.Remote = remote - - def add_MD5(self,addStr:str)->str: - hl = hashlib.md5() - hl.update(addStr.encode("utf-8")) - return hl.hexdigest() - - def sendMysScript(self,script:str) -> bool: - #print(str(self.Remote)+"/?Logon="+str(self.userName)+"?Passwd="+str(self.add_MD5(self.Passwd))+"?Command="+script) - r = requests.get(str(self.Remote)+"/?Logon="+str(self.userName)+"?Passwd="+str(self.add_MD5(self.Passwd))+"?Command="+script) - getText = r.text - split:list[str] = getText.split("\n") - message:str = "" - j = 0 - splitADD:list[str] = [] - for i in split: - j += 1 - splitADD.append(str(i)+"\n") - - message = message.join(splitADD) - - j = j - 1 - self.Message = message - if j == 0: - return False - else: - return True - def getMessage(self) -> str: - return self.Message - def outValue(self) -> None: - print(self.userName+" "+self.Passwd+" "+self.Remote) - - def listDatabase(self) -> list[str]: - if self.sendMysScript("list database") == True: - return self.getMessage().split("\n") - else: - return [] - - def deleteDatabase(self,name:str) -> bool: - return self.sendMysScript("delete database "+str(name)) - - def deleteData(self,name:str,database:str) -> bool: - return self.sendMysScript("delete data '"+str(name)+"' in "+database) - - def reNameDatabase(self,name:str,NewName:str) -> bool: - return self.sendMysScript("rename database '"+name+"' '"+NewName+"'") - - def reNameData(self,name:str,NewName:str,database:str) -> bool: - return self.sendMysScript("rename data '"+name+"' '"+NewName+"' in "+database) - - def createDatabase(self,name:str) -> bool: - return self.sendMysScript("create database '"+name+"'") - - def createData(self,name:str,database:str) -> bool: - return self.sendMysScript("create data '"+name+"' in "+database) - - def findDatabase(self,index:str) -> list[str]: - self.sendMysScript("find database "+index) - return self.getMessage().split("\n") - - def findData(self,index:str) -> list[str]: - self.sendMysScript("find data "+index) - return self.getMessage().split("\n") - - def getData(self,dataName:str,type:str,database:str) -> str: - self.sendMysScript("get '"+dataName+"'."+type+" in"+database) - return self.getMessage().replace("\n","") - - def indexData(self,index:str,database:str) -> list[str]: - self.sendMysScript("index '"+index+"' in "+database) - return self.getMessage().split("\n") - - def copyDatabase(self,name:str,target:str) -> bool: - return self.sendMysScript("copy '"+name+"' '"+target+"'") - - def getAlldata_FromDatabase(self,database:str) -> list[str]: - self.sendMysScript("ls "+database) - return self.getMessage().split("\n") \ No newline at end of file diff --git a/Python/SqlDrive/__pycache__/SqlDrive.cpython-310.pyc b/Python/SqlDrive/__pycache__/SqlDrive.cpython-310.pyc deleted file mode 100644 index 25f3ae095ee1a23ef50f5c6f451a2745cefab87e..0000000000000000000000000000000000000000 Binary files a/Python/SqlDrive/__pycache__/SqlDrive.cpython-310.pyc and /dev/null differ diff --git a/Python/__init__.py b/Python/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..30f534bcf65d152933693c8fceb4c4cde8e5fee2 --- /dev/null +++ b/Python/__init__.py @@ -0,0 +1,6 @@ +from drive import driver + + +__all__ = [ + "driver", +] diff --git a/Python/drive/__init__.py b/Python/drive/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..2542e3be63cf081ea9c74ebb325d03533db7c967 --- /dev/null +++ b/Python/drive/__init__.py @@ -0,0 +1,5 @@ +from . import driver + +__all__ = [ + "driver", +] diff --git a/Python/drive/driver.py b/Python/drive/driver.py new file mode 100644 index 0000000000000000000000000000000000000000..53784052782a64ba2cb6cd905f356d6374da2c3b --- /dev/null +++ b/Python/drive/driver.py @@ -0,0 +1,97 @@ +import requests +import hashlib +from typing import List, Iterable + + +class DatabaseError(Exception): + pass + + +class Driver(object): + """ + LinWin DB Server Python Client. + e.g. + >>> from drive import driver + >>> driver = driver.Driver( + >>> host="127.0.0.1", + >>> username="root", + >>> password="123456", + >>> ) + + >>> driver.remote + > 'http://127.0.0.1:8888' + + + """ + + def __init__(self, username: str, password: str, host: str, port: int = 8888, enable_ssl=False) -> None: + """ + :param username: user name (like root, linwin) + :param password: raw password (like 123456) + :param host: host name of the database (like 127.0.0.1, localhost, example.org) + :param port: port of the database, default is 8888 + :param enable_ssl: enable ssl. if the variable is true, it will be https:// . + """ + self.username = username + self.password = hashlib.md5(password.encode("utf-8")).hexdigest() # generate md5 value of raw password + self.host = host + self.port = port + self.enable_ssl = enable_ssl + + @property + def remote(self): + return f"{'https' if self.enable_ssl else 'http'}://{self.host}:{self.port}/" + + def execute(self, script: str) -> str: + raw = requests.get(f"{self.remote}/?Logon={self.username}?Passwd={self.password}?Command={script}").text + assert raw != "\n", DatabaseError("Request execution failure!") + return raw + + def execute_ignore(self, script: str) -> bool: + try: + self.execute(script) + return True + except DatabaseError: + return False + + def __str__(self) -> str: + return f"Driver(username={self.username}, password={self.password}, remote={self.remote})" + + def listDatabase(self) -> List[str]: + return self.execute("list database").split("\n") + + def deleteDatabase(self, name: str) -> bool: + return self.execute_ignore(f"delete database {name}") + + def deleteData(self, name: str, database: str) -> bool: + return self.execute_ignore(f"delete data '{name}' in {database}") + + def renameDatabase(self, name: str, NewName: str) -> bool: + return self.execute_ignore(f"rename database '{name}' '{NewName}'") + + def renameData(self, name: str, NewName: str, database: str) -> bool: + return self.execute_ignore(f"rename data '{name}' '{NewName}' in {database}") + + def createDatabase(self, name: str) -> bool: + return self.execute_ignore(f"create database '{name}'") + + def createData(self, name: str, database: str) -> bool: + return self.execute_ignore(f"create data '{name}' in {database}") + + def findDatabase(self, index: str) -> List[str]: + return self.execute(f"find database {index}").split("\n") + + def findData(self, index: str) -> List[str]: + return self.execute(f"find data {index}").split("\n") + + def getData(self, name: str, type: str, database: str) -> str: + return self.execute(f"get '{name}'.{type} in {database}").replace("\n", "") + + def indexData(self, index: str, database: str) -> List[str]: + return self.execute(f"index '{index}' in {database}").split("\n") + + def copyDatabase(self, name: str, target: str) -> bool: + return self.execute_ignore(f"copy '{name}' '{target}'") + + def iterFromDatabase(self, database: str) -> Iterable[str]: + return iter(self.execute(f"ls {database}").split("\n")) diff --git a/Python/requirements.txt b/Python/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..e465b3b29c3fe53eb5bdac655b86537b3a812714 --- /dev/null +++ b/Python/requirements.txt @@ -0,0 +1 @@ +requests>=2 \ No newline at end of file diff --git a/Python/shell.py b/Python/shell.py new file mode 100644 index 0000000000000000000000000000000000000000..f00608cf53a532ac17aacd6f3ff285cf2bc28d24 --- /dev/null +++ b/Python/shell.py @@ -0,0 +1,50 @@ +# +# Author: Linwincloud & zmh-program +# Description: Mydb Shell for Linwin Data Server +# Usage: Operate the Linwin Database. +# + +import sys +from time import time +from drive import driver + + +# 因为控制台输出时序问题,暂不用logging + + +def _save_qps_count(bench: float) -> str: + return f'{round(1 / bench, 2) if bench != 0 else "*"} qps' + + +def _get_query_params(bench: float) -> str: + return "Query executed completely! (%0.3f sec, %s)" % (bench, _save_qps_count(bench)) + + +if __name__ == "__main__": + _driver = driver.Driver( + host=input("Logon Host[default 127.0.0.1]: ").strip() or "127.0.0.1", + port=int(input("Logon Port[default 8888]: ").strip() or 8888), + username=input("Logon User[default root]: ").strip() or "root", + password=input("Logon Password[default 123456]: ").strip() or "123456", + ) + + print(" Linwin DB Client ".center(64, "=")) + while True: + script = input("LinwinDB-Mydb Shell $ ").strip() + if script == "quit": + sys.exit(0) + elif not script: + continue + mark = time() + try: + response = _driver.execute(script) + except driver.DatabaseError: + benchmark = time() - mark + print(_get_query_params(benchmark)) + else: + print(response, end="") + if response not in ("Error Command and Script\r\n", "Command syntax error!\r\n"): + benchmark = time() - mark + print(_get_query_params(benchmark)) + continue + print(end="\n") diff --git a/Python/test.py b/Python/test.py index a189d563d10b6076d7a7bb6ccd8582b7bca02671..46d7b4bef095df758439dd6a34dba22e0bc5f901 100644 --- a/Python/test.py +++ b/Python/test.py @@ -1,9 +1,15 @@ -import SqlDrive.SqlDrive as a -import time +from drive import driver +from timeit import timeit -b = a.SQL_DO("http://127.0.0.1:8888/","root","123456") +driver = driver.Driver( + host="127.0.0.1", + username="root", + password="123456", +) -s = time.time() -print(len(b.findData("d"))) -e = time.time() -print((e-s)) \ No newline at end of file +# tip: Linwin DB Database ip 节流, 短时间内请求次数请不要设置过多 + +driver.createDatabase("Linwin") +driver.createData("Data", "Linwin") + +print("qps:", 1/timeit('driver.findData("d")', globals=globals(), number=1))