1. C# / Говнокод #3628

    +116

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    public void Parse(string sqlScript)
    {
    	batches = new List<string>();
    	State state = State.WaitingGO;
    	StartNewBatch();
    	for(position = 0; position < sqlScript.Length; position++)
    	{
    		char c = sqlScript[position];
    		if(state == State.WaitingGO)
    		{
    			PutToBuffer(c);
    			if(IsWhiteSpace(c) || IsEndOfLineCharacter(c)) continue;
    			else if(c == 'g' || c == 'G') state = State.ReadingGO;
    			else
    			{
    				state = State.ReadingBatch;
    				FlushBuffer();
    			}
    		}
    		else if(state == State.ReadingGO)
    		{
    			PutToBuffer(c);
    			if(c == 'o' || c == 'O') state = State.ReadedGO;
    			else if(IsEndOfLineCharacter(c))
    			{
    				state = State.WaitingGO;
    				FlushBuffer();
    			}
    			else
    			{
    				state = State.ReadingBatch;
    				FlushBuffer();
    			}
    		}
    		else if(state == State.ReadedGO)
    		{
    			if(IsWhiteSpace(c) || IsEndOfLineCharacter(c))
    			{
    				state = State.WaitingGO;
    				FinishBatch();
    				StartNewBatch();
    			}
    			else
    			{
    				state = State.ReadingBatch;
    				PutToBuffer(c);
    				FlushBuffer();
    			}
    		}
    		else if(state == State.ReadingBatch)
    		{
    			PutToBatch(c);
    			if(IsEndOfLineCharacter(c)) state = State.WaitingGO;
    		}
    	}
    	if(state != State.ReadedGO) FlushBuffer();
    	FinishBatch();
    }
    
    private enum State
    {
    	WaitingGO,
    	ReadingGO,
    	ReadedGO,
    	ReadingBatch
    }

    Требовалось распарсить string с sql-текстом на отдельные транзакции (т.е. просто разбить текст по go).
    Функции для работы с Batch-ем не привожу и так уйма говнокода

    Запостил: FedorFo, 02 Июля 2010

    Комментарии (23) RSS

    • если нужно выполнить сразу весть batch - есть специальный тип из сборок Microsoft.SqlServer.*
      Ответить
    • показать все, что скрытонеужели в С# нет красивых методов неиспользования конструкции
      if(state == State.WaitingGO)
      else if(state == State.ReadingGO)
      ...
      ???
      Ответить
      • switch(state)
        {
                 case State.WaitingGO: /* ... */ break;
                 case State.ReadingGO: /* ... */ break;
                 default: /* ... */ break;
        }
        Ответить
        • это тоже выглядит не очень, когда много стейтов...
          Ответить
          • А как надо? И причём тут сишарп? "Очень много стейтов" можно накуралесить на любом языке.
            Ответить
            • "Replace Conditional Logic with Strategy" надо, но тут это из пушки по воробьям
              Ответить
              • > но тут это из пушки по воробьям

                из воробья по пушкову
                Ответить
      • Вообще есть отличный рефакторинг "замена условной логики состоянием/стратегией".
        Но тут этого явно не надо
        Ответить
        • типа да... я ждал этого на уровне языка... В С++ приходится пользоваться фабрикой, для которой создавать таблицу соответствия...
          Ответить
      • >неужели в С# нет красивых методов неиспользования конструкции
        >if(state == State.WaitingGO)
        >else if(state == State.ReadingGO)

        тебе не понравилась конструкция State.WaitingGO? Уж это лучше, чем приходится в С++ писать State_WaitingGO, что-бы имена констант из различных энумов не совпали.
        Ответить
        • в новом стандарте будет State::WaitingGo

          а вообще можно так выкрутиться
          struct State
          {
            enum value_type
            {
              Waiting_Go,
              SomeOther,
            };
          }
          
          State::value_type var = State::Waiting_Go;
          Ответить
      • >неужели в С# нет красивых методов неиспользования конструкции
        >if(state == State.WaitingGO)
        >else if(state == State.ReadingGO)

        Какие проблемы?
        Заводи Dictionary для (типа Map) возвращающий функции и радуйся жизни. Можно даже просто массив завести для увеличения быстродействия.
        Итого будет типа:
        funcMap[state]();
        Ответить
        • Да, причём если создать сразу внутри метода и задействовать замыкания - тогда лямбды внутри словаря смогут получать доступ к локальным данным метода. Это то, чего нет в С++. Не этого ли хотел Пушкофф?
          Ответить
          • >Это то, чего нет в С++.
            Чего? Лямбды в стандарте С++0х есть и могут получать доступ к локальным данным метода.
            Ответить
            • Смешно читать "в стандарте С++0х есть", где суффикс -0x означает "to be released somewhere in 2000's". А на дворе 2010-ый год...

              Есть в стандарте, которого нет - это мощно!)
              Ответить
              • А между тем компиляторы уже есть и давно.
                Ответить
                • Да, но теоретически всё могут поменять, компиляторы что-то могут не поддерживать, расходиться в чём-то, коль стандарта реального нет. Не ынтырпрайз это всё!
                  Ответить
                  • Неспорю, но врятли уже что-то будут отменять, раз компиляторов понаписали.
                    Ответить
          • я фабрику написал, составил таблицу соответствия, вызов нужной функции одна (правда длинная) строка...
            всеравно это не то и не удобно (хотя удобнее чем 100 else if)...
            Ответить
    • это вместо sqlScript.Split(new[]{"GO","Go","go","gO"},StringSplitOptions .RemoveEmptyEntries) столько ифов колотить...
      Ответить
      • особенно если у вас будет таблица, содержащая сочетание букв go - от шикарные будут у вас кастрированные запросы
        Ответить
        • сделать тогда без StringSplitOptions .RemoveEmptyEntries, и 1 раз проверять на первый и последний пробел/энтер/таб
          Ответить
    • > ReadedGO
      Finish MGIMO?
      Ответить

    Добавить комментарий